Skip to content

fix(ios): Keep manual time to display working without legacy interop - #7015

Closed
antonis wants to merge 5 commits into
mainfrom
fix/ios-ondraw-reporter-without-interop
Closed

antonis wants to merge 5 commits into
mainfrom
fix/ios-ondraw-reporter-without-interop

Conversation

@antonis

@antonis antonis commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

Keeps <Sentry.TimeToInitialDisplay> and <Sentry.TimeToFullDisplay> working on iOS when an app builds React Native with RCT_REMOVE_LEGACY_COMPONENT_INTEROP=1.

The Fabric registration is only compiled in under that flag. In JS, the static view config is used whenever React Native doesn't expose its legacy interop view config. That covers apps with the flag on, and may also include custom hosts that start RCTHost directly or override the feature flag, even though they keep interop. Standard apps stay on the existing path.

  • RNSentryOnDrawReporterComponentView (new, New Architecture only): a thin Fabric adapter that forwards props to the existing RNSentryOnDrawReporterView, so the timing logic is unchanged. It registers itself in +load, only under #ifdef RCT_REMOVE_LEGACY_COMPONENT_INTEROP. It is deliberately not in ios.componentProvider, because React Native prefers that over interop for every build.
  • timetodisplaynative.tsx: keeps requireNativeComponent while React Native has a native view config. It only uses a static view config when RN$LegacyInterop_UIManager_getConstants is absent.
  • RNSentryOnDrawReporterNativeComponent.ts (new): the codegen spec.
  • react-native.config.js: lists the Android componentDescriptors explicitly so autolinking skips this component. excludedPlatforms only removes the generated Java classes, so without this Android would move off interop too.

💡 Motivation and Context

Refs #7014

The reporter is a legacy RCTViewManager, so on the New Architecture it only exists through React Native's interop layer. With the flag on it isn't registered, and the components silently fall back to a plain View. The flag is opt-in since RN 0.88, and RN says it will become the default in a future release.

This doesn't close #7014: with both RCT_REMOVE_LEGACY_COMPONENT_INTEROP and RCT_REMOVE_LEGACY_MODULE_INTEROP, the RNSentry module itself doesn't load. See Next steps.

💚 How did you test it?

samples/react-native on RN 0.88.1, Release, with RN compiled from source on iOS (RCT_USE_PREBUILT_RNCORE=0), navigating through the Errors, Performance and Tracker screens. iOS ran on an iPhone 16 Pro simulator and Android on a Pixel 8 emulator (API 37).

Build Reporter registered Tracker initial display Tracker full display Sentry
iOS, flag on, fix disabled No auto.ui.time_to_display, 582 ms Missing trace
iOS, flag on, this PR Yes manual.ui.time_to_display, 49 ms 2083 ms trace
iOS, default, this PR Yes manual.ui.time_to_display, 48 ms 2066 ms trace
Android, default, this PR Yes manual.ui.time_to_display, 71 ms 2130 ms trace

"Fix disabled" is this PR with the +load registration compiled out. The Android autolinking output lists only the Mask and Unmask descriptors, so this component stays on interop there.

Unit tests cover the view config selection: Old Architecture, interop available, interop removed, and component not registered. Type check, lint, API report and circular dependency checks pass locally.

Not verified yet:

  • RN's prebuilt framework and SwiftPM with the flag on.
  • Older New Architecture releases. The new .mm and generated code compile for every New Architecture build, and CI's only older RN jobs (0.71) are Old Architecture.
  • Custom hosts that use the static view config while keeping interop.
  • There is no native unit test for the adapter's empty parentSpanId mapping or recycling.

📝 Checklist

  • I added tests to verify changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • All tests passing.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.
  • No breaking changes.

🔮 Next steps

  • Handle RCT_REMOVE_LEGACY_MODULE_INTEROP. A plain modulesProvider entry crashes at launch, because RNSentry doesn't declare NativeRNSentrySpec conformance and React Native then treats it as a C++ module. Declaring conformance under that flag is the likely fix, separately from this PR.
  • Add a CI build with the flag on, since this path only runs for apps that opt in.
  • If React Native removes the macro along with interop, this registration needs a follow-up before then.

🤖 Generated with Claude Code

antonis and others added 2 commits November 10, 2026 15:39
RNSentryOnDrawReporter is a legacy view manager, so React Native drops it
when RCT_REMOVE_LEGACY_COMPONENT_INTEROP is set, and the TTID and TTFD
components silently fall back to a plain View.

Add a Fabric component that is only registered under that flag, and use a
static view config only when React Native has no interop view config.
Other builds stay on the existing path.

Refs #7014

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

⚪ None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


  • fix(ios): Keep manual time to display working without legacy interop by antonis and claude in #7015
  • feat(ios): Forward experimental enableWatchdogTerminationsV2 to sentry-cocoa by alwx in #7012
  • docs: Update Warden skills mentioned in the review skill by antonis and claude in #7004
  • ci: Skip CI for warden.toml-only changes by antonis and claude in #7005
  • build(deps): Bump joi to 17.13.9 to resolve ReDoS advisory by antonis and claude in #7003
  • chore(deps): bump getsentry/craft from 3.9.0 to 3.11.1 by dependabot in #7001
  • chore(deps): bump getsentry/craft/.github/workflows/changelog-preview.yml from 3.9.0 to 3.11.1 by dependabot in #6999
  • chore(deps): bump actions/setup-java from 6.1.0 to 6.2.0 by dependabot in #7002
  • chore(deps): bump ruby/setup-ruby from 1.336.0 to 1.338.0 by dependabot in #7000
  • chore(deps): bump the codeql-action group with 3 updates by dependabot in #6998
  • chore(warden): Remove find-bugs, already covered by code-review by dcramer with sentry-junior in #6997
  • chore(deps): update Sentry Android Gradle Plugin to v6.26.0 by github-actions in #6995
  • chore(warden): Enable incremental review by Jeffreyhung with sentry-junior in #6994
  • chore(deps): update Android SDK to v8.63.0 by github-actions in #6990

🤖 This preview updates automatically when you update the PR.

@antonis antonis added the ready-to-merge Triggers the full CI test suite label Nov 10, 2026
Comment thread packages/core/react-native.config.js Resolved

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit af5d6cf. Configure here.

@sentry

sentry Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
Sentry RN io.sentry.reactnative.sample 8.34.0 (114) Release

⚙️ sentry-react-native Build Distribution Settings

antonis and others added 3 commits November 10, 2026 15:59
Codegen reads the spec from the published package, and .npmignore lists
each spec by name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er-without-interop

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…olinking

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@antonis

antonis commented Nov 11, 2026

Copy link
Copy Markdown
Contributor Author

Closing for now. The issue only affects apps that opt in to RCT_REMOVE_LEGACY_COMPONENT_INTEROP and build React Native from source, and the fix depends on RN internals that may change before the default flips. The impact analysis and next steps are in #7014. The branch is kept as a starting point.

@antonis antonis closed this Nov 11, 2026
@antonis
antonis deleted the fix/ios-ondraw-reporter-without-interop branch November 11, 2026 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Triggers the full CI test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

iOS: Manual TTID/TTFD components stop working with RCT_REMOVE_LEGACY_COMPONENT_INTEROP

1 participant