Skip to content

Babel preset: Add Hermes V1 native runtime workarounds for hermes#1761#56816

Open
ramonclaudio wants to merge 1 commit into
facebook:mainfrom
ramonclaudio:fix/hermes-v1-bug-workarounds
Open

Babel preset: Add Hermes V1 native runtime workarounds for hermes#1761#56816
ramonclaudio wants to merge 1 commit into
facebook:mainfrom
ramonclaudio:fix/hermes-v1-bug-workarounds

Conversation

@ramonclaudio
Copy link
Copy Markdown

@ramonclaudio ramonclaudio commented May 13, 2026

Summary:

Three Babel plugins for @react-native/babel-preset that work around runtime bugs in the bundled Hermes V1 (250829098.0.13). Rewrites the code patterns at compile time so Hermes never sees them. Port of @kitten's plugins in babel-preset-expo (expo/expo#45601).

Changelog:

[GENERAL] [FIXED] - Work around three Hermes V1 source-level codegen bugs in @react-native/babel-preset (async-arrow non-simple params, class-in-finally, super-in-object-accessor)

Test Plan:

Test repro at ramonclaudio/hermes-1761-repro. 55/55 PASS on iPhone 17 Pro / iOS 26.5 in both Debug and Release builds.

Locally on packages/react-native-babel-preset:

  • 18 new inline-snapshot unit tests cover the transformed output and the skip-when-irrelevant path.
  • yarn jest packages/react-native-babel-preset clean (65 tests, 24 snapshots).
  • Full repo yarn test clean (279 suites, 5656 tests, 1816 snapshots).
  • yarn lint, yarn format-check, yarn flow-check, yarn test-typescript, yarn featureflags --verify-unchanged, yarn build-types --validate all clean.
  • Existing transform-snapshot-test is unchanged: the kitchen-sink fixture has none of the bug patterns so the new plugins don't alter its output.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label May 13, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label May 13, 2026
@ramonclaudio ramonclaudio force-pushed the fix/hermes-v1-bug-workarounds branch from 469ebb8 to a5fff17 Compare May 13, 2026 22:04
## Summary:

Three Babel plugins added to `@react-native/babel-preset` that work
around runtime codegen bugs in the bundled Hermes V1 (250829098.0.13,
branch cut 2025-08-29) by rewriting source patterns before they reach
the engine. Each plugin papers over a different bug that has been fixed
on Hermes `static_h` but has not been backported to the V1 stable
branch.

- `fix-hermes-v1-async-arrow-non-simple-params`:
  facebook/hermes#1761 (fixed in static_h by 68bfb3a48b31, 2025-09-11).
  Async arrow functions with destructured, defaulted, or rest parameters
  silently resolve `await` with `undefined` while the function body
  continues executing in the background. The plugin rewrites the params
  to a simple identifier with inline destructuring so Hermes never sees
  the buggy shape. Gated on `isHermesProfile && preserveAsync` since
  `plugin-transform-async-to-generator` rewrites the pattern away when
  `preserveAsync` is false.

- `fix-hermes-v1-class-in-finally`:
  Fixed in static_h by 1e94fbe0ebb4 (2026-02-12). Class declarations
  inside a `finally` block trip Hermes V1's variable caching path. The
  plugin wraps them in an IIFE so the class lives in its own scope.

- `fix-hermes-v1-super-in-object-accessor`:
  Fixed in static_h by 18a963465944 (2025-11-04). Object-literal getters
  and setters using `super.x` trip the `genFunctionExpression` home
  object path. The plugin marks the accessor as computed with a string
  key.

All three gate on `isHermesProfile` and bail out fast on the common
case. The plugins are a direct port of work by @kitten (Phil Pluckthun,
Expo team) in `babel-preset-expo` (expo/expo#45601, MIT licensed). All
plugin design and implementation credit belongs to him. This PR carries
his work over to `@react-native/babel-preset` so bare React Native
consumers benefit from the same fix.

## Changelog:

[GENERAL] [FIXED] - Work around three Hermes V1 source-level codegen bugs in `@react-native/babel-preset` (async-arrow non-simple params, class-in-finally, super-in-object-accessor)

## Test Plan:

- 18 new inline-snapshot test cases across three new test files verify both the transformed output and the fast-bail behavior on irrelevant patterns.
- `yarn jest packages/react-native-babel-preset` clean (65 tests, 24 snapshots).
- Full repo `yarn test` clean (279 suites, 5656 tests passed, 1816 snapshots).
- `yarn lint`, `yarn format-check`, `yarn flow-check`, `yarn test-typescript`, `yarn featureflags --verify-unchanged`, `yarn build-types --validate` all clean.
- Existing `transform-snapshot-test` passes byte-identical: the kitchen-sink fixture has none of the buggy patterns so the new plugins do not change its output for any profile.
- Verified end-to-end downstream: `babel-preset-expo@56.0.7` (which carries the same plugins) applied to vanilla `@convex-dev/better-auth@0.12.2` fixes the `useConvexAuth.isAuthenticated` race that the destructured-param async-arrow shape produces on Hermes V1.
- Public repro: https://github.com/ramonclaudio/convex-better-auth-368-repro

## Caveats:

`fix-hermes-v1-class-in-finally` rewrites block-scoped `class`
declarations inside `finally` blocks to function-scoped `var`
initializers. Observable only when code references the class by name
from outside the `finally` (rare pattern). The same plugin shape has
run in `babel-preset-expo@56.0.6+` and Expo SDK 56 preview for a week
without reported regressions, but flagging in case Meta's internal test
fleet surfaces an edge case the OSS test suite does not catch.

## References:

- facebook/hermes#1761 (root-cause issue, fixed in static_h)
- expo/expo#45601 (source of the ported plugins, by @kitten)
- expo/expo#45592 (user-facing bug report on SDK 56 preview)

Co-authored-by: Phil Pluckthun <phil@kitten.sh>
@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented May 18, 2026

@CalixTang has imported this pull request. If you are a Meta employee, you can view this in D105609206.

@github-actions
Copy link
Copy Markdown

Warning

JavaScript API change detected

This PR commits an update to ReactNativeApi.d.ts, indicating a change to React Native's public JavaScript API.

  • Please include a clear changelog message.
  • This change will be subject to additional review.

This change was flagged as: POTENTIALLY_BREAKING

@ramonclaudio
Copy link
Copy Markdown
Author

Anything I can do to help push this forward @CalixTang?

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

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant