From 46559d8ba3952cd31a7b4136f6b286a5aae2cf86 Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Sun, 19 Jul 2020 02:48:23 -0700 Subject: [PATCH] fix #273: span re-exported symbols across chunks --- CHANGELOG.md | 4 ++ internal/bundler/bundler_splitting_test.go | 47 ++++++++++++++++++++++ internal/bundler/linker.go | 14 ++----- 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 857b16bc1c..d16ae25db3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ The install script now downloads the binary directly from npmjs.org instead of using the `npm` command to install the package. This should be more compatible with unusual node environments (e.g. having multiple old copies of npm installed). +* Fix a code splitting bug with re-exported symbols ([#273](https://github.com/evanw/esbuild/issues/273)) + + Re-exporting a symbol in an entry point didn't correctly track the cross-chunk dependency, which caused the output file to be missing a required import. This bug has been fixed. + ## 0.6.3 * Fix `/* @__PURE__ */` IIFEs at start of statement ([#258](https://github.com/evanw/esbuild/issues/258)) diff --git a/internal/bundler/bundler_splitting_test.go b/internal/bundler/bundler_splitting_test.go index 673daffc53..a3963b7dfd 100644 --- a/internal/bundler/bundler_splitting_test.go +++ b/internal/bundler/bundler_splitting_test.go @@ -530,3 +530,50 @@ console.log(bar()); }, }) } + +func TestSplittingReExportIssue273(t *testing.T) { + expectBundled(t, bundled{ + files: map[string]string{ + "/a.js": ` + export const a = 1 + `, + "/b.js": ` + export { a } from './a' + `, + }, + entryPaths: []string{"/a.js", "/b.js"}, + options: config.Options{ + IsBundling: true, + CodeSplitting: true, + OutputFormat: config.FormatESModule, + AbsOutputDir: "/out", + }, + expected: map[string]string{ + "/out/a.js": `import { + a +} from "./chunk.xL6KqlYO.js"; + +// /a.js +export { + a +}; +`, + "/out/b.js": `import { + a +} from "./chunk.xL6KqlYO.js"; + +// /b.js +export { + a +}; +`, + "/out/chunk.xL6KqlYO.js": `// /a.js +const a = 1; + +export { + a +}; +`, + }, + }) +} diff --git a/internal/bundler/linker.go b/internal/bundler/linker.go index 1d4316c37b..39fbda8723 100644 --- a/internal/bundler/linker.go +++ b/internal/bundler/linker.go @@ -576,14 +576,11 @@ func (c *linkerContext) computeCrossChunkDependencies(chunks []chunkMeta) { continue } + // If this is imported from another file, follow the import + // reference and reference the symbol in that file instead if importToBind, ok := fileMeta.importsToBind[ref]; ok { - // If this is imported from another file, follow the import - // reference and reference the symbol in that file instead ref = importToBind.ref symbol = c.symbols.Get(ref) - } else if _, ok := file.ast.TopLevelSymbolToParts[ref]; !ok { - // Skip symbols that aren't imports or top-level symbols - continue } // If this is an ES6 import from a CommonJS file, it will become a @@ -612,11 +609,8 @@ func (c *linkerContext) computeCrossChunkDependencies(chunks []chunkMeta) { // Find all uses in this chunk of symbols from other chunks importsFromOtherChunks := make(map[uint32][]ast.Ref) for importRef := range chunkMetas[chunkIndex].imports { - otherChunkIndex, ok := topLevelDeclaredSymbolToChunk[importRef] - if !ok { - panic("Internal error") - } - if otherChunkIndex != uint32(chunkIndex) { + // Ignore uses that aren't top-level symbols + if otherChunkIndex, ok := topLevelDeclaredSymbolToChunk[importRef]; ok && otherChunkIndex != uint32(chunkIndex) { importsFromOtherChunks[otherChunkIndex] = append(importsFromOtherChunks[otherChunkIndex], importRef) chunkMetas[otherChunkIndex].exports[importRef] = true }