Repository navigation
chore(mobile): React Native 0.81.6 (old arch) - #14642
Conversation
|
|
Dependency limit exceeded — report not shown. This pull request scan exceeded the 10,000-dependency limit applied to this scan, so the results are incomplete and may be inaccurate. To avoid reporting false positives, Socket has not posted a report. Upgrade your plan to raise the dependency limit and get complete reports, or view the partial scan in the dashboard. Socket is always free for open source. If this is a non-commercial open source project, contact us to request a free Team account. |
|
Heads-up from #14643: the Hermes For this branch, once #14643 merges:
|
…ground (#14644) ## Problem Signed-in mobile builds log this every time the app comes to the foreground: ``` [SyntaxError: JSON Parse error: Unexpected character: <] ``` It shows up on Android 16 (RN 0.79.5), the 1.5.186 RC on a Saga (Android 14), and iOS 26.5 (RN 0.81.6, #14642), so it isn't tied to the RN version. ## Cause `useResetNotificationBadgeCount` runs on every foreground. It calls `audiusBackend.clearNotificationBadges`, which POSTs to `identityservice.audius.co/notifications/clear_badges` and then calls `.json()` on the response. #14207 removed that route from identity-service on 2026-04-30, so Express now returns its HTML 404 page: ``` $ curl -X POST https://identityservice.audius.co/notifications/clear_badges <!DOCTYPE html> ... <pre>Cannot POST /notifications/clear_badges</pre> -> 404 text/html ``` The `catch` passes the bare error to `console.error`, which produces the log line above. ## Evidence I foregrounded the signed-in iOS 26.5 release build on a simulator and read CFNetwork logs from the unified log: ``` 22:28:43.627 [C530 ... url: https://identityservice.audius.co/notifications/clear_badges] 22:28:43.629 Task <4088> setting up Connection 530 22:28:43.793 Task <4088> received response, status 404 22:28:43.795 [com.facebook.react.log:javascript] [SyntaxError: JSON Parse error: Unexpected character: <] ``` Both earlier occurrences that session (17:17:04 and 17:18:05) were also a 404 from identity, 2 ms before the error. Each one came right after UIKit cleared the app's deactivation reasons. On iOS, `useEnterForeground` also fires on `inactive -> active` (Control Center, the notification shade, the app switcher), so the "about once a minute" pattern was how often the app was re-activated, not a timer. In the same session, a process that stayed in the foreground for 5 hours made no 404s and logged no errors. `clear_badges` is the only identity route in `AudiusBackend` that no longer exists. I checked every other path it calls against `identity-service/src/routes`. ## Fix - Remove the dead `clear_badges` request and `audiusBackend.clearNotificationBadges`. It had no other callers. - Keep clearing the local badge (`PushNotifications.setBadgeCount(0)`) on foreground. The server-side `PushNotificationBadgeCounts.iosBadgeCount` is now reset to 0 by pedalboard's `notification_seen` listener (`apps/notifications/src/notificationSeenListener.ts`) when notifications are marked seen. This PR doesn't change server behaviour: the reset on app open has already been gone since #14207. ## Testing - ESLint passes on the changed files. `tsc` shows no errors in the changed files. - I did not rebuild the app to watch the log line disappear. The request is removed outright, and the repro above was deterministic. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…14643) ## What the patch does #13609 added a fix to React Native's `Libraries/Core/ExceptionsManager.js`. It adds a `getErrorStackSafe()` helper that reads `.stack` inside a try/catch, and returns it only when it's a string. The helper replaces the three places where the exception handler reads `.stack` directly: - `parseErrorStack(e?.stack)` in `reportException` - `rawStack: e.stack` in `reportException` - `if (firstArg?.stack)` in `reactConsoleErrorHandler` On Hermes, reading `.stack` on a value that inherits from `Error` in the legacy way (`Foo.prototype = new Error()`) throws `Error.stack getter called with an invalid receiver`. When that happens inside the global exception handler, the original error gets lost and the handler throws again. See react/react-native#43636 and facebook/hermes#1496. ## Why it never applied `packages/mobile/scripts/patch-react-native-exceptions.js` looked for `packages/mobile/node_modules/react-native/...`. npm hoists react-native to the root `node_modules` (it's in the root of `package-lock.json` on both 0.79.5 and 0.81.6). When the file wasn't found, the script ran `process.exit(0)`, so postinstall printed "Patching React Native ExceptionsManager" and changed nothing. On main the installed `ExceptionsManager.js` is byte-identical to the npm tarball, so this fix has never shipped. ## Fix - Moved the same edits into `patches/react-native+0.79.5.patch`. - Deleted the custom script and its block in `scripts/postinstall.sh`. `scripts/patch-package.sh` already runs root patches with `--error-on-fail`. So if react-native stops being installed at the root, or an RN upgrade changes the lines being replaced, `npm install` / postinstall now fails instead of silently doing nothing. The diff is identical to the old script's output, generated from a pristine 0.79.5 tarball. ## RN 0.81 (#14642) All four anchor lines are unchanged in 0.81.6. This patch applies cleanly to 0.81.6 (output byte-identical to a patch generated against 0.81.6), with patch-package's version-mismatch warning only. The upgrade PR should rename it to `react-native+0.81.6.patch` once this lands. ## Verification - patch-package 6.5.1 in a scratch project: - applies to pristine 0.79.5 and to 0.81.6, exit 0 - exits 1 when react-native is missing from `node_modules/` - exits 1 when a replaced line has changed (simulated drift) - `bash scripts/patch-package.sh` in a worktree with cloned `node_modules`: - every patch reports ✔, exit 0 - a second run (the CI cache-hit path, which reruns postinstall) also exits 0 - The patched file parses with hermes-parser. - The patched file compiles with `@react-native/babel-preset`; the output contains the helper and its 3 call sites. - No native build. This is a JS-only change that Metro bundles, so it ships in the next build or OTA. Behavior change to note: this is the first time the fix ships. `rawStack` and the `firstArg` check now treat a non-string `.stack` as absent. Before, they passed it through or treated it as truthy. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
Note for the upgrade: #14643 (merged) adds |
- react-native 0.80.3, @react-native/* 0.80.3, community CLI 19.1.2 - React 19.1.0 across the monorepo. The 0.80.3 renderer throws unless react is exactly 19.1.0. - @amplitude/analytics-react-native 1.4.14: Kotlin 2.1 rejects the deprecated toUpperCase in 1.4.11 - patch track-player and tiktok-opensdk for Kotlin 2.1 / RN 0.80 nullability; pin tiktok-opensdk to 0.10.7 so the patch keeps applying - Android template: Kotlin 2.1.20, Gradle 8.14.1, loadReactNative - Info.plist: RCTNewArchEnabled=false, which 0.80 reads at runtime - replace react-native/types deep imports Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- react-native 0.81.6, @react-native/* 0.81.6, community CLI 20.1.3 - React 19.1.4 across the monorepo; the 0.81.6 renderer requires exactly 19.1.4 - react-native-gesture-handler 2.28.0, the first 2.x release that supports 0.81 - Android template: Gradle 8.14.3, edgeToEdgeEnabled=false, and drop suppressUnsupportedCompileSdk now that AGP 8.11 supports API 36 - resolve @react-native/gradle-plugin through react-native, since npm nests it under react-native in this lockfile - type fixes for the TextInput blur event and the ExternalLink spread Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
85c816a to
892c19d
Compare
…14647) Prepares react-native-track-player 4.1.2 (Apache-2.0) for the new architecture. It ships with 1.5.188 on the old architecture, where it changes nothing. **Base: `chore/mobile-rn-0.81` (#14642).** Rebased 2026-10-08 after #14642 moved onto the 1.5.188 release branch (#14654). Merge #14652 into this branch first, then this into #14642. Don't merge to main on its own. We are staying on RNTP 4.1.2. v5 (`@rntp/player`) is commercially licensed. 4.1.2 is the last 4.x release, and the fixes below were never published for it. ## Changes (Android only, in `patches/react-native-track-player+4.1.2.patch`) **1. Event emission in bridgeless mode** (doublesymmetry/react-native-track-player#2593, #2619) - `MusicService.emit()` / `emitList()` read the context from `reactNativeHost.reactInstanceManager.currentReactContext`. That is null in bridgeless mode, so every native-to-JS event was dropped: playback state, active track, remote/notification controls, progress and errors. - They now use the `reactContext` getter that `HeadlessJsTaskService` already provides. It returns `ReactInstanceManager.currentReactContext` on the old architecture (the same call as before) and `ReactHost.currentReactContext` in bridgeless mode. - That getter throws if `ReactHost` is null. Emission, `startTask` in `onStartCommand`, and `super.onDestroy()` now log and carry on instead of crashing the service. This is the same approach as upstream's fix for #2619 (ed52dc5, v5 line). **2. `@ReactMethod`s return `Unit`** - Every `TrackPlayerModule` method was written as `fun play(callback: Promise) = scope.launch { ... }`, so each one returned a `Job`. - The bridgeless TurboModule interop layer rejects a non-void return on an async method, so it threw while loading the module: > Unable to parse @ReactMethod annotations from native module: TrackPlayerModule On the new architecture the app aborted at startup (found in the spike, #14648). - They are now `fun play(callback: Promise) { scope.launch { ... } }`. The old bridge ignored the return value, so nothing changes there. The diff touches only the first and last line of each of the 37 methods. **Not applicable to 4.1.2:** - #2670 (`BackgroundServiceStartNotAllowedException` while emitting in the background) and #2662 (Android Auto cold start never starting the headless task) are v5 issues. In v5, emitting an event starts a `TrackPlayerTaskService`. In 4.1.2, `emit` never starts a service, and `onStartCommand` already calls `startTask`, which creates the React host when there is none. That cold path was checked on the new architecture in the spike. - iOS needs no change. The Swift `RCTEventEmitter` module works through the interop layer as it is. ## Verification (old architecture, `prodRelease` arm64 signed with the debug keystore, Android 16 emulator) I tested with a temporary JS harness that was not committed. It wraps the root component, logs every RNTP event with `console.warn` (visible in logcat) and in an on-screen overlay, queues 3 public tracks, seeks, and then seeks near the end. Signed out, `pm clear` before each launch, and logcat confirmed `Loading JS bundle from "assets://index.android.bundle"`. | Check | Result | |---|---| | Release build | ✅ | | Runtime arch | ✅ `bridgeless:false, fabric:false`, "Legacy Architecture" warning | | `PlaybackState` / `PlaybackActiveTrackChanged` reach JS | ✅ stopped → loading → buffering → ready → playing, `index:0` | | Seek | ✅ `seekTo(60)` → position 60–62.8 | | Auto-advance | ✅ `active-track-changed` 0 → 1 at the end of track 0, `getActiveTrackIndex()` = 1 | | `adb shell cmd media_session dispatch pause/play/next` | ✅ `remote-pause` / `remote-play` / `remote-next` reach JS, and the state follows | | Notification shade pause / play / previous | ✅ `remote-pause`, `remote-play`, `remote-previous` reach JS | | Screen off and backgrounded for 75 s | ✅ progress events kept arriving, MediaSession `PLAYING` | | iOS Release (old arch, 26.5 sim) | ✅ unchanged: events, seek and auto-advance all work | The same harness on the new architecture is in the spike PR. ## Still needs a real device Lock-screen and notification controls, Bluetooth, and background playback for more than 2 minutes, together with the rest of the 1.5.188 checklist in #14642. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ver (#14651) Moves the play bar tracker, the now playing scrubber and the track-list eq bars off JS-driven `Animated` and onto the native driver. JS-only, so it can ship as an OTA. ## Why All three used `useNativeDriver: false`, so every frame ran in JS and committed through `setNativeProps`. On old arch that's cheap. On the new architecture each one is a full `ShadowTree::commit`, and Reanimated 3's commit hook clones the tree on every commit. It was half of the CPU regression in #14648 (blocker 6): playing with the drawer open went from ~15% to ~50%. ## What changed - `animateLinear` in `utils/animation.ts` runs a long linear animation as 10 s native-driver segments. The native driver precomputes one frame per 16 ms, which is why the old code avoided it for track-length animations (the old comment about Hermes). Each segment starts from the wall-clock position, so the bar can't drift after the app is backgrounded. - `TrackingBar` and `Slider` use it with the start position passed in explicitly (from `seek` or `TrackPlayer.getProgress()`), instead of continuing from whatever the JS value was. Seeking, dragging and pausing behave the same. The scrubber's 100 ms tap-to-seek timing moved to the native driver too, because a value can't mix drivers. Both stop the chain on unmount. - `AnimatedEqBars` animated `height`, which the native driver can't do. Each bar is now a full-height bar slid down with `translateY` inside a clip view with the same 2 px radius. The visible shape at every height matches the old one (rounded top from the bar, rounded bottom from the clip). ## Base **Base: `chore/mobile-rn-0.81` (#14642), shipping in native release 1.5.188 (#14654).** Rebased 2026-10-08 after #14642 moved onto the release branch. Merge this into #14642, not main. The svg `LinearGradient` it imports is on main since 1.5.187, so it no longer depends on #14642's code, but it ships with 1.5.188 so the new native-driver animations get device-tested on the RC builds. It doesn't overlap the iOS queue fix (#14649, on main): that change is in `AudioPlayer.tsx` and `addTracksAroundCurrent.ts`, which this PR doesn't touch. ## Measurements (iOS 26.5 simulator, Release, signed in, 30 s `top` averages) | Scenario | Old arch before → after | New arch before → after | |---|---|---| | Feed, playing | 17.1% → 12.9% | 50.4% → 15.3% | | Now playing drawer open, playing | 15.3% → 13.7% | 50.6% → 15.6% | | Background, playing | 9.5% → 12.2% | 12.2% → 14.5% | New-arch "after" also includes #14648's svg and Lottie fixes, which don't affect these screens. Old-arch "after" is the #14642 Release app with this branch's JS bundle swapped in. ## Testing - Simulator, both architectures: the bar and the scrubber advance at the right rate on a 56-minute and a 3-minute track. Tap-to-seek to the middle lands at 28:02 and keeps going. The play bar is at the right position after 30 s in the background. - `tsc` and `eslint` clean on the changed files. - Not checked by eye: the eq bars. In album track lists, the `TrackImage` children (eq bars, play icon overlay) don't show on either architecture, before or after this change. That looks like an existing bug and is out of scope here. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
e5f2984
into
chore/mobile-native-release-1.5.188
## Summary Version bump for native release **1.5.188**. Merging it starts the RC and production native builds. - `packages/mobile/package.json`: 1.5.187 → 1.5.188 (and the matching `package-lock.json` entry) - iOS `CFBundleShortVersionString`: 1.1.200 → 1.1.201 - Android `versionName`: 1.1.536 → 1.1.537 1.5.188 contains (all still on the old architecture): - #14642: React Native 0.79.5 → 0.81.6, React 19.1.4 monorepo-wide - #14647: RNTP 4.1.2 patch for bridgeless events and `Unit` module methods (no change on old arch) - #14651: playback progress and eq bars on the native driver - #14652: react-native-svg 15.15.1 and the Lottie `shouldBeRecycled NO` patch (no change on old arch) 1.5.189 is then only the new-architecture flag flip. ## Stack ``` main └── chore/mobile-native-release-1.5.188 (this PR) └── chore/mobile-rn-0.81 #14642 ├── fix/mobile-rntp-bridgeless #14647 │ └── fix/mobile-new-arch-prereqs #14652 └── fix/mobile-native-driver-progress #14651 ``` ## Verification of the rebased stack (2026-10-08) Built from a local, unpushed integration branch: #14652's tip (which contains #14647) merged with #14651, on top of #14654. | Check | Result | |---|---| | `npx tsc --noEmit -p packages/mobile` | pass | | eslint on the touched files / `turbo run verify` lint | pass (1 existing warning in `HostRemixContestDrawer.tsx`) | | `cd packages/mobile && npm test` | 9 suites, 34 tests pass | | iOS Release, `generic/platform=iOS Simulator`, arm64, `ENVFILE=.env.prod` | builds; Info.plist 1.1.201, `RCTNewArchEnabled=false`; bundle carries 1.5.188 | | Android `assembleProdRelease`, arm64-v8a, debug keystore | builds; versionName 1.1.537 | | iOS 26.5 sim, installed over the signed-in app, CodePush moved aside | launch to feed; JS thread `com.facebook.react.JavaScript` (old arch) | | Playback from the 2nd feed track | plays; play bar tracker moves | | Auto-advance | seek to 2:43/2:45 on track 2, advanced to track 3 | | Now playing drawer | opens, scrubber advances, tap-to-seek works | | Profile tabs | swipe Tracks → Albums, tap Reposts | | notifee/RNFB APNs token | a temporary console log (not committed, rebuilt without it afterwards) printed an 80-byte lowercase APNs token at startup | | Android 16 emulator, `pm clear` | `Loading JS bundle from "assets://index.android.bundle"`, "Legacy Architecture" warning, sign-up and sign-in screens render | | Android hardware Back | **not verified**: the emulator's system_server was killed by its watchdog three times under host load, so Back never got a clean run | | JS errors on iOS | only `Could not cache profile images` (content node timeout) | ## Merge order 1. **Wait until 1.5.187 is live in both stores.** Until then, any native change on main would go into a 1.5.187 rebuild. 2. **Dispatch a production OTA from main before merging anything below**, for every store version that can run main's JS: ``` gh workflow run mobile.yml --repo AudiusProject/apps --ref main -f ota_channel=production ``` With main at 1.5.187 this publishes to `production/1.5.187`. **Do not** dispatch `-f binary_version=1.5.186` or `1.5.185` from main any more: main now carries #14627, which calls `TurboModuleRegistry.getEnforcing('ReactNativeFs')` at import, so that JS crashes 1.5.186 and older binaries. If 1.5.186 users still need a fix, dispatch from a commit before 5c4ee7e. 3. **Land everything on main in one push.** Merge the stack into this branch from the top down: #14652 into #14647, #14647 and #14651 into #14642, #14642 into this branch. Then merge this PR into main. Any push to main that leaves the version unchanged publishes an RC OTA to the current binary's history, and RN 0.81 JS on a 0.79 binary will not start. With one push that also changes the version, the version check skips the OTA and starts the native builds. After that, OTAs route to `1.5.188` histories. 4. **Device-test the RC builds before submitting:** - cold launch on both platforms, old arch at runtime (iOS JS thread `com.facebook.react.JavaScript`; Android "Legacy Architecture" warning) - background audio with the screen locked for more than 2 minutes - lock-screen and notification controls, Bluetooth, Chromecast - auto-advance, including starting from the 2nd track of a list (#14649/#14650) - play bar and scrubber position: seek, drag, pause/resume, background then foreground - first play does not pause itself (Lottie) - push: token registered after the 1.5.187 → 1.5.188 update and taps open the right screen (#14640) - Android hardware Back on a pushed screen and at the root - gradients and offline downloads 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Phase 1 of the React Native upgrade: 0.79.5 → 0.81.6 with the old architecture still on.
Base:
chore/mobile-native-release-1.5.188(#14654). Rebased onto it after 1.5.187 (#14645, which squashed #14627, #14640 and #14650) merged to main; the two lib-swap commits are gone from this branch. Merge #14647 and #14651 into this branch first, then this into #14654, then #14654 into main as one push (see #14654 for the full order).Rebase onto 1.5.187 (2026-10-08)
patches/react-native+0.79.5.patch(the ExceptionsManager Hermes fix from fix(mobile): apply RN ExceptionsManager Hermes fix via patch-package #14643) is renamed toreact-native+0.81.6.patch. The anchors are unchanged in 0.81.6, andscripts/patch-package.shapplies it with--error-on-failduringnpm install(checked:getErrorStackSafeis in the installedExceptionsManager.js).@notifee/react-native9.1.8 is the latest release and@react-native-firebase/app/messaging24.1.1 build on 0.81.6 on the old arch (both declarereact-native: *). No bump needed.AppDelegate.mm(feat(mobile): adopt UIScene lifecycle on iOS #14626, feat(mobile): move push notifications to notifee + firebase messaging #14640) are untouched by this branch.package-lock.jsonandPodfile.lockwere regenerated (npm install, thenRCT_NEW_ARCH_ENABLED=0 bundle exec pod install); the release xcconfig has noRCT_NEW_ARCH_ENABLED=1. The SwiftAudioEx post_install patch (fix(mobile): patch SwiftAudioEx insert index for one-item queues #14650) still applies.Needs a native release (1.5.188). Don't OTA this JS onto older binaries. Old architecture stays on: Android
newArchEnabled=false, iOSRCTNewArchEnabled=false, pods installed withRCT_NEW_ARCH_ENABLED=0.Two commits, one per step. Each step builds on iOS and Android:
Version bumps
@react-native/*(babel-preset, eslint-config, metro-config, metro-babel-transformer, typescript-config)@react-native-community/cli,cli-platform-android,cli-platform-iosoverridestoo)reactis exactly its version: 19.1.0 for 0.80.3, 19.1.4 for 0.81.6. The old ladder branch used 19.1.8, which would throw "Incompatible React versions" on launch.toUpperCase(Locale)in 1.4.11 into a compile errorhandleOpenURL/handleUserActivitydeclarations that SceneDelegate importsPatches added (
patches/):react-native-track-player+4.1.2.patch: Kotlin 2.1 rejectsArguments.fromBundle(Bundle?). Now resolvesnullwhen there is no item. 4.1.2 is the last 4.x and has no fixed release.tiktok-opensdk-react-native+0.10.7.patch:onNewIntent(intent: Intent)(RN 0.80 madeActivityEventListenernon-null) andreactApplicationContext.currentActivity.Checked against 0.81 on the old architecture and left alone: Reanimated 3.19.5 (the official table lists 3.19.x for 0.78–0.81 on Paper; Reanimated 4 is out of scope), track-player 4.1.2 (patched above), collapsible-tab-view 8.0.1 (JS only), screens 4.18.0 (0.81 support since 4.14;
react-native-screens+4.18.0.patchstill applies; 4.25+ drops the old arch), pager-view 6.7.1 (7+ drops the old arch), video 6.18.0, svg 15.15.0 (0.81 support since 15.12.1), google-cast 4.6.2 (5.x is new-arch only), notifications 5.1.0, code-push 12.3.2 (README lists 0.77–0.86; 13.x needs a new OTA history), bootsplash 6.3.11, safe-area-context 5.6.2, keyboard-controller 1.19.0, flash-list 1.8.3, datetimepicker 8.3.0 (builds against 0.81.6).Template changes (rn-diff-purge 0.79.5 → 0.81.6)
gradlew/gradlew.bat/wrapper jar,MainApplicationusesloadReactNative(this)in place ofSoLoader.initplusload(), andedgeToEdgeEnabled=falseis added as in the template. The app already draws edge-to-edge through react-native-bars and the SDK 36 target, so this flag changes nothing.android.suppressUnsupportedCompileSdk=36is removed.settings.gradleresolves@react-native/gradle-pluginthroughrequire.resolvefromreact-native, not a hard-coded hoisted path. With this lockfile npm nests it undernode_modules/react-native/node_modules.newArchEnabled=false, theAudiusScryptmodule (ScryptPackageis still registered), the debug manifest (it addsSYSTEM_ALERT_WINDOW), andandroid:enableOnBackInvokedCallback="false".ReactActivityregisters anOnBackPressedCallbackwhen targetSdk ≥ 36, which callsonBackPressed()→ JSBackHandler. OurinvokeDefaultOnBackPressedoverride (moveTaskToBack) still runs. The manifest opt-out is kept as asked and can probably go in a later release.Info.plistandRichPushExtension/Info.plistnow setRCTNewArchEnabled=false, which RN 0.80+ reads at runtime; a missing key means new arch.pod installwrites the key and re-sorts the plist each time, so the sorted version is committed.AppDelegate / UIScene
No code change needed.
RCTAppDelegateis marked deprecated in 0.81 in favour ofRCTReactNativeFactory, so there is a-Wdeprecated-declarationswarning, but every API we use is unchanged:automaticallyLoadReactNativeWindow,rootViewFactory,createRootViewController,setRootView:toRootViewController:,customizeRootView:,bundleURL, anddependencyProvider.didFinishLaunchingstill creates the factory and skips the window. Moving toRCTReactNativeFactorycan wait for the 0.82+ phase.Verified on a Release build: cold launch, a deep link while killed, and a deep link while backgrounded, on iOS 26.5 and iOS 27. iOS 27 needs UIScene and showed no launch crash.
Web / React 19.1
vite build(prod env): succeeds.TrackTile › Public Premium (non-owner)timed out once while the machine was under heavy load, then passed 3 out of 3 when run alone.Verification matrix (before the rebase; see the bottom for the rebased stack)
generic/platform=iOS Simulatorcom.facebook.react.JavaScriptReactRootView+ "Legacy Architecture" warningassets://index.android.bundleaudius://audiusaudius://deadmau5JSON Parse error: Unexpected character: <(not yet traced)The CodePush folder was moved aside or cleared before every cold launch, so all results above are from the bundled JS.
Still needs a real device
Notes
ExceptionsManagerfix now applies through patch-package (fix(mobile): apply RN ExceptionsManager Hermes fix via patch-package #14643), renamed for 0.81.6 above.Verification of the rebased stack (2026-10-08)
Built from a local, unpushed integration branch: #14652's tip (which contains #14647) merged with #14651, on top of #14654.
npx tsc --noEmit -p packages/mobileturbo run verifylintHostRemixContestDrawer.tsx)cd packages/mobile && npm testgeneric/platform=iOS Simulator, arm64,ENVFILE=.env.prodRCTNewArchEnabled=false; bundle carries 1.5.188assembleProdRelease, arm64-v8a, debug keystorecom.facebook.react.JavaScript(old arch)pm clearLoading JS bundle from "assets://index.android.bundle", "Legacy Architecture" warning, sign-up and sign-in screens renderCould not cache profile images(content node timeout)🤖 Generated with Claude Code