Commit eae9020
refactor(ios): Migrate from PrivateSentrySDKOnly to SentrySDK.internal (#6380)
* refactor(ios): Migrate from PrivateSentrySDKOnly to SentrySDK.internal
Replace the deprecated PrivateSentrySDKOnly SPI and SentrySwizzle.h macro
with the new SentrySDK.internal Swift API exposed by sentry-cocoa 9.19.0,
via a thin in-pod ObjC<->Swift bridge (RNSentryInternal.swift). Imports
Sentry with @_spi(Private) for SPI-gated sub-APIs (performance, replay,
envelope). Drops the performSelector workaround around getReplayIntegration
since SentrySDK.internal.replay.capture() returns Bool directly.
Closes #6370
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test(ios): Migrate Swift Cocoa tests off PrivateSentrySDKOnly
Move RNSentryStartTests, RNSentryStartFromFileTests, and RNSentryReplayOptionsTests
to SentrySDK.internal.{options, options(fromDictionary:), appStart.hybridSDKMode,
performance.framesTrackingHybridSDKMode}.
The ObjC RNSentryTests.m keeps PrivateSentrySDKOnly for now — the test target
is a separate consumer of the RNSentry static-lib pod and cannot see
RNSentry-Swift.h without modulemap surgery. Worth revisiting when sentry-cocoa
removes PrivateSentrySDKOnly in the next major.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ios): Include visionOS in the RNSScreen swizzle bridge
`SentryInternalSwizzleApi` in sentry-cocoa has no platform gating, and
`SENTRY_HAS_UIKIT` (which guards the `[RNSentryRNSScreen swizzleViewDidAppear]`
call in RNSentry.mm) covers visionOS. The Swift bridge was gated to
`iOS/tvOS/macCatalyst` only, silently no-oping the swizzle on visionOS
where the deprecated `SentrySwizzle` macro used to work.
Also documents why `setCurrentScreen` remains a visionOS no-op: sentry-cocoa's
`SentryInternalScreenApi` is intentionally gated to iOS/tvOS, so the new API
surface itself doesn't expose the setter on visionOS.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ios): Scope RNSScreen swizzle key pointer inside withUnsafePointer
`withUnsafePointer(to:)` only guarantees the pointer stays valid inside
the closure body. Capturing it in `keyPtr` and using it outside the
closure was undefined behaviour by contract (even though `static var`
storage happens to be stable in practice). Wrap the entire
`instanceMethod` call inside `withUnsafePointer` so the pointer is
always used within its documented lifetime; the `static var` backing
storage keeps the address itself stable across calls, so sentry-cocoa's
`oncePerClass` dedup keeps working.
Flagged by Cursor Bugbot.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ios): Use conditional import for RNSentry-Swift.h
Handle both static-lib and framework-style Pod integrations by falling
back from `<RNSentry/RNSentry-Swift.h>` (frameworks path) to the local
`"RNSentry-Swift.h"` (static-lib path) via `__has_include`. Applied to
every `.m`/`.mm` in packages/core/ios that consumes the Swift bridge.
Suggested by @antonis.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ios): Guard against nil NSData and pin tests to SPI import
Two fixes flagged by Warden:
1. `RNSentryInternal.envelope(fromData:)` accepted a non-optional Swift
`Data`. If the ObjC caller passed a nil `NSData*` (e.g. from a failed
base64 decode of the envelope payload), the ObjC→Swift bridge would
force-unwrap it and crash before the method body ran. Change the
parameter to `Data?` with an internal `guard let` — matches the
nil-tolerant behaviour of the deprecated
`PrivateSentrySDKOnly.envelopeWithData:`.
2. Swift Cocoa tests accessed `SentrySDK.internal.*` with plain
`import Sentry`. The `.internal` accessor is public today, but the
sub-APIs the tests touch (`options`, `appStart`, `performance`) sit
next to `@_spi(Private)`-gated siblings on the same struct. Add
`@_spi(Private) import Sentry` to `RNSentryStartTests.swift`,
`RNSentryStartFromFileTests.swift`, and `RNSentryReplayOptionsTests.swift`
so they keep compiling if the surface is ever tightened.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ios): Resolve fetchViewHierarchy with nil on capture failure
When `captureViewHierarchy` returned nil the ObjC code still constructed
an empty `NSMutableArray` and resolved with it. In JS, `[]` is truthy —
the caller would treat the failure as a successful (empty) attachment.
Bail out with `resolve(nil)` up front so the JS side sees the actual
failure signal.
Pre-existing since 2023; flagged by Seer while reviewing this PR.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test(ios): Add smoke tests for RNSentryInternal Swift bridge
Cover the bridge's own contract — nil-guard on `envelope(fromData:)`,
metadata accessors, options factory, hybrid-SDK-mode flags, and the
`swizzleRNSScreenViewDidAppear` early-return when RNSScreen is
unavailable. sentry-cocoa owns the underlying `SentrySDK.internal.*`
behaviour; we just assert the wrapper forwards correctly and honours
the documented nil / platform guards.
Registers the new file in the RNSentryCocoaTester project explicitly
(the target does not use file-system-synchronized groups yet).
Flagged by Warden.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ci): Enable modular headers in e2e Podfile patch
Adding Swift to the RNSentry pod means CocoaPods refuses to integrate it
against non-modular ObjC dependencies. On older React Native versions
(e.g. 0.71 with Hermes) the React-hermes pod does not define modules, so
`pod install` fails with:
The Swift pod `RNSentry` depends upon `React-hermes`, which does not
define modules.
Inject `use_modular_headers!` into the Podfile via the existing e2e patch
script, and document the same knob for downstream users in the CHANGELOG.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ci): Only mark Podfile patched when anchor actually matched
Previous version unconditionally set `modularPatched = true` inside the
`use_modular_headers!` branch, so a Podfile without a
`prepare_react_native_project!` anchor would be reported as successfully
patched even though `content.replace` returned it unchanged.
Compare replace output against the input and log a warning instead when
the anchor is missing.
Flagged by Cursor Bugbot.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* docs: Note visionOS setCurrentScreen no-op in CHANGELOG
The migration to `SentrySDK.internal.screen.setCurrent` drops the
current-screen breadcrumb enrichment on visionOS because sentry-cocoa's
new `SentryInternalScreenApi` is gated to iOS/tvOS only. Already
documented in a code comment; call it out for downstream users too.
Flagged by Seer.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(test): Import RNSentry in RNSentryInternalTests
`RNSentryInternal` is a Swift type compiled into the `RNSentry` pod
module, not the `Sentry` module. Without `@_spi(Private) import RNSentry`
the test target cannot resolve `RNSentryInternal.*` and fails to build.
Flagged by Warden.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* docs: Move iOS use_modular_headers note to Changes; reorder Unreleased
Antonis review nit: the use_modular_headers! requirement is a
user-facing Podfile change on older RN versions, not internal-only —
promote it from ### Internal into ### Changes alongside the visionOS
setCurrentScreen note. Also reorder the Unreleased sections to the
usual Features / Changes / Fixes / Internal layout used elsewhere in
this file.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ios): Drop macOS SentryScreenFrames stub + link PR in CHANGELOG
Two Lucas review nits:
1. `RNSentryInternal.currentScreenFrames` had a `nil`-returning stub in
the non-UIKit `#else` branch that still referenced the
`SentryScreenFrames` type in its return signature. sentry-cocoa
doesn't compile `SentryScreenFrames` on macOS/watchOS, so the pod's
Swift source failed to type-check there — CI reproduced with
`cannot find type 'SentryScreenFrames' in scope`. Every ObjC caller
is already gated to `TARGET_OS_IPHONE || TARGET_OS_MACCATALYST`, so
we can just omit the property entirely on non-UIKit platforms.
2. CHANGELOG entries pointed to the issue (#6370) instead of the PR
(#6380). Repo convention links the PR.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ios): Give TIME_TO_DISPLAY_ENTRIES_MAX_SIZE external linkage
Adding Swift to the RNSentry pod (via `RNSentryInternal.swift`) turned
RNSentry into a Swift module. Swift's ObjC header import through modules
doesn't inline `static const int` at use sites — it emits a reference to
an external symbol. Because `static const int` at file scope has
internal linkage, the symbol never exists at link time and
RNSentryTimeToDisplayTests.swift fails to link:
Undefined symbol: _TIME_TO_DISPLAY_ENTRIES_MAX_SIZE
Change the header to `extern const int` and define the value in
RNSentryTimeToDisplay.m so it gets a single exported symbol that both
ObjC and Swift consumers can bind to.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(test): Drop SDK close in RNSentryInternalTests tearDown
CI reported the iOS test bundle hung at ~14 min with
\`IDETestOperationsObserverDebug: Failure collecting diagnostics from
simulator: Timed out after 600.0 seconds\`. Calling
\`SentrySDK.close()\` in tearDown races with sentry-cocoa's background
workers (frame tracker CADisplayLink, session tracker, etc.), and the
simulator process becomes unresponsive between tests.
Match the lifecycle pattern from \`RNSentryStartTests\` — no explicit
setUp/tearDown SDK management. Each test that needs a live SDK starts
it via a helper; tests that only exercise stateless bridge methods
(nil-guard, factory, mutation of process-global flags) don't touch
lifecycle at all.
Also drop \`testSetSdkNameAndAddPackageRoundTrip\` — it mutated
process-global SDK metadata, which would leak across tests running
after it in the same process.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Revert "test(ios): Add smoke tests for RNSentryInternal Swift bridge"
The new smoke suite hung the iOS test bundle at test-run time on CI
(`IDETestOperationsObserverDebug: Failure collecting diagnostics from
simulator: Timed out after 600.0 seconds`), even after removing the
`SentrySDK.close()` call. Best guess: the mutations of
`framesTrackingHybridSDKMode` / `appStartMeasurementHybridSDKMode`
leak into the shared XCTest process and trip up cocoa's UIApplication-
observer path in a way we don't see on main.
The bridge is already exercised end-to-end by `RNSentryStartTests`
(which starts the SDK through `RNSentryStart.start`, i.e. the exact
`RNSentryInternal.*` path) and `RNSentryReplayOptionsTests` (which
calls `SentrySDK.internal.options(fromDictionary:)`), so we're not
losing meaningful coverage by dropping the dedicated file. Revisit
with a proper investigation instead of gambling more CI cycles.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ios): Preserve screenshot/view-hierarchy/setCurrentScreen on visionOS
sentry-cocoa gates the new `SentryInternalScreen/Screenshot/ViewHierarchyApi`
sub-APIs to iOS/tvOS only. Straight-mapping the bridge to them left three
behaviour regressions on visionOS relative to pre-migration:
* `captureScreenshots` returned an empty array (no screenshots on
error events)
* `captureViewHierarchy` returned nil (no view-hierarchy attachments)
* `setCurrentScreen` was a no-op (no current-screen breadcrumb
enrichment)
The deprecated `PrivateSentrySDKOnly` still exposes those three APIs
under `SENTRY_HAS_UIKIT` (which does cover visionOS), so route the
visionOS bridge through it as a narrow, temporary fallback. Everywhere
else the migration still uses `SentrySDK.internal.*` — visionOS is the
only platform that keeps a `PrivateSentrySDKOnly` reference, and it
goes away as soon as sentry-cocoa either exposes these APIs on visionOS
in the hybrid surface or drops `PrivateSentrySDKOnly` in its next major.
With this fallback the PR becomes non-breaking on visionOS, so the
Changes-section note is no longer accurate — dropped from the CHANGELOG.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>1 parent ef0ab1c commit eae9020
20 files changed
Lines changed: 495 additions & 177 deletions
File tree
- dev-packages/e2e-tests/patch-scripts
- packages/core
- RNSentryCocoaTester
- RNSentryCocoaTester.xcodeproj
- RNSentryCocoaTesterTests
- ios
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
21 | 25 | | |
22 | 26 | | |
23 | 27 | | |
| |||
31 | 35 | | |
32 | 36 | | |
33 | 37 | | |
| 38 | + | |
34 | 39 | | |
35 | 40 | | |
36 | 41 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
66 | 85 | | |
67 | | - | |
| 86 | + | |
68 | 87 | | |
69 | 88 | | |
70 | 89 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
66 | 58 | | |
67 | 59 | | |
68 | 60 | | |
| |||
Lines changed: 40 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
10 | 11 | | |
11 | 12 | | |
12 | 13 | | |
| |||
17 | 18 | | |
18 | 19 | | |
19 | 20 | | |
20 | | - | |
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| |||
52 | 52 | | |
53 | 53 | | |
54 | 54 | | |
55 | | - | |
56 | 55 | | |
| 56 | + | |
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| |||
169 | 169 | | |
170 | 170 | | |
171 | 171 | | |
| 172 | + | |
172 | 173 | | |
173 | 174 | | |
174 | 175 | | |
| |||
214 | 215 | | |
215 | 216 | | |
216 | 217 | | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
217 | 235 | | |
218 | 236 | | |
219 | 237 | | |
| |||
334 | 352 | | |
335 | 353 | | |
336 | 354 | | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
337 | 363 | | |
338 | 364 | | |
339 | 365 | | |
340 | 366 | | |
| 367 | + | |
341 | 368 | | |
342 | 369 | | |
343 | 370 | | |
344 | | - | |
| 371 | + | |
345 | 372 | | |
346 | 373 | | |
347 | 374 | | |
| |||
393 | 420 | | |
394 | 421 | | |
395 | 422 | | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
396 | 431 | | |
397 | 432 | | |
398 | 433 | | |
399 | 434 | | |
| 435 | + | |
400 | 436 | | |
401 | 437 | | |
402 | | - | |
| 438 | + | |
403 | 439 | | |
404 | 440 | | |
405 | 441 | | |
| |||
0 commit comments