Skip to content

Commit

Permalink
fix #910: esm "export {}" must still use cjs "exports"
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Mar 3, 2021
1 parent b27d5a9 commit 54ef111
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 1 deletion.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

* Fix bug when ESM file has empty exports and is converted to CommonJS ([#910](https://github.com/evanw/esbuild/issues/910))

A file containing the contents `export {}` is still considered to be an ESM file even though it has no exports. However, if a file containing this edge case is converted to CommonJS internally during bundling (e.g. when it is the target of `require()`), esbuild failed to mark the `exports` symbol from the CommonJS wrapping closure as used even though it is actually needed. This resulted in an output file that crashed when run. The `exports` symbol is now considered used in this case, so the bug has been fixed.

## 0.8.54

* Fix ordering issue with private class methods ([#901](https://github.com/evanw/esbuild/issues/901))
Expand Down
20 changes: 20 additions & 0 deletions internal/bundler/bundler_default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2752,6 +2752,26 @@ func TestMinifiedExportsAndModuleFormatCommonJS(t *testing.T) {
})
}

func TestEmptyExportClauseBundleAsCommonJSIssue910(t *testing.T) {
default_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.js": `
console.log(require('./types.mjs'))
`,
"/types.mjs": `
export {}
`,
},
entryPaths: []string{"/entry.js"},
options: config.Options{
Mode: config.ModeBundle,
OutputFormat: config.FormatCommonJS,
AbsOutputFile: "/out.js",
Platform: config.PlatformNode,
},
})
}

// The minifier should not remove "use strict" or join it with other expressions
func TestUseStrictDirectiveMinifyNoBundle(t *testing.T) {
default_suite.expectBundled(t, bundled{
Expand Down
4 changes: 3 additions & 1 deletion internal/bundler/linker.go
Original file line number Diff line number Diff line change
Expand Up @@ -1672,8 +1672,10 @@ func (c *linkerContext) createExportsForFile(sourceIndex uint32) {
nsExportNonLocalDependencies = append(nsExportNonLocalDependencies, dep)
}

// Pull in the "__markAsModule" symbol later
// Pull in the "__markAsModule" symbol later. Also make sure the "exports"
// variable is marked as used because we used it above.
repr.meta.needsMarkAsModuleSymbolFromRuntime = true
repr.ast.UsesExportsRef = true
}

// "__export(exports, { foo: () => foo })"
Expand Down
11 changes: 11 additions & 0 deletions internal/bundler/snapshots/snapshots_default.txt
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,17 @@ var import_foo = __toModule(require_foo());
var import_bar = __toModule(require_bar());
console.log(import_foo.foo(), import_bar.bar());

================================================================================
TestEmptyExportClauseBundleAsCommonJSIssue910
---------- /out.js ----------
// types.mjs
var require_types = __commonJS((exports2) => {
__markAsModule(exports2);
});

// entry.js
console.log(require_types());

================================================================================
TestExportChain
---------- /out.js ----------
Expand Down

0 comments on commit 54ef111

Please sign in to comment.