From 6df66526295364c66239b1f61a7304ec382be862 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 28 Dec 2014 09:35:47 +1100 Subject: [PATCH] better circular references in amd/umd/system module formatter --- CHANGELOG.md | 5 +++ lib/6to5/transformation/modules/_default.js | 44 +++++++++++-------- lib/6to5/transformation/modules/system.js | 21 ++++++++- lib/6to5/traverse/index.js | 16 +++++-- .../exports-default/expected.js | 2 +- .../exports-default/expected.js | 8 ++-- .../exports-variable/expected.js | 8 ++-- .../hoist-function-exports/expected.js | 14 +++--- .../exports-default/expected.js | 2 +- 9 files changed, 79 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8eac47e1b..16839b2aa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ Gaps between patch versions are faulty/broken releases. +## 2.0.3 + + * Hoist function declarations in system module formatter for circular references. + * Hoist default function declarations in umd and amd module formatters for circular references. + ## 2.0.2 * Inherit comments in `for-of` transformer. diff --git a/lib/6to5/transformation/modules/_default.js b/lib/6to5/transformation/modules/_default.js index a5c9e76801..1f1747f44d 100644 --- a/lib/6to5/transformation/modules/_default.js +++ b/lib/6to5/transformation/modules/_default.js @@ -169,30 +169,36 @@ DefaultFormatter.prototype._exportsAssign = function (id, init) { DefaultFormatter.prototype.exportDeclaration = function (node, nodes) { var declar = node.declaration; + var id = declar.id; + if (node.default) { - nodes.push( - this._exportsAssign(t.identifier("default"), this._pushStatement(declar, nodes)) - ); - } else { - var assign; + id = t.identifier("default"); + } - if (t.isVariableDeclaration(declar)) { - for (var i in declar.declarations) { - var decl = declar.declarations[i]; + var assign; - decl.init = this._exportsAssign(decl.id, decl.init).expression; + if (t.isVariableDeclaration(declar)) { + for (var i in declar.declarations) { + var decl = declar.declarations[i]; - var newDeclar = t.variableDeclaration(declar.kind, [decl]); - if (i === "0") t.inherits(newDeclar, declar); - nodes.push(newDeclar); - } - } else { - assign = this._exportsAssign(declar.id, declar.id); + decl.init = this._exportsAssign(decl.id, decl.init).expression; - nodes.push(t.toStatement(declar)); - nodes.push(assign); - - this._hoistExport(declar, assign); + var newDeclar = t.variableDeclaration(declar.kind, [decl]); + if (i === "0") t.inherits(newDeclar, declar); + nodes.push(newDeclar); } + } else { + var ref = declar; + + if (t.isFunctionDeclaration(declar) || t.isClassDeclaration(declar)) { + ref = declar.id; + nodes.push(declar); + } + + assign = this._exportsAssign(id, ref); + + nodes.push(assign); + + this._hoistExport(declar, assign); } }; diff --git a/lib/6to5/transformation/modules/system.js b/lib/6to5/transformation/modules/system.js index e9d109bbbd..8a24bca43f 100644 --- a/lib/6to5/transformation/modules/system.js +++ b/lib/6to5/transformation/modules/system.js @@ -2,6 +2,7 @@ module.exports = SystemFormatter; var DefaultFormatter = require("./_default"); var AMDFormatter = require("./amd"); +var traverse = require("../../traverse"); var util = require("../../util"); var t = require("../../types"); var _ = require("lodash"); @@ -74,12 +75,28 @@ SystemFormatter.prototype.transform = function (ast) { EXECUTE: t.functionExpression(null, [], t.blockStatement(program.body)) }, true); + var handlerBody = runner.expression.arguments[2].body.body; + var returnStatement = handlerBody.pop(); + + // hoist up function declarations for circular references + traverse(program, { + enter: function (node, parent) { + if (t.isFunction(node)) this.stop(); + + if (t.isFunctionDeclaration(node) || node._blockHoist) { + handlerBody.push(node); + this.remove(); + } + } + }); + if (!_.isEmpty(this.ids)) { - var handlerBody = runner.expression.arguments[2].body.body; - handlerBody.unshift(t.variableDeclaration("var", _.map(this.ids, function (uid) { + handlerBody.push(t.variableDeclaration("var", _.map(this.ids, function (uid) { return t.variableDeclarator(uid); }))); } + handlerBody.push(returnStatement); + program.body = [runner]; }; diff --git a/lib/6to5/traverse/index.js b/lib/6to5/traverse/index.js index c04eb88ece..bc85ed7248 100644 --- a/lib/6to5/traverse/index.js +++ b/lib/6to5/traverse/index.js @@ -50,11 +50,16 @@ function traverse(parent, opts, scope) { } }; - var stop = false; + var stopped = false; + var removed = false; var context = { stop: function () { - stop = true; + stopped = true; + }, + + remove: function () { + stopped = removed = true; } }; @@ -67,8 +72,13 @@ function traverse(parent, opts, scope) { var result = opts.enter.call(context, node, parent, ourScope); maybeReplace(result); + if (removed) { + delete obj[key]; + updated = true; + } + // stop iteration - if (stop || result === false) return; + if (stopped || result === false) return; } // traverse node diff --git a/test/fixtures/transformation/es6-modules-amd/exports-default/expected.js b/test/fixtures/transformation/es6-modules-amd/exports-default/expected.js index 1bd8fd5ca9..3ba52475d7 100644 --- a/test/fixtures/transformation/es6-modules-amd/exports-default/expected.js +++ b/test/fixtures/transformation/es6-modules-amd/exports-default/expected.js @@ -1,6 +1,7 @@ define(["exports"], function (exports) { "use strict"; + exports["default"] = foo; exports["default"] = 42; exports["default"] = {}; exports["default"] = []; @@ -10,7 +11,6 @@ define(["exports"], function (exports) { exports["default"] = function () {}; function foo() {} - exports["default"] = foo; var Foo = function Foo() {}; exports["default"] = Foo; diff --git a/test/fixtures/transformation/es6-modules-system/exports-default/expected.js b/test/fixtures/transformation/es6-modules-system/exports-default/expected.js index 074d3026c8..4320d66b13 100644 --- a/test/fixtures/transformation/es6-modules-system/exports-default/expected.js +++ b/test/fixtures/transformation/es6-modules-system/exports-default/expected.js @@ -1,4 +1,7 @@ System.register("es6-modules-system/exports-default/expected", [], function (_export) { + _export("default", foo); + + function foo() {} return { setters: [], execute: function () { @@ -16,12 +19,9 @@ System.register("es6-modules-system/exports-default/expected", [], function (_ex _export("default", function () {}); - function foo() {} - _export("default", foo); - var Foo = function Foo() {}; _export("default", Foo); } }; -}); \ No newline at end of file +}); diff --git a/test/fixtures/transformation/es6-modules-system/exports-variable/expected.js b/test/fixtures/transformation/es6-modules-system/exports-variable/expected.js index 636a73a17d..a3f1095a16 100644 --- a/test/fixtures/transformation/es6-modules-system/exports-variable/expected.js +++ b/test/fixtures/transformation/es6-modules-system/exports-variable/expected.js @@ -1,21 +1,21 @@ System.register("es6-modules-system/exports-variable/expected", [], function (_export) { + _export("foo7", foo7); + + function foo7() {} return { setters: [], execute: function () { "use strict"; - _export("foo7", foo7); - 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); - function foo7() {} var foo8 = function foo8() {}; _export("foo8", foo8); } }; -}); \ No newline at end of file +}); diff --git a/test/fixtures/transformation/es6-modules-system/hoist-function-exports/expected.js b/test/fixtures/transformation/es6-modules-system/hoist-function-exports/expected.js index ad626fc12d..de2d3946ce 100644 --- a/test/fixtures/transformation/es6-modules-system/hoist-function-exports/expected.js +++ b/test/fixtures/transformation/es6-modules-system/hoist-function-exports/expected.js @@ -1,4 +1,10 @@ System.register("es6-modules-system/hoist-function-exports/expected", ["./evens"], function (_export) { + _export("nextOdd", nextOdd); + + function nextOdd(n) { + return isEven(n) ? n + 1 : n + 2; + } + var _evens; return { setters: [function (m) { @@ -7,13 +13,7 @@ System.register("es6-modules-system/hoist-function-exports/expected", ["./evens" execute: function () { "use strict"; - _export("nextOdd", nextOdd); - var isEven = _evens.isEven; - function nextOdd(n) { - return isEven(n) ? n + 1 : n + 2; - } - var isOdd = _export("isOdd", (function (isEven) { return function (n) { return !isEven(n); @@ -21,4 +21,4 @@ System.register("es6-modules-system/hoist-function-exports/expected", ["./evens" })(isEven)); } }; -}); \ No newline at end of file +}); diff --git a/test/fixtures/transformation/es6-modules-umd/exports-default/expected.js b/test/fixtures/transformation/es6-modules-umd/exports-default/expected.js index 4a4269a21b..2bcbf30aa6 100644 --- a/test/fixtures/transformation/es6-modules-umd/exports-default/expected.js +++ b/test/fixtures/transformation/es6-modules-umd/exports-default/expected.js @@ -7,6 +7,7 @@ })(function (exports) { "use strict"; + exports["default"] = foo; exports["default"] = 42; exports["default"] = {}; exports["default"] = []; @@ -16,7 +17,6 @@ exports["default"] = function () {}; function foo() {} - exports["default"] = foo; var Foo = function Foo() {}; exports["default"] = Foo;