Repository navigation
Auto-detect TurboModules on the New Architecture #6898
Copy link
Copy link
Open
Labels
Description
turboModuleContextIntegration is on by default (enableNative), but on the New Architecture it only wraps RNSentry, which is in ignoreTurboModules by default. The default setup therefore records no statistics, span attributes, or slow-call breadcrumbs, and crash context only covers crashes during the SDK's own calls. To get data, users have to list every module in modules: [...].
Current behavior
- Verified in the RN sample (iOS, New Architecture, RN 0.87.1): the TurboModule Playground span has all
turbo_module.*attributes when the sample's modules are passed inmodules, and none with the defaultturboModuleContextIntegration(). - Automatic instrumentation exists only on the Old Architecture (
enableLegacyNativeModules: true), which is gone as of RN 0.82. The automatic path is on the architecture apps are leaving; the manual path is on the one they're moving to.
Why manual registration falls short
- Third-party libraries resolve their modules internally, so users usually don't have the module objects to pass in.
- Libraries that copy methods out at import time (
const { foo } = NativeX) keep the unwrapped functions. - The JS wrapper writes the
turbo_modulecontext and two tags to the scope at the start and end of every call. With scope sync on, each write is a native call (scopeSync.ts), so each instrumented call costs about 6 extra native calls.
RN 0.87 module resolution constraints
- Bridgeless mode (the default) has no
global.__turboModuleProxy;TurboModuleRegistry.get()falls back toNativeModules[name], which reads from the read-onlyglobal.nativeModuleProxy. getModule()caches one JS object per module name, so in-place wrapping reaches other users of the same module, but the cache is a weak reference, so a wrapper must hold strong references.- JS can't enumerate registered modules, and calling
geton every name would eagerly load all modules (some with side effects). - Libraries usually look up their module at import time, before
Sentry.init.
Proposed direction (from team discussion)
- Options considered: patching
TurboModuleRegistry.get/getEnforcingat init (misses lookups before init, not recommended), a Metro resolver redirect viawithSentryConfig(skipped: depends on RN internal paths, keeps JS per-call overhead, misses JSI host objects), and nativeTurboModulePerfLog. - Aleksandr Pantiukhov favors the native
TurboModulePerfLogroute, since it builds on the existingSentryTurboModulePerfSink.hsink interface and needs no new install path. Prior work: WireTurboModulePerfLoggeron iOS and Android #6162. - Native crash attribution can be tracked separately with the Cocoa and Java SDK teams; the rest of the work doesn't depend on it.
Raised by Antonis Lilis while reviewing the docs (getsentry/sentry-docs#19949) and changelog (getsentry/sentry-changelog#224) PRs. Related GitHub issue for the Linear bug: #6886; Linear RN-824.
via Antonis Lilis.
--
Reactions are currently unavailable
Activity
linear-code commentedon Oct 16, 2026
RN-829