Skip to content

Commit

Permalink
fix: fix panic when optional chain partially replaced with defines (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
hi-ogawa committed Dec 18, 2023
1 parent b76b54f commit accfb14
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 3 deletions.
58 changes: 58 additions & 0 deletions internal/bundler_tests/bundler_default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5329,6 +5329,64 @@ func TestDefineOptionalChainLowered(t *testing.T) {
})
}

// See: https://github.com/evanw/esbuild/issues/3551
func TestDefineOptionalChainPanicIssue3551(t *testing.T) {
defines := config.ProcessDefines(map[string]config.DefineData{
"x": {
DefineExpr: &config.DefineExpr{
Constant: &js_ast.EObject{},
},
},
"a.b": {
DefineExpr: &config.DefineExpr{
Constant: &js_ast.EObject{},
},
},
})
default_suite.expectBundled(t, bundled{
files: map[string]string{
"/id-define.js": `
x?.y.z;
(x?.y).z;
x?.y["z"];
(x?.y)["z"];
x?.y();
(x?.y)();
x?.y.z();
(x?.y).z();
x?.y["z"]();
(x?.y)["z"]();
delete x?.y.z;
delete (x?.y).z;
delete x?.y["z"];
delete (x?.y)["z"];
`,
"/dot-define.js": `
a?.b.c;
(a?.b).c;
a?.b["c"];
(a?.b)["c"];
a?.b();
(a?.b)();
a?.b.c();
(a?.b).c();
a?.b["c"]();
(a?.b)["c"]();
delete a?.b.c;
delete (a?.b).c;
delete a?.b["c"];
delete (a?.b)["c"];
`,
},
entryPaths: []string{"/id-define.js", "/dot-define.js"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputDir: "/out",
Defines: &defines,
},
})
}

// See: https://github.com/evanw/esbuild/issues/2407
func TestDefineInfiniteLoopIssue2407(t *testing.T) {
defines := config.ProcessDefines(map[string]config.DefineData{
Expand Down
36 changes: 36 additions & 0 deletions internal/bundler_tests/snapshots/snapshots_default.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,42 @@ console.log([
(_a = a[b]) == null ? void 0 : _a[c]
]);

================================================================================
TestDefineOptionalChainPanicIssue3551
---------- /out/id-define.js ----------
// id-define.js
({})?.y.z;
({}?.y).z;
({})?.y["z"];
({}?.y)["z"];
({})?.y();
({}?.y)();
({})?.y.z();
({}?.y).z();
({})?.y["z"]();
({}?.y)["z"]();
delete {}?.y.z;
delete ({}?.y).z;
delete {}?.y["z"];
delete ({}?.y)["z"];

---------- /out/dot-define.js ----------
// dot-define.js
({}).c;
({}).c;
({})["c"];
({})["c"];
({})();
({})();
({}).c();
({}).c();
({})["c"]();
({})["c"]();
delete {}.c;
delete {}.c;
delete {}["c"];
delete {}["c"];

================================================================================
TestDefineThis
---------- /out.js ----------
Expand Down
9 changes: 6 additions & 3 deletions internal/js_parser/js_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -13462,7 +13462,8 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO
}

// Lower optional chaining if we're the top of the chain
containsOptionalChain := e.OptionalChain != js_ast.OptionalChainNone
containsOptionalChain := e.OptionalChain == js_ast.OptionalChainStart ||
(e.OptionalChain == js_ast.OptionalChainContinue && out.childContainsOptionalChain)
if containsOptionalChain && !in.hasChainParent {
return p.lowerOptionalChain(expr, in, out)
}
Expand Down Expand Up @@ -13620,7 +13621,8 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO
}

// Lower optional chaining if we're the top of the chain
containsOptionalChain := e.OptionalChain != js_ast.OptionalChainNone
containsOptionalChain := e.OptionalChain == js_ast.OptionalChainStart ||
(e.OptionalChain == js_ast.OptionalChainContinue && out.childContainsOptionalChain)
if containsOptionalChain && !in.hasChainParent {
return p.lowerOptionalChain(expr, in, out)
}
Expand Down Expand Up @@ -14718,7 +14720,8 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO
}

// Lower optional chaining if we're the top of the chain
containsOptionalChain := e.OptionalChain != js_ast.OptionalChainNone
containsOptionalChain := e.OptionalChain == js_ast.OptionalChainStart ||
(e.OptionalChain == js_ast.OptionalChainContinue && out.childContainsOptionalChain)
if containsOptionalChain && !in.hasChainParent {
return p.lowerOptionalChain(expr, in, out)
}
Expand Down

0 comments on commit accfb14

Please sign in to comment.