Skip to content

Commit

Permalink
fix #2097: no babel mode special case of "default"
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Mar 14, 2022
1 parent f4ff26d commit edaf32a
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 43 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## Unreleased

* Avoid generating an enumerable `default` import for CommonJS files in Babel mode ([#2097](https://github.com/evanw/esbuild/issues/2097))

Importing a CommonJS module into an ES module can be done in two different ways. In node mode the `default` import is always set to `module.exports`, while in Babel mode the `default` import passes through to `module.exports.default` instead. Node mode is triggered when the importing file ends in `.mjs`, has `type: "module"` in its `package.json` file, or the imported module does not have a `__esModule` marker.

Previously esbuild always created the forwarding `default` import in Babel mode, even if `module.exports` had no property called `default`. This was problematic because the getter named `default` still showed up as a property on the imported namespace object, and could potentially interfere with code that iterated over the properties of the imported namespace object. With this release the getter named `default` will now only be added in Babel mode if the `default` property exists at the time of the import.

## 0.14.26

* Fix a tree shaking regression regarding `var` declarations ([#2080](https://github.com/evanw/esbuild/issues/2080), [#2085](https://github.com/evanw/esbuild/pull/2085), [#2098](https://github.com/evanw/esbuild/issues/2098), [#2099](https://github.com/evanw/esbuild/issues/2099))
Expand Down
26 changes: 13 additions & 13 deletions internal/bundler/snapshots/snapshots_splitting.txt
Original file line number Diff line number Diff line change
Expand Up @@ -205,19 +205,19 @@ TestSplittingDynamicAndNotDynamicCommonJSIntoES6
import {
__toESM,
require_foo
} from "./chunk-KUHUE66N.js";
} from "./chunk-6FVSQLGP.js";

// entry.js
var import_foo = __toESM(require_foo());
import("./foo-U6JCMRHQ.js").then(({ default: { bar: b } }) => console.log(import_foo.bar, b));
import("./foo-NCFYBVPB.js").then(({ default: { bar: b } }) => console.log(import_foo.bar, b));

---------- /out/foo-U6JCMRHQ.js ----------
---------- /out/foo-NCFYBVPB.js ----------
import {
require_foo
} from "./chunk-KUHUE66N.js";
} from "./chunk-6FVSQLGP.js";
export default require_foo();

---------- /out/chunk-KUHUE66N.js ----------
---------- /out/chunk-6FVSQLGP.js ----------
// foo.js
var require_foo = __commonJS({
"foo.js"(exports) {
Expand Down Expand Up @@ -260,9 +260,9 @@ export {
TestSplittingDynamicCommonJSIntoES6
---------- /out/entry.js ----------
// entry.js
import("./foo-PPQD77K4.js").then(({ default: { bar } }) => console.log(bar));
import("./foo-MGFNEEYE.js").then(({ default: { bar } }) => console.log(bar));

---------- /out/foo-PPQD77K4.js ----------
---------- /out/foo-MGFNEEYE.js ----------
// foo.js
var require_foo = __commonJS({
"foo.js"(exports) {
Expand Down Expand Up @@ -317,7 +317,7 @@ TestSplittingHybridESMAndCJSIssue617
import {
foo,
init_a
} from "./chunk-QRBKE4XE.js";
} from "./chunk-WNGDXRWX.js";
init_a();
export {
foo
Expand All @@ -328,15 +328,15 @@ import {
__toCommonJS,
a_exports,
init_a
} from "./chunk-QRBKE4XE.js";
} from "./chunk-WNGDXRWX.js";

// b.js
var bar = (init_a(), __toCommonJS(a_exports));
export {
bar
};

---------- /out/chunk-QRBKE4XE.js ----------
---------- /out/chunk-WNGDXRWX.js ----------
// a.js
var a_exports = {};
__export(a_exports, {
Expand Down Expand Up @@ -487,7 +487,7 @@ TestSplittingSharedCommonJSIntoES6
---------- /out/a.js ----------
import {
require_shared
} from "./chunk-KTJ3L72M.js";
} from "./chunk-GI5SL2RW.js";

// a.js
var { foo } = require_shared();
Expand All @@ -496,13 +496,13 @@ console.log(foo);
---------- /out/b.js ----------
import {
require_shared
} from "./chunk-KTJ3L72M.js";
} from "./chunk-GI5SL2RW.js";

// b.js
var { foo } = require_shared();
console.log(foo);

---------- /out/chunk-KTJ3L72M.js ----------
---------- /out/chunk-GI5SL2RW.js ----------
// shared.js
var require_shared = __commonJS({
"shared.js"(exports) {
Expand Down
59 changes: 29 additions & 30 deletions internal/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,6 @@ func code(isES6 bool) string {
}
export var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b))
// Tells importing modules that this can be considered an ES module
var __markAsModule = target => __defProp(target, '__esModule', { value: true })
// Update the "name" property on the function or class for "--keep-names"
export var __name = (target, value) => __defProp(target, 'name', { value, configurable: true })
Expand Down Expand Up @@ -185,53 +182,55 @@ func code(isES6 bool) string {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true })
}
export var __reExport = (target, module, copyDefault, desc) => {
if (module && typeof module === 'object' || typeof module === 'function')
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === 'object' || typeof from === 'function')
`

// Avoid "let" when not using ES6
if isES6 {
text += `
for (let key of __getOwnPropNames(module))
if (!__hasOwnProp.call(target, key) && (copyDefault || key !== 'default'))
__defProp(target, key, { get: () => module[key], enumerable: !(desc = __getOwnPropDesc(module, key)) || desc.enumerable })
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable })
`
} else {
text += `
for (var keys = __getOwnPropNames(module), i = 0, n = keys.length, key; i < n; i++) {
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i]
if (!__hasOwnProp.call(target, key) && (copyDefault || key !== 'default'))
__defProp(target, key, { get: (k => module[k]).bind(null, key), enumerable: !(desc = __getOwnPropDesc(module, key)) || desc.enumerable })
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: (k => from[k]).bind(null, key), enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable })
}
`
}

text += `
return target
return to
}
// Converts the module from CommonJS to ESM
export var __toESM = (module, isNodeMode) => {
return __reExport(__markAsModule(
__defProp(
module != null ? __create(__getProtoOf(module)) : {},
'default',
// If the importer is not in node compatibility mode and this is an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has been set), then forward
// "default" to the export named "default". Otherwise set "default" to
// "module.exports" for node compatibility.
!isNodeMode && module && module.__esModule
? { get: () => module.default, enumerable: true }
: { value: module, enumerable: true })
), module)
}
export var __reExport = (target, mod) => __copyProps(target, mod, 'default')
// Converts the module from CommonJS to ESM. When in node mode (i.e. in an
// ".mjs" file, package.json has "type: module", or the "__esModule" export
// in the CommonJS file is falsy or missing), the "default" property is
// overridden to point to the original CommonJS exports object instead.
export var __toESM = (mod, isNodeMode, target) => (
target = mod != null ? __create(__getProtoOf(mod)) : {},
__copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule
? __defProp(target, 'default', { value: mod, enumerable: true })
: target,
mod)
)
// Converts the module from ESM to CommonJS. This clones the input module
// object with the addition of a non-enumerable "__esModule" property set
// to "true", which overwrites any existing export named "__esModule".
export var __toCommonJS = module => __reExport(__markAsModule({}), module, /* copyDefault */ 1)
export var __toCommonJS = mod => __copyProps(__defProp({}, '__esModule', { value: true }), mod)
// For TypeScript decorators
// - kind === undefined: class
Expand Down

0 comments on commit edaf32a

Please sign in to comment.