From 3fdf492dcf9c4edcbd61a90f851926478c7dfaf8 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 25 Jan 2015 14:03:25 +1100 Subject: [PATCH] safer common interop - closes #493 --- lib/6to5/transformation/modules/amd-strict.js | 3 -- lib/6to5/transformation/modules/amd.js | 2 +- lib/6to5/transformation/modules/common.js | 35 +++++++------------ .../templates/common-export-default-assign.js | 1 - ...lt-module.js => exports-default-assign.js} | 0 .../exports-default-module-override.js | 1 - .../templates/exports-module-declaration.js | 1 + .../templates/interop-require-wildcard.js | 2 +- .../templates/interop-require.js | 2 +- .../es6-modules-amd/exports-from/expected.js | 2 +- .../imports-default/expected.js | 2 +- .../imports-mixing/expected.js | 4 +-- .../es6-modules-amd/overview/expected.js | 15 ++------ .../exports-default-non-function/expected.js | 13 +------ .../exports-from/expected.js | 2 +- .../imports-default/expected.js | 2 +- .../imports-glob/expected.js | 2 +- .../imports-mixing/expected.js | 2 +- .../es6-modules-common/overview/expected.js | 4 +-- .../es6-modules-umd/exports-from/expected.js | 2 +- .../imports-default/expected.js | 2 +- .../imports-mixing/expected.js | 4 +-- .../es6-modules-umd/overview/expected.js | 15 ++------ 23 files changed, 36 insertions(+), 82 deletions(-) delete mode 100644 lib/6to5/transformation/modules/amd-strict.js delete mode 100644 lib/6to5/transformation/templates/common-export-default-assign.js rename lib/6to5/transformation/templates/{exports-default-module.js => exports-default-assign.js} (100%) delete mode 100644 lib/6to5/transformation/templates/exports-default-module-override.js create mode 100644 lib/6to5/transformation/templates/exports-module-declaration.js diff --git a/lib/6to5/transformation/modules/amd-strict.js b/lib/6to5/transformation/modules/amd-strict.js deleted file mode 100644 index a055b94763..0000000000 --- a/lib/6to5/transformation/modules/amd-strict.js +++ /dev/null @@ -1,3 +0,0 @@ -"use strict"; - -module.exports = require("./_strict")(require("./amd")); diff --git a/lib/6to5/transformation/modules/amd.js b/lib/6to5/transformation/modules/amd.js index 9c46440cb5..cdc8252443 100644 --- a/lib/6to5/transformation/modules/amd.js +++ b/lib/6to5/transformation/modules/amd.js @@ -107,7 +107,7 @@ AMDFormatter.prototype.importSpecifier = function (specifier, node, nodes) { }; AMDFormatter.prototype.exportDeclaration = function (node) { - if (node.default) { + if (node.default && !this.noInteropRequire) { this.passModuleArg = true; } diff --git a/lib/6to5/transformation/modules/common.js b/lib/6to5/transformation/modules/common.js index 2bf7f61f1b..d8be6f82d5 100644 --- a/lib/6to5/transformation/modules/common.js +++ b/lib/6to5/transformation/modules/common.js @@ -20,6 +20,7 @@ function CommonJSFormatter(file) { var state = { hasNonDefaultExports: false }; traverse(file.ast, visitor, file.scope, state); + this.insertedModuleDeclaration = false; this.hasNonDefaultExports = state.hasNonDefaultExports; } @@ -71,33 +72,23 @@ CommonJSFormatter.prototype.exportDeclaration = function (node, nodes) { var declar = node.declaration; var assign; - // module.exports = VALUE; - var templateName = "exports-default-module"; - - // exports = module.exports = VALUE; - if (this.hasNonDefaultExports) templateName = "exports-default-module-override"; - - if (t.isFunctionDeclaration(declar) || !this.hasNonDefaultExports) { - assign = util.template(templateName, { + if (this.hasNonDefaultExports) { + if (!this.insertedModuleDeclaration) { + nodes.push(util.template("exports-module-declaration", true)); + this.insertedModuleDeclaration = true; + } + } else { + var assign = util.template("exports-default-assign", { VALUE: this._pushStatement(declar, nodes) }, true); - // 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 = _extends(exports["default"], exports) - // - - assign = util.template("common-export-default-assign", { - EXTENDS_HELPER: this.file.addHelper("extends") - }, true); - assign._blockHoist = 0; + if (t.isFunctionDeclaration(declar)) { + // we can hoist this assignment to the top of the file + assign._blockHoist = 3; + } nodes.push(assign); + return; } } diff --git a/lib/6to5/transformation/templates/common-export-default-assign.js b/lib/6to5/transformation/templates/common-export-default-assign.js deleted file mode 100644 index 557c221edb..0000000000 --- a/lib/6to5/transformation/templates/common-export-default-assign.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = EXTENDS_HELPER(exports["default"], exports); diff --git a/lib/6to5/transformation/templates/exports-default-module.js b/lib/6to5/transformation/templates/exports-default-assign.js similarity index 100% rename from lib/6to5/transformation/templates/exports-default-module.js rename to lib/6to5/transformation/templates/exports-default-assign.js diff --git a/lib/6to5/transformation/templates/exports-default-module-override.js b/lib/6to5/transformation/templates/exports-default-module-override.js deleted file mode 100644 index 4ce92a4fd1..0000000000 --- a/lib/6to5/transformation/templates/exports-default-module-override.js +++ /dev/null @@ -1 +0,0 @@ -exports = module.exports = VALUE; diff --git a/lib/6to5/transformation/templates/exports-module-declaration.js b/lib/6to5/transformation/templates/exports-module-declaration.js new file mode 100644 index 0000000000..32b83d4a5a --- /dev/null +++ b/lib/6to5/transformation/templates/exports-module-declaration.js @@ -0,0 +1 @@ +exports.__esModule = true; diff --git a/lib/6to5/transformation/templates/interop-require-wildcard.js b/lib/6to5/transformation/templates/interop-require-wildcard.js index 89287917c8..92ade67d5c 100644 --- a/lib/6to5/transformation/templates/interop-require-wildcard.js +++ b/lib/6to5/transformation/templates/interop-require-wildcard.js @@ -1,3 +1,3 @@ (function (obj) { - return obj && obj.constructor === Object ? obj : { default: obj }; + return obj && obj.__esModule ? obj.default : { default: obj }; }) diff --git a/lib/6to5/transformation/templates/interop-require.js b/lib/6to5/transformation/templates/interop-require.js index b48ee8c30e..55911c817c 100644 --- a/lib/6to5/transformation/templates/interop-require.js +++ b/lib/6to5/transformation/templates/interop-require.js @@ -1,3 +1,3 @@ (function (obj) { - return obj && (obj["default"] || obj); + return obj && obj.__esModule ? obj.default : obj; }) diff --git a/test/fixtures/transformation/es6-modules-amd/exports-from/expected.js b/test/fixtures/transformation/es6-modules-amd/exports-from/expected.js index 374e2f4043..7601d9d483 100644 --- a/test/fixtures/transformation/es6-modules-amd/exports-from/expected.js +++ b/test/fixtures/transformation/es6-modules-amd/exports-from/expected.js @@ -2,7 +2,7 @@ define(["exports", "foo"], function (exports, _foo) { "use strict"; var _interopRequireWildcard = function (obj) { - return obj && obj.constructor === Object ? obj : { + return obj && obj.__esModule ? obj["default"] : { "default": obj }; }; diff --git a/test/fixtures/transformation/es6-modules-amd/imports-default/expected.js b/test/fixtures/transformation/es6-modules-amd/imports-default/expected.js index bcc4b497c9..b983b462ed 100644 --- a/test/fixtures/transformation/es6-modules-amd/imports-default/expected.js +++ b/test/fixtures/transformation/es6-modules-amd/imports-default/expected.js @@ -2,7 +2,7 @@ define(["exports", "foo"], function (exports, _foo) { "use strict"; var _interopRequire = function (obj) { - return obj && (obj["default"] || obj); + return obj && obj.__esModule ? obj["default"] : obj; }; var foo = _interopRequire(_foo); diff --git a/test/fixtures/transformation/es6-modules-amd/imports-mixing/expected.js b/test/fixtures/transformation/es6-modules-amd/imports-mixing/expected.js index 8acd23bf34..8d9fb05272 100644 --- a/test/fixtures/transformation/es6-modules-amd/imports-mixing/expected.js +++ b/test/fixtures/transformation/es6-modules-amd/imports-mixing/expected.js @@ -2,10 +2,10 @@ define(["exports", "foo"], function (exports, _foo) { "use strict"; var _interopRequire = function (obj) { - return obj && (obj["default"] || obj); + return obj && obj.__esModule ? obj["default"] : obj; }; var foo = _interopRequire(_foo); var xyz = _foo.baz; -}); \ No newline at end of file +}); diff --git a/test/fixtures/transformation/es6-modules-amd/overview/expected.js b/test/fixtures/transformation/es6-modules-amd/overview/expected.js index 563f241fd3..b8ed01c2b6 100644 --- a/test/fixtures/transformation/es6-modules-amd/overview/expected.js +++ b/test/fixtures/transformation/es6-modules-amd/overview/expected.js @@ -1,19 +1,8 @@ define(["exports", "module", "foo", "foo-bar", "./directory/foo-bar"], function (exports, module, _foo, _fooBar, _directoryFooBar) { "use strict"; - var _extends = function (target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i]; - for (var key in source) { - target[key] = source[key]; - } - } - - return target; - }; - var _interopRequire = function (obj) { - return obj && (obj["default"] || obj); + return obj && obj.__esModule ? obj["default"] : obj; }; var foo = _interopRequire(_foo); @@ -24,6 +13,6 @@ define(["exports", "module", "foo", "foo-bar", "./directory/foo-bar"], function exports.test = test; var test2 = exports.test2 = 5; + exports.__esModule = true; exports["default"] = test; - module.exports = _extends(exports["default"], exports); }); 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 index a8d178e952..0f6c24422b 100644 --- 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 @@ -1,17 +1,6 @@ "use strict"; -var _extends = function (target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i]; - for (var key in source) { - target[key] = source[key]; - } - } - - return target; -}; - exports.Cachier = Cachier; +exports.__esModule = true; exports["default"] = new Cachier(); function Cachier(databaseName) {} -module.exports = _extends(exports["default"], exports); diff --git a/test/fixtures/transformation/es6-modules-common/exports-from/expected.js b/test/fixtures/transformation/es6-modules-common/exports-from/expected.js index 5a4b431d17..690de1d0fa 100644 --- a/test/fixtures/transformation/es6-modules-common/exports-from/expected.js +++ b/test/fixtures/transformation/es6-modules-common/exports-from/expected.js @@ -1,7 +1,7 @@ "use strict"; var _interopRequireWildcard = function (obj) { - return obj && obj.constructor === Object ? obj : { + return obj && obj.__esModule ? obj["default"] : { "default": obj }; }; diff --git a/test/fixtures/transformation/es6-modules-common/imports-default/expected.js b/test/fixtures/transformation/es6-modules-common/imports-default/expected.js index 02c8997cb6..1a287b128a 100644 --- a/test/fixtures/transformation/es6-modules-common/imports-default/expected.js +++ b/test/fixtures/transformation/es6-modules-common/imports-default/expected.js @@ -1,7 +1,7 @@ "use strict"; var _interopRequire = function (obj) { - return obj && (obj["default"] || obj); + return obj && obj.__esModule ? obj["default"] : obj; }; var foo = _interopRequire(require("foo")); diff --git a/test/fixtures/transformation/es6-modules-common/imports-glob/expected.js b/test/fixtures/transformation/es6-modules-common/imports-glob/expected.js index d885f06222..b6b74312f4 100644 --- a/test/fixtures/transformation/es6-modules-common/imports-glob/expected.js +++ b/test/fixtures/transformation/es6-modules-common/imports-glob/expected.js @@ -1,7 +1,7 @@ "use strict"; var _interopRequireWildcard = function (obj) { - return obj && obj.constructor === Object ? obj : { + return obj && obj.__esModule ? obj["default"] : { "default": obj }; }; diff --git a/test/fixtures/transformation/es6-modules-common/imports-mixing/expected.js b/test/fixtures/transformation/es6-modules-common/imports-mixing/expected.js index 09ea4cec86..2ea5ac36b3 100644 --- a/test/fixtures/transformation/es6-modules-common/imports-mixing/expected.js +++ b/test/fixtures/transformation/es6-modules-common/imports-mixing/expected.js @@ -1,7 +1,7 @@ "use strict"; var _interopRequire = function (obj) { - return obj && (obj["default"] || obj); + return obj && obj.__esModule ? obj["default"] : obj; }; var foo = _interopRequire(require("foo")); diff --git a/test/fixtures/transformation/es6-modules-common/overview/expected.js b/test/fixtures/transformation/es6-modules-common/overview/expected.js index a15f34dd81..dfe2d85e62 100644 --- a/test/fixtures/transformation/es6-modules-common/overview/expected.js +++ b/test/fixtures/transformation/es6-modules-common/overview/expected.js @@ -1,13 +1,13 @@ "use strict"; var _interopRequireWildcard = function (obj) { - return obj && obj.constructor === Object ? obj : { + return obj && obj.__esModule ? obj["default"] : { "default": obj }; }; var _interopRequire = function (obj) { - return obj && (obj["default"] || obj); + return obj && obj.__esModule ? obj["default"] : obj; }; require("foo"); diff --git a/test/fixtures/transformation/es6-modules-umd/exports-from/expected.js b/test/fixtures/transformation/es6-modules-umd/exports-from/expected.js index 2b8ca3d179..15f8cabf4c 100644 --- a/test/fixtures/transformation/es6-modules-umd/exports-from/expected.js +++ b/test/fixtures/transformation/es6-modules-umd/exports-from/expected.js @@ -8,7 +8,7 @@ "use strict"; var _interopRequireWildcard = function (obj) { - return obj && obj.constructor === Object ? obj : { + return obj && obj.__esModule ? obj["default"] : { "default": obj }; }; diff --git a/test/fixtures/transformation/es6-modules-umd/imports-default/expected.js b/test/fixtures/transformation/es6-modules-umd/imports-default/expected.js index 30aa739b11..9dffd5ee3e 100644 --- a/test/fixtures/transformation/es6-modules-umd/imports-default/expected.js +++ b/test/fixtures/transformation/es6-modules-umd/imports-default/expected.js @@ -8,7 +8,7 @@ "use strict"; var _interopRequire = function (obj) { - return obj && (obj["default"] || obj); + return obj && obj.__esModule ? obj["default"] : obj; }; var foo = _interopRequire(_foo); diff --git a/test/fixtures/transformation/es6-modules-umd/imports-mixing/expected.js b/test/fixtures/transformation/es6-modules-umd/imports-mixing/expected.js index f677ceee86..85c3161db2 100644 --- a/test/fixtures/transformation/es6-modules-umd/imports-mixing/expected.js +++ b/test/fixtures/transformation/es6-modules-umd/imports-mixing/expected.js @@ -8,10 +8,10 @@ "use strict"; var _interopRequire = function (obj) { - return obj && (obj["default"] || obj); + return obj && obj.__esModule ? obj["default"] : obj; }; var foo = _interopRequire(_foo); var xyz = _foo.baz; -}); \ No newline at end of file +}); diff --git a/test/fixtures/transformation/es6-modules-umd/overview/expected.js b/test/fixtures/transformation/es6-modules-umd/overview/expected.js index adbd4539cc..efc240bcf5 100644 --- a/test/fixtures/transformation/es6-modules-umd/overview/expected.js +++ b/test/fixtures/transformation/es6-modules-umd/overview/expected.js @@ -7,19 +7,8 @@ })(function (exports, module, _foo, _fooBar, _directoryFooBar) { "use strict"; - var _extends = function (target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i]; - for (var key in source) { - target[key] = source[key]; - } - } - - return target; - }; - var _interopRequire = function (obj) { - return obj && (obj["default"] || obj); + return obj && obj.__esModule ? obj["default"] : obj; }; var foo = _interopRequire(_foo); @@ -30,6 +19,6 @@ exports.test = test; var test2 = exports.test2 = 5; + exports.__esModule = true; exports["default"] = test; - module.exports = _extends(exports["default"], exports); });