Fix parsing of arrow function params inside ternaries with Flow by robhogan · Pull Request #18240 · babel/babel · GitHub
Skip to content

Fix parsing of arrow function params inside ternaries with Flow - #18240

Merged
nicolo-ribaudo merged 1 commit into
babel:mainfrom
robhogan:flow-block-body-arrow-params
Sep 15, 2026
Merged

nicolo-ribaudo merged 1 commit into
babel:mainfrom
robhogan:flow-block-body-arrow-params

Conversation

@robhogan

@robhogan robhogan commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor
Q                       A
Fixed Issues? react/metro/issues/1725 (happy to file locally?)
Patch: Bug Fix? 👍
Major: Breaking Change?
Minor: New Feature?
Tests Added + Pass? Yes
Documentation PR Link N/A
Any Dependency Changes? No
License MIT

The flow plugin must disambiguate between a ternary :, and : specifying a type. One case of this is an arrow function within a ternary consequent (true branch) e.g:

a ? (b): c => d

To do this, the params of an arrow at the start of a ternary consequent are not converted to patterns when the arrow is parsed, so that the result can be disambiguated afterwards in parseConditional.

getArrowLikeExpressions should handle that, but it currently skips arrows with a block body entirely - that was actually a regression introduced during type coverage improvements (#16425, released 7.24.5), probably because it looked like a necessary refinement:

https://github.com/babel/babel/pull/16425/changes#diff-53c81cc57639357b0d9cca6420b37ecf42e39930e60c0bf6d5b16473bf78e129R2148

That bogus constraint had three symptoms:

  • The main one: params of block-bodied arrow in that position stayed as expressions: ObjectExpression, ArrayExpression, AssignmentExpression, and SpreadElement for async arrows, whereas they should be ObjectPattern, ArrayPattern, AssignmentPattern and RestElement, respectively. For example, in a ? async ({ b }) => {} : c the param is an ObjectExpression, should be ObjectPattern.

  • The params were also never validated, so a ? ({ b, b }) => {} : c and a ? async (...b = 1) => {} : c parsed without errors, while a ? ({ b, b }) => b : c throws Argument name clash.

  • A block-bodied arrow with a return type was never considered for re-parsing, so a ? (b) : c => {}; threw Unexpected token, expected ":", although a ? (b) : c => d; parses as a ? b : (c => d).

With this PR, block-bodied arrows are now validated, or collected as possibly ambiguous, in the same way as arrows with an expression body. Only the traversal into the body (the stack.push) is still limited to expression bodies, since a block body can't contain the conditional's :.

Found via a report to Metro react/metro#1725, where investigation showed the SpreadElement param crashed a downstream Expo Babel plugin.

…l consequents

Disclaimer: This commit description was generated by an LLM (Claude).

With the `flow` plugin, the params of an arrow at the start of a conditional consequent are not converted to patterns when the arrow is parsed, so that `a ? (b): c => d` can be disambiguated afterwards in `parseConditional`. `getArrowLikeExpressions` then converts them, but it skipped arrows with a block body entirely. As a result:

- The params of a block-bodied arrow in that position stayed as expressions: `ObjectExpression`, `ArrayExpression`, `AssignmentExpression` and `TypeCastExpression`, and `SpreadElement` for async arrows. For example, in `a ? async ({ b }) => {} : c` the param is an `ObjectExpression`. The params were also never validated, so `a ? ({ b, b }) => {} : c` and `a ? async (...b = 1) => {} : c` parsed without errors, while `a ? ({ b, b }) => b : c` throws `Argument name clash`.
- A block-bodied arrow with a return type was never considered for re-parsing, so `a ? (b) : c => {};` threw `Unexpected token, expected ":"`, although `a ? (b) : c => d;` parses as `a ? b : (c => d)`.

This is a regression from babel#16425, first released in 7.24.5: it added the `node.body.type !== "BlockStatement"` condition to narrow `node.body` for `stack.push(node.body)`, which also stopped block-bodied arrows from being validated or collected. 7.24.4 handles all of the cases above.

Block-bodied arrows are now validated, or collected as possibly ambiguous, in the same way as arrows with an expression body. Only the traversal into the body is still limited to expression bodies, since a block body can't contain the conditional's `:`.

Found via react/metro#1725, where the `SpreadElement` param crashed a downstream Babel plugin.

Tests: added `flow/arrows-in-ternaries/block-body-params`, `flow/arrows-in-ternaries/block-body-invalid-params` and `flow/arrows-in-ternaries/block-body-return-type-like`. `yarn jest packages/babel-parser` and `yarn jest flow` pass, with and without `BABEL_8_BREAKING=true`.
@github-actions

Copy link
Copy Markdown

Thanks for opening this pull request! 🎉

We really appreciate you taking the time to contribute, @robhogan.

A maintainer will take a look as soon as they can. In the meantime, please make sure that:

  • the description explains what changed and why
  • any related issues are linked
  • existing tests still pass

If anything needs adjusting we'll leave comments here. Thanks again!

@babel-bot

Copy link
Copy Markdown
Collaborator

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/62133

@pkg-pr-new

pkg-pr-new Bot commented Sep 14, 2026

Copy link
Copy Markdown

Open in StackBlitz

commit: 3e7af35

@JLHwung JLHwung left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@liuxingbaoyu

Copy link
Copy Markdown
Member

Thanks!

@nicolo-ribaudo nicolo-ribaudo added the PR: Bug Fix 🐛 A type of pull request used for our changelog categories label Sep 15, 2026
@nicolo-ribaudo nicolo-ribaudo changed the title fix(parser): Flow plugin - fix params of arrow functions inside ternaries Fix parsing of arrow function params inside ternaries with Flow Sep 15, 2026
@nicolo-ribaudo
nicolo-ribaudo merged commit 87fee9e into babel:main Sep 15, 2026
58 checks passed
@robhogan
robhogan deleted the flow-block-body-arrow-params branch September 15, 2026 14:09
@robhogan

Copy link
Copy Markdown
Contributor Author

Thanks everyone. Is there a process / anything I can help with to pick this back to Babel 7? (We're hoping to upgrade to v8 but not quite there yet)

@nicolo-ribaudo

Copy link
Copy Markdown
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR: Bug Fix 🐛 A type of pull request used for our changelog categories

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants