js_parser: don't fold [x][0] in call position so this stays the array - #37085
Open
robobun wants to merge 1 commit into
Open
js_parser: don't fold [x][0] in call position so this stays the array#37085robobun wants to merge 1 commit into
this stays the array#37085robobun wants to merge 1 commit into
Conversation
Calling through [x][0]() evaluates the callee as a property Reference, so this inside the callee is the array literal itself. The fold emitted (0, x)() for member-expression items and a bare x() for everything else, binding this to undefined instead. Bail out of the fold for call targets and bump the runtime transpiler cache version.
Contributor
WalkthroughArray literal index folding now skips call targets to preserve ChangesArray index call-target folding
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
With
minify_syntaxon (the default forbun run), the[x][0] -> xfold rebindsthiswhen the folded expression is the callee of a call:Node prints
array array array array true. Bun printsundefined array undefined undefined false.Per ECMA-262 EvaluateCall, when the callee is a property Reference like
[o.f][0], thisValue is GetThisValue of that Reference, i.e. the array literal itself. #36730 changed the fold to emit(0, o.f)()for member-expression items "so this is not rebound", but that bindsthisto undefined, not the array. Items that are plain identifiers or function expressions were inlined bare ([y][0]()->y()), which is wrong the same way.Fix
No folded form can reproduce "
thisis the array literal", so thee_indexarray fold now bails out entirely when the index expression is a call target. This covers optional calls ([o.f][0]?.()) sincee_callsets the samecall_target. The multi-item path ([0, y][1]()) goes through the same gate.Unaffected on purpose:
new [C][0]()still folds tonew C:e_newdoes not mark a call target andnewdoes not threadthisthrough the callee Reference."foo"[2] -> "o"string fold still fires in call position: a primitive callee throws TypeError either way.{f: x}.ffold already bails on call targets.??/||/&&/ternary folds keep emitting(0, x)(): their bases are values, not References, so undefined is the correct receiver there.Bumps the runtime transpiler cache version since cached minified output changes.
Tagged templates (
[o.f][0]followed by a template literal) have the same receiver rule but need thetemplate_tagtracking from #36735; that PR also bails this fold in tag position. Whichever lands first, the other rebases with a trivial conflict here and in the cache version.Verification
Also green with the fix:
bundler_minify.test.ts(42 pass),esbuild/default.test.ts(192 tests),esbuild/dce.test.ts(95 tests),runtime-transpiler.test.ts(15 pass),transpiler-cache.test.ts(11 pass). The repro above printsarray array array array true, matching Node.[review] gate passed · iteration 0 · 3 files touched
fails on main (without fix)
passes on PR (with fix)
diff hotspot
gate history · 1 passed · 0 rejected · iteration 0
evidence per changed file