From a891b7340114d92f1c772c8c69b8449585fce4bf Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Mon, 11 Mar 2019 00:33:19 +0200 Subject: [PATCH] System modules - Hoist classes like other variables (#9639) --- .../src/index.js | 105 +++++++++++------- .../systemjs/export-default-8/output.mjs | 8 +- .../systemjs/exports-variable/output.mjs | 10 +- .../systemjs/hoist-function-class/input.mjs | 15 +++ .../systemjs/hoist-function-class/output.mjs | 26 +++++ .../hoist-function-exports/output.mjs | 7 +- .../systemjs/hoisting-bindings/output.mjs | 4 +- 7 files changed, 122 insertions(+), 53 deletions(-) create mode 100644 packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoist-function-class/input.mjs create mode 100644 packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoist-function-class/output.mjs diff --git a/packages/babel-plugin-transform-modules-systemjs/src/index.js b/packages/babel-plugin-transform-modules-systemjs/src/index.js index 0159e2257f..0542d0d692 100644 --- a/packages/babel-plugin-transform-modules-systemjs/src/index.js +++ b/packages/babel-plugin-transform-modules-systemjs/src/index.js @@ -216,10 +216,11 @@ export default declare((api, options) => { state.contextIdent = path.scope.generateUid("context"); }, exit(path, state) { + const undefinedIdent = path.scope.buildUndefinedNode(); const exportIdent = path.scope.generateUid("export"); const contextIdent = state.contextIdent; - const exportNames = Object.create(null); + const exportMap = Object.create(null); const modules = []; let beforeBody = []; @@ -229,8 +230,8 @@ export default declare((api, options) => { const removedPaths = []; function addExportName(key, val) { - exportNames[key] = exportNames[key] || []; - exportNames[key].push(val); + exportMap[key] = exportMap[key] || []; + exportMap[key].push(val); } function pushModule(source, key, specifiers) { @@ -257,12 +258,26 @@ export default declare((api, options) => { ); } + const exportNames = []; + const exportValues = []; + const body: Array = path.get("body"); for (const path of body) { if (path.isFunctionDeclaration()) { beforeBody.push(path.node); 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()) { const source = path.node.source.value; pushModule(source, "imports", path.node.specifiers); @@ -276,29 +291,38 @@ export default declare((api, options) => { path.remove(); } else if (path.isExportDefaultDeclaration()) { const declar = path.get("declaration"); - if ( - declar.isClassDeclaration() || - declar.isFunctionDeclaration() - ) { - const id = declar.node.id; - const nodes = []; - + const id = declar.node.id; + if (declar.isClassDeclaration()) { if (id) { - nodes.push(declar.node); - nodes.push(buildExportCall("default", t.cloneNode(id))); + exportNames.push("default"); + exportValues.push(undefinedIdent); + variableIds.push(id); addExportName(id.name, "default"); - } else { - nodes.push( - buildExportCall("default", t.toExpression(declar.node)), + path.replaceWith( + t.expressionStatement( + t.assignmentExpression( + "=", + t.cloneNode(id), + t.toExpression(declar.node), + ), + ), ); - } - - if (declar.isClassDeclaration()) { - path.replaceWithMultiple(nodes); } else { - beforeBody = beforeBody.concat(nodes); + exportNames.push("default"); + exportValues.push(t.toExpression(declar.node)); 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 { path.replaceWith(buildExportCall("default", declar.node)); } @@ -313,12 +337,24 @@ export default declare((api, options) => { const name = node.id.name; addExportName(name, name); beforeBody.push(node); - beforeBody.push(buildExportCall(name, t.cloneNode(node.id))); + exportNames.push(name); + exportValues.push(t.cloneNode(node.id)); removedPaths.push(path); } else if (path.isClass()) { 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); - path.insertAfter([buildExportCall(name, t.identifier(name))]); } else { for (const name of Object.keys( declar.getBindingIdentifiers(), @@ -344,12 +380,8 @@ export default declare((api, options) => { binding && t.isFunctionDeclaration(binding.path.node) ) { - beforeBody.push( - buildExportCall( - specifier.exported.name, - t.cloneNode(specifier.local), - ), - ); + exportNames.push(specifier.exported.name); + exportValues.push(t.cloneNode(specifier.local)); } // only globals also exported this way else if (!binding) { @@ -453,13 +485,13 @@ export default declare((api, options) => { let moduleName = this.getModuleName(); if (moduleName) moduleName = t.stringLiteral(moduleName); - const uninitializedVars = []; hoistVariables( path, (id, name, hasInit) => { variableIds.push(id); if (!hasInit) { - uninitializedVars.push(name); + exportNames.push(name); + exportValues.push(undefinedIdent); } }, null, @@ -474,25 +506,20 @@ export default declare((api, options) => { ); } - if (uninitializedVars.length) { - const undefinedValues = []; - const undefinedIdent = path.scope.buildUndefinedNode(); - for (let i = 0; i < uninitializedVars.length; i++) { - undefinedValues[i] = undefinedIdent; - } + if (exportNames.length) { beforeBody = beforeBody.concat( constructExportCall( path, t.identifier(exportIdent), - uninitializedVars, - undefinedValues, + exportNames, + exportValues, null, ), ); } path.traverse(reassignmentVisitor, { - exports: exportNames, + exports: exportMap, buildCall: buildExportCall, scope: path.scope, }); diff --git a/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/export-default-8/output.mjs b/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/export-default-8/output.mjs index d3a5a24dbe..84456f8638 100644 --- a/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/export-default-8/output.mjs +++ b/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/export-default-8/output.mjs @@ -1,12 +1,14 @@ System.register([], function (_export, _context) { "use strict"; + var Foo; + + _export("default", void 0); + return { setters: [], execute: function () { - class Foo {} - - _export("default", Foo); + _export("default", Foo = class Foo {}); } }; }); diff --git a/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/exports-variable/output.mjs b/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/exports-variable/output.mjs index be63333c5b..540eaf3755 100644 --- a/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/exports-variable/output.mjs +++ b/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/exports-variable/output.mjs @@ -1,13 +1,13 @@ System.register([], function (_export, _context) { "use strict"; - var foo, foo2, foo3, foo4, foo5, foo6; + var foo8, foo, foo2, foo3, foo4, foo5, foo6; function foo7() {} - _export("foo7", foo7); - _export({ + foo7: foo7, + foo8: void 0, foo3: void 0, foo5: void 0 }); @@ -23,9 +23,7 @@ System.register([], function (_export, _context) { _export("foo6", foo6 = 3); - class foo8 {} - - _export("foo8", foo8); + _export("foo8", foo8 = class foo8 {}); _export("foo3", foo3 = 5); } diff --git a/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoist-function-class/input.mjs b/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoist-function-class/input.mjs new file mode 100644 index 0000000000..b417eeefc1 --- /dev/null +++ b/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoist-function-class/input.mjs @@ -0,0 +1,15 @@ +export function hoisted () { + return HoistedClass, HoistedClassExport, HoistedClassDefaultExport; +} + +class HoistedClass { + +} + +export class HoistedClassExport { + +} + +export default class HoistedClassDefaultExport { + +} \ No newline at end of file diff --git a/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoist-function-class/output.mjs b/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoist-function-class/output.mjs new file mode 100644 index 0000000000..e39d30ddd1 --- /dev/null +++ b/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoist-function-class/output.mjs @@ -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 {}); + } + }; +}); diff --git a/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoist-function-exports/output.mjs b/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoist-function-exports/output.mjs index 54c3d53e71..61759df89e 100644 --- a/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoist-function-exports/output.mjs +++ b/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoist-function-exports/output.mjs @@ -7,9 +7,10 @@ System.register(["./evens"], function (_export, _context) { return _export("p", p = isEven(n) ? n + 1 : n + 2); } - _export("nextOdd", nextOdd); - - _export("a", void 0); + _export({ + nextOdd: nextOdd, + a: void 0 + }); return { setters: [function (_evens) { diff --git a/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoisting-bindings/output.mjs b/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoisting-bindings/output.mjs index 3c774382ca..74730bf289 100644 --- a/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoisting-bindings/output.mjs +++ b/packages/babel-plugin-transform-modules-systemjs/test/fixtures/systemjs/hoisting-bindings/output.mjs @@ -8,12 +8,12 @@ System.register([], function (_export, _context) { _export("c", +c + 1), c++; } - _export("a", a); - function b() { a(); } + _export("a", a); + return { setters: [], execute: function () {