fix subtle ordering issue with imports

This commit is contained in:
Evan Wallace
2020-10-07 02:14:47 -07:00
parent 954d68ec9d
commit 1d9348337a
4 changed files with 46 additions and 13 deletions

View File

@@ -1,5 +1,11 @@
# Changelog
## Unreleased
* Fix another subtle ordering issue with `import` statements
When importing a file while bundling, the import statement was ordered before the imported code. This could affect import execution order in complex scenarios involving nested hybrid ES6/CommonJS modules. The fix was to move the import statement to after the imported code instead. This issue affected the `@sentry/browser` package.
## 0.7.11
* Fix regression in 0.7.9 when minifying with code splitting ([#437](https://github.com/evanw/esbuild/issues/437))

View File

@@ -2536,16 +2536,6 @@ func (c *linkerContext) chunkFileOrder(chunk *chunkInfo) (js []uint32, jsParts [
for partIndex, part := range repr.ast.Parts {
isPartInThisChunk := chunk.entryBits.equals(repr.meta.partMeta[partIndex].entryBits)
if isPartInThisChunk {
isFileInThisChunk = true
if canFileBeSplit && uint32(partIndex) != repr.meta.nsExportPartIndex && c.shouldIncludePart(repr, part) {
if sourceIndex == runtime.SourceIndex {
jsPartsPrefix = appendOrExtendPartRange(jsPartsPrefix, sourceIndex, uint32(partIndex))
} else {
jsParts = appendOrExtendPartRange(jsParts, sourceIndex, uint32(partIndex))
}
}
}
// Also traverse any files imported by this part
for _, importRecordIndex := range part.ImportRecordIndices {
@@ -2558,6 +2548,18 @@ func (c *linkerContext) chunkFileOrder(chunk *chunkInfo) (js []uint32, jsParts [
visit(*record.SourceIndex)
}
}
// Then include this part after the files it imports
if isPartInThisChunk {
isFileInThisChunk = true
if canFileBeSplit && uint32(partIndex) != repr.meta.nsExportPartIndex && c.shouldIncludePart(repr, part) {
if sourceIndex == runtime.SourceIndex {
jsPartsPrefix = appendOrExtendPartRange(jsPartsPrefix, sourceIndex, uint32(partIndex))
} else {
jsParts = appendOrExtendPartRange(jsParts, sourceIndex, uint32(partIndex))
}
}
}
}
if isFileInThisChunk {

View File

@@ -372,9 +372,6 @@ var require_h = __commonJS((exports) => {
foo.prop = 123;
});
// /entry.js
require_commonjs();
// /a.js
const abc = void 0;
@@ -386,6 +383,7 @@ __export(b_exports, {
const xyz = null;
// /entry.js
require_commonjs();
require_c();
require_d();
require_e();

View File

@@ -146,6 +146,33 @@
test(['--bundle', 'in.js', '--outfile=node.js'], {
'in.js': `export default 123; const out = require('./in'); if (!out.__esModule || out.default !== 123) throw 'fail'`,
}),
// Complex circular import case, must not crash
test(['--bundle', 'in.js', '--outfile=node.js'], {
'in.js': `
import {bar} from './re-export'
if (bar() !== 123) throw 'fail'
`,
're-export.js': `
export * from './foo'
export * from './bar'
`,
'foo.js': `
export function foo() {
return module.exports.foo ? 123 : 234 // "module" makes this a CommonJS file
}
`,
'bar.js': `
import {getFoo} from './get'
export let bar = getFoo(module) // "module" makes this a CommonJS file
`,
'get.js': `
import {foo} from './foo'
export function getFoo() {
return foo
}
`,
}),
)
// Test internal ES6 export