clean up dynamic imports, disable hoisting in system module formatter when **any** dynamic imports are included - fixes #1219

This commit is contained in:
Sebastian McKenzie 2015-04-11 17:22:48 -07:00
parent aba2d1c23c
commit 7905f48280
10 changed files with 57 additions and 41 deletions

View File

@ -36,10 +36,9 @@ function checkNode(stack, node, scope) {
export default class File {
constructor(opts = {}) {
this.dynamicImportedNoDefault = [];
this.dynamicImportIds = {};
this.dynamicImported = [];
this.dynamicImports = [];
this.dynamicImportAbsoluteDefaults = [];
this.dynamicImportIds = {};
this.dynamicImports = [];
this.usedHelpers = {};
this.dynamicData = {};
@ -335,7 +334,7 @@ export default class File {
return source;
}
addImport(source: string, name?: string, noDefault?: boolean): Object {
addImport(source: string, name?: string, absoluteDefault?: boolean): Object {
name ||= source;
var id = this.dynamicImportIds[name];
@ -346,9 +345,7 @@ export default class File {
var specifiers = [t.importDefaultSpecifier(id)];
var declar = t.importDeclaration(specifiers, t.literal(source));
declar._blockHoist = 3;
this.dynamicImported.push(declar);
if (noDefault) this.dynamicImportedNoDefault.push(declar);
if (absoluteDefault) this.dynamicImportAbsoluteDefaults.push(declar);
if (this.transformers["es6.modules"].canTransform()) {
this.moduleFormatter.importSpecifier(specifiers[0], declar, this.dynamicImports);

View File

@ -80,9 +80,10 @@ export default class AMDFormatter extends DefaultFormatter {
this.defaultIds[key] = specifier.local;
}
if (includes(this.file.dynamicImportedNoDefault, node)) {
// Prevent unnecessary renaming of dynamic imports.
if (includes(this.file.dynamicImportAbsoluteDefaults, node)) {
// prevent unnecessary renaming of dynamic imports
this.ids[node.source.value] = ref;
ref = t.memberExpression(ref, t.identifier("default"));
} else if (t.isImportNamespaceSpecifier(specifier)) {
// import * as bar from "foo";
} else if (!includes(this.file.dynamicImported, node) && t.isSpecifierDefault(specifier) && !this.noInteropRequireImport) {

View File

@ -45,20 +45,18 @@ export default class CommonJSFormatter extends DefaultFormatter {
// import foo from "foo";
if (t.isSpecifierDefault(specifier)) {
if (includes(this.file.dynamicImportedNoDefault, node)) {
if (includes(this.file.dynamicImportAbsoluteDefaults, node)) {
this.internalRemap[variableName.name] = ref;
} else if (this.noInteropRequireImport) {
this.internalRemap[variableName.name] = t.memberExpression(ref, t.identifier("default"));
} else {
if (this.noInteropRequireImport) {
this.internalRemap[variableName.name] = t.memberExpression(ref, t.identifier("default"));
} else if (!includes(this.file.dynamicImported, node)) {
var uid = this.scope.generateUidBasedOnNode(node, "import");
var uid = this.scope.generateUidBasedOnNode(node, "import");
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(uid, t.callExpression(this.file.addHelper("interop-require-wildcard"), [ref]))
]));
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(uid, t.callExpression(this.file.addHelper("interop-require-wildcard"), [ref]))
]));
this.internalRemap[variableName.name] = t.memberExpression(uid, t.identifier("default"));
}
this.internalRemap[variableName.name] = t.memberExpression(uid, t.identifier("default"));
}
} else {
if (t.isImportNamespaceSpecifier(specifier)) {
@ -106,7 +104,7 @@ export default class CommonJSFormatter extends DefaultFormatter {
var call = t.callExpression(t.identifier("require"), [node.source]);
var uid;
if (includes(this.file.dynamicImported, node) && !includes(this.file.dynamicImportedNoDefault, node)) {
if (includes(this.file.dynamicImportAbsoluteDefaults, node)) {
call = t.memberExpression(call, t.identifier("default"));
uid = node.specifiers[0].local;
} else {

View File

@ -6,12 +6,8 @@ import each from "lodash/collection/each";
import map from "lodash/collection/map";
import * as t from "../../types";
var canHoist = function (node, file) {
return node._blockHoist && !file.transformers.runtime.canTransform();
}
var hoistVariablesVisitor = {
enter(node, parent, scope, hoistDeclarators) {
enter(node, parent, scope, state) {
if (t.isFunction(node)) {
// nothing inside is accessible
return this.skip();
@ -24,13 +20,13 @@ var hoistVariablesVisitor = {
}
// ignore block hoisted nodes as these can be left in
if (canHoist(node, scope.file)) return;
if (state.formatter.canHoist(node)) return;
var nodes = [];
for (var i = 0; i < node.declarations.length; i++) {
var declar = node.declarations[i];
hoistDeclarators.push(t.variableDeclarator(declar.id));
state.hoistDeclarators.push(t.variableDeclarator(declar.id));
if (declar.init) {
// no initializer so we can just hoist it as-is
var assign = t.expressionStatement(t.assignmentExpression("=", declar.id, declar.init));
@ -56,11 +52,11 @@ var hoistVariablesVisitor = {
};
var hoistFunctionsVisitor = {
enter(node, parent, scope, handlerBody) {
enter(node, parent, scope, state) {
if (t.isFunction(node)) this.skip();
if (t.isFunctionDeclaration(node) || canHoist(node, scope.file)) {
handlerBody.push(node);
if (t.isFunctionDeclaration(node) || state.formatter.canHoist(node)) {
state.handlerBody.push(node);
this.remove();
}
}
@ -174,6 +170,10 @@ export default class SystemFormatter extends AMDFormatter {
}));
}
canHoist(node) {
return node._blockHoist && !this.file.dynamicImports.length;
}
transform(program) {
DefaultFormatter.prototype.transform.apply(this, arguments);
@ -197,7 +197,10 @@ export default class SystemFormatter extends AMDFormatter {
var returnStatement = handlerBody.pop();
// hoist up all variable declarations
this.file.scope.traverse(block, hoistVariablesVisitor, hoistDeclarators);
this.file.scope.traverse(block, hoistVariablesVisitor, {
formatter: this,
hoistDeclarators: hoistDeclarators
});
if (hoistDeclarators.length) {
var hoistDeclar = t.variableDeclaration("var", hoistDeclarators);
@ -206,7 +209,10 @@ export default class SystemFormatter extends AMDFormatter {
}
// hoist up function declarations for circular references
this.file.scope.traverse(block, hoistFunctionsVisitor, handlerBody);
this.file.scope.traverse(block, hoistFunctionsVisitor, {
formatter: this,
handlerBody: handlerBody
});
handlerBody.push(returnStatement);

View File

@ -15,7 +15,7 @@ exports.Function = function (node, parent, scope, file) {
return remapAsyncToGenerator(
node,
t.memberExpression(file.addImport("bluebird", null, true), t.identifier("coroutine")),
t.memberExpression(file.addImport("bluebird"), t.identifier("coroutine")),
scope
);
};

View File

@ -79,15 +79,15 @@ exports.Program = function (node, parent, scope, file) {
exports.pre = function (file) {
file.set("helperGenerator", function (name) {
return file.addImport(`babel-runtime/helpers/${name}`, name);
return file.addImport(`babel-runtime/helpers/${name}`, name, true);
});
file.setDynamic("coreIdentifier", function () {
return file.addImport("babel-runtime/core-js", "core");
return file.addImport("babel-runtime/core-js", "core", true);
});
file.setDynamic("regeneratorIdentifier", function () {
return file.addImport("babel-runtime/regenerator", "regeneratorRuntime");
return file.addImport("babel-runtime/regenerator", "regeneratorRuntime", true);
});
};

View File

@ -2,6 +2,8 @@
var _bluebird2 = require("bluebird");
var _bluebird3 = babelHelpers.interopRequireWildcard(_bluebird2);
var Foo = (function () {
function Foo() {
babelHelpers.classCallCheck(this, Foo);
@ -9,7 +11,7 @@ var Foo = (function () {
babelHelpers.createClass(Foo, [{
key: "foo",
value: _bluebird2.coroutine(function* () {
value: _bluebird3["default"].coroutine(function* () {
var wat = yield bar();
})
}]);

View File

@ -2,6 +2,10 @@
var _bluebird2 = require("bluebird");
var foo = _bluebird2.coroutine(function* () {
var _bluebird3 = _interopRequireWildcard(_bluebird2);
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; };
var foo = _bluebird3["default"].coroutine(function* () {
var wat = yield bar();
});

View File

@ -2,9 +2,13 @@
var _bluebird2 = require("bluebird");
var _bluebird3 = _interopRequireWildcard(_bluebird2);
var _bar;
var foo = _bar = _bluebird2.coroutine(function* () {
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; };
var foo = _bar = _bluebird3["default"].coroutine(function* () {
console.log(_bar);
});

View File

@ -2,6 +2,10 @@
var _bluebird2 = require("bluebird");
var foo = _bluebird2.coroutine(function* () {
var _bluebird3 = _interopRequireWildcard(_bluebird2);
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; };
var foo = _bluebird3["default"].coroutine(function* () {
var wat = yield bar();
});