diff --git a/lib/6to5/transform.js b/lib/6to5/transform.js index 3005eb6621..47d47cc827 100644 --- a/lib/6to5/transform.js +++ b/lib/6to5/transform.js @@ -34,7 +34,7 @@ var transform = module.exports = function (code, opts) { }; transform._run = function (code, tree, opts) { - traverse.replace(tree, function (node) { + traverse(tree, function (node) { if (node.type === "EmptyStatement") { return traverse.Delete; } @@ -70,13 +70,22 @@ transform._run = function (code, tree, opts) { }; transform._runTransformer = function (transformer, tree, opts, generateUid) { - if (transformer.Program) transformer.Program(tree, opts); + var build = function (exit) { + return function (node, parent) { + var fns = transformer[node.type] || transformer.all; + if (!fns) return; - traverse.replace(tree, function (node, parent) { - var fn = transformer[node.type] || transformer.all; - if (!fn) return; + var fn = fns.enter || fns; + if (exit) fn = fns.exit; + if (!fn || !_.isFunction(fn)) return; - return fn(node, parent, opts, generateUid); + return fn(node, parent, opts, generateUid); + }; + }; + + traverse(tree, { + enter: build(), + exit: build(true) }); }; diff --git a/lib/6to5/transformers/modules.js b/lib/6to5/transformers/modules.js index 4588245bb4..fe1d37e70a 100644 --- a/lib/6to5/transformers/modules.js +++ b/lib/6to5/transformers/modules.js @@ -61,7 +61,7 @@ var pushExportSpecifiers = function (node, nodes) { }); }; -var pushExportDeclaration = function (node, nodes) { +var pushExportDeclaration = function (node, parent, nodes) { var declar = node.declaration; if (node.default) { @@ -80,19 +80,43 @@ var pushExportDeclaration = function (node, nodes) { id = declar.declarations[0].id; } - nodes.push(declar); - nodes.push(util.template("exports-assign", { + var assign = util.template("exports-assign", { VALUE: id, KEY: id - }, true)); + }, true); + + nodes.push(declar); + + if (declar.type === "FunctionDeclaration") { + assign._modulesHoist = true; + } + + nodes.push(assign); } }; -exports.ExportDeclaration = function (node) { +exports.Program = { + exit: function (node) { + var unshift = []; + + node.body = node.body.filter(function (bodyNode) { + if (bodyNode._modulesHoist) { + unshift.push(bodyNode); + return false; + } else { + return true; + } + }); + + node.body = unshift.concat(node.body); + } +}; + +exports.ExportDeclaration = function (node, parent) { var nodes = []; if (node.declaration) { - pushExportDeclaration(node, nodes); + pushExportDeclaration(node, parent, nodes); } else { pushExportSpecifiers(node, nodes); } diff --git a/test/fixtures/modules/exports-variable/expected.js b/test/fixtures/modules/exports-variable/expected.js index 5b005e5383..c4d9fb7c29 100644 --- a/test/fixtures/modules/exports-variable/expected.js +++ b/test/fixtures/modules/exports-variable/expected.js @@ -3,6 +3,8 @@ var foo2; var foo3; var foo8; (function () { + exports.foo7 = foo7; + foo = 1; exports.foo = foo; @@ -21,7 +23,6 @@ var foo8; exports.foo6 = foo6; function foo7 () {} - exports.foo7 = foo7; foo8 = function () { function foo8() { diff --git a/test/fixtures/modules/hoist-function-exports/actual.js b/test/fixtures/modules/hoist-function-exports/actual.js new file mode 100644 index 0000000000..5e5c8fc494 --- /dev/null +++ b/test/fixtures/modules/hoist-function-exports/actual.js @@ -0,0 +1,11 @@ +import { isEven } from "./evens"; + +export function nextOdd(n) { + return isEven(n) ? n + 1 : n + 2; +} + +export var isOdd = (function(isEven) { + return function(n) { + return !isEven(n); + }; +})(isEven); diff --git a/test/fixtures/modules/hoist-function-exports/expected.js b/test/fixtures/modules/hoist-function-exports/expected.js new file mode 100644 index 0000000000..25b941b8ef --- /dev/null +++ b/test/fixtures/modules/hoist-function-exports/expected.js @@ -0,0 +1,13 @@ +exports.nextOdd = nextOdd; + +var isEven = require("./evens").isEven; +function nextOdd(n) { + return isEven(n) ? n + 1 : n + 2; +} + +var isOdd = (function(isEven) { + return function(n) { + return !isEven(n); + }; +})(isEven); +exports.isOdd = isOdd;