diff --git a/CHANGELOG.md b/CHANGELOG.md index 6644b2e7c61..0f1da971230 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +* Fix a regression with `export {} from` and CommonJS ([#1890](https://github.com/evanw/esbuild/issues/1890)) + + This release fixes a regression that was introduced by the change in 0.14.7 that avoids calling the `__toESM` wrapper for import statements that are converted to `require` calls and that don't use the `default` or `__esModule` export names. The previous change was correct for the `import {} from` syntax but not for the `export {} from` syntax, which meant that in certain cases with re-exported values, the value of the `default` import could be different than expected. This release fixes the regression. + * Warn about using `module` or `exports` in ESM code ([#1887](https://github.com/evanw/esbuild/issues/1887)) CommonJS export variables cannot be referenced in ESM code. If you do this, they are treated as global variables instead. This release includes a warning for people that try to use both CommonJS and ES module export styles in the same file. Here's an example: diff --git a/internal/bundler/snapshots/snapshots_default.txt b/internal/bundler/snapshots/snapshots_default.txt index 91febeabc29..7cabe8c42b2 100644 --- a/internal/bundler/snapshots/snapshots_default.txt +++ b/internal/bundler/snapshots/snapshots_default.txt @@ -2372,10 +2372,10 @@ __export(entry_exports, { bar: () => import_bar.default, foo: () => import_foo.default }); -var import_foo = require("foo"); +var import_foo = __toESM(require("foo")); // bar.js -var import_bar = require("bar"); +var import_bar = __toESM(require("bar")); module.exports = __toCommonJS(entry_exports); ================================================================================ @@ -2418,8 +2418,8 @@ __export(entry_exports, { bar: () => import_bar.default, foo: () => import_foo.default }); -var import_foo = require("./foo"); -var import_bar = require("./bar"); +var import_foo = __toESM(require("./foo")); +var import_bar = __toESM(require("./bar")); module.exports = __toCommonJS(entry_exports); ================================================================================ diff --git a/internal/bundler/snapshots/snapshots_importstar.txt b/internal/bundler/snapshots/snapshots_importstar.txt index 53ac07b50f0..23be9e99c8a 100644 --- a/internal/bundler/snapshots/snapshots_importstar.txt +++ b/internal/bundler/snapshots/snapshots_importstar.txt @@ -869,7 +869,7 @@ var entry_exports = {}; __export(entry_exports, { out: () => out }); -var out = require("foo"); +var out = __toESM(require("foo")); module.exports = __toCommonJS(entry_exports); ================================================================================ @@ -888,7 +888,7 @@ var entry_exports = {}; __export(entry_exports, { out: () => out }); -var out = require("foo"); +var out = __toESM(require("foo")); module.exports = __toCommonJS(entry_exports); ================================================================================ @@ -909,7 +909,7 @@ var mod = (() => { __export(entry_exports, { out: () => out }); - var out = __require("foo"); + var out = __toESM(__require("foo")); return __toCommonJS(entry_exports); })(); @@ -921,7 +921,7 @@ var mod = (() => { __export(entry_exports, { out: () => out }); - var out = require("foo"); + var out = __toESM(require("foo")); return __toCommonJS(entry_exports); })(); diff --git a/internal/js_parser/js_parser.go b/internal/js_parser/js_parser.go index 537c0d39413..84f9cfc15e1 100644 --- a/internal/js_parser/js_parser.go +++ b/internal/js_parser/js_parser.go @@ -13849,6 +13849,7 @@ func (p *parser) scanForImportsAndExports(stmts []js_ast.Stmt) (result importsEx } case *js_ast.SExportStar: + record := &p.importRecords[s.ImportRecordIndex] p.importRecordsForCurrentPart = append(p.importRecordsForCurrentPart, s.ImportRecordIndex) if s.Alias != nil { @@ -13861,12 +13862,15 @@ func (p *parser) scanForImportsAndExports(stmts []js_ast.Stmt) (result importsEx IsExported: true, } p.recordExport(s.Alias.Loc, s.Alias.OriginalName, s.NamespaceRef) + + record.Flags |= ast.ContainsImportStar } else { // "export * from 'path'" p.exportStarImportRecords = append(p.exportStarImportRecords, s.ImportRecordIndex) } case *js_ast.SExportFrom: + record := &p.importRecords[s.ImportRecordIndex] p.importRecordsForCurrentPart = append(p.importRecordsForCurrentPart, s.ImportRecordIndex) for _, item := range s.Items { @@ -13881,6 +13885,12 @@ func (p *parser) scanForImportsAndExports(stmts []js_ast.Stmt) (result importsEx IsExported: true, } p.recordExport(item.Name.Loc, item.Alias, item.Name.Ref) + + if item.OriginalName == "default" { + record.Flags |= ast.ContainsDefaultAlias + } else if item.OriginalName == "__esModule" { + record.Flags |= ast.ContainsESModuleAlias + } } } diff --git a/scripts/end-to-end-tests.js b/scripts/end-to-end-tests.js index 371c55b6e91..b9d3b1fd60d 100644 --- a/scripts/end-to-end-tests.js +++ b/scripts/end-to-end-tests.js @@ -1395,6 +1395,39 @@ 'in.mjs': `import * as ns from './foo'; if (!ns.default || ns.default.foo !== 123) throw 'fail'`, 'foo.js': `exports.__esModule = true; exports.foo = 123`, }), + + // Make sure "import {} from; export {}" behaves like "export {} from" + // https://github.com/evanw/esbuild/issues/1890 + test(['node.ts', 'foo.ts', '--outdir=.', '--format=cjs'], { + 'node.ts': `import * as foo from './foo.js'; if (foo.bar !== 123) throw 'fail'`, + 'foo.ts': `import bar from './lib.js'; export { bar }`, + 'lib.js': `module.exports = 123`, + }), + test(['node.ts', 'foo.ts', '--outdir=.', '--format=cjs'], { + 'node.ts': `import * as foo from './foo.js'; if (foo.bar !== 123) throw 'fail'`, + 'foo.ts': `import { default as bar } from './lib.js'; export { bar }`, + 'lib.js': `module.exports = 123`, + }), + test(['node.ts', 'foo.ts', '--outdir=.', '--format=cjs'], { + 'node.ts': `import * as foo from './foo.js'; if (foo.bar !== 123) throw 'fail'`, + 'foo.ts': `export { default as bar } from './lib.js'`, + 'lib.js': `module.exports = 123`, + }), + test(['node.ts', 'foo.ts', '--outdir=.', '--format=cjs'], { + 'node.ts': `import { foo } from './foo.js'; if (foo.default !== 123) throw 'fail'`, + 'foo.ts': `import * as foo from './lib.js'; export { foo }`, + 'lib.js': `module.exports = 123`, + }), + test(['node.ts', 'foo.ts', '--outdir=.', '--format=cjs'], { + 'node.ts': `import { foo } from './foo.js'; if (foo.default !== 123) throw 'fail'`, + 'foo.ts': `export * as foo from './lib.js'`, + 'lib.js': `module.exports = 123`, + }), + test(['node.ts', 'foo.ts', '--outdir=.', '--format=cjs'], { + 'node.ts': `import * as foo from './foo.js'; if (foo.default !== void 0) throw 'fail'`, + 'foo.ts': `export * from './lib.js'`, + 'lib.js': `module.exports = 123`, + }), ) // Test external CommonJS export