system hoisting and export refinements (#8104)
This commit is contained in:
parent
3c46e75b8f
commit
036c429ce1
@ -29,7 +29,7 @@ const visitor = {
|
||||
}
|
||||
|
||||
for (const name in declar.getBindingIdentifiers()) {
|
||||
state.emit(t.identifier(name), name);
|
||||
state.emit(t.identifier(name), name, declar.node.init !== null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,81 @@ const buildExportAll = template(`
|
||||
}
|
||||
`);
|
||||
|
||||
function constructExportCall(
|
||||
path,
|
||||
exportIdent,
|
||||
exportNames,
|
||||
exportValues,
|
||||
exportStarTarget,
|
||||
) {
|
||||
const statements = [];
|
||||
if (exportNames.length === 1) {
|
||||
statements.push(
|
||||
t.expressionStatement(
|
||||
t.callExpression(exportIdent, [
|
||||
t.stringLiteral(exportNames[0]),
|
||||
exportValues[0],
|
||||
]),
|
||||
),
|
||||
);
|
||||
} else if (!exportStarTarget) {
|
||||
const objectProperties = [];
|
||||
for (let i = 0; i < exportNames.length; i++) {
|
||||
const exportName = exportNames[i];
|
||||
const exportValue = exportValues[i];
|
||||
objectProperties.push(
|
||||
t.objectProperty(t.identifier(exportName), exportValue),
|
||||
);
|
||||
}
|
||||
statements.push(
|
||||
t.expressionStatement(
|
||||
t.callExpression(exportIdent, [t.objectExpression(objectProperties)]),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
const exportObj = path.scope.generateUid("exportObj");
|
||||
|
||||
statements.push(
|
||||
t.variableDeclaration("var", [
|
||||
t.variableDeclarator(t.identifier(exportObj), t.objectExpression([])),
|
||||
]),
|
||||
);
|
||||
|
||||
statements.push(
|
||||
buildExportAll({
|
||||
KEY: path.scope.generateUidIdentifier("key"),
|
||||
EXPORT_OBJ: t.identifier(exportObj),
|
||||
TARGET: exportStarTarget,
|
||||
}),
|
||||
);
|
||||
|
||||
for (let i = 0; i < exportNames.length; i++) {
|
||||
const exportName = exportNames[i];
|
||||
const exportValue = exportValues[i];
|
||||
|
||||
statements.push(
|
||||
t.expressionStatement(
|
||||
t.assignmentExpression(
|
||||
"=",
|
||||
t.memberExpression(
|
||||
t.identifier(exportObj),
|
||||
t.identifier(exportName),
|
||||
),
|
||||
exportValue,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
statements.push(
|
||||
t.expressionStatement(
|
||||
t.callExpression(exportIdent, [t.identifier(exportObj)]),
|
||||
),
|
||||
);
|
||||
}
|
||||
return statements;
|
||||
}
|
||||
|
||||
const TYPE_IMPORT = "Import";
|
||||
|
||||
export default declare((api, options) => {
|
||||
@ -35,6 +110,25 @@ export default declare((api, options) => {
|
||||
path.node[IGNORE_REASSIGNMENT_SYMBOL] = true;
|
||||
|
||||
const arg = path.get(path.isAssignmentExpression() ? "left" : "argument");
|
||||
|
||||
if (arg.isObjectPattern() || arg.isArrayPattern()) {
|
||||
const exprs = [path.node];
|
||||
for (const name in arg.getBindingIdentifiers()) {
|
||||
if (this.scope.getBinding(name) !== path.scope.getBinding(name)) {
|
||||
return;
|
||||
}
|
||||
const exportedNames = this.exports[name];
|
||||
if (!exportedNames) return;
|
||||
for (const exportedName of exportedNames) {
|
||||
exprs.push(
|
||||
this.buildCall(exportedName, t.identifier(name)).expression,
|
||||
);
|
||||
}
|
||||
}
|
||||
path.replaceWith(t.sequenceExpression(exprs));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!arg.isIdentifier()) return;
|
||||
|
||||
const name = arg.node.name;
|
||||
@ -163,17 +257,8 @@ export default declare((api, options) => {
|
||||
|
||||
const body: Array<Object> = path.get("body");
|
||||
|
||||
let canHoist = true;
|
||||
for (let path of body) {
|
||||
if (path.isExportDeclaration()) path = path.get("declaration");
|
||||
if (path.isVariableDeclaration() && path.node.kind !== "var") {
|
||||
canHoist = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const path of body) {
|
||||
if (canHoist && path.isFunctionDeclaration()) {
|
||||
if (path.isFunctionDeclaration()) {
|
||||
beforeBody.push(path.node);
|
||||
removedPaths.push(path);
|
||||
} else if (path.isImportDeclaration()) {
|
||||
@ -206,7 +291,7 @@ export default declare((api, options) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (!canHoist || declar.isClassDeclaration()) {
|
||||
if (declar.isClassDeclaration()) {
|
||||
path.replaceWithMultiple(nodes);
|
||||
} else {
|
||||
beforeBody = beforeBody.concat(nodes);
|
||||
@ -221,29 +306,22 @@ export default declare((api, options) => {
|
||||
if (declar.node) {
|
||||
path.replaceWith(declar);
|
||||
|
||||
const nodes = [];
|
||||
let bindingIdentifiers;
|
||||
if (path.isFunction()) {
|
||||
const node = declar.node;
|
||||
const name = node.id.name;
|
||||
if (canHoist) {
|
||||
addExportName(name, name);
|
||||
beforeBody.push(node);
|
||||
beforeBody.push(
|
||||
buildExportCall(name, t.cloneNode(node.id)),
|
||||
);
|
||||
removedPaths.push(path);
|
||||
} else {
|
||||
bindingIdentifiers = { [name]: node.id };
|
||||
}
|
||||
} else {
|
||||
bindingIdentifiers = declar.getBindingIdentifiers();
|
||||
}
|
||||
for (const name in bindingIdentifiers) {
|
||||
addExportName(name, name);
|
||||
nodes.push(buildExportCall(name, t.identifier(name)));
|
||||
beforeBody.push(node);
|
||||
beforeBody.push(buildExportCall(name, t.cloneNode(node.id)));
|
||||
removedPaths.push(path);
|
||||
} else if (path.isClass()) {
|
||||
const name = declar.node.id.name;
|
||||
addExportName(name, name);
|
||||
path.insertAfter([buildExportCall(name, t.identifier(name))]);
|
||||
} else {
|
||||
for (const name in declar.getBindingIdentifiers()) {
|
||||
addExportName(name, name);
|
||||
}
|
||||
}
|
||||
path.insertAfter(nodes);
|
||||
} else {
|
||||
const specifiers = path.node.specifiers;
|
||||
if (specifiers && specifiers.length) {
|
||||
@ -254,12 +332,15 @@ export default declare((api, options) => {
|
||||
const nodes = [];
|
||||
|
||||
for (const specifier of specifiers) {
|
||||
nodes.push(
|
||||
buildExportCall(
|
||||
specifier.exported.name,
|
||||
specifier.local,
|
||||
),
|
||||
);
|
||||
// only globals exported this way
|
||||
if (!path.scope.getBinding(specifier.local.name)) {
|
||||
nodes.push(
|
||||
buildExportCall(
|
||||
specifier.exported.name,
|
||||
specifier.local,
|
||||
),
|
||||
);
|
||||
}
|
||||
addExportName(
|
||||
specifier.local.name,
|
||||
specifier.exported.name,
|
||||
@ -274,7 +355,7 @@ export default declare((api, options) => {
|
||||
}
|
||||
|
||||
modules.forEach(function(specifiers) {
|
||||
const setterBody = [];
|
||||
let setterBody = [];
|
||||
const target = path.scope.generateUid(specifiers.key);
|
||||
|
||||
for (let specifier of specifiers.imports) {
|
||||
@ -312,49 +393,30 @@ export default declare((api, options) => {
|
||||
}
|
||||
|
||||
if (specifiers.exports.length) {
|
||||
const exportObj = path.scope.generateUid("exportObj");
|
||||
|
||||
setterBody.push(
|
||||
t.variableDeclaration("var", [
|
||||
t.variableDeclarator(
|
||||
t.identifier(exportObj),
|
||||
t.objectExpression([]),
|
||||
),
|
||||
]),
|
||||
);
|
||||
const exportNames = [];
|
||||
const exportValues = [];
|
||||
let hasExportStar = false;
|
||||
|
||||
for (const node of specifiers.exports) {
|
||||
if (t.isExportAllDeclaration(node)) {
|
||||
setterBody.push(
|
||||
buildExportAll({
|
||||
KEY: path.scope.generateUidIdentifier("key"),
|
||||
EXPORT_OBJ: t.identifier(exportObj),
|
||||
TARGET: t.identifier(target),
|
||||
}),
|
||||
);
|
||||
hasExportStar = true;
|
||||
} else if (t.isExportSpecifier(node)) {
|
||||
setterBody.push(
|
||||
t.expressionStatement(
|
||||
t.assignmentExpression(
|
||||
"=",
|
||||
t.memberExpression(
|
||||
t.identifier(exportObj),
|
||||
node.exported,
|
||||
),
|
||||
t.memberExpression(t.identifier(target), node.local),
|
||||
),
|
||||
),
|
||||
exportNames.push(node.exported.name);
|
||||
exportValues.push(
|
||||
t.memberExpression(t.identifier(target), node.local),
|
||||
);
|
||||
} else {
|
||||
// todo
|
||||
}
|
||||
}
|
||||
|
||||
setterBody.push(
|
||||
t.expressionStatement(
|
||||
t.callExpression(t.identifier(exportIdent), [
|
||||
t.identifier(exportObj),
|
||||
]),
|
||||
setterBody = setterBody.concat(
|
||||
constructExportCall(
|
||||
path,
|
||||
t.identifier(exportIdent),
|
||||
exportNames,
|
||||
exportValues,
|
||||
hasExportStar ? t.identifier(target) : null,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -372,9 +434,17 @@ export default declare((api, options) => {
|
||||
let moduleName = this.getModuleName();
|
||||
if (moduleName) moduleName = t.stringLiteral(moduleName);
|
||||
|
||||
if (canHoist) {
|
||||
hoistVariables(path, id => variableIds.push(id));
|
||||
}
|
||||
const uninitializedVars = [];
|
||||
hoistVariables(
|
||||
path,
|
||||
(id, name, hasInit) => {
|
||||
variableIds.push(id);
|
||||
if (!hasInit) {
|
||||
uninitializedVars.push(name);
|
||||
}
|
||||
},
|
||||
null,
|
||||
);
|
||||
|
||||
if (variableIds.length) {
|
||||
beforeBody.unshift(
|
||||
@ -385,6 +455,23 @@ 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;
|
||||
}
|
||||
beforeBody = beforeBody.concat(
|
||||
constructExportCall(
|
||||
path,
|
||||
t.identifier(exportIdent),
|
||||
uninitializedVars,
|
||||
undefinedValues,
|
||||
null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
path.traverse(reassignmentVisitor, {
|
||||
exports: exportNames,
|
||||
buildCall: buildExportCall,
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
System.register([], function (_export, _context) {
|
||||
"use strict";
|
||||
|
||||
var foo, bar;
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
const [foo, bar = 2] = [];
|
||||
|
||||
_export("foo", foo);
|
||||
|
||||
_export("bar", bar);
|
||||
[foo, bar = 2] = [], _export("foo", foo), _export("bar", bar);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@ -1,16 +1,11 @@
|
||||
System.register([], function (_export, _context) {
|
||||
"use strict";
|
||||
|
||||
var foo, bar, baz;
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
const [foo, bar, ...baz] = [];
|
||||
|
||||
_export("foo", foo);
|
||||
|
||||
_export("bar", bar);
|
||||
|
||||
_export("baz", baz);
|
||||
[foo, bar, ...baz] = [], _export("foo", foo), _export("bar", bar), _export("baz", baz);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
System.register([], function (_export, _context) {
|
||||
"use strict";
|
||||
|
||||
var foo, bar;
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
const [foo, bar] = [];
|
||||
|
||||
_export("foo", foo);
|
||||
|
||||
_export("bar", bar);
|
||||
[foo, bar] = [], _export("foo", foo), _export("bar", bar);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@ -1,18 +1,15 @@
|
||||
System.register([], function (_export, _context) {
|
||||
"use strict";
|
||||
|
||||
var baz, qux;
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
const {
|
||||
({
|
||||
foo: {
|
||||
bar: [baz, qux]
|
||||
}
|
||||
} = {};
|
||||
|
||||
_export("baz", baz);
|
||||
|
||||
_export("qux", qux);
|
||||
} = {}), _export("baz", baz), _export("qux", qux);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@ -1,17 +1,14 @@
|
||||
System.register([], function (_export, _context) {
|
||||
"use strict";
|
||||
|
||||
var foo, bar;
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
const {
|
||||
({
|
||||
foo,
|
||||
bar = 1
|
||||
} = {};
|
||||
|
||||
_export("foo", foo);
|
||||
|
||||
_export("bar", bar);
|
||||
} = {}), _export("foo", foo), _export("bar", bar);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@ -1,17 +1,14 @@
|
||||
System.register([], function (_export, _context) {
|
||||
"use strict";
|
||||
|
||||
var foo, bar;
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
const {
|
||||
({
|
||||
foo,
|
||||
...bar
|
||||
} = {};
|
||||
|
||||
_export("foo", foo);
|
||||
|
||||
_export("bar", bar);
|
||||
} = {}), _export("foo", foo), _export("bar", bar);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@ -1,17 +1,14 @@
|
||||
System.register([], function (_export, _context) {
|
||||
"use strict";
|
||||
|
||||
var bar, baz;
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
const {
|
||||
({
|
||||
foo: bar,
|
||||
baz
|
||||
} = {};
|
||||
|
||||
_export("bar", bar);
|
||||
|
||||
_export("baz", baz);
|
||||
} = {}), _export("bar", bar), _export("baz", baz);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@ -3,10 +3,7 @@ System.register(["foo"], function (_export, _context) {
|
||||
|
||||
return {
|
||||
setters: [function (_foo) {
|
||||
var _exportObj = {};
|
||||
_exportObj.foo = _foo.foo;
|
||||
|
||||
_export(_exportObj);
|
||||
_export("foo", _foo.foo);
|
||||
}],
|
||||
execute: function () {}
|
||||
};
|
||||
|
||||
@ -3,11 +3,10 @@ System.register(["foo"], function (_export, _context) {
|
||||
|
||||
return {
|
||||
setters: [function (_foo) {
|
||||
var _exportObj = {};
|
||||
_exportObj.foo = _foo.foo;
|
||||
_exportObj.bar = _foo.bar;
|
||||
|
||||
_export(_exportObj);
|
||||
_export({
|
||||
foo: _foo.foo,
|
||||
bar: _foo.bar
|
||||
});
|
||||
}],
|
||||
execute: function () {}
|
||||
};
|
||||
|
||||
@ -3,10 +3,7 @@ System.register(["foo"], function (_export, _context) {
|
||||
|
||||
return {
|
||||
setters: [function (_foo) {
|
||||
var _exportObj = {};
|
||||
_exportObj.bar = _foo.foo;
|
||||
|
||||
_export(_exportObj);
|
||||
_export("bar", _foo.foo);
|
||||
}],
|
||||
execute: function () {}
|
||||
};
|
||||
|
||||
@ -3,10 +3,7 @@ System.register(["foo"], function (_export, _context) {
|
||||
|
||||
return {
|
||||
setters: [function (_foo) {
|
||||
var _exportObj = {};
|
||||
_exportObj.default = _foo.foo;
|
||||
|
||||
_export(_exportObj);
|
||||
_export("default", _foo.foo);
|
||||
}],
|
||||
execute: function () {}
|
||||
};
|
||||
|
||||
@ -3,11 +3,10 @@ System.register(["foo"], function (_export, _context) {
|
||||
|
||||
return {
|
||||
setters: [function (_foo) {
|
||||
var _exportObj = {};
|
||||
_exportObj.default = _foo.foo;
|
||||
_exportObj.bar = _foo.bar;
|
||||
|
||||
_export(_exportObj);
|
||||
_export({
|
||||
default: _foo.foo,
|
||||
bar: _foo.bar
|
||||
});
|
||||
}],
|
||||
execute: function () {}
|
||||
};
|
||||
|
||||
@ -0,0 +1 @@
|
||||
export var m;
|
||||
@ -0,0 +1,12 @@
|
||||
System.register([], function (_export, _context) {
|
||||
"use strict";
|
||||
|
||||
var m;
|
||||
|
||||
_export("m", void 0);
|
||||
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {}
|
||||
};
|
||||
});
|
||||
@ -1,36 +1,27 @@
|
||||
System.register([], function (_export, _context) {
|
||||
"use strict";
|
||||
|
||||
var foo, foo2, foo3, foo4, foo5, foo6;
|
||||
|
||||
function foo7() {}
|
||||
|
||||
_export("foo7", foo7);
|
||||
|
||||
_export({
|
||||
foo3: void 0,
|
||||
foo5: void 0
|
||||
});
|
||||
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
var foo = 1;
|
||||
_export("foo", foo = 1);
|
||||
|
||||
_export("foo", foo);
|
||||
_export("foo2", foo2 = function () {});
|
||||
|
||||
var foo2 = function () {};
|
||||
_export("foo4", foo4 = 2);
|
||||
|
||||
_export("foo2", foo2);
|
||||
|
||||
var foo3;
|
||||
|
||||
_export("foo3", foo3);
|
||||
|
||||
let foo4 = 2;
|
||||
|
||||
_export("foo4", foo4);
|
||||
|
||||
let foo5;
|
||||
|
||||
_export("foo5", foo5);
|
||||
|
||||
const foo6 = 3;
|
||||
|
||||
_export("foo6", foo6);
|
||||
|
||||
function foo7() {}
|
||||
|
||||
_export("foo7", foo7);
|
||||
_export("foo6", foo6 = 3);
|
||||
|
||||
class foo8 {}
|
||||
|
||||
|
||||
@ -9,6 +9,8 @@ System.register(["./evens"], function (_export, _context) {
|
||||
|
||||
_export("nextOdd", nextOdd);
|
||||
|
||||
_export("a", void 0);
|
||||
|
||||
return {
|
||||
setters: [function (_evens) {
|
||||
isEven = _evens.isEven;
|
||||
@ -16,8 +18,6 @@ System.register(["./evens"], function (_export, _context) {
|
||||
execute: function () {
|
||||
_export("p", p = 5);
|
||||
|
||||
_export("p", p);
|
||||
|
||||
for (a in b);
|
||||
|
||||
for (i = 0, j = 0;;);
|
||||
@ -27,8 +27,6 @@ System.register(["./evens"], function (_export, _context) {
|
||||
return !isEven(n);
|
||||
};
|
||||
}(isEven));
|
||||
|
||||
_export("isOdd", isOdd);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@ -19,8 +19,6 @@ System.register([], function (_export, _context) {
|
||||
execute: function () {
|
||||
_export("c", c = 5);
|
||||
|
||||
_export("c", c);
|
||||
|
||||
b();
|
||||
}
|
||||
};
|
||||
|
||||
@ -6,8 +6,6 @@ System.register([], function (_export, _context) {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
_export("name", name = _context.id);
|
||||
|
||||
_export("name", name);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@ -14,8 +14,6 @@ System.register(["foo", "foo-bar", "./directory/foo-bar"], function (_export, _c
|
||||
|
||||
_export("test2", test2 = 5);
|
||||
|
||||
_export("test2", test2);
|
||||
|
||||
_export("default", test);
|
||||
}
|
||||
};
|
||||
|
||||
@ -7,8 +7,6 @@ System.register([], function (_export, _context) {
|
||||
execute: function () {
|
||||
_export("test", test = 2);
|
||||
|
||||
_export("test", test);
|
||||
|
||||
_export("test", test = 5);
|
||||
|
||||
_export("test", +test + 1), test++;
|
||||
@ -21,22 +19,14 @@ System.register([], function (_export, _context) {
|
||||
|
||||
_export("a", a = 2);
|
||||
|
||||
_export("a", a);
|
||||
|
||||
_export("a", a = 3);
|
||||
|
||||
_export("c", b = 2);
|
||||
|
||||
_export("c", b);
|
||||
|
||||
_export("c", b = 3);
|
||||
|
||||
_export("f", _export("e", d = 3));
|
||||
|
||||
_export("e", d);
|
||||
|
||||
_export("f", d);
|
||||
|
||||
_export("f", _export("e", d = 4));
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user