mirror of
https://github.com/hanzoai/esbuild.git
synced 2026-09-24 16:58:50 +00:00
fix #4507: import assignment tree-shaking bug
This commit is contained in:
@@ -2,6 +2,15 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
* Fix tree shaking bug due to TypeScript import alias ([#4507](https://github.com/evanw/esbuild/issues/4507))
|
||||
|
||||
This release fixes a bug that could cause esbuild to incorrectly tree-shake imports that are used in a TypeScript type alias under certain circumstances. Affected code uses a TypeScript-specific `import` assignment and looks something like this:
|
||||
|
||||
```ts
|
||||
import Base from './dep.js';
|
||||
import Alias = Base.SomeType;
|
||||
```
|
||||
|
||||
* Avoid overwriting input files without `--allow-overwrite` ([#4484](https://github.com/evanw/esbuild/issues/4484))
|
||||
|
||||
For example: `esbuild input.js --outfile=input.js` tells esbuild to overwrite `input.js` with the output of running esbuild on it. This was supposed to already be prevented by default, but it accidentally regressed in version 0.17.0 and apparently didn't have any test coverage. The error message was being printed but the input file was still being overwritten. Oops.
|
||||
|
||||
@@ -3064,3 +3064,29 @@ func TestParameterPropsUseDefineForClassFieldsTrueLowered(t *testing.T) {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// See: https://github.com/evanw/esbuild/issues/4507
|
||||
func TestTreeShakingImportAliasIssue4507(t *testing.T) {
|
||||
ts_suite.expectBundled(t, bundled{
|
||||
files: map[string]string{
|
||||
"/entry.ts": `
|
||||
import Base from './dep.js';
|
||||
import Alias = Base.SomeType;
|
||||
|
||||
export function make() {
|
||||
return new Base();
|
||||
}
|
||||
`,
|
||||
"/dep.js": `
|
||||
export default class Base {
|
||||
static hello() { return 'dep code is present'; }
|
||||
}
|
||||
`,
|
||||
},
|
||||
entryPaths: []string{"/entry.ts"},
|
||||
options: config.Options{
|
||||
Mode: config.ModeBundle,
|
||||
AbsOutputFile: "/out.js",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2251,3 +2251,21 @@ if (nested) {
|
||||
new Bar(bar2(objBar));
|
||||
}
|
||||
var bar;
|
||||
|
||||
================================================================================
|
||||
TestTreeShakingImportAliasIssue4507
|
||||
---------- /out.js ----------
|
||||
// dep.js
|
||||
var Base = class {
|
||||
static hello() {
|
||||
return "dep code is present";
|
||||
}
|
||||
};
|
||||
|
||||
// entry.ts
|
||||
function make() {
|
||||
return new Base();
|
||||
}
|
||||
export {
|
||||
make
|
||||
};
|
||||
|
||||
@@ -1752,12 +1752,16 @@ func (p *parser) ignoreUsage(ref ast.Ref) {
|
||||
// Roll back the use count increment in recordUsage()
|
||||
if !p.isControlFlowDead {
|
||||
p.symbols[ref.InnerIndex].UseCountEstimate--
|
||||
use := p.symbolUses[ref]
|
||||
use.CountEstimate--
|
||||
if use.CountEstimate == 0 {
|
||||
delete(p.symbolUses, ref)
|
||||
} else {
|
||||
p.symbolUses[ref] = use
|
||||
|
||||
// Only remove this usage if we're currently processing a part
|
||||
if p.symbolUses != nil {
|
||||
use := p.symbolUses[ref]
|
||||
use.CountEstimate--
|
||||
if use.CountEstimate == 0 {
|
||||
delete(p.symbolUses, ref)
|
||||
} else {
|
||||
p.symbolUses[ref] = use
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17729,6 +17733,9 @@ func (p *parser) appendPart(parts []js_ast.Part, stmts []js_ast.Stmt) []js_ast.P
|
||||
part.Scopes = p.scopesForCurrentPart
|
||||
parts = append(parts, part)
|
||||
}
|
||||
|
||||
// Reset the state for this part so we don't accidentally mutate it
|
||||
p.symbolUses = nil
|
||||
return parts
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user