add support for circular references and hoist all variable declarations
This commit is contained in:
@@ -15,8 +15,13 @@ function SystemFormatter(file) {
|
||||
|
||||
util.inherits(SystemFormatter, AMDFormatter);
|
||||
|
||||
SystemFormatter.prototype._exportsWildcard = function (objectIdentifier) {
|
||||
var leftIdentifier = t.identifier("i");
|
||||
SystemFormatter.prototype._addImportSource = function (node, exportNode) {
|
||||
node._importSource = exportNode.source && exportNode.source.value;
|
||||
return node;
|
||||
};
|
||||
|
||||
SystemFormatter.prototype._exportsWildcard = function (objectIdentifier, node) {
|
||||
var leftIdentifier = this.file.generateUidIdentifier("key");
|
||||
var valIdentifier = t.memberExpression(objectIdentifier, leftIdentifier, true);
|
||||
|
||||
var left = t.variableDeclaration("var", [
|
||||
@@ -29,11 +34,12 @@ SystemFormatter.prototype._exportsWildcard = function (objectIdentifier) {
|
||||
this.buildExportCall(leftIdentifier, valIdentifier)
|
||||
]);
|
||||
|
||||
return t.forInStatement(left, right, block);
|
||||
return this._addImportSource(t.forInStatement(left, right, block), node);
|
||||
};
|
||||
|
||||
SystemFormatter.prototype._exportsAssign = function (id, init) {
|
||||
return this.buildExportCall(t.literal(id.name), init, true);
|
||||
SystemFormatter.prototype._exportsAssign = function (id, init, node) {
|
||||
var call = this.buildExportCall(t.literal(id.name), init, true);
|
||||
return this._addImportSource(call, node);
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.remapExportAssignment = function (node) {
|
||||
@@ -49,28 +55,53 @@ SystemFormatter.prototype.buildExportCall = function (id, init, isStatement) {
|
||||
}
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.buildRunnerSetters = function () {
|
||||
return t.arrayExpression(_.map(this.ids, function (uid) {
|
||||
var moduleIdentifier = t.identifier("m");
|
||||
SystemFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
|
||||
AMDFormatter.prototype.importSpecifier.apply(this, arguments);
|
||||
this._addImportSource(_.last(nodes), node);
|
||||
};
|
||||
|
||||
return t.functionExpression(null, [moduleIdentifier], t.blockStatement([
|
||||
t.assignmentExpression("=", uid, moduleIdentifier)
|
||||
]));
|
||||
SystemFormatter.prototype.buildRunnerSetters = function (block, hoistDeclarators) {
|
||||
return t.arrayExpression(_.map(this.ids, function (uid, source) {
|
||||
var nodes = [];
|
||||
|
||||
traverse(block, {
|
||||
enter: function (node) {
|
||||
if (node._importSource === source) {
|
||||
if (t.isVariableDeclaration(node)) {
|
||||
_.each(node.declarations, function (declar) {
|
||||
hoistDeclarators.push(t.variableDeclarator(declar.id));
|
||||
nodes.push(t.expressionStatement(
|
||||
t.assignmentExpression("=", declar.id, declar.init)
|
||||
));
|
||||
});
|
||||
} else {
|
||||
nodes.push(node);
|
||||
}
|
||||
|
||||
this.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return t.functionExpression(null, [uid], t.blockStatement(nodes));
|
||||
}));
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.transform = function (ast) {
|
||||
var program = ast.program;
|
||||
|
||||
var hoistDeclarators = [];
|
||||
var moduleName = this.getModuleName();
|
||||
var moduleNameLiteral = t.literal(moduleName);
|
||||
|
||||
var block = t.blockStatement(program.body);
|
||||
|
||||
var runner = util.template("system", {
|
||||
MODULE_NAME: moduleNameLiteral,
|
||||
MODULE_DEPENDENCIES: t.arrayExpression(this.buildDependencyLiterals()),
|
||||
EXPORT_IDENTIFIER: this.exportIdentifier,
|
||||
SETTERS: this.buildRunnerSetters(),
|
||||
EXECUTE: t.functionExpression(null, [], t.blockStatement(program.body))
|
||||
SETTERS: this.buildRunnerSetters(block, hoistDeclarators),
|
||||
EXECUTE: t.functionExpression(null, [], block)
|
||||
}, true);
|
||||
|
||||
var handlerBody = runner.expression.arguments[2].body.body;
|
||||
@@ -78,8 +109,55 @@ SystemFormatter.prototype.transform = function (ast) {
|
||||
|
||||
var returnStatement = handlerBody.pop();
|
||||
|
||||
// hoist up all variable declarations
|
||||
traverse(block, {
|
||||
enter: function (node, parent, scope) {
|
||||
if (t.isFunction(node)) {
|
||||
// nothing inside is accessible
|
||||
return this.stop();
|
||||
}
|
||||
|
||||
if (t.isVariableDeclaration(node)) {
|
||||
if (node.kind !== "var" && !t.isProgram(parent)) { // let, const
|
||||
// can't be accessed
|
||||
return;
|
||||
}
|
||||
|
||||
var nodes = [];
|
||||
|
||||
_.each(node.declarations, function (declar) {
|
||||
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));
|
||||
nodes.push(assign);
|
||||
}
|
||||
});
|
||||
|
||||
// for (var i in test)
|
||||
// for (var i = 0;;)
|
||||
if (t.isFor(parent)) {
|
||||
if (parent.left === node) {
|
||||
return node.declarations[0].id;
|
||||
}
|
||||
|
||||
if (parent.init === node) {
|
||||
return t.toSequenceExpression(nodes, scope);
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (hoistDeclarators.length) {
|
||||
var hoistDeclar = t.variableDeclaration("var", hoistDeclarators);
|
||||
hoistDeclar._blockHoist = true;
|
||||
handlerBody.unshift(hoistDeclar);
|
||||
}
|
||||
|
||||
// hoist up function declarations for circular references
|
||||
traverse(program, {
|
||||
traverse(block, {
|
||||
enter: function (node) {
|
||||
if (t.isFunction(node)) this.stop();
|
||||
|
||||
@@ -90,12 +168,6 @@ SystemFormatter.prototype.transform = function (ast) {
|
||||
}
|
||||
});
|
||||
|
||||
if (!_.isEmpty(this.ids)) {
|
||||
handlerBody.push(t.variableDeclaration("var", _.map(this.ids, function (uid) {
|
||||
return t.variableDeclarator(uid);
|
||||
})));
|
||||
}
|
||||
|
||||
handlerBody.push(returnStatement);
|
||||
|
||||
program.body = [runner];
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
System.register([], function (_export) {
|
||||
var Foo;
|
||||
_export("default", foo);
|
||||
|
||||
function foo() {}
|
||||
@@ -19,7 +20,7 @@ System.register([], function (_export) {
|
||||
|
||||
_export("default", function () {});
|
||||
|
||||
var Foo = function Foo() {};
|
||||
Foo = function Foo() {};
|
||||
|
||||
_export("default", Foo);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
System.register(["foo"], function (_export) {
|
||||
var _foo;
|
||||
return {
|
||||
setters: [function (m) {
|
||||
_foo = m
|
||||
|
||||
for (var i in _foo) {
|
||||
_export(i, _foo[i])
|
||||
setters: [function (_foo) {
|
||||
for (var _key in _foo) {
|
||||
_export(_key, _foo[_key])
|
||||
}
|
||||
|
||||
_export("foo", _foo.foo);
|
||||
|
||||
_export("foo", _foo.foo);
|
||||
@@ -20,7 +18,6 @@ System.register(["foo"], function (_export) {
|
||||
_export("default", _foo.foo);
|
||||
|
||||
_export("bar", _foo.bar);
|
||||
|
||||
}],
|
||||
execute: function () {
|
||||
"use strict";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
System.register([], function (_export) {
|
||||
var foo, foo2, foo3, foo4, foo5, foo6, foo8;
|
||||
_export("foo7", foo7);
|
||||
|
||||
function foo7() {}
|
||||
@@ -7,13 +8,13 @@ System.register([], function (_export) {
|
||||
execute: function () {
|
||||
"use strict";
|
||||
|
||||
var foo = _export("foo", 1);
|
||||
var foo2 = _export("foo2", function () {});
|
||||
var foo3 = _export("foo3", undefined);
|
||||
var foo4 = _export("foo4", 2);
|
||||
var foo5 = _export("foo5", undefined);
|
||||
var foo6 = _export("foo6", 3);
|
||||
var foo8 = function foo8() {};
|
||||
foo = _export("foo", 1);
|
||||
foo2 = _export("foo2", function () {});
|
||||
foo3 = _export("foo3", undefined);
|
||||
foo4 = _export("foo4", 2);
|
||||
foo5 = _export("foo5", undefined);
|
||||
foo6 = _export("foo6", 3);
|
||||
foo8 = function foo8() {};
|
||||
|
||||
_export("foo8", foo8);
|
||||
}
|
||||
|
||||
@@ -1,24 +1,20 @@
|
||||
System.register(["./evens"], function (_export) {
|
||||
var p;
|
||||
|
||||
var isEven, p, isOdd;
|
||||
_export("nextOdd", nextOdd);
|
||||
|
||||
function nextOdd(n) {
|
||||
return _export("p", p = isEven(n) ? n + 1 : n + 2);
|
||||
}
|
||||
|
||||
var _evens;
|
||||
return {
|
||||
setters: [function (m) {
|
||||
_evens = m
|
||||
setters: [function (_evens) {
|
||||
isEven = _evens.isEven;
|
||||
}],
|
||||
execute: function () {
|
||||
"use strict";
|
||||
|
||||
var isEven = _evens.isEven;
|
||||
_export("p", p = 5);
|
||||
|
||||
var isOdd = _export("isOdd", (function (isEven) {
|
||||
p = _export("p", 5);
|
||||
isOdd = _export("isOdd", (function (isEven) {
|
||||
return function (n) {
|
||||
return !isEven(n);
|
||||
};
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
System.register([], function (_export) {
|
||||
var _foo;
|
||||
System.register(["foo"], function (_export) {
|
||||
var foo, foo;
|
||||
return {
|
||||
setters: [function (m) {
|
||||
_foo = m
|
||||
setters: [function (_foo) {
|
||||
foo = _foo["default"];
|
||||
foo = _foo["default"];
|
||||
}],
|
||||
execute: function () {
|
||||
"use strict";
|
||||
|
||||
var foo = _foo["default"];
|
||||
var foo = _foo["default"];
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
System.register(["foo"], function (_export) {
|
||||
var _foo;
|
||||
var foo;
|
||||
return {
|
||||
setters: [function (m) {
|
||||
_foo = m
|
||||
setters: [function (_foo) {
|
||||
foo = _foo;
|
||||
}],
|
||||
execute: function () {
|
||||
"use strict";
|
||||
|
||||
var foo = _foo;
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
System.register(["foo"], function (_export) {
|
||||
var _foo;
|
||||
var foo, xyz;
|
||||
return {
|
||||
setters: [function (m) {
|
||||
_foo = m
|
||||
setters: [function (_foo) {
|
||||
foo = _foo["default"];
|
||||
xyz = _foo.baz;
|
||||
}],
|
||||
execute: function () {
|
||||
"use strict";
|
||||
|
||||
var foo = _foo["default"];
|
||||
var xyz = _foo.baz;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
System.register(["foo"], function (_export) {
|
||||
var _foo;
|
||||
var bar, bar, baz, baz, baz, xyz;
|
||||
return {
|
||||
setters: [function (m) {
|
||||
_foo = m
|
||||
setters: [function (_foo) {
|
||||
bar = _foo.bar;
|
||||
bar = _foo.bar;
|
||||
baz = _foo.baz;
|
||||
baz = _foo.bar;
|
||||
baz = _foo.bar;
|
||||
xyz = _foo.xyz;
|
||||
}],
|
||||
execute: function () {
|
||||
"use strict";
|
||||
|
||||
var bar = _foo.bar;
|
||||
var bar = _foo.bar;
|
||||
var baz = _foo.baz;
|
||||
var baz = _foo.bar;
|
||||
var baz = _foo.bar;
|
||||
var xyz = _foo.xyz;
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
System.register(["foo", "foo-bar", "./directory/foo-bar"], function (_export) {
|
||||
var _foo, _fooBar, _directoryFooBar;
|
||||
return {
|
||||
setters: [function (m) {
|
||||
_foo = m
|
||||
}, function (m) {
|
||||
_fooBar = m
|
||||
}, function (m) {
|
||||
_directoryFooBar = m
|
||||
}],
|
||||
setters: [function (_foo) {}, function (_fooBar) {}, function (_directoryFooBar) {}],
|
||||
execute: function () {
|
||||
"use strict";
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,24 +1,18 @@
|
||||
System.register(["foo", "foo-bar", "./directory/foo-bar"], function (_export) {
|
||||
var _foo, _fooBar, _directoryFooBar;
|
||||
var foo, foo, bar, bar, test;
|
||||
return {
|
||||
setters: [function (m) {
|
||||
_foo = m
|
||||
}, function (m) {
|
||||
_fooBar = m
|
||||
}, function (m) {
|
||||
_directoryFooBar = m
|
||||
}],
|
||||
setters: [function (_foo) {
|
||||
foo = _foo["default"];
|
||||
foo = _foo;
|
||||
bar = _foo.bar;
|
||||
bar = _foo.foo;
|
||||
}, function (_fooBar) {}, function (_directoryFooBar) {}],
|
||||
execute: function () {
|
||||
"use strict";
|
||||
|
||||
var foo = _foo["default"];
|
||||
var foo = _foo;
|
||||
var bar = _foo.bar;
|
||||
var bar = _foo.foo;
|
||||
_export("test", test);
|
||||
|
||||
var test = _export("test", 5);
|
||||
|
||||
test = _export("test", 5);
|
||||
_export("default", test);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
System.register([], function (_export) {
|
||||
var test;
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
"use strict";
|
||||
|
||||
var test = _export("test", 2);
|
||||
test = _export("test", 2);
|
||||
_export("test", test = 5);
|
||||
_export("test", test += 1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user