From 52e23473ed98c47a2c9c4f1b87d7ad0c311fb740 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Thu, 1 Jan 2015 22:58:46 +1100 Subject: [PATCH] allow `export default` non-functions mapping to `module.exports` in common module formatter - fixes #356 --- lib/6to5/transformation/modules/_default.js | 2 +- lib/6to5/transformation/modules/common.js | 29 ++++++++++++++----- .../templates/common-export-default-assign.js | 1 + .../transformers/_block-hoist.js | 14 +++++++-- .../exports-default-non-function/actual.js | 3 ++ .../exports-default-non-function/expected.js | 6 ++++ .../es6-modules-common/overview/actual.js | 2 -- .../es6-modules-common/overview/expected.js | 2 -- 8 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 lib/6to5/transformation/templates/common-export-default-assign.js create mode 100644 test/fixtures/transformation/es6-modules-common/exports-default-non-function/actual.js create mode 100644 test/fixtures/transformation/es6-modules-common/exports-default-non-function/expected.js diff --git a/lib/6to5/transformation/modules/_default.js b/lib/6to5/transformation/modules/_default.js index 2c5ffaebe1..3959abec4a 100644 --- a/lib/6to5/transformation/modules/_default.js +++ b/lib/6to5/transformation/modules/_default.js @@ -126,7 +126,7 @@ DefaultFormatter.prototype._pushStatement = function (ref, nodes) { DefaultFormatter.prototype._hoistExport = function (declar, assign, priority) { if (t.isFunctionDeclaration(declar)) { - assign._blockHoist = priority || 1; + assign._blockHoist = priority || 2; } return assign; diff --git a/lib/6to5/transformation/modules/common.js b/lib/6to5/transformation/modules/common.js index 6f5025f5ab..d2735ecd2d 100644 --- a/lib/6to5/transformation/modules/common.js +++ b/lib/6to5/transformation/modules/common.js @@ -57,6 +57,7 @@ CommonJSFormatter.prototype.importDeclaration = function (node, nodes) { CommonJSFormatter.prototype.exportDeclaration = function (node, nodes) { if (node.default) { var declar = node.declaration; + var assign; // module.exports = VALUE; var templateName = "exports-default-module"; @@ -64,15 +65,29 @@ CommonJSFormatter.prototype.exportDeclaration = function (node, nodes) { // exports = module.exports = VALUE; if (this.hasNonDefaultExports) templateName = "exports-default-module-override"; - var assign = util.template(templateName, { - VALUE: this._pushStatement(declar, nodes) - }, true); + if (t.isFunction(declar) || !this.hasNonDefaultExports) { + assign = util.template(templateName, { + VALUE: this._pushStatement(declar, nodes) + }, true); - // hoist to the top if this default is a function - nodes.push(this._hoistExport(declar, assign, 2)); - } else { - DefaultFormatter.prototype.exportDeclaration.apply(this, arguments); + // hoist to the top if this default is a function + nodes.push(this._hoistExport(declar, assign, 3)); + return; + } else { + // this export isn't a function so we can't hoist it to the top so we need to set it + // at the very end of the file with something like: + // + // module.exports = Object.assign(exports["default"], exports) + // + + assign = util.template("common-export-default-assign", true); + assign._blockHoist = 0; + + nodes.push(assign); + } } + + DefaultFormatter.prototype.exportDeclaration.apply(this, arguments); }; CommonJSFormatter.prototype.exportSpecifier = function (specifier, node, nodes) { diff --git a/lib/6to5/transformation/templates/common-export-default-assign.js b/lib/6to5/transformation/templates/common-export-default-assign.js new file mode 100644 index 0000000000..17a1f96968 --- /dev/null +++ b/lib/6to5/transformation/templates/common-export-default-assign.js @@ -0,0 +1 @@ +module.exports = Object.assign(exports["default"], exports); diff --git a/lib/6to5/transformation/transformers/_block-hoist.js b/lib/6to5/transformation/transformers/_block-hoist.js index 6d7eb6a469..b6fff4a860 100644 --- a/lib/6to5/transformation/transformers/_block-hoist.js +++ b/lib/6to5/transformation/transformers/_block-hoist.js @@ -1,17 +1,27 @@ var _ = require("lodash"); +// Priority: +// +// - 0 We want this to be at the **very** bottom +// - 1 Default node position +// - 2 Priority over normal nodes +// - 3 We want this to be at the **very** top + exports.BlockStatement = exports.Program = { exit: function (node) { var hasChange = false; for (var i in node.body) { var bodyNode = node.body[i]; - if (bodyNode && bodyNode._blockHoist) hasChange = true; + if (bodyNode && bodyNode._blockHoist != null) hasChange = true; } if (!hasChange) return; var nodePriorities = _.groupBy(node.body, function (bodyNode) { - return bodyNode._blockHoist || 0; + var priority = bodyNode._blockHoist; + if (priority == null) priority = 1; + if (priority === true) priority = 2; + return priority; }); node.body = _.flatten(_.values(nodePriorities).reverse()); diff --git a/test/fixtures/transformation/es6-modules-common/exports-default-non-function/actual.js b/test/fixtures/transformation/es6-modules-common/exports-default-non-function/actual.js new file mode 100644 index 0000000000..44bb8e1880 --- /dev/null +++ b/test/fixtures/transformation/es6-modules-common/exports-default-non-function/actual.js @@ -0,0 +1,3 @@ +export default new Cachier() + +export function Cachier(databaseName) {} diff --git a/test/fixtures/transformation/es6-modules-common/exports-default-non-function/expected.js b/test/fixtures/transformation/es6-modules-common/exports-default-non-function/expected.js new file mode 100644 index 0000000000..8922e90b48 --- /dev/null +++ b/test/fixtures/transformation/es6-modules-common/exports-default-non-function/expected.js @@ -0,0 +1,6 @@ +"use strict"; + +exports.Cachier = Cachier; +exports["default"] = new Cachier(); +function Cachier(databaseName) {} +module.exports = Object.assign(exports["default"], exports); diff --git a/test/fixtures/transformation/es6-modules-common/overview/actual.js b/test/fixtures/transformation/es6-modules-common/overview/actual.js index a77d4d5dfa..36e32b3470 100644 --- a/test/fixtures/transformation/es6-modules-common/overview/actual.js +++ b/test/fixtures/transformation/es6-modules-common/overview/actual.js @@ -8,5 +8,3 @@ import {foo as bar} from "foo"; export {test}; export var test = 5; - -export default test; diff --git a/test/fixtures/transformation/es6-modules-common/overview/expected.js b/test/fixtures/transformation/es6-modules-common/overview/expected.js index f0d7868fc9..ed9175cbfb 100644 --- a/test/fixtures/transformation/es6-modules-common/overview/expected.js +++ b/test/fixtures/transformation/es6-modules-common/overview/expected.js @@ -18,5 +18,3 @@ var bar = require("foo").bar; var bar = require("foo").foo; exports.test = test; var test = exports.test = 5; - -exports = module.exports = test;