chore: bump react-native to 0.81.6#7366
Conversation
|
All alerts resolved. Learn more about Socket for GitHub. This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored. |
de84f7f to
70bfcfe
Compare
b57f054 to
d1a672a
Compare
|
π§ͺ Flashlight Performance Report (AWS Device Farm) π Commit: 0f2ed9d π View Artifacts
|
a824755 to
452bed7
Compare
| // Files outside native dirs that still affect the produced .app (mostly the | ||
| // JS bundle baked in via `rock bundle`). Without these, JS-only changes | ||
| // hit a stale cached .app and never make it into CI builds. | ||
| extraSources: ['is_testing', '.xcode-version', 'metro.config.js', 'metro.transform.js', 'babel.config.js'], |
There was a problem hiding this comment.
This seems like an independent fix that is also "broken" on develop today and thus could be extracted to its own PR?
There was a problem hiding this comment.
Good catch β turns out it wasn't even needed in this PR. I had assumed rock's remote cache stored the final .app/.apk (with the JS bundle baked in) and that JS-only changes wouldn't bust the fingerprint, but the cache is actually only for the native build artifacts. rock bundle runs every CI run, so JS-only changes always make it into the binary regardless of fingerprint.
The "stale APK" symptom that originally motivated the addition turned out to be a silent fall-through in the metro resolver caused by a Node 22 ERR_PACKAGE_PATH_NOT_EXPORTED (fixed in 96e5f1a), unrelated to caching.
Reverted in 9443553 β rock.config.mjs now matches develop.
| @@ -1,12 +1,15 @@ | |||
| // eslint-disable-next-line import/no-extraneous-dependencies | |||
| const blacklist = require('metro-config/src/defaults/exclusionList'); | |||
| const path = require('path'); | |||
There was a problem hiding this comment.
Still used β the resolver fallback chain a few lines down references path.dirname(context.originModulePath) and path.isAbsolute(resolution). That fallback existed on develop too, but path was never imported there, so the require.resolve recovery path would have ReferenceError'd if it ever fired. This swap (dead blacklist import β path) makes the existing fallback actually work.
Screen.Recording.2026-05-05.at.6.28.54.PM.movThis is the only regression I found so far, typing on Android changes the height of the input, while previously it was stable. |
|
added workaround for that issue here 75a61e5 |
This can go now right? |
|
Also desc is off here I think?
|
patch-package failed to parse the previous hunk β the header line counts were off and blank context lines had no leading space, which patch-package's parser treats as end-of-hunk.
RN 0.81 no longer exposes $REACT_NATIVE_PATH to the Xcode build env, so the old Bundle React Native script phase broke with "react-native-xcode.sh: No such file or directory". The sentry-xcode.sh wrapper already invokes react-native-xcode.sh internally, so pass it directly under with-environment.sh without the extra argument layer.
Metro's unstable_enablePackageExports now defaults to true in RN 0.81. Zustand's ESM entry points use import.meta, which Hermes does not support β causing SyntaxError 'import.meta' is currently unsupported at store creation (createRainbowStore, createQueryStore). Add explicit mappings under the package.json react-native field to force Metro to resolve zustand and its subpaths to the CJS files, bypassing the exports map.
β¦e export condition With zustand@5.0.10, the package's own exports map routes the `react-native` condition to the CJS entry (`./index.js`), so Metro no longer resolves to the ESM files that used import.meta. The manual subpath overrides added in 592d73b to work around v4's exports map are no longer needed.
v1.2.3 overrode setHitSlopRect and referenced removed RN APIs; v2.0.0 drops those for RN 0.80+. Patch file renamed to match the new version β contents are effectively the same minus line-number shifts.
β¦for RN 0.81 - flash-list: BlankAreaEvent.dispatch references eventData directly, but in RN 0.81's Event<T> base class eventData is protected and must be accessed via getEventData(). New patch file. - react-native-performance: PerformanceMarkerManager's getExportedCustomDirectEventTypeConstants() overrode the base's MutableMap<String, Any> return type. In RN 0.81 the base changed to Map<String, Any> (covariant narrowing). Updated the patch to match. Both hunks ported from #6924.
react-native@0.81.6 ships react-native-renderer built against react@19.1.4. Pinning react to 19.1.5 caused a runtime crash: Incompatible React versions: The 'react' and 'react-native-renderer' packages must have the exact same version. Instead got: - react: 19.1.5 - react-native-renderer: 19.1.4 Downgrading one patch matches the bundled renderer and resolves it.
The internal react-native-sandbox repo has its own RN 0.81 branch. Set SANDBOX_BRANCH so rainbow-scripts' iOS / Android prebuild hooks check that out instead of the default branch β needed until the sandbox branch is merged. Applied to ios-e2e, android-e2e, ios-builds (both install steps), and unit-test workflows.
β¦on drift
Two Android startup crashes on RN 0.81 caused by libraries reflecting on
internal RN Java fields that were renamed in 0.81's Kotlin rewrite:
- Bump react-native-animateable-text 0.16.0-beta.0 β 0.17.1 to pull in RN
0.81 + old-arch support. The pre-bump build crashed at first text view
creation:
java.lang.NoSuchFieldException: No field mPreparedSpannableText in
class Lcom/facebook/react/views/text/ReactTextShadowNode;
at com.reactnativereanimatedtext.JBTextShadowNode.<clinit>
RN 0.81 renamed the spannable text field; v0.17.1 reads the new one.
- Bump react-native-reanimated 3.19.4 β 3.19.5 (latest 3.x). Picks up
bridge-lifecycle fixes that resolve a -Xcheck:jni abort in debug
builds (NativeProxyCommon.requestRender called on null after JS thread
bounces).
Verified locally with `yarn android` on Pixel 6 emulator + RN 0.81.6 +
Hermes β Wallet Screen renders cleanly after both bumps.
Note: the in-repo InternalModule.java reflection on
NativeModuleRegistry.mModules / ModuleHolder.mModule also needs renaming
to moduleMap / module respectively for SafeWebSocketModule to install on
RN 0.81. Filed separately since the stub committed on develop differs
from the runtime version.
RN 0.81's Metro respects package.json `exports`, routing static `import`
statements to the `.import` condition. `@reservoir0x/reservoir-sdk`
ships a Parcel-bundled `.mjs` there whose mangled named exports
(e.g. `$6496f8ee40d0c4eb$export$5d730b7aed1a3eb0 as createClient`) come
through as `undefined` once Hermes loads the release bundle.
The crash showed up on every cold launch:
[TypeError: Cannot read property 'createClient' of undefined]
at initializeReservoirClient
β¦which kills the app before the welcome screen mounts, breaking every
E2E test (iOS sim and Android emulator both β same JS root cause). Local
debug builds happen to work because Metro serves a different transform
in dev mode.
Override the resolver for this one package to its CJS file (`./dist/index.js`,
its `main` field). No effect on other packages.
`require.resolve('@reservoir0x/reservoir-sdk/dist/index.js')` and even
`require.resolve('@reservoir0x/reservoir-sdk/package.json')` throw
`ERR_PACKAGE_PATH_NOT_EXPORTED` on Node 22+ because the package's
`exports` field only exposes `.` (no subpath, no `./package.json`).
CI bundle step crashed in `metro.config.js` evaluation, blowing up
`Test Build` before the bundle could be produced.
Compute the path off `__dirname` instead β metro.config.js sits at the
workspace root, so `node_modules/@reservoir0x/reservoir-sdk/dist/index.js`
is the deterministic path. Bypasses Node's exports check entirely.
Rock's remote-build cache fingerprints native files + package.json by default but not `metro.config.js`. Yesterday's reservoir-sdk resolveRequest override never reached CI builds β rock kept serving the older cached `.app` (fingerprint `188295d8...` β pre-fix) because nothing in the fingerprint changed. Add metro.config.js, metro.transform.js, and babel.config.js to extraSources so JS-bundle config changes properly invalidate the cache.
RN 0.81's Metro defaults `unstable_enablePackageExports` to true, which
routes static `import` statements to packages' `import` condition. Many
npm libs ship ESM there (often Parcel-mangled, e.g. @reservoir0x/reservoir-sdk
and any transitive `class X extends Y` deps); when bundled for Hermes,
their named exports come through as `undefined` and the app crashes on
launch:
[TypeError: Cannot read property 'prototype' of undefined]
[TypeError: Cannot read property 'createClient' of undefined]
at initializeReservoirClient
at Root (App.tsx)
β¦which kills the app before the welcome screen mounts and breaks every
E2E + Perf test on iOS sim and Android (real device + emulator).
Disabling package exports makes Metro fall back to the `main` field
(CJS), matching what RN 0.79 effectively did and what these packages
historically test against. Replaces the per-package reservoir-sdk
override from b05b3d5 / 96e5f1a with a single config flag.
Replaces the global `unstable_enablePackageExports: false` from d50271b (too broad β flips behaviour for every package) with a per-package map of `exact moduleName β CJS filepath` overrides in `metro.config.js`. The RN 0.81 Metro / Hermes interaction crashes on launch when packages ship Parcel-mangled ESM via the `import` condition: their named exports come through as `undefined` in the release bundle. Reservoir-sdk was the visible top-of-stack symptom; the underlying `prototype of undefined` fires deeper in viem (transitively required by reservoir's CJS β but viem itself shares the same export shape). Add packages to `FORCE_CJS_PACKAGES` as we find them. If this list grows much further, reconsider the global flag.
These three packages all ship parallel `_esm/*` and `_cjs/*` (or `dist/esm`/`dist/cjs`) directories with mirrored `import`/`default` conditions. Rainbow imports a handful of subpaths directly (e.g. `viem/accounts`) and many more transitively through reservoir-sdk and WalletConnect, so listing each subpath was unworkable. Replace the static map with a prefix-matched override that resolves each request to the package's `default` (CJS) export by reading the package's `package.json` exports field directly. Bypasses Node 22's strict subpath enforcement by joining against the package root rather than re-resolving the subpath through `require.resolve`. Eliminates 22 ESM module duplicates from the production Metro bundle.
Reservoir-sdk's CJS calls `axios.create()` at top-level, which fires the moment reservoir-sdk loads. Axios's exports map gates the browser-safe build behind a `browser` condition that Metro doesn't add on native platforms (only on `web`), so Metro picks `dist/node/axios.cjs` β which `require()`s `http`, `https`, `url`, `stream`, `zlib`, etc. Those Node builtins resolve to undefined-or-stub in the bundle, and their absence cascades into `Cannot read property 'prototype' of undefined` during axios load β manifesting as a launch crash that short-circuits reservoir-sdk's exports and produces the secondary `createClient of undefined` error users see. Pin `axios` to its browser CJS through FORCE_CJS_PACKAGES; the bundle drops from 24 axios deps to 10 (Node builtins eliminated).
β¦N 0.81 `RNFSManager.reject(...)` calls `promise.reject(null, ex.getMessage())` for the generic exception path. RN 0.81's `PromiseImpl.reject(code, message)` is annotated `@NonNull` for `code` and trips a `java.lang.NullPointerException: Parameter specified as non-null is null` the moment it's invoked β currently fires on `unlink` during the wallet-creation flow and crashes the app. Pass an "ERROR" code plus the original throwable instead.
The launch crash root-caused to axios picking its Node CJS entry (which require()s http/https/url/stream/zlib). axios 1.10.0+ added a `react-native` export condition that maps to the browser CJS, so forcing axios to ^1.16.0 via yarn resolutions lets Metro's normal resolver pick the right entry. With axios fixed, the speculative viem/ox/abitype prefix overrides and the reservoir-sdk single-file override are no longer needed. Strip the custom FORCE_CJS_PACKAGES map and the resolveToCjs helper entirely; resolveRequest now just delegates to Metro and falls back through the existing recovery chain. axios in the production bundle is now v1.16.0 from `dist/browser/axios.cjs`, with the Node-only deps eliminated.
The hand-rolled `diff -u` patch didn't include the `diff --git` header that patch-package requires to locate the target file, so CI failed postinstall with "ERROR: Failed to apply patch for package react-native-fs". Re-emit the same one-line edit (RNFSManager.reject null code β "ERROR") in patch-package's expected format (`diff --git a/... b/...` + index + function-context hunk header). Verified against a fresh node_modules install of react-native-fs@2.16.6.
PR #7396 bumped @shopify/flash-list to 1.8.3, which carries the BlankAreaEvent.kt fix our patch was applying. patch-package was already skipping our 1.8.2-named patch because the installed version no longer matches; remove the dead file.
β¦ 0.81 On RN 0.81, an Android TextInput with bold weight and size 18 stops honoring includeFontPadding:false once it has content β measured height jumps from ~28px (placeholder-only) to ~40px (with text), making the Send recipient row reflow as the user types. The placeholder path still respects the flag, so only the populated state regresses. Lock the input to the RN 0.79 measurement (28px β 18px font + ~10px Android ascender/caret padding) so both states render identically.
The fingerprint controls only the native build cache; `rock bundle` runs every CI build and produces a fresh JS bundle regardless. Adding metro.config.js / metro.transform.js / babel.config.js to extraSources doesn't keep stale bundles out of CI β the original "stale APK" symptom that motivated this addition was actually a silent fall-through in the metro resolver after a Node 22 ERR_PACKAGE_PATH_NOT_EXPORTED error, fixed in 96e5f1a. Restore extraSources to the develop state.
iOS:
- Restore OpenInRainbow / ShareWithRainbow Info.plist to develop (last
pod-install run reformatted these from 2-space indent to tabs; pure
whitespace, no semantic change).
- Trim Rainbow/Info.plist back to the single RCTNewArchEnabled=false
addition required by RN 0.81's bundle main info dictionary read in
RCTUtils.mm. Remove four alternate-app-icon entries (baggy, chonks,
mog, redacted) that came in via the local internals prebuild hook
during the same pod-install dance and don't belong in this PR.
Patches:
- Drop patches/react-native-reanimated+3.19.4.patch β package.json now
pins 3.19.5 which ships makeSynchronizable / Synchronizable upstream
(verified in node_modules ReanimatedModuleProxySpec.{cpp,h}).
Patch was already a no-op (filename version mismatch makes
patch-package skip it).
- Drop patches/react-native-animateable-text+0.16.0-beta.0.patch β
package.json now pins 0.17.1, which ships the `children`-allowed
AnimateableTextProps shape upstream (verified in node_modules
src/TextProps.tsx and lib/typescript/src/index.d.ts). Same no-op
status pre-deletion.
Add `# PATCH CONTEXT` headers to the six patches affected by the RN 0.81 work, per the Patch Management RFC. Each header captures Why, Upstream Issue, Linear Issue, and Remove when so the patch is self- documenting and tracking is anchored to a Linear ticket. - react-native+0.81.6.patch β FEPLAT-97 - react-native-fs+2.16.6.patch β FEPLAT-93 - @Shopify+react-native-performance+4.1.2.patch β FEPLAT-94 - expo-linear-gradient+15.0.8.patch β FEPLAT-96 - @react-native-menu+menu+2.0.0.patch β FEPLAT-95 - react-native-animateable-text+0.17.1.patch β FEPLAT-98 (new) The animateable-text patch was deleted in d3b7aff on the assumption that the upstream fix in 0.17.1 was complete. Source was fixed but the published `lib/typescript/src/*.d.ts` still ship the old `Omit<TextProps, "children">` shape, so consumers fail TypeScript with TS2322 on `<AnimatedText>{children}</AnimatedText>` (reproduced by `yarn lint:ci` on src/design-system/components/Text/AnimatedText.tsx). Restore the patch against 0.17.1's distributed types until upstream republishes. ios/Podfile.lock: pick up animateable-text 0.16.0-beta.0 β 0.17.1 (was already bumped in package.json/yarn.lock; lockfile was stale).
The previous patch only updated lib/typescript/src/TextProps.d.ts and AnimateableText.web.d.ts, but `package.json#types` points to lib/typescript/src/index.d.ts β which carries the same un-regenerated `Omit<TextProps, "children">` shape and is what TypeScript actually consumes when resolving the package. Local lint passed only because I had hand-edited that file during exploration; CI hit pristine state and TS2322 stuck. Add the third hunk so all three published .d.ts files are aligned with the upstream source. lint:ts now runs clean against pristine node_modules.
9197129 to
c4aee5c
Compare
|
AI was very eager to reply to you, but basically addressed all issues. |
What changed (plus any additional context for devs)
Upgrades React Native to 0.81.6 (from 0.79.5), React to 19.1.4 (from 19.0.0), Expo SDK to 54 (from 53),
@react-native-community/clito 20.x, and@react-native/babel-preset+metro-configto 0.81.x. Old architecture is preserved βnewArchEnabled=falseon both platforms.Plan doc: Mobile React Native 0.81 Upgrade Plan (Notion).
Native changes
buildToolsVersion,compileSdkVersion,targetSdkVersion: 35 β 36MainApplication.kt: replaceSoLoader.init(...)+ new-archload()conditional withloadReactNative(this)AndroidManifest.xml: addandroid:usesCleartextTraffic="${usesCleartextTraffic}"(cleartext config consolidated into main manifest in the 0.81 template)gradle.properties: addedgeToEdgeEnabled=false(opt-in on old Android, mandatory on API 36)Podfile: remove:hermes_enabledand:new_arch_enabledfromuse_react_native!(no longer accepted by 0.81); pass:new_arch_enabled => falseexplicitly so it doesn't default to trueInfo.plist(per target): addRCTNewArchEnabled=falseβ RN 0.81'sRCTUtils.mmreads it from the bundle main info dictionary at runtime to decide whether to enable the new architectureJS / config changes
metro.config.js:metro-config/src/defaults/exclusionListβmetro-config/private/defaults/exclusionList(with.defaultexport). Dropsunstable_enablePackageExports = falseoverride (now the default).src/debugging/network.js:XHRInterceptormoved fromreact-native/src/private/inspector/toreact-native/src/private/devsupport/devmenu/elementinspector/.package.jsonresolution: pinaxiosto^1.16.0so thereact-nativeexport condition (added in axios 1.10) routes Metro todist/browser/axios.cjsinstead of the Node CJS that requireshttp/https/stream/etc. Without it, reservoir-sdk's top-levelaxios.create()crashes Hermes on launch withCannot read property 'prototype' of undefined.Patches
react-native+0.79.5.patchβreact-native+0.81.6.patch: accessibility-label nil-check was upstreamed in 0.81 and is dropped. Only thecornerCurve = kCACornerCurveContinuousfix inRCTView.mremains (targeting the old-arch ObjC path).expo-linear-gradient+14.1.5.patchβexpo-linear-gradient+15.0.8.patch: same 1-line Display P3 color-space change, renamed for the new version (content applies cleanly).@react-native-menu+menu+1.2.3.patchβ@react-native-menu+menu+2.0.0.patch: same Android dismiss/disabled/modal-tracking patch, renamed for the new version.patches/@shopify+react-native-performance+4.1.2.patchadds an override-return-type fix forgetExportedCustomDirectEventTypeConstants(MutableMapβMapin 0.81).patches/react-native-fs+2.16.6.patchβRNFSManager.unlink'sPromise.reject(null, β¦)trips RN 0.81's@NonNull codeannotation; pass"ERROR"instead.patches/react-native-animateable-text+0.16.0-beta.0.patchβpatches/react-native-animateable-text+0.17.1.patch. The runtime fix is upstream in 0.17.1's source but the publishedlib/typescript/src/*.d.tsfiles weren't regenerated and still carryOmit<TextProps, "children">. Patch updates the two distributed.d.tsfiles so TypeScript stops failing on<AnimatedText>{children}</AnimatedText>.patches/react-native-reanimated+3.19.4.patchβ themakeSynchronizable/Synchronizableadditions are upstream in 3.19.5.All six patches affected by this PR have a
# PATCH CONTEXTheader (per Ivan's Patch Management RFC) with Why / Upstream Issue / Linear Issue / Remove when, anchored to FEPLAT tickets:react-native+0.81.6.patchβ FEPLAT-97react-native-fs+2.16.6.patchβ FEPLAT-93 (migrate to expo-file-system; draft PR #7428)@shopify+react-native-performance+4.1.2.patchβ FEPLAT-94 (deprecated lib; replacement PoCs #7424 and #7426)expo-linear-gradient+15.0.8.patchβ FEPLAT-96@react-native-menu+menu+2.0.0.patchβ FEPLAT-95react-native-animateable-text+0.17.1.patchβ FEPLAT-98Out of scope
react-native-reanimatedis bumped to 3.19.5 (last 3.x release that still supports the old architecture; v4 is new-arch only).react-native-webviewalready migrated to the rainbow fork in #7314, which tracks 13.16.x with RN 0.81 compatibility.react-native-svg(15.15.4) andreact-native-gesture-handler(2.31.1) are already above Expo 54's pinned versions β no action needed.Screen recordings / screenshots
TODO: add after running builds locally.
What to test
bundle exec pod installinios/succeeds, app builds and launches on a simulator.yarn android), launches, and basic navigation works (predictive back gesture is opt-in by default on API 36 viaedgeToEdgeEnabled=false).yarn start:cleanand reload the app.XHRInterceptorimport path moved).RNFSManager.unlink(the patched code path).<AnimatedText>{children}</AnimatedText>type-checks (yarn lint:ci).