The Starling JS parser rejects the in operator inside a parenthesized expression in a for-loop head with expected ')' to close grouping (got In 'in'). The code is legal: the no-in restriction applies only to the top-level expression of the for head (so the parser can tell for(;;) from for-in), never inside parentheses. x.com's shared~ondemand.XChat~ondemand.ChatDrawer.ba31fdba.js chunk dies on this.
What happens
The parser threads the restriction through _disallowInDepth (src/Starling.Js/Parse/JsParser.cs:21). Binary-operator parsing skips in whenever the depth is non-zero (JsParser.cs:748, 764). The depth is correctly saved and zeroed when entering contexts where the restriction must not apply:
- arrow concise bodies (
JsParser.cs:510-519)
- call arguments (
JsParser.cs:1143-1157)
- bracket subscripts (
JsParser.cs:1437-1473)
- computed member keys (
JsParser.cs:1658-1663)
The parenthesized-expression arm does not. The LParen case of the primary-expression parser (JsParser.cs:1279-1299) calls ParseAssignment() with _disallowInDepth still set, so in is suppressed as a binary operator and the parser then trips over the unconsumed in token.
Per the grammar, CoverParenthesizedExpressionAndArrowParameterList always contains Expression[+In] — parentheses reset the restriction.
Repro
for (var x = ('a' in {a: 1}) ? 1 : 2; x < 3; x++) {} // legal everywhere, node accepts it
The chunk-level failure was verified on 2026-06-10 against the real x.com chunk with the exact message above. The minimal form follows directly from the cited parse path.
Fix
Real fix: in the LParen arm of the primary-expression parser, save _disallowInDepth, zero it, and restore it in a finally — the same pattern the bracket-subscript and call-argument paths already use. No band-aid applies.
Context
Found during the x.com/nasa boot investigation on 2026-06-10 (branch feat/js-stack-trampoline). Same blast-radius pattern as the sibling parser issues (regex Unicode property escapes, template-substitution comma): one parse error kills every webpack module in the chunk.
The Starling JS parser rejects the
inoperator inside a parenthesized expression in afor-loop head withexpected ')' to close grouping (got In 'in'). The code is legal: the no-inrestriction applies only to the top-level expression of theforhead (so the parser can tellfor(;;)fromfor-in), never inside parentheses. x.com'sshared~ondemand.XChat~ondemand.ChatDrawer.ba31fdba.jschunk dies on this.What happens
The parser threads the restriction through
_disallowInDepth(src/Starling.Js/Parse/JsParser.cs:21). Binary-operator parsing skipsinwhenever the depth is non-zero (JsParser.cs:748,764). The depth is correctly saved and zeroed when entering contexts where the restriction must not apply:JsParser.cs:510-519)JsParser.cs:1143-1157)JsParser.cs:1437-1473)JsParser.cs:1658-1663)The parenthesized-expression arm does not. The
LParencase of the primary-expression parser (JsParser.cs:1279-1299) callsParseAssignment()with_disallowInDepthstill set, soinis suppressed as a binary operator and the parser then trips over the unconsumedintoken.Per the grammar,
CoverParenthesizedExpressionAndArrowParameterListalways containsExpression[+In]— parentheses reset the restriction.Repro
The chunk-level failure was verified on 2026-06-10 against the real x.com chunk with the exact message above. The minimal form follows directly from the cited parse path.
Fix
Real fix: in the
LParenarm of the primary-expression parser, save_disallowInDepth, zero it, and restore it in afinally— the same pattern the bracket-subscript and call-argument paths already use. No band-aid applies.Context
Found during the x.com/nasa boot investigation on 2026-06-10 (branch
feat/js-stack-trampoline). Same blast-radius pattern as the sibling parser issues (regex Unicode property escapes, template-substitution comma): one parse error kills every webpack module in the chunk.