From 6c3017d757cd6c6ef6993c2ea09a69df41bab941 Mon Sep 17 00:00:00 2001 From: Alexander Pantiukhov Date: Tue, 30 Jun 2026 13:48:54 +0200 Subject: [PATCH 1/2] 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 --- CHANGELOG.md | 6 + packages/core/RNSentry.podspec | 3 +- packages/core/ios/AGENTS.md | 12 +- packages/core/ios/RNSentry+fetchNativeStack.m | 1 - packages/core/ios/RNSentry.mm | 100 +++----- packages/core/ios/RNSentryInternal.swift | 218 ++++++++++++++++++ packages/core/ios/RNSentryRNSScreen.m | 22 +- packages/core/ios/RNSentryReplay.mm | 6 +- .../RNSentryReplayBreadcrumbConverterHelper.m | 3 +- packages/core/ios/RNSentrySDK.m | 4 +- packages/core/ios/RNSentryStart.m | 25 +- packages/core/ios/SentrySDKWrapper.m | 5 +- packages/core/ios/SentryScreenFramesWrapper.m | 9 +- 13 files changed, 299 insertions(+), 115 deletions(-) create mode 100644 packages/core/ios/RNSentryInternal.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index c15fbe004a..5bed1b20ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ ## Unreleased +### Internal + +- Migrate iOS code from the deprecated `PrivateSentrySDKOnly` SPI (and `SentrySwizzle.h` macro) to the new `SentrySDK.internal` Swift API exposed by sentry-cocoa 9.19.0, via a thin in-pod ObjC↔Swift bridge ([#6370](https://github.com/getsentry/sentry-react-native/issues/6370)) + +## 8.16.0 + ### Features - Capture errors that hit Expo Router's per-route `ErrorBoundary` ([#6318](https://github.com/getsentry/sentry-react-native/pull/6318)) diff --git a/packages/core/RNSentry.podspec b/packages/core/RNSentry.podspec index eae5941355..14dbd84fd4 100644 --- a/packages/core/RNSentry.podspec +++ b/packages/core/RNSentry.podspec @@ -41,7 +41,8 @@ Pod::Spec.new do |s| s.preserve_paths = '*.js' - s.source_files = 'ios/**/*.{h,m,mm}' + s.source_files = 'ios/**/*.{h,m,mm,swift}' + s.swift_versions = ['5.5'] s.public_header_files = 'ios/RNSentry.h', 'ios/RNSentrySDK.h', 'ios/RNSentryStart.h', 'ios/RNSentryVersion.h', 'ios/RNSentryBreadcrumb.h', 'ios/RNSentryReplay.h', 'ios/RNSentryReplayBreadcrumbConverter.h', 'ios/Replay/RNSentryReplayMask.h', 'ios/Replay/RNSentryReplayUnmask.h', 'ios/RNSentryTimeToDisplay.h' s.compiler_flags = other_cflags diff --git a/packages/core/ios/AGENTS.md b/packages/core/ios/AGENTS.md index b13a4c617a..04edda1bad 100644 --- a/packages/core/ios/AGENTS.md +++ b/packages/core/ios/AGENTS.md @@ -56,5 +56,15 @@ RCT_EXPORT_METHOD(nativeOperation:(NSString *)param 2. Edit `RNSentry.podspec` to remove version constraint 3. Add local pod to sample's Podfile: ```ruby - pod 'Sentry/HybridSDK', :path => '../../../../sentry-cocoa' + pod 'Sentry', :path => '../../../../sentry-cocoa' ``` + +## Internal API access (`SentrySDK.internal`) + +RNSentry consumes sentry-cocoa's hybrid-SDK surface (`SentrySDK.internal.*`) +through a Swift bridge in `RNSentryInternal.swift`. The bridge imports Sentry +with `@_spi(Private)` because several sub-APIs (`performance.currentScreenFrames`, +`replay.configure`, `envelope.{store,capture,deserialize}`) are SPI-gated. +`.m`/`.mm` callers import the auto-generated `RNSentry-Swift.h` and route +through `[RNSentryInternal …]` instead of touching `PrivateSentrySDKOnly` +(deprecated since cocoa 9.19.0 and slated for removal in the next major). diff --git a/packages/core/ios/RNSentry+fetchNativeStack.m b/packages/core/ios/RNSentry+fetchNativeStack.m index 196e726ddf..1298cf10c3 100644 --- a/packages/core/ios/RNSentry+fetchNativeStack.m +++ b/packages/core/ios/RNSentry+fetchNativeStack.m @@ -2,7 +2,6 @@ #import "RNSentryBreadcrumb.h" #import "RNSentryHexFormatter.h" #import "RNSentryId.h" -#import @import Sentry; // This method was moved to a new category so we can use `@import Sentry` to use Sentry's Swift diff --git a/packages/core/ios/RNSentry.mm b/packages/core/ios/RNSentry.mm index 0d528e9acb..81e0bbb7cd 100644 --- a/packages/core/ios/RNSentry.mm +++ b/packages/core/ios/RNSentry.mm @@ -16,9 +16,9 @@ # define SENTRY_TARGET_PROFILING_SUPPORTED 0 #endif +#import "RNSentry-Swift.h" #import "RNSentryBreadcrumb.h" #import "RNSentryId.h" -#import #import #import #import @@ -352,10 +352,8 @@ - (void)handleShakeDetected RCT_EXPORT_METHOD( fetchNativeSdkInfo : (RCTPromiseResolveBlock)resolve rejecter : (RCTPromiseRejectBlock)reject) { - resolve(@ { - @"name" : PrivateSentrySDKOnly.getSdkName, - @"version" : PrivateSentrySDKOnly.getSdkVersionString - }); + resolve( + @ { @"name" : RNSentryInternal.sdkName, @"version" : RNSentryInternal.sdkVersionString }); } RCT_EXPORT_METHOD( @@ -407,7 +405,7 @@ - (void)handleShakeDetected contexts[@"release"] = releaseName; } // Merge extra context - NSDictionary *extraContext = [PrivateSentrySDKOnly getExtraContext]; + NSDictionary *extraContext = [RNSentryInternal extraContext]; if (extraContext) { NSDictionary *extraDevice = extraContext[@"device"]; @@ -445,8 +443,7 @@ - (void)handleShakeDetected NSDictionary *user = [serializedScope valueForKey:@"user"]; if (user == nil) { - [serializedScope setValue:@ { @"id" : PrivateSentrySDKOnly.installationID } - forKey:@"user"]; + [serializedScope setValue:@ { @"id" : RNSentryInternal.installationID } forKey:@"user"]; } if ([SentrySDKWrapper debug]) { @@ -459,7 +456,7 @@ - (void)handleShakeDetected } }]; - NSDictionary *extraContext = [PrivateSentrySDKOnly getExtraContext]; + NSDictionary *extraContext = [RNSentryInternal extraContext]; NSMutableDictionary *> *contexts = [serializedScope[@"context"] mutableCopy]; @@ -496,8 +493,7 @@ - (void)handleShakeDetected fetchNativeAppStart : (RCTPromiseResolveBlock)resolve rejecter : (RCTPromiseRejectBlock)reject) { #if SENTRY_HAS_UIKIT - NSDictionary *measurements = - [PrivateSentrySDKOnly appStartMeasurementWithSpans]; + NSDictionary *measurements = [RNSentryInternal appStartMeasurementWithSpans]; if (measurements == nil) { resolve(nil); return; @@ -523,7 +519,7 @@ - (void)handleShakeDetected { #if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST - if (PrivateSentrySDKOnly.isFramesTrackingRunning) { + if (RNSentryInternal.isFramesTrackingRunning) { if (![SentryScreenFramesWrapper canTrackFrames]) { resolve(nil); return; @@ -575,20 +571,20 @@ - (void)handleShakeDetected { NSData *data = [[NSData alloc] initWithBase64EncodedString:rawBytes options:0]; - SentryEnvelope *envelope = [PrivateSentrySDKOnly envelopeWithData:data]; + SentryEnvelope *envelope = [RNSentryInternal envelopeFromData:data]; if (envelope == nil) { reject(@"SentryReactNative", @"Failed to parse envelope from byte array.", nil); return; } #if DEBUG - [PrivateSentrySDKOnly captureEnvelope:envelope]; + [RNSentryInternal capture:envelope]; #else if ([[options objectForKey:@"hardCrashed"] boolValue]) { // Storing to disk happens asynchronously with captureEnvelope - [PrivateSentrySDKOnly storeEnvelope:envelope]; + [RNSentryInternal store:envelope]; } else { - [PrivateSentrySDKOnly captureEnvelope:envelope]; + [RNSentryInternal capture:envelope]; } #endif resolve(@YES); @@ -598,7 +594,7 @@ - (void)handleShakeDetected captureScreenshot : (RCTPromiseResolveBlock)resolve rejecter : (RCTPromiseRejectBlock)reject) { #if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST - NSArray *rawScreenshots = [PrivateSentrySDKOnly captureScreenshots]; + NSArray *rawScreenshots = [RNSentryInternal captureScreenshots]; NSMutableArray *screenshotsArray = [NSMutableArray arrayWithCapacity:[rawScreenshots count]]; int counter = 1; @@ -631,7 +627,7 @@ - (void)handleShakeDetected fetchViewHierarchy : (RCTPromiseResolveBlock)resolve rejecter : (RCTPromiseRejectBlock)reject) { #if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST - NSData *rawViewHierarchy = [PrivateSentrySDKOnly captureViewHierarchy]; + NSData *rawViewHierarchy = [RNSentryInternal captureViewHierarchy]; NSMutableArray *viewHierarchy = [NSMutableArray arrayWithCapacity:rawViewHierarchy.length]; const char *bytes = (char *)[rawViewHierarchy bytes]; @@ -682,7 +678,7 @@ + (SentryUser *_Nullable)userFrom:(NSDictionary *)userKeys #if SENTRY_HAS_UIKIT NSString *_Nullable screen = [RNSentryBreadcrumb getCurrentScreenFrom:breadcrumb]; if (screen != nil) { - [PrivateSentrySDKOnly setCurrentScreen:screen]; + [RNSentryInternal setCurrentScreen:screen]; } #endif // SENTRY_HAS_UIKIT } @@ -765,52 +761,19 @@ + (SentryUser *_Nullable)userFrom:(NSDictionary *)userKeys RCT_EXPORT_METHOD(resumeAppHangTracking) { [SentrySDKWrapper resumeAppHangTracking]; } -/** - * Calls captureReplay on the native replay integration and returns - * the BOOL result indicating whether the capture succeeded. - * - * PrivateSentrySDKOnly.captureReplay is void and discards the result, - * so we call the integration directly to get the success status. - * This prevents returning a stale buffer-mode replay ID when the - * capture actually failed (e.g., replay not running). - * - * Falls back to the old void captureReplay if the integration - * cannot be accessed directly (e.g., future Cocoa SDK changes). - * - * See https://github.com/getsentry/sentry-react-native/issues/5074 - */ +// Calls `SentrySDK.internal.replay.capture()` via the Swift bridge and returns +// the BOOL result. The `@try`/`@catch` is retained as cheap insurance for one +// release cycle — see getsentry/sentry-react-native#5074 for the historical +// fault path that motivated defensive handling here. + (BOOL)captureReplayWithReturnValue { #if SENTRY_TARGET_REPLAY_SUPPORTED @try { - if ([PrivateSentrySDKOnly respondsToSelector:@selector(getReplayIntegration)]) { -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Warc-performSelector-leaks" - id replayIntegration = - [PrivateSentrySDKOnly performSelector:@selector(getReplayIntegration)]; -# pragma clang diagnostic pop - if (replayIntegration && - [replayIntegration respondsToSelector:@selector(captureReplay)]) { - typedef BOOL (*CaptureReplayIMP)(id, SEL); - CaptureReplayIMP captureFunc = (CaptureReplayIMP) - [replayIntegration methodForSelector:@selector(captureReplay)]; - return captureFunc(replayIntegration, @selector(captureReplay)); - } - } - } @catch (NSException *exception) { - NSLog(@"[RNSentry] Failed to call captureReplay on integration: %@", exception); - } - // Fallback: call the void method and assume success if a replay ID exists. - // This preserves the old behavior when the integration isn't directly accessible. - // clang-format off - @try { - [PrivateSentrySDKOnly captureReplay]; - return [PrivateSentrySDKOnly getReplayId] != nil; + return [RNSentryInternal captureReplay]; } @catch (NSException *exception) { - NSLog(@"[RNSentry] Failed to call captureReplay fallback: %@", exception); + NSLog(@"[RNSentry] Failed to call captureReplay: %@", exception); return NO; } - // clang-format on #else return NO; #endif @@ -822,7 +785,7 @@ + (BOOL)captureReplayWithReturnValue #if SENTRY_TARGET_REPLAY_SUPPORTED BOOL captured = [RNSentry captureReplayWithReturnValue]; if (captured) { - resolve([PrivateSentrySDKOnly getReplayId]); + resolve([RNSentryInternal replayId]); } else { resolve(nil); } @@ -912,7 +875,7 @@ + (BOOL)isPathUnderAllowedRootsForTesting:(NSString *)path RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSString *, getCurrentReplayId) { #if SENTRY_TARGET_REPLAY_SUPPORTED - return [PrivateSentrySDKOnly getReplayId]; + return [RNSentryInternal replayId]; #else return nil; #endif @@ -938,8 +901,7 @@ + (BOOL)isPathUnderAllowedRootsForTesting:(NSString *)path if (nativeProfileTraceId == nil && nativeProfileStartTime == 0 && platformProfilers) { # if SENTRY_TARGET_PROFILING_SUPPORTED nativeProfileTraceId = [RNSentryId newId]; - nativeProfileStartTime = - [PrivateSentrySDKOnly startProfilerForTrace:nativeProfileTraceId]; + nativeProfileStartTime = [RNSentryInternal startProfilerForTrace:nativeProfileTraceId]; # endif } else { if (!platformProfilers) { @@ -953,7 +915,7 @@ + (BOOL)isPathUnderAllowedRootsForTesting:(NSString *)path } catch (const std::exception &ex) { if (nativeProfileTraceId != nil) { # if SENTRY_TARGET_PROFILING_SUPPORTED - [PrivateSentrySDKOnly discardProfilerForTrace:nativeProfileTraceId]; + [RNSentryInternal discardProfilerForTrace:nativeProfileTraceId]; # endif nativeProfileTraceId = nil; } @@ -965,7 +927,7 @@ + (BOOL)isPathUnderAllowedRootsForTesting:(NSString *)path } catch (...) { if (nativeProfileTraceId != nil) { # if SENTRY_TARGET_PROFILING_SUPPORTED - [PrivateSentrySDKOnly discardProfilerForTrace:nativeProfileTraceId]; + [RNSentryInternal discardProfilerForTrace:nativeProfileTraceId]; # endif nativeProfileTraceId = nil; } @@ -985,9 +947,9 @@ + (BOOL)isPathUnderAllowedRootsForTesting:(NSString *)path if (nativeProfileTraceId != nil && nativeProfileStartTime != 0) { # if SENTRY_TARGET_PROFILING_SUPPORTED uint64_t nativeProfileStopTime = clock_gettime_nsec_np(CLOCK_UPTIME_RAW); - nativeProfile = [PrivateSentrySDKOnly collectProfileBetween:nativeProfileStartTime - and:nativeProfileStopTime - forTrace:nativeProfileTraceId]; + nativeProfile = [RNSentryInternal collectProfileBetween:nativeProfileStartTime + and:nativeProfileStopTime + forTrace:nativeProfileTraceId]; # endif } // Cleanup native profiles @@ -1042,7 +1004,7 @@ + (BOOL)isPathUnderAllowedRootsForTesting:(NSString *)path } catch (const std::exception &ex) { if (nativeProfileTraceId != nil) { # if SENTRY_TARGET_PROFILING_SUPPORTED - [PrivateSentrySDKOnly discardProfilerForTrace:nativeProfileTraceId]; + [RNSentryInternal discardProfilerForTrace:nativeProfileTraceId]; # endif nativeProfileTraceId = nil; } @@ -1054,7 +1016,7 @@ + (BOOL)isPathUnderAllowedRootsForTesting:(NSString *)path } catch (...) { if (nativeProfileTraceId != nil) { # if SENTRY_TARGET_PROFILING_SUPPORTED - [PrivateSentrySDKOnly discardProfilerForTrace:nativeProfileTraceId]; + [RNSentryInternal discardProfilerForTrace:nativeProfileTraceId]; # endif nativeProfileTraceId = nil; } diff --git a/packages/core/ios/RNSentryInternal.swift b/packages/core/ios/RNSentryInternal.swift new file mode 100644 index 0000000000..6c33218063 --- /dev/null +++ b/packages/core/ios/RNSentryInternal.swift @@ -0,0 +1,218 @@ +import Foundation +@_spi(Private) import Sentry + +/// Thin Objective-C-visible bridge over `SentrySDK.internal.*`. +/// +/// React Native's iOS code is mostly `.m`/`.mm`, but the new hybrid-SDK API +/// (`SentrySDK.internal`) is Swift-only and several methods are gated by +/// `@_spi(Private)`. This file imports with the SPI name and exposes a flat +/// `@objc` surface that mirrors the call sites we use today. +/// +/// Platform gating mirrors each `SentryInternal*Api` in sentry-cocoa +/// (`Sources/Swift/HybridSDK/`). Where a sub-API is excluded on a platform, +/// stubs return safe defaults so `.m`/`.mm` callers still resolve symbols. +@_spi(Private) @objc public final class RNSentryInternal: NSObject { + + // MARK: - SDK metadata + + @_spi(Private) @objc public static var sdkName: String { SentrySDK.internal.sdk.name } + + @_spi(Private) @objc public static var sdkVersionString: String { SentrySDK.internal.sdk.versionString } + + @_spi(Private) @objc public static func setSdkName(_ name: String, version: String) { + SentrySDK.internal.sdk.setName(name, version: version) + } + + @_spi(Private) @objc public static func addSdkPackage(_ name: String, version: String) { + SentrySDK.internal.sdk.addPackage(name: name, version: version) + } + + @_spi(Private) @objc public static var extraContext: [String: Any] { + SentrySDK.internal.sdk.extraContext + } + + @_spi(Private) @objc public static var installationID: String { + SentrySDK.internal.sdk.installationID + } + + // MARK: - Options + + @_spi(Private) @objc public static var options: Options { SentrySDK.internal.options } + + @_spi(Private) @objc public static func options(fromDictionary dict: [String: Any]) throws -> Options { + try SentrySDK.internal.options(fromDictionary: dict) + } + + // MARK: - App start + + @_spi(Private) @objc public static var appStartMeasurementHybridSDKMode: Bool { + get { SentrySDK.internal.appStart.hybridSDKMode } + set { SentrySDK.internal.appStart.hybridSDKMode = newValue } + } + + @_spi(Private) @objc public static var appStartMeasurementWithSpans: [String: Any]? { + SentrySDK.internal.appStart.measurementWithSpans + } + + // MARK: - Performance / frames + + #if os(iOS) || os(tvOS) || os(visionOS) + @_spi(Private) @objc public static var framesTrackingMeasurementHybridSDKMode: Bool { + get { SentrySDK.internal.performance.framesTrackingHybridSDKMode } + set { SentrySDK.internal.performance.framesTrackingHybridSDKMode = newValue } + } + + @_spi(Private) @objc public static var isFramesTrackingRunning: Bool { + SentrySDK.internal.performance.isFramesTrackingRunning + } + + @_spi(Private) @objc public static var currentScreenFrames: SentryScreenFrames? { + SentrySDK.internal.performance.currentScreenFrames + } + #else + @_spi(Private) @objc public static var framesTrackingMeasurementHybridSDKMode: Bool { + get { false } + set {} + } + + @_spi(Private) @objc public static var isFramesTrackingRunning: Bool { false } + + @_spi(Private) @objc public static var currentScreenFrames: SentryScreenFrames? { nil } + #endif + + // MARK: - Envelope + + @_spi(Private) @objc public static func envelope(fromData data: Data) -> SentryEnvelope? { + SentrySDK.internal.envelope.deserialize(from: data) + } + + @_spi(Private) @objc public static func capture(_ envelope: SentryEnvelope) { + SentrySDK.internal.envelope.capture(envelope) + } + + @_spi(Private) @objc public static func store(_ envelope: SentryEnvelope) { + SentrySDK.internal.envelope.store(envelope) + } + + // MARK: - Screenshot / view hierarchy / screen + + #if os(iOS) || os(tvOS) + @_spi(Private) @objc public static var captureScreenshots: [Data]? { + SentrySDK.internal.screenshot.capture() + } + + @_spi(Private) @objc public static var captureViewHierarchy: Data? { + SentrySDK.internal.viewHierarchy.capture() + } + + @_spi(Private) @objc public static func setCurrentScreen(_ screenName: String?) { + SentrySDK.internal.screen.setCurrent(screenName) + } + #else + @_spi(Private) @objc public static var captureScreenshots: [Data]? { nil } + @_spi(Private) @objc public static var captureViewHierarchy: Data? { nil } + @_spi(Private) @objc public static func setCurrentScreen(_ screenName: String?) {} + #endif + + // MARK: - Replay + + #if os(iOS) || os(tvOS) + @_spi(Private) @objc public static func captureReplay() -> Bool { + SentrySDK.internal.replay.capture() + } + + @_spi(Private) @objc public static var replayId: String? { + SentrySDK.internal.replay.replayId + } + + @_spi(Private) @objc public static func setReplayRedactContainerClass(_ containerClass: AnyClass) { + SentrySDK.internal.replay.setRedactContainerClass(containerClass) + } + + @_spi(Private) @objc public static func setReplayIgnoreContainerClass(_ containerClass: AnyClass) { + SentrySDK.internal.replay.setIgnoreContainerClass(containerClass) + } + + @_spi(Private) @objc public static func configureReplay( + breadcrumbConverter: SentryReplayBreadcrumbConverter + ) { + SentrySDK.internal.replay.configure( + breadcrumbConverter: breadcrumbConverter, + screenshotProvider: nil + ) + } + #else + @_spi(Private) @objc public static func captureReplay() -> Bool { false } + @_spi(Private) @objc public static var replayId: String? { nil } + @_spi(Private) @objc public static func setReplayRedactContainerClass(_ containerClass: AnyClass) {} + @_spi(Private) @objc public static func setReplayIgnoreContainerClass(_ containerClass: AnyClass) {} + @_spi(Private) @objc public static func configureReplay( + breadcrumbConverter: SentryReplayBreadcrumbConverter + ) {} + #endif + + // MARK: - Swizzle + + #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) + /// Stable identity for the `RNSScreen.viewDidAppear:` swizzle so the underlying + /// `oncePerClass` bookkeeping in sentry-cocoa can dedupe re-entries. + private static var rnsScreenViewDidAppearKey: UInt8 = 0 + + /// Swizzles `-[RNSScreen viewDidAppear:]`, invoking `hook` before the original + /// implementation on every call. No-op when RNSScreen is unavailable. + @_spi(Private) @objc public static func swizzleRNSScreenViewDidAppear(hook: @escaping () -> Void) { + guard let cls = NSClassFromString("RNSScreen") else { return } + let selector = NSSelectorFromString("viewDidAppear:") + let keyPtr = withUnsafePointer(to: &rnsScreenViewDidAppearKey) { + UnsafeRawPointer($0) + } + + _ = SentrySDK.internal.swizzle.instanceMethod( + selector, + in: cls, + mode: .oncePerClass, + key: keyPtr, + factory: { getOriginal in + let block: @convention(block) (AnyObject, ObjCBool) -> Void = { receiver, animated in + hook() + typealias OriginalIMP = @convention(c) (AnyObject, Selector, ObjCBool) -> Void + let original = unsafeBitCast(getOriginal(), to: OriginalIMP.self) + original(receiver, selector, animated) + } + return block as AnyObject + } + ) + } + #else + @_spi(Private) @objc public static func swizzleRNSScreenViewDidAppear(hook: @escaping () -> Void) {} + #endif + + // MARK: - Profiling + + #if !(os(watchOS) || os(tvOS) || os(visionOS)) + @_spi(Private) @objc public static func startProfiler(forTrace traceId: SentryId) -> UInt64 { + SentrySDK.internal.profiling.start(for: traceId) + } + + @_spi(Private) @objc(collectProfileBetween:and:forTrace:) + public static func collectProfile( + between startTime: UInt64, + and endTime: UInt64, + forTrace traceId: SentryId + ) -> [String: Any]? { + SentrySDK.internal.profiling.collect(between: startTime, and: endTime, for: traceId) + } + + @_spi(Private) @objc public static func discardProfiler(forTrace traceId: SentryId) { + SentrySDK.internal.profiling.discard(for: traceId) + } + #else + @_spi(Private) @objc public static func startProfiler(forTrace traceId: SentryId) -> UInt64 { 0 } + @_spi(Private) @objc public static func collectProfile( + between startTime: UInt64, + and endTime: UInt64, + forTrace traceId: SentryId + ) -> [String: Any]? { nil } + @_spi(Private) @objc public static func discardProfiler(forTrace traceId: SentryId) {} + #endif +} diff --git a/packages/core/ios/RNSentryRNSScreen.m b/packages/core/ios/RNSentryRNSScreen.m index 91bbb58c08..edd1a1f6db 100644 --- a/packages/core/ios/RNSentryRNSScreen.m +++ b/packages/core/ios/RNSentryRNSScreen.m @@ -2,31 +2,17 @@ #if SENTRY_HAS_UIKIT +# import "RNSentry-Swift.h" # import "RNSentryDependencyContainer.h" # import "RNSentryFramesTrackerListener.h" -# if __has_include() -# import -# else -# import "SentrySwizzle.h" -# endif -@import Sentry; @implementation RNSentryRNSScreen + (void)swizzleViewDidAppear { - Class rnsscreenclass = NSClassFromString(@"RNSScreen"); - if (rnsscreenclass == nil) { - return; - } - - SEL selector = NSSelectorFromString(@"viewDidAppear:"); - SentrySwizzleInstanceMethod(rnsscreenclass, selector, SentrySWReturnType(void), - SentrySWArguments(BOOL animated), SentrySWReplacement({ - [[[RNSentryDependencyContainer sharedInstance] framesTrackerListener] startListening]; - SentrySWCallOriginal(animated); - }), - SentrySwizzleModeOncePerClass, (void *)selector); + [RNSentryInternal swizzleRNSScreenViewDidAppearWithHook:^{ + [[[RNSentryDependencyContainer sharedInstance] framesTrackerListener] startListening]; + }]; } @end diff --git a/packages/core/ios/RNSentryReplay.mm b/packages/core/ios/RNSentryReplay.mm index 520aca6b9e..7f01fa278c 100644 --- a/packages/core/ios/RNSentryReplay.mm +++ b/packages/core/ios/RNSentryReplay.mm @@ -1,10 +1,10 @@ #import "RNSentryReplay.h" +#import "RNSentry-Swift.h" #import "RNSentryReplayBreadcrumbConverterHelper.h" #import "RNSentryReplayQuality.h" #import "RNSentryVersion.h" #import "Replay/RNSentryReplayMask.h" #import "Replay/RNSentryReplayUnmask.h" -#import #if SENTRY_TARGET_REPLAY_SUPPORTED @@ -68,8 +68,8 @@ + (void)postInit { // We can't import RNSentryReplayMask.h here because it's Objective-C++ // To avoid typos, we test the class existence in the tests - [PrivateSentrySDKOnly setRedactContainerClass:[RNSentryReplay getMaskClass]]; - [PrivateSentrySDKOnly setIgnoreContainerClass:[RNSentryReplay getUnmaskClass]]; + [RNSentryInternal setReplayRedactContainerClass:[RNSentryReplay getMaskClass]]; + [RNSentryInternal setReplayIgnoreContainerClass:[RNSentryReplay getUnmaskClass]]; [RNSentryReplayBreadcrumbConverterHelper configureSessionReplayWithConverter]; } diff --git a/packages/core/ios/RNSentryReplayBreadcrumbConverterHelper.m b/packages/core/ios/RNSentryReplayBreadcrumbConverterHelper.m index ef3da7ec38..d22c872d7e 100644 --- a/packages/core/ios/RNSentryReplayBreadcrumbConverterHelper.m +++ b/packages/core/ios/RNSentryReplayBreadcrumbConverterHelper.m @@ -1,6 +1,7 @@ #import "RNSentryReplayBreadcrumbConverterHelper.h" #if SENTRY_TARGET_REPLAY_SUPPORTED +# import "RNSentry-Swift.h" # import "RNSentryReplayBreadcrumbConverter.h" @implementation RNSentryReplayBreadcrumbConverterHelper @@ -9,7 +10,7 @@ + (void)configureSessionReplayWithConverter { RNSentryReplayBreadcrumbConverter *breadcrumbConverter = [[RNSentryReplayBreadcrumbConverter alloc] init]; - [PrivateSentrySDKOnly configureSessionReplayWith:breadcrumbConverter screenshotProvider:nil]; + [RNSentryInternal configureReplayWithBreadcrumbConverter:breadcrumbConverter]; } @end diff --git a/packages/core/ios/RNSentrySDK.m b/packages/core/ios/RNSentrySDK.m index 0f38cf6c7b..56e5e5cc20 100644 --- a/packages/core/ios/RNSentrySDK.m +++ b/packages/core/ios/RNSentrySDK.m @@ -1,6 +1,6 @@ #import "RNSentrySDK.h" +#import "RNSentry-Swift.h" #import "RNSentryStart.h" -#import #import static NSString *SENTRY_OPTIONS_RESOURCE_NAME = @"sentry.options"; @@ -60,7 +60,7 @@ + (void)start:(NSString *)path configureOptions:(void (^)(SentryOptions *options if (options == nil) { // Fallback in case that options file could not be parsed. NSError *fallbackError = nil; - options = [PrivateSentrySDKOnly optionsWithDictionary:@{ } didFailWithError:&fallbackError]; + options = [RNSentryInternal optionsFromDictionary:@{ } error:&fallbackError]; if (fallbackError != nil) { NSLog(@"[RNSentry] Failed to create fallback options with error: %@", fallbackError.localizedDescription); diff --git a/packages/core/ios/RNSentryStart.m b/packages/core/ios/RNSentryStart.m index fa463f116e..d724dbf4e2 100644 --- a/packages/core/ios/RNSentryStart.m +++ b/packages/core/ios/RNSentryStart.m @@ -3,7 +3,7 @@ #import "RNSentryReplay.h" #import "RNSentryVersion.h" -#import +#import "RNSentry-Swift.h" #import @import Sentry; @@ -31,14 +31,14 @@ + (void)startWithOptions:(SentryOptions *)options NS_SWIFT_NAME(start(options:)) + (void)startWithOptions:(SentryOptions *)options jsSdkVersion:(NSString *_Nullable)jsSdkVersion { - NSString *sdkVersion = [PrivateSentrySDKOnly getSdkVersionString]; - [PrivateSentrySDKOnly setSdkName:NATIVE_SDK_NAME andVersionString:sdkVersion]; - [PrivateSentrySDKOnly addSdkPackage:REACT_NATIVE_SDK_PACKAGE_NAME - version:REACT_NATIVE_SDK_PACKAGE_VERSION]; + NSString *sdkVersion = [RNSentryInternal sdkVersionString]; + [RNSentryInternal setSdkName:NATIVE_SDK_NAME version:sdkVersion]; + [RNSentryInternal addSdkPackage:REACT_NATIVE_SDK_PACKAGE_NAME + version:REACT_NATIVE_SDK_PACKAGE_VERSION]; if (jsSdkVersion != nil && ![jsSdkVersion isEqualToString:REACT_NATIVE_SDK_PACKAGE_VERSION]) { NSString *otaPackageName = [REACT_NATIVE_SDK_PACKAGE_NAME stringByAppendingString:@":ota"]; - [PrivateSentrySDKOnly addSdkPackage:otaPackageName version:jsSdkVersion]; + [RNSentryInternal addSdkPackage:otaPackageName version:jsSdkVersion]; } [SentrySDK startWithOptions:options]; @@ -62,8 +62,8 @@ + (SentryOptions *_Nullable)createOptionsWithDictionary:(NSDictionary *_Nonnull) [RNSentryReplay updateOptions:mutableOptions]; #endif - SentryOptions *sentryOptions = [PrivateSentrySDKOnly optionsWithDictionary:mutableOptions - didFailWithError:errorPointer]; + SentryOptions *sentryOptions = [RNSentryInternal optionsFromDictionary:mutableOptions + error:errorPointer]; if (*errorPointer != nil) { return nil; } @@ -237,12 +237,11 @@ + (void)updateWithReactFinals:(SentryOptions *)options // App Start Hybrid mode doesn't wait for didFinishLaunchNotification and the // didBecomeVisibleNotification as they will be missed when auto initializing from JS // App Start measurements are created right after the tracking starts - PrivateSentrySDKOnly.appStartMeasurementHybridSDKMode = options.enableAutoPerformanceTracing; + RNSentryInternal.appStartMeasurementHybridSDKMode = options.enableAutoPerformanceTracing; #if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST // Frames Tracking Hybrid Mode ensures tracking // is enabled without tracing enabled in the native SDK - PrivateSentrySDKOnly.framesTrackingMeasurementHybridSDKMode - = options.enableAutoPerformanceTracing; + RNSentryInternal.framesTrackingMeasurementHybridSDKMode = options.enableAutoPerformanceTracing; #endif } @@ -301,8 +300,8 @@ + (void)postDidBecomeActiveNotification // If the app is active/in foreground, and we have not sent the SentryHybridSdkDidBecomeActive // notification, send it. if (appIsActive && !sentHybridSdkDidBecomeActive - && (PrivateSentrySDKOnly.options.enableAutoSessionTracking - || PrivateSentrySDKOnly.options.enableWatchdogTerminationTracking)) { + && (RNSentryInternal.options.enableAutoSessionTracking + || RNSentryInternal.options.enableWatchdogTerminationTracking)) { // Updates Native App State Manager // https://github.com/getsentry/sentry-cocoa/blob/888a145b144b8077e03151a886520f332e47e297/Sources/Sentry/SentryAppStateManager.m#L136 // Triggers Session Tracker diff --git a/packages/core/ios/SentrySDKWrapper.m b/packages/core/ios/SentrySDKWrapper.m index 9aa5a62493..f46a436419 100644 --- a/packages/core/ios/SentrySDKWrapper.m +++ b/packages/core/ios/SentrySDKWrapper.m @@ -1,4 +1,5 @@ #import "SentrySDKWrapper.h" +#import "RNSentry-Swift.h" @import Sentry; @implementation SentrySDKWrapper @@ -35,12 +36,12 @@ + (void)configureScope:(void (^)(SentryScope *scope))callback + (BOOL)debug { - return PrivateSentrySDKOnly.options.debug; + return RNSentryInternal.options.debug; } + (NSString *)releaseName { - return PrivateSentrySDKOnly.options.releaseName; + return RNSentryInternal.options.releaseName; } @end diff --git a/packages/core/ios/SentryScreenFramesWrapper.m b/packages/core/ios/SentryScreenFramesWrapper.m index dd79c5a214..05a12998fe 100644 --- a/packages/core/ios/SentryScreenFramesWrapper.m +++ b/packages/core/ios/SentryScreenFramesWrapper.m @@ -1,4 +1,5 @@ #import "SentryScreenFramesWrapper.h" +#import "RNSentry-Swift.h" @import Sentry; #if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST @@ -7,7 +8,7 @@ @implementation SentryScreenFramesWrapper + (BOOL)canTrackFrames { - return PrivateSentrySDKOnly.currentScreenFrames != nil; + return RNSentryInternal.currentScreenFrames != nil; } + (NSNumber *)totalFrames @@ -15,7 +16,7 @@ + (NSNumber *)totalFrames if (![self canTrackFrames]) { return nil; } - return [NSNumber numberWithLong:PrivateSentrySDKOnly.currentScreenFrames.total]; + return [NSNumber numberWithLong:RNSentryInternal.currentScreenFrames.total]; } + (NSNumber *)frozenFrames @@ -23,7 +24,7 @@ + (NSNumber *)frozenFrames if (![self canTrackFrames]) { return nil; } - return [NSNumber numberWithLong:PrivateSentrySDKOnly.currentScreenFrames.frozen]; + return [NSNumber numberWithLong:RNSentryInternal.currentScreenFrames.frozen]; } + (NSNumber *)slowFrames @@ -31,7 +32,7 @@ + (NSNumber *)slowFrames if (![self canTrackFrames]) { return nil; } - return [NSNumber numberWithLong:PrivateSentrySDKOnly.currentScreenFrames.slow]; + return [NSNumber numberWithLong:RNSentryInternal.currentScreenFrames.slow]; } + (NSNumber *)framesDelayForStartTimestamp:(double)startTimestampSeconds From 7835dd81e41a6b6415b3cafbbc057c9f4654c7a2 Mon Sep 17 00:00:00 2001 From: Alexander Pantiukhov Date: Tue, 30 Jun 2026 14:28:32 +0200 Subject: [PATCH 2/2] test(ios): Migrate Swift Cocoa tests off PrivateSentrySDKOnly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../RNSentryReplayOptionsTests.swift | 40 +++++++++---------- .../RNSentryStartFromFileTests.swift | 11 ++--- .../RNSentryStartTests.swift | 29 +++++++------- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryReplayOptionsTests.swift b/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryReplayOptionsTests.swift index c8b43348a9..20c0c78d3b 100644 --- a/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryReplayOptionsTests.swift +++ b/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryReplayOptionsTests.swift @@ -69,7 +69,7 @@ final class RNSentryReplayOptions: XCTestCase { ] as NSDictionary).mutableCopy() as! NSMutableDictionary RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertEqual(actualOptions.sessionReplay.sessionSampleRate, 0.75) } @@ -80,7 +80,7 @@ final class RNSentryReplayOptions: XCTestCase { ] as NSDictionary).mutableCopy() as! NSMutableDictionary RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertEqual(actualOptions.sessionReplay.onErrorSampleRate, 0.75) } @@ -110,7 +110,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertEqual(actualOptions.sessionReplay.maskAllImages, true) assertContainsClass(classArray: actualOptions.sessionReplay.maskedViewClasses, stringClass: "RCTImageView") @@ -125,7 +125,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertEqual(actualOptions.sessionReplay.maskAllImages, false) XCTAssertEqual(actualOptions.sessionReplay.maskedViewClasses.count, 0) @@ -140,7 +140,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertEqual(actualOptions.sessionReplay.maskAllText, true) assertContainsClass(classArray: actualOptions.sessionReplay.maskedViewClasses, stringClass: "RCTTextView") @@ -167,7 +167,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertEqual(actualOptions.sessionReplay.maskAllText, false) XCTAssertEqual(actualOptions.sessionReplay.maskedViewClasses.count, 0) @@ -181,7 +181,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertTrue(actualOptions.sessionReplay.enableViewRendererV2) } @@ -195,7 +195,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertTrue(actualOptions.sessionReplay.enableViewRendererV2) } @@ -209,7 +209,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertFalse(actualOptions.sessionReplay.enableViewRendererV2) } @@ -222,7 +222,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertFalse(actualOptions.sessionReplay.enableFastViewRendering) } @@ -236,7 +236,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertTrue(actualOptions.sessionReplay.enableFastViewRendering) } @@ -250,7 +250,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertFalse(actualOptions.sessionReplay.enableFastViewRendering) } @@ -263,7 +263,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertEqual(actualOptions.sessionReplay.quality, SentryReplayOptions.SentryReplayQuality.medium) } @@ -277,7 +277,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertEqual(actualOptions.sessionReplay.quality, SentryReplayOptions.SentryReplayQuality.low) } @@ -291,7 +291,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertEqual(actualOptions.sessionReplay.quality, SentryReplayOptions.SentryReplayQuality.medium) } @@ -305,7 +305,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertEqual(actualOptions.sessionReplay.quality, SentryReplayOptions.SentryReplayQuality.high) } @@ -319,7 +319,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) XCTAssertEqual(actualOptions.sessionReplay.quality, SentryReplayOptions.SentryReplayQuality.medium) } @@ -333,7 +333,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) let includedViewClasses = actualOptions.sessionReplay.includedViewClasses XCTAssertEqual(includedViewClasses.count, 3) @@ -351,7 +351,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) let excludedViewClasses = actualOptions.sessionReplay.excludedViewClasses XCTAssertEqual(excludedViewClasses.count, 3) @@ -372,7 +372,7 @@ final class RNSentryReplayOptions: XCTestCase { RNSentryReplay.updateOptions(optionsDict) - let actualOptions = try! PrivateSentrySDKOnly.options(with: optionsDict as! [String: Any]) + let actualOptions = try! SentrySDK.internal.options(fromDictionary: optionsDict as! [String: Any]) let includedViewClasses = actualOptions.sessionReplay.includedViewClasses XCTAssertEqual(includedViewClasses.count, 2) diff --git a/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryStartFromFileTests.swift b/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryStartFromFileTests.swift index e0269a5961..feb66ba7d3 100644 --- a/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryStartFromFileTests.swift +++ b/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryStartFromFileTests.swift @@ -1,3 +1,4 @@ +import Sentry import XCTest final class RNSentryStartFromFileTests: XCTestCase { @@ -11,7 +12,7 @@ final class RNSentryStartFromFileTests: XCTestCase { XCTAssertTrue(wasConfigurationCalled) - let actualOptions = PrivateSentrySDKOnly.options + let actualOptions = SentrySDK.internal.options XCTAssertNil(actualOptions.dsn) XCTAssertNil(actualOptions.parsedDsn) } @@ -25,7 +26,7 @@ final class RNSentryStartFromFileTests: XCTestCase { XCTAssertTrue(wasConfigurationCalled) - let actualOptions = PrivateSentrySDKOnly.options + let actualOptions = SentrySDK.internal.options XCTAssertNil(actualOptions.dsn) XCTAssertNil(actualOptions.parsedDsn) } @@ -39,7 +40,7 @@ final class RNSentryStartFromFileTests: XCTestCase { XCTAssertTrue(wasConfigurationCalled) - let actualOptions = PrivateSentrySDKOnly.options + let actualOptions = SentrySDK.internal.options XCTAssertNil(actualOptions.dsn) XCTAssertNotNil(actualOptions.parsedDsn) XCTAssertEqual(actualOptions.environment, "environment-from-invalid-file") @@ -54,7 +55,7 @@ final class RNSentryStartFromFileTests: XCTestCase { XCTAssertTrue(wasConfigurationCalled) - let actualOptions = PrivateSentrySDKOnly.options + let actualOptions = SentrySDK.internal.options XCTAssertNil(actualOptions.dsn) XCTAssertNotNil(actualOptions.parsedDsn) XCTAssertEqual(actualOptions.environment, "environment-from-valid-file") @@ -76,7 +77,7 @@ final class RNSentryStartFromFileTests: XCTestCase { options.environment = "new-environment" } - let actualOptions = PrivateSentrySDKOnly.options + let actualOptions = SentrySDK.internal.options XCTAssertEqual(actualOptions.environment, "new-environment") } diff --git a/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryStartTests.swift b/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryStartTests.swift index c437b83049..e98f43eb4c 100644 --- a/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryStartTests.swift +++ b/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryStartTests.swift @@ -1,3 +1,4 @@ +import Sentry import XCTest final class RNSentryStartTests: XCTestCase { @@ -29,7 +30,7 @@ final class RNSentryStartTests: XCTestCase { "dsn": "https://abcd@efgh.ingest.sentry.io/123456" ]) - let actualOptions = PrivateSentrySDKOnly.options + let actualOptions = SentrySDK.internal.options assertReactDefaults(actualOptions) } @@ -63,10 +64,10 @@ final class RNSentryStartTests: XCTestCase { for startMethod in testCases { try startMethod() - let actualOptions = PrivateSentrySDKOnly.options + let actualOptions = SentrySDK.internal.options - XCTAssertTrue(PrivateSentrySDKOnly.appStartMeasurementHybridSDKMode) - XCTAssertTrue(PrivateSentrySDKOnly.framesTrackingMeasurementHybridSDKMode) + XCTAssertTrue(SentrySDK.internal.appStart.hybridSDKMode) + XCTAssertTrue(SentrySDK.internal.performance.framesTrackingHybridSDKMode) } } @@ -89,10 +90,10 @@ final class RNSentryStartTests: XCTestCase { for startMethod in testCases { try startMethod() - let actualOptions = PrivateSentrySDKOnly.options + let actualOptions = SentrySDK.internal.options - XCTAssertFalse(PrivateSentrySDKOnly.appStartMeasurementHybridSDKMode) - XCTAssertFalse(PrivateSentrySDKOnly.framesTrackingMeasurementHybridSDKMode) + XCTAssertFalse(SentrySDK.internal.appStart.hybridSDKMode) + XCTAssertFalse(SentrySDK.internal.performance.framesTrackingHybridSDKMode) } } @@ -113,7 +114,7 @@ final class RNSentryStartTests: XCTestCase { for startMethod in testCases { try startMethod() - let actualOptions = PrivateSentrySDKOnly.options + let actualOptions = SentrySDK.internal.options let actualEvent = actualOptions.beforeSend!(createUnhandledJsExceptionEvent()) @@ -138,7 +139,7 @@ final class RNSentryStartTests: XCTestCase { for startMethod in testCases { try startMethod() - let actualOptions = PrivateSentrySDKOnly.options + let actualOptions = SentrySDK.internal.options let actualEvent = actualOptions.beforeSend!(createNativeEvent()) @@ -160,7 +161,7 @@ final class RNSentryStartTests: XCTestCase { } } - PrivateSentrySDKOnly.options.beforeSend!(genericEvent()) + SentrySDK.internal.options.beforeSend!(genericEvent()) XCTAssertTrue(executed) } @@ -207,7 +208,7 @@ final class RNSentryStartTests: XCTestCase { ] ]) - let actualOptions = PrivateSentrySDKOnly.options + let actualOptions = SentrySDK.internal.options XCTAssertTrue(actualOptions.attachScreenshot) XCTAssertFalse(actualOptions.screenshot.maskAllText) XCTAssertTrue(actualOptions.screenshot.maskAllImages) @@ -219,7 +220,7 @@ final class RNSentryStartTests: XCTestCase { "attachScreenshot": true ]) - let actualOptions = PrivateSentrySDKOnly.options + let actualOptions = SentrySDK.internal.options XCTAssertTrue(actualOptions.attachScreenshot) XCTAssertTrue(actualOptions.screenshot.maskAllText) XCTAssertTrue(actualOptions.screenshot.maskAllImages) @@ -258,8 +259,8 @@ final class RNSentryStartTests: XCTestCase { var actualEvent: Event? // This is the closest to the sent event we can get using the actual Sentry start method - let originalBeforeSend = PrivateSentrySDKOnly.options.beforeSend - PrivateSentrySDKOnly.options.beforeSend = { event in + let originalBeforeSend = SentrySDK.internal.options.beforeSend + SentrySDK.internal.options.beforeSend = { event in if let originalBeforeSend = originalBeforeSend { let processedEvent = originalBeforeSend(event) actualEvent = processedEvent