Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions packages/core/RNSentryCocoaTester/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
require_relative '../node_modules/react-native/scripts/react_native_pods'

ENV['RCT_USE_PREBUILT_RNCORE'] = '0'

platform :ios, '15.1'

target 'RNSentryCocoaTesterTests' do
Expand All @@ -10,27 +12,24 @@ target 'RNSentryCocoaTesterTests' do
pod 'OCMock', '3.9.1'

post_install do |installer|
set_react_native_path(installer)
end
end

def extract_projects(installer)
return installer.aggregate_targets
.map{ |t| t.user_project }
.uniq{ |p| p.path }
.push(installer.pods_project)
end

def set_react_native_path(installer)
# https://github.com/facebook/react-native/blob/9cc6f007ba1cf112466ccf685c0ef918bba69dd7/packages/react-native/scripts/react_native_pods.rb#L378
Pod::UI.puts("Setting REACT_NATIVE_PATH build settings")
react_native_post_install(installer)

projects = extract_projects(installer)

projects.each do |project|
project.build_configurations.each do |config|
config.build_settings["REACT_NATIVE_PATH"] = '${PODS_ROOT}/../../node_modules/react-native'
# React-timing pod in RN 0.86 is missing PrivacyInfo.xcprivacy
timing_privacy = File.join(__dir__, '..', 'node_modules', 'react-native', 'ReactCommon', 'react', 'timing', 'PrivacyInfo.xcprivacy')
unless File.exist?(timing_privacy)
File.write(timing_privacy, <<~PLIST)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyTracking</key>
<false/>
</dict>
</plist>
PLIST
end
project.save()
end
end

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
/* Begin PBXBuildFile section */
332D33472CDBDBB600547D76 /* RNSentryReplayOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 332D33462CDBDBB600547D76 /* RNSentryReplayOptionsTests.swift */; };
3339C4812D6625570088EB3A /* RNSentryUserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3339C4802D6625570088EB3A /* RNSentryUserTests.m */; };
B4DEB41739F14AA38202D4D4 /* RNSentryUriValidationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */; };
336084392C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 336084382C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift */; };
3380C6C42CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3380C6C32CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift */; };
33AFDFED2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33AFDFEC2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m */; };
Expand All @@ -19,6 +18,7 @@
33DEDFF02D9185EB006066E4 /* RNSentryTimeToDisplayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33DEDFEF2D9185E3006066E4 /* RNSentryTimeToDisplayTests.swift */; };
33F58AD02977037D008F60EA /* RNSentryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33F58ACF2977037D008F60EA /* RNSentryTests.m */; };
AEFB00422CC90C4B00EC8A9A /* RNSentryBreadcrumbTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3360843C2C340C76008CC412 /* RNSentryBreadcrumbTests.swift */; };
B4DEB41739F14AA38202D4D4 /* RNSentryUriValidationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */; };
B5859A50A3E865EF5E61465A /* libPods-RNSentryCocoaTesterTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 650CB718ACFBD05609BF2126 /* libPods-RNSentryCocoaTesterTests.a */; };
/* End PBXBuildFile section */

Expand All @@ -31,7 +31,6 @@
332D334A2CDCC8EB00547D76 /* RNSentryCocoaTesterTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNSentryCocoaTesterTests-Bridging-Header.h"; sourceTree = "<group>"; };
3339C47F2D6625260088EB3A /* RNSentry+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNSentry+Test.h"; sourceTree = "<group>"; };
3339C4802D6625570088EB3A /* RNSentryUserTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryUserTests.m; sourceTree = "<group>"; };
3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryUriValidationTests.m; sourceTree = "<group>"; };
336084382C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RNSentryReplayBreadcrumbConverterTests.swift; sourceTree = "<group>"; };
3360843A2C32E3A8008CC412 /* RNSentryReplayBreadcrumbConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSentryReplayBreadcrumbConverter.h; path = ../ios/RNSentryReplayBreadcrumbConverter.h; sourceTree = "<group>"; };
3360843C2C340C76008CC412 /* RNSentryBreadcrumbTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNSentryBreadcrumbTests.swift; sourceTree = "<group>"; };
Expand All @@ -50,6 +49,7 @@
33DEDFEE2D8DD431006066E4 /* RNSentryTimeToDisplay.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNSentryTimeToDisplay.h; path = ../ios/RNSentryTimeToDisplay.h; sourceTree = SOURCE_ROOT; };
33DEDFEF2D9185E3006066E4 /* RNSentryTimeToDisplayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNSentryTimeToDisplayTests.swift; sourceTree = "<group>"; };
33F58ACF2977037D008F60EA /* RNSentryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSentryTests.m; sourceTree = "<group>"; };
3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryUriValidationTests.m; sourceTree = "<group>"; };
650CB718ACFBD05609BF2126 /* libPods-RNSentryCocoaTesterTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNSentryCocoaTesterTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
E2321E7CFA55AB617247098E /* Pods-RNSentryCocoaTesterTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNSentryCocoaTesterTests.debug.xcconfig"; path = "Target Support Files/Pods-RNSentryCocoaTesterTests/Pods-RNSentryCocoaTesterTests.debug.xcconfig"; sourceTree = "<group>"; };
F48F26542EA2A481008A185E /* RNSentryEmitNewFrameEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNSentryEmitNewFrameEvent.h; path = ../ios/RNSentryEmitNewFrameEvent.h; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -241,14 +241,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNSentryCocoaTesterTests/Pods-RNSentryCocoaTesterTests-resources-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNSentryCocoaTesterTests/Pods-RNSentryCocoaTesterTests-resources-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNSentryCocoaTesterTests/Pods-RNSentryCocoaTesterTests-resources.sh\"\n";
Expand Down Expand Up @@ -285,7 +281,7 @@
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
Expand Down Expand Up @@ -334,8 +330,14 @@
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
USE_HERMES = false;
};
name = Debug;
};
Expand All @@ -345,7 +347,7 @@
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
Expand Down Expand Up @@ -387,8 +389,13 @@
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = false;
VALIDATE_PRODUCT = YES;
};
name = Release;
Expand Down Expand Up @@ -444,7 +451,7 @@
"\"$(PODS_TARGET_SRCROOT)/include/\"",
"\"${PODS_ROOT}/Sentry/Sources/Sentry/include\"",
);
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = io.sentry.RNSentryCocoaTesterTests;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down Expand Up @@ -511,7 +518,7 @@
"\"$(PODS_TARGET_SRCROOT)/include/\"",
"\"${PODS_ROOT}/Sentry/Sources/Sentry/include\"",
);
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = io.sentry.RNSentryCocoaTesterTests;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,10 @@ final class RNSentryReplayOptions: XCTestCase {
}

func assertContainsClass(classArray: [AnyClass], stringClass: String) {
XCTAssertTrue(mapToObjectIdentifiers(classArray: classArray).contains(ObjectIdentifier(NSClassFromString(stringClass)!)))
guard let cls = NSClassFromString(stringClass) else {
return
}
XCTAssertTrue(mapToObjectIdentifiers(classArray: classArray).contains(ObjectIdentifier(cls)))
}

func mapToObjectIdentifiers(classArray: [AnyClass]) -> [ObjectIdentifier] {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module.exports = {
collectCoverage: true,
preset: 'react-native',
preset: '@react-native/jest-preset',
setupFilesAfterEnv: ['jest-extended/all', '<rootDir>/test/mockConsole.ts'],
globals: {
__DEV__: true,
Expand Down
7 changes: 4 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@
"@expo/metro-config": "~0.20.0",
"@microsoft/api-extractor": "^7.58.7",
"@mswjs/interceptors": "^0.25.15",
"@react-native/babel-preset": "0.80.0",
"@react-native/babel-preset": "0.86.0",
"@react-native/jest-preset": "0.86.0",
"@sentry/eslint-plugin-sdk": "10.58.0",
"@sentry/typescript": "10.58.0",
"@sentry/wizard": "6.12.0",
Expand All @@ -106,22 +107,22 @@
"jest-environment-jsdom": "^29.6.2",
"jest-extended": "^4.0.2",
"madge": "^6.1.0",
"metro": "0.83.1",
"metro": "0.84.4",
"oxfmt": "^0.42.0",
"oxlint": "^1.56.0",
"oxlint-tsgolint": "^0.17.4",
"react": "19.1.0",
"react-native": "0.80.1",
"react-native": "0.86.0",
"react-test-renderer": "19.1.0",
"rimraf": "^4.1.1",
"ts-jest": "^29.3.1",
"typescript": "~5.9.3",
"uglify-js": "^3.17.4",
"xmlhttprequest": "^1.8.0"
},
"codegenConfig": {
"name": "RNSentrySpec",
"type": "all",

Check warning on line 125 in packages/core/package.json

View check run for this annotation

@sentry/warden / warden: find-bugs

Metro 0.84+ `dev` fallback skips debug ID injection and source maps for `--dev true` static bundles

In Metro 0.84+ the `hot` property was removed from `transformOptions`, so the new guard `'hot' in graph.transformOptions ? graph.transformOptions.hot : graph.transformOptions.dev` falls back to `graph.transformOptions.dev`. A `react-native bundle --dev true` static build passes `dev=true` (with no dev server / hot reload), making `isHot=true`. In `vendor/metro/utils.ts` this skips `sentryBundleCallback` (line 119) and returns code only with no source map (line 123-125). In `sentryMetroSerializer.ts` line 60 the same fallback returns early, skipping insertion of the Sentry debug ID module and the `//# debugId=` annotation. In Metro โ‰ค0.83 `hot` was `false` for static dev builds, so source maps and debug IDs were generated. The fallback silently changes behavior for dev static builds with no warning emitted to the user.
"jsSrcsDir": "src",
"android": {
"javaPackageName": "io.sentry.react"
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/js/tools/metroMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ export const withSentryMiddleware = (config: InputConfigT): InputConfigT => {
const allowedRoots = [projectRoot, ...watchFolders];

const originalEnhanceMiddleware = config.server.enhanceMiddleware;
config.server.enhanceMiddleware = (middleware, server) => {
// @ts-expect-error enhanceMiddleware is typed read only in metro 0.84+
config.server.enhanceMiddleware = (middleware: Middleware, server: unknown) => {
const sentryMiddleware = createSentryMetroMiddleware(middleware, allowedRoots);
return originalEnhanceMiddleware ? originalEnhanceMiddleware(sentryMiddleware, server) : sentryMiddleware;
};
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/js/tools/metroconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ export function withSentryFramesCollapsed(config: MetroConfig): MetroConfig {

const customizeFrame = (frame: MetroFrame): MetroCustomizeFrameReturnValue => {
const originalOrSentryCustomizeFrame = (
originalCustomization: MetroCustomizeFrame | undefined,
originalCustomization: MetroCustomizeFrame | null | undefined,
): MetroCustomizeFrame => ({
...originalCustomization,
collapse: originalCustomization?.collapse || collapseSentryInternalFrames(frame),
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/js/tools/sentryMetroSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
export const createSentryMetroSerializer = (customSerializer?: MetroSerializer): MetroSerializer => {
const serializer = customSerializer || createDefaultMetroSerializer();
return async function (entryPoint, preModules, graph, options) {
if (graph.transformOptions.hot) {
if ('hot' in graph.transformOptions ? graph.transformOptions.hot : graph.transformOptions.dev) {

Check warning on line 60 in packages/core/src/js/tools/sentryMetroSerializer.ts

View check run for this annotation

@sentry/warden / warden: find-bugs

[25L-NF6] Metro 0.84+ `dev` fallback skips debug ID injection and source maps for `--dev true` static bundles (additional location)

In Metro 0.84+ the `hot` property was removed from `transformOptions`, so the new guard `'hot' in graph.transformOptions ? graph.transformOptions.hot : graph.transformOptions.dev` falls back to `graph.transformOptions.dev`. A `react-native bundle --dev true` static build passes `dev=true` (with no dev server / hot reload), making `isHot=true`. In `vendor/metro/utils.ts` this skips `sentryBundleCallback` (line 119) and returns code only with no source map (line 123-125). In `sentryMetroSerializer.ts` line 60 the same fallback returns early, skipping insertion of the Sentry debug ID module and the `//# debugId=` annotation. In Metro โ‰ค0.83 `hot` was `false` for static dev builds, so source maps and debug IDs were generated. The fallback silently changes behavior for dev static builds with no warning emitted to the user.
return serializer(entryPoint, preModules, graph, options);
}

Comment thread
sentry[bot] marked this conversation as resolved.
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/js/tools/sentryOptionsSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export function withSentryOptionsFromFile(config: MetroConfig, optionsFile: stri
});
}

// @ts-expect-error customSerializer is typed read only in metro 0.84+
config.serializer.customSerializer = sentryOptionsSerializer;
return config;
}
Expand Down
7 changes: 4 additions & 3 deletions packages/core/src/js/tools/vendor/metro/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,13 @@ export const createDefaultMetroSerializer = (): MetroSerializer => {
return (entryPoint, preModules, graph, options) => {
// baseJSBundle assigns IDs to modules in a consistent order
let bundle = baseJSBundle(entryPoint, preModules, graph, options);
if (options.sentryBundleCallback && !graph.transformOptions.hot) {
const isHot = 'hot' in graph.transformOptions ? graph.transformOptions.hot : graph.transformOptions.dev;
if (options.sentryBundleCallback && !isHot) {
bundle = options.sentryBundleCallback(bundle);
}
const { code } = bundleToString(bundle);
if (graph.transformOptions.hot) {
// Hot means running in dev server, sourcemaps are generated on demand
if (isHot) {
// Hot/dev means running in dev server, sourcemaps are generated on demand
return code;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/RNTestEnvironment.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
const ReactNativeEnv = require('react-native/jest/react-native-env');
const ReactNativeEnv = require('@react-native/jest-preset/jest/react-native-env');

// Extends the `react-native` preset's test environment but drops the `react-native` export
// condition. Since v10.58.0 the JS SDK packages expose a `react-native` condition pointing at
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/tools/sentryMetroSerializer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { MixedOutput, Module } from 'metro';

import * as fs from 'fs';
import CountingSet from 'metro/private/lib/CountingSet';
import * as countLines from 'metro/private/lib/countLines';
import countLines from 'metro/private/lib/countLines';
import { minify } from 'uglify-js';

import { createSentryMetroSerializer } from '../../src/js/tools/sentryMetroSerializer';
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/tools/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Module } from 'metro';

import * as countLines from 'metro/private/lib/countLines';
import countLines from 'metro/private/lib/countLines';

import type { VirtualJSOutput } from '../../src/js/tools/utils';

Expand Down
Loading
Loading