Skip to content
This repository was archived by the owner on Mar 29, 2018. It is now read-only.

Commit cb36ece

Browse files
Merge pull request #182 from esnext/es6-class-support
Add support for exporting ES6 classes.
2 parents 4191a26 + b527ce9 commit cb36ece

File tree

10 files changed

+91
-2
lines changed

10 files changed

+91
-2
lines changed

lib/exports.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ ExportDeclarationList.prototype.declarationForNode = function(node) {
5151
return new VariableExportDeclaration(this.module, node);
5252
} else if (n.FunctionDeclaration.check(node.declaration)) {
5353
return new FunctionExportDeclaration(this.module, node);
54+
} else if (n.ClassDeclaration.check(node.declaration)) {
55+
return new ClassExportDeclaration(this.module, node);
5456
} else if (n.ExportBatchSpecifier.check(node.specifiers[0])) {
5557
throw new Error(
5658
'`export *` found at ' + sourcePosition(this.module, node) +
@@ -200,6 +202,31 @@ memo(VariableExportDeclaration.prototype, 'specifiers', /** @this VariableExport
200202
});
201203
});
202204

205+
/**
206+
* Represents an export declaration of the form:
207+
*
208+
* export class Foo {}
209+
*
210+
* @constructor
211+
* @extends ExportDeclaration
212+
* @param {Module} mod
213+
* @param {AST.ExportDeclaration} node
214+
*/
215+
function ClassExportDeclaration(mod, node) {
216+
ExportDeclaration.call(this, mod, node);
217+
}
218+
extend(ClassExportDeclaration, ExportDeclaration);
219+
220+
/**
221+
* Gets the list of export specifiers for this declaration.
222+
*
223+
* @type {ExportSpecifier[]}
224+
* @name ClassExportDeclaration#specifiers
225+
*/
226+
memo(ClassExportDeclaration.prototype, 'specifiers', /** @this ClassExportDeclaration */function() {
227+
return [new ExportSpecifier(this, this.node.declaration)];
228+
});
229+
203230
/**
204231
* Represents an export declaration of the form:
205232
*

lib/formatters/bundle_formatter.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,14 @@ BundleFormatter.prototype.processExportDeclaration = function(mod, nodePath) {
329329
// transform the function
330330
this.processFunctionDeclaration(mod, nodePath.get('declaration'))
331331
);
332+
} else if (n.ClassDeclaration.check(node.declaration)) {
333+
return Replacement.swaps(
334+
// drop `export`
335+
nodePath, node.declaration
336+
).and(
337+
// transform the class
338+
this.processClassDeclaration(mod, nodePath.get('declaration'))
339+
);
332340
} else if (n.VariableDeclaration.check(node.declaration)) {
333341
return Replacement.swaps(
334342
// drop `export`
@@ -394,6 +402,28 @@ BundleFormatter.prototype.processFunctionDeclaration = function(mod, nodePath) {
394402
);
395403
};
396404

405+
/**
406+
* Rename the top-level class declaration to a unique name.
407+
*
408+
* ```js
409+
* class Foo {}
410+
* ```
411+
*
412+
* Becomes e.g.
413+
*
414+
* ```js
415+
* class mod$$Foo {}
416+
* ```
417+
*
418+
* @override
419+
*/
420+
BundleFormatter.prototype.processClassDeclaration = function(mod, nodePath) {
421+
return Replacement.swaps(
422+
nodePath.get('id'),
423+
this.reference(mod, nodePath.node.id)
424+
);
425+
};
426+
397427
/**
398428
* Since import declarations only control how we rewrite references we can just
399429
* remove them -- they don't turn into any actual statements.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
},
4747
"devDependencies": {
4848
"browserify": "^5.12.1",
49+
"es6-class": "^0.9.1",
4950
"example-runner": "^0.1.0",
5051
"fake-fs": "^0.4.0",
5152
"mocha": "^1.20.1",
@@ -55,4 +56,4 @@
5556
"fs": "./lib/browser/fs.js",
5657
"./lib/index.js": "./lib/browser/index.js"
5758
}
58-
}
59+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/* jshint esnext:true */
2+
3+
export default class {};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/* jshint esnext:true */
2+
3+
import Foo from './exporter';
4+
5+
assert.strictEqual(new Foo().constructor, Foo);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/* jshint esnext:true */
2+
3+
export class Foo {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/* jshint esnext:true */
2+
3+
import { Foo } from './exporter';
4+
5+
assert.strictEqual(new Foo().constructor, Foo);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/* jshint esnext:true */
2+
3+
export default class Point {
4+
constructor(x, y) {
5+
this.x = x;
6+
this.y = y;
7+
}
8+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/* jshint esnext:true */
2+
3+
import Point from './exporter';
4+
5+
assert.strictEqual(new Point(1, 2).x, 1);
6+
assert.strictEqual(new Point(1, 2).y, 2);

test/runner.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var fs = require('fs');
66
var Path = require('path');
77
var vm = require('vm');
88
var assert = require('assert');
9+
var es6class = require('es6-class');
910

1011
var modules = require('../lib');
1112
var utils = require('../lib/utils');
@@ -183,7 +184,7 @@ function requireTestFile(path, relativeTo, assert) {
183184
};
184185

185186
// Hack to work around an issue where vm does not set `this` to the context.
186-
code = '(function(){' + code + '\n}).call(global);';
187+
code = '(function(){' + es6class.compile(code).code + '\n}).call(global);';
187188
vm.runInNewContext(code, testFileGlobal, path);
188189

189190
testFileCache[path] = mod.exports;

0 commit comments

Comments
 (0)