Skip to content

fix(ffi/objc): key thread_local bridge caches by a per-bridge id - #81

Merged
ammarahm-ed merged 1 commit into
android-react-nativefrom
fix/objc-bridge-cache-ids
Oct 25, 2026
Merged

ammarahm-ed merged 1 commit into
android-react-nativefrom
fix/objc-bridge-cache-ids

Conversation

@NathanWalker

Copy link
Copy Markdown
Contributor

Split out of #77.

Summary

The thread_local lookup caches in ObjCBridge.mm (property getters, round-trip values, object expandos) identified a bridge by its address. After a JS reload, a new NativeApiBridge can be allocated where a destroyed one lived and match its stale entries. The property-getter cache then returns a raw pointer into the freed bridge, and cached misses can hide values that exist.

 struct PropertyGetterCacheEntry {
-  const NativeApiBridge* bridge;   // reused address matches stale entries
+  uint64_t bridgeId;               // process-unique per bridge, never reused
   ...

The same change is made in all three caches. The napi ObjC tree (NativeScript/ffi/objc/napi) has no bridge-keyed caches, so it needs no change.

Evidence

iOS 26.5 simulator, Debug, RN 0.86.3 / Expo. Tested in #77 together with the bridge-teardown change, which is now a separate PR.

  • Before: EXC_BAD_ACCESS in preparedObjCInvocationIsInit on the launch after a reload, once the new bridge was allocated at the old one's address.
  • After: four reloads in a row with no crash reports.

Merge Danger

Door: two-way

Blast Radius: ObjC bridge lookup caches

The id is an atomic counter, so the only behaviour change is that stale entries never match.

The property-getter, round-trip and expando lookup caches identified a
bridge by its address. After a JS reload a new bridge can be allocated
where a destroyed one lived and match its entries: the getter cache then
returned a raw pointer into the freed bridge (EXC_BAD_ACCESS in
preparedObjCInvocationIsInit on the next launch), and cached misses
could hide values that exist.
@coderabbitai

coderabbitai Bot commented Oct 24, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f57ca323-6e2f-4bf3-a544-8e2c8461f9f6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ammarahm-ed
ammarahm-ed merged commit 066a38e into android-react-native Oct 25, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants