Skip to content

Commit

Permalink
fix #3311: pop scope after --drop-labels= runs
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Aug 14, 2023
1 parent f2d23b2 commit 4d9b764
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@

Note that this change means esbuild no longer considers any existing browser to support CSS nesting since none of the existing browsers support this new syntax. CSS nesting will now always be transformed when targeting a browser. This situation will change in the future as browsers add support for this new syntax.

* Fix a scope-related bug with `--drop-labels=` ([#3311](https://github.com/evanw/esbuild/issues/3311))

The recently-released `--drop-labels=` feature previously had a bug where esbuild's internal scope stack wasn't being restored properly when a statement with a label was dropped. This could manifest as a tree-shaking issue, although it's possible that this could have also been causing other subtle problems too. The bug has been fixed in this release.

* Make renamed CSS names unique across entry points ([#3295](https://github.com/evanw/esbuild/issues/3295))

Previously esbuild's generated names for local names in CSS were only unique within a given entry point (or across all entry points when code splitting was enabled). That meant that building multiple entry points with esbuild could result in local names being renamed to the same identifier even when those entry points were built simultaneously within a single esbuild API call. This problem was especially likely to happen with minification enabled. With this release, esbuild will now avoid renaming local names from two separate entry points to the same name if those entry points were built with a single esbuild API call, even when code splitting is disabled.
Expand Down
21 changes: 21 additions & 0 deletions internal/bundler_tests/bundler_dce_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4510,3 +4510,24 @@ func TestRemoveCodeAfterLabelWithReturn(t *testing.T) {
},
})
}

func TestDropLabelTreeShakingBugIssue3311(t *testing.T) {
dce_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.js": `
const myFunc = ()=> {
DROP: {console.log("drop")}
console.log("keep")
}
export default myFunc
`,
},
entryPaths: []string{"/entry.js"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/out.js",
DropLabels: []string{"DROP"},
OutputFormat: config.FormatESModule,
},
})
}
12 changes: 12 additions & 0 deletions internal/bundler_tests/snapshots/snapshots_dce.txt
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,18 @@ var keepMe4 = keepMe3();
var keepMe5 = pure();
var keepMe6 = some.fn();

================================================================================
TestDropLabelTreeShakingBugIssue3311
---------- /out.js ----------
// entry.js
var myFunc = () => {
console.log("keep");
};
var entry_default = myFunc;
export {
entry_default as default
};

================================================================================
TestDropLabels
---------- /out.js ----------
Expand Down
16 changes: 10 additions & 6 deletions internal/js_parser/js_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -10089,18 +10089,22 @@ func (p *parser) visitAndAppendStmt(stmts []js_ast.Stmt, stmt js_ast.Stmt) []js_
p.currentScope.LabelStmtIsLoop = true
}

// Drop this entire statement if requested
if _, ok := p.dropLabelsMap[name]; ok {
old := p.isControlFlowDead
// If we're dropping this statement, consider control flow to be dead
_, shouldDropLabel := p.dropLabelsMap[name]
old := p.isControlFlowDead
if shouldDropLabel {
p.isControlFlowDead = true
s.Stmt = p.visitSingleStmt(s.Stmt, stmtsNormal)
p.isControlFlowDead = old
return stmts
}

s.Stmt = p.visitSingleStmt(s.Stmt, stmtsNormal)
p.popScope()

// Drop this entire statement if requested
if shouldDropLabel {
p.isControlFlowDead = old
return stmts
}

if p.options.minifySyntax {
// Optimize "x: break x" which some people apparently write by hand
if child, ok := s.Stmt.Data.(*js_ast.SBreak); ok && child.Label != nil && child.Label.Ref == s.Name.Ref {
Expand Down

0 comments on commit 4d9b764

Please sign in to comment.