System modules - Hoist classes like other variables (#9639)

This commit is contained in:
Guy Bedford 2019-03-11 00:33:19 +02:00 committed by Nicolò Ribaudo
parent dd2ffda387
commit a891b73401
7 changed files with 122 additions and 53 deletions

View File

@ -216,10 +216,11 @@ export default declare((api, options) => {
state.contextIdent = path.scope.generateUid("context"); state.contextIdent = path.scope.generateUid("context");
}, },
exit(path, state) { exit(path, state) {
const undefinedIdent = path.scope.buildUndefinedNode();
const exportIdent = path.scope.generateUid("export"); const exportIdent = path.scope.generateUid("export");
const contextIdent = state.contextIdent; const contextIdent = state.contextIdent;
const exportNames = Object.create(null); const exportMap = Object.create(null);
const modules = []; const modules = [];
let beforeBody = []; let beforeBody = [];
@ -229,8 +230,8 @@ export default declare((api, options) => {
const removedPaths = []; const removedPaths = [];
function addExportName(key, val) { function addExportName(key, val) {
exportNames[key] = exportNames[key] || []; exportMap[key] = exportMap[key] || [];
exportNames[key].push(val); exportMap[key].push(val);
} }
function pushModule(source, key, specifiers) { function pushModule(source, key, specifiers) {
@ -257,12 +258,26 @@ export default declare((api, options) => {
); );
} }
const exportNames = [];
const exportValues = [];
const body: Array<Object> = path.get("body"); const body: Array<Object> = path.get("body");
for (const path of body) { for (const path of body) {
if (path.isFunctionDeclaration()) { if (path.isFunctionDeclaration()) {
beforeBody.push(path.node); beforeBody.push(path.node);
removedPaths.push(path); removedPaths.push(path);
} else if (path.isClassDeclaration()) {
variableIds.push(path.node.id);
path.replaceWith(
t.expressionStatement(
t.assignmentExpression(
"=",
t.cloneNode(path.node.id),
t.toExpression(path.node),
),
),
);
} else if (path.isImportDeclaration()) { } else if (path.isImportDeclaration()) {
const source = path.node.source.value; const source = path.node.source.value;
pushModule(source, "imports", path.node.specifiers); pushModule(source, "imports", path.node.specifiers);
@ -276,29 +291,38 @@ export default declare((api, options) => {
path.remove(); path.remove();
} else if (path.isExportDefaultDeclaration()) { } else if (path.isExportDefaultDeclaration()) {
const declar = path.get("declaration"); const declar = path.get("declaration");
if ( const id = declar.node.id;
declar.isClassDeclaration() || if (declar.isClassDeclaration()) {
declar.isFunctionDeclaration()
) {
const id = declar.node.id;
const nodes = [];
if (id) { if (id) {
nodes.push(declar.node); exportNames.push("default");
nodes.push(buildExportCall("default", t.cloneNode(id))); exportValues.push(undefinedIdent);
variableIds.push(id);
addExportName(id.name, "default"); addExportName(id.name, "default");
} else { path.replaceWith(
nodes.push( t.expressionStatement(
buildExportCall("default", t.toExpression(declar.node)), t.assignmentExpression(
"=",
t.cloneNode(id),
t.toExpression(declar.node),
),
),
); );
}
if (declar.isClassDeclaration()) {
path.replaceWithMultiple(nodes);
} else { } else {
beforeBody = beforeBody.concat(nodes); exportNames.push("default");
exportValues.push(t.toExpression(declar.node));
removedPaths.push(path); removedPaths.push(path);
} }
} else if (declar.isFunctionDeclaration()) {
if (id) {
beforeBody.push(declar.node);
exportNames.push("default");
exportValues.push(t.cloneNode(id));
addExportName(id.name, "default");
} else {
exportNames.push("default");
exportValues.push(t.toExpression(declar.node));
}
removedPaths.push(path);
} else { } else {
path.replaceWith(buildExportCall("default", declar.node)); path.replaceWith(buildExportCall("default", declar.node));
} }
@ -313,12 +337,24 @@ export default declare((api, options) => {
const name = node.id.name; const name = node.id.name;
addExportName(name, name); addExportName(name, name);
beforeBody.push(node); beforeBody.push(node);
beforeBody.push(buildExportCall(name, t.cloneNode(node.id))); exportNames.push(name);
exportValues.push(t.cloneNode(node.id));
removedPaths.push(path); removedPaths.push(path);
} else if (path.isClass()) { } else if (path.isClass()) {
const name = declar.node.id.name; const name = declar.node.id.name;
exportNames.push(name);
exportValues.push(undefinedIdent);
variableIds.push(declar.node.id);
path.replaceWith(
t.expressionStatement(
t.assignmentExpression(
"=",
t.cloneNode(declar.node.id),
t.toExpression(declar.node),
),
),
);
addExportName(name, name); addExportName(name, name);
path.insertAfter([buildExportCall(name, t.identifier(name))]);
} else { } else {
for (const name of Object.keys( for (const name of Object.keys(
declar.getBindingIdentifiers(), declar.getBindingIdentifiers(),
@ -344,12 +380,8 @@ export default declare((api, options) => {
binding && binding &&
t.isFunctionDeclaration(binding.path.node) t.isFunctionDeclaration(binding.path.node)
) { ) {
beforeBody.push( exportNames.push(specifier.exported.name);
buildExportCall( exportValues.push(t.cloneNode(specifier.local));
specifier.exported.name,
t.cloneNode(specifier.local),
),
);
} }
// only globals also exported this way // only globals also exported this way
else if (!binding) { else if (!binding) {
@ -453,13 +485,13 @@ export default declare((api, options) => {
let moduleName = this.getModuleName(); let moduleName = this.getModuleName();
if (moduleName) moduleName = t.stringLiteral(moduleName); if (moduleName) moduleName = t.stringLiteral(moduleName);
const uninitializedVars = [];
hoistVariables( hoistVariables(
path, path,
(id, name, hasInit) => { (id, name, hasInit) => {
variableIds.push(id); variableIds.push(id);
if (!hasInit) { if (!hasInit) {
uninitializedVars.push(name); exportNames.push(name);
exportValues.push(undefinedIdent);
} }
}, },
null, null,
@ -474,25 +506,20 @@ export default declare((api, options) => {
); );
} }
if (uninitializedVars.length) { if (exportNames.length) {
const undefinedValues = [];
const undefinedIdent = path.scope.buildUndefinedNode();
for (let i = 0; i < uninitializedVars.length; i++) {
undefinedValues[i] = undefinedIdent;
}
beforeBody = beforeBody.concat( beforeBody = beforeBody.concat(
constructExportCall( constructExportCall(
path, path,
t.identifier(exportIdent), t.identifier(exportIdent),
uninitializedVars, exportNames,
undefinedValues, exportValues,
null, null,
), ),
); );
} }
path.traverse(reassignmentVisitor, { path.traverse(reassignmentVisitor, {
exports: exportNames, exports: exportMap,
buildCall: buildExportCall, buildCall: buildExportCall,
scope: path.scope, scope: path.scope,
}); });

View File

@ -1,12 +1,14 @@
System.register([], function (_export, _context) { System.register([], function (_export, _context) {
"use strict"; "use strict";
var Foo;
_export("default", void 0);
return { return {
setters: [], setters: [],
execute: function () { execute: function () {
class Foo {} _export("default", Foo = class Foo {});
_export("default", Foo);
} }
}; };
}); });

View File

@ -1,13 +1,13 @@
System.register([], function (_export, _context) { System.register([], function (_export, _context) {
"use strict"; "use strict";
var foo, foo2, foo3, foo4, foo5, foo6; var foo8, foo, foo2, foo3, foo4, foo5, foo6;
function foo7() {} function foo7() {}
_export("foo7", foo7);
_export({ _export({
foo7: foo7,
foo8: void 0,
foo3: void 0, foo3: void 0,
foo5: void 0 foo5: void 0
}); });
@ -23,9 +23,7 @@ System.register([], function (_export, _context) {
_export("foo6", foo6 = 3); _export("foo6", foo6 = 3);
class foo8 {} _export("foo8", foo8 = class foo8 {});
_export("foo8", foo8);
_export("foo3", foo3 = 5); _export("foo3", foo3 = 5);
} }

View File

@ -0,0 +1,15 @@
export function hoisted () {
return HoistedClass, HoistedClassExport, HoistedClassDefaultExport;
}
class HoistedClass {
}
export class HoistedClassExport {
}
export default class HoistedClassDefaultExport {
}

View File

@ -0,0 +1,26 @@
System.register([], function (_export, _context) {
"use strict";
var HoistedClass, HoistedClassExport, HoistedClassDefaultExport;
function hoisted() {
return HoistedClass, HoistedClassExport, HoistedClassDefaultExport;
}
_export({
hoisted: hoisted,
HoistedClassExport: void 0,
default: void 0
});
return {
setters: [],
execute: function () {
HoistedClass = class HoistedClass {};
_export("HoistedClassExport", HoistedClassExport = class HoistedClassExport {});
_export("default", HoistedClassDefaultExport = class HoistedClassDefaultExport {});
}
};
});

View File

@ -7,9 +7,10 @@ System.register(["./evens"], function (_export, _context) {
return _export("p", p = isEven(n) ? n + 1 : n + 2); return _export("p", p = isEven(n) ? n + 1 : n + 2);
} }
_export("nextOdd", nextOdd); _export({
nextOdd: nextOdd,
_export("a", void 0); a: void 0
});
return { return {
setters: [function (_evens) { setters: [function (_evens) {

View File

@ -8,12 +8,12 @@ System.register([], function (_export, _context) {
_export("c", +c + 1), c++; _export("c", +c + 1), c++;
} }
_export("a", a);
function b() { function b() {
a(); a();
} }
_export("a", a);
return { return {
setters: [], setters: [],
execute: function () { execute: function () {