Babel preset: Add Hermes V1 native runtime workarounds for hermes#1761#56816
Open
ramonclaudio wants to merge 1 commit into
Open
Babel preset: Add Hermes V1 native runtime workarounds for hermes#1761#56816ramonclaudio wants to merge 1 commit into
ramonclaudio wants to merge 1 commit into
Conversation
469ebb8 to
a5fff17
Compare
## 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>
a5fff17 to
b2e38cc
Compare
|
@CalixTang has imported this pull request. If you are a Meta employee, you can view this in D105609206. |
|
Warning JavaScript API change detected This PR commits an update to
This change was flagged as: |
Author
|
Anything I can do to help push this forward @CalixTang? |
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.
Summary:
Three Babel plugins for
@react-native/babel-presetthat 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 inbabel-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:yarn jest packages/react-native-babel-presetclean (65 tests, 24 snapshots).yarn testclean (279 suites, 5656 tests, 1816 snapshots).yarn lint,yarn format-check,yarn flow-check,yarn test-typescript,yarn featureflags --verify-unchanged,yarn build-types --validateall clean.transform-snapshot-testis unchanged: the kitchen-sink fixture has none of the bug patterns so the new plugins don't alter its output.