Skip to content

Commit 88735e9

Browse files
antonisclaude
andauthored
chore(core): Bump react-native and metro devDependencies to 0.86.0 (#6316)
* chore(core): Bump react-native and metro devDependencies to 0.86.0 Bumps react-native devDependency from 0.80.1 to 0.86.0 and metro from 0.83.1 to 0.84.4 to align type-checking with the latest RN release. Type fixes: - Accept null in MetroCustomizeFrame callback parameter - Add ts-expect-error for readonly enhanceMiddleware and customSerializer - Add explicit parameter types in enhanceMiddleware callback - Replace removed `hot` field with `dev` in transform options checks - Update jest preset from react-native to @react-native/jest-preset - Update RNTestEnvironment to use new jest-preset path Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Use runtime check for hot field removed in metro 0.84 Metro 0.84 removed `transformOptions.hot` from JsTransformOptions. Instead of blindly replacing with `dev` (which would skip debug ID injection for `--dev` CLI builds), check at runtime whether `hot` exists and fall back to `dev` only when it doesn't. Also improve ts-expect-error comments to note metro version context. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ios): Update RNSentryCocoaTester for RN 0.86 prebuilt pods - Replace custom `set_react_native_path` with `react_native_post_install` to generate React-VFS.yaml needed by RN 0.86's prebuilt frameworks - Bump IPHONEOS_DEPLOYMENT_TARGET from 15.0 to 15.1 to match RN 0.86 minimum Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ios): Force source builds for RN 0.86 CocoaTester compatibility Set RCT_USE_PREBUILT_RNCORE=0 to build React Native from source instead of using prebuilt frameworks, fixing modulemap discovery failures with Xcode 26's explicit modules. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ios): Fix RN 0.86 CocoaTester build and test failures Work around missing PrivacyInfo.xcprivacy in React-timing pod and guard against nil NSClassFromString for classes removed by RCT_REMOVE_LEGACY_ARCH. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 21a1e70 commit 88735e9

14 files changed

Lines changed: 62 additions & 763 deletions

File tree

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
require_relative '../node_modules/react-native/scripts/react_native_pods'
22

3+
ENV['RCT_USE_PREBUILT_RNCORE'] = '0'
4+
35
platform :ios, '15.1'
46

57
target 'RNSentryCocoaTesterTests' do
@@ -10,27 +12,24 @@ target 'RNSentryCocoaTesterTests' do
1012
pod 'OCMock', '3.9.1'
1113

1214
post_install do |installer|
13-
set_react_native_path(installer)
14-
end
15-
end
16-
17-
def extract_projects(installer)
18-
return installer.aggregate_targets
19-
.map{ |t| t.user_project }
20-
.uniq{ |p| p.path }
21-
.push(installer.pods_project)
22-
end
23-
24-
def set_react_native_path(installer)
25-
# https://github.com/facebook/react-native/blob/9cc6f007ba1cf112466ccf685c0ef918bba69dd7/packages/react-native/scripts/react_native_pods.rb#L378
26-
Pod::UI.puts("Setting REACT_NATIVE_PATH build settings")
15+
react_native_post_install(installer)
2716

28-
projects = extract_projects(installer)
29-
30-
projects.each do |project|
31-
project.build_configurations.each do |config|
32-
config.build_settings["REACT_NATIVE_PATH"] = '${PODS_ROOT}/../../node_modules/react-native'
17+
# React-timing pod in RN 0.86 is missing PrivacyInfo.xcprivacy
18+
timing_privacy = File.join(__dir__, '..', 'node_modules', 'react-native', 'ReactCommon', 'react', 'timing', 'PrivacyInfo.xcprivacy')
19+
unless File.exist?(timing_privacy)
20+
File.write(timing_privacy, <<~PLIST)
21+
<?xml version="1.0" encoding="UTF-8"?>
22+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
23+
<plist version="1.0">
24+
<dict>
25+
<key>NSPrivacyCollectedDataTypes</key>
26+
<array/>
27+
<key>NSPrivacyTracking</key>
28+
<false/>
29+
</dict>
30+
</plist>
31+
PLIST
3332
end
34-
project.save()
3533
end
3634
end
35+

packages/core/RNSentryCocoaTester/RNSentryCocoaTester.xcodeproj/project.pbxproj

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
/* Begin PBXBuildFile section */
1010
332D33472CDBDBB600547D76 /* RNSentryReplayOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 332D33462CDBDBB600547D76 /* RNSentryReplayOptionsTests.swift */; };
1111
3339C4812D6625570088EB3A /* RNSentryUserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3339C4802D6625570088EB3A /* RNSentryUserTests.m */; };
12-
B4DEB41739F14AA38202D4D4 /* RNSentryUriValidationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */; };
1312
336084392C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 336084382C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift */; };
1413
3380C6C42CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3380C6C32CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift */; };
1514
33AFDFED2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33AFDFEC2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m */; };
@@ -19,6 +18,7 @@
1918
33DEDFF02D9185EB006066E4 /* RNSentryTimeToDisplayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33DEDFEF2D9185E3006066E4 /* RNSentryTimeToDisplayTests.swift */; };
2019
33F58AD02977037D008F60EA /* RNSentryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33F58ACF2977037D008F60EA /* RNSentryTests.m */; };
2120
AEFB00422CC90C4B00EC8A9A /* RNSentryBreadcrumbTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3360843C2C340C76008CC412 /* RNSentryBreadcrumbTests.swift */; };
21+
B4DEB41739F14AA38202D4D4 /* RNSentryUriValidationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */; };
2222
B5859A50A3E865EF5E61465A /* libPods-RNSentryCocoaTesterTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 650CB718ACFBD05609BF2126 /* libPods-RNSentryCocoaTesterTests.a */; };
2323
/* End PBXBuildFile section */
2424

@@ -31,7 +31,6 @@
3131
332D334A2CDCC8EB00547D76 /* RNSentryCocoaTesterTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNSentryCocoaTesterTests-Bridging-Header.h"; sourceTree = "<group>"; };
3232
3339C47F2D6625260088EB3A /* RNSentry+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNSentry+Test.h"; sourceTree = "<group>"; };
3333
3339C4802D6625570088EB3A /* RNSentryUserTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryUserTests.m; sourceTree = "<group>"; };
34-
3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryUriValidationTests.m; sourceTree = "<group>"; };
3534
336084382C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RNSentryReplayBreadcrumbConverterTests.swift; sourceTree = "<group>"; };
3635
3360843A2C32E3A8008CC412 /* RNSentryReplayBreadcrumbConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSentryReplayBreadcrumbConverter.h; path = ../ios/RNSentryReplayBreadcrumbConverter.h; sourceTree = "<group>"; };
3736
3360843C2C340C76008CC412 /* RNSentryBreadcrumbTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNSentryBreadcrumbTests.swift; sourceTree = "<group>"; };
@@ -50,6 +49,7 @@
5049
33DEDFEE2D8DD431006066E4 /* RNSentryTimeToDisplay.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNSentryTimeToDisplay.h; path = ../ios/RNSentryTimeToDisplay.h; sourceTree = SOURCE_ROOT; };
5150
33DEDFEF2D9185E3006066E4 /* RNSentryTimeToDisplayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNSentryTimeToDisplayTests.swift; sourceTree = "<group>"; };
5251
33F58ACF2977037D008F60EA /* RNSentryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSentryTests.m; sourceTree = "<group>"; };
52+
3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryUriValidationTests.m; sourceTree = "<group>"; };
5353
650CB718ACFBD05609BF2126 /* libPods-RNSentryCocoaTesterTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNSentryCocoaTesterTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
5454
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>"; };
5555
F48F26542EA2A481008A185E /* RNSentryEmitNewFrameEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNSentryEmitNewFrameEvent.h; path = ../ios/RNSentryEmitNewFrameEvent.h; sourceTree = SOURCE_ROOT; };
@@ -241,14 +241,10 @@
241241
inputFileListPaths = (
242242
"${PODS_ROOT}/Target Support Files/Pods-RNSentryCocoaTesterTests/Pods-RNSentryCocoaTesterTests-resources-${CONFIGURATION}-input-files.xcfilelist",
243243
);
244-
inputPaths = (
245-
);
246244
name = "[CP] Copy Pods Resources";
247245
outputFileListPaths = (
248246
"${PODS_ROOT}/Target Support Files/Pods-RNSentryCocoaTesterTests/Pods-RNSentryCocoaTesterTests-resources-${CONFIGURATION}-output-files.xcfilelist",
249247
);
250-
outputPaths = (
251-
);
252248
runOnlyForDeploymentPostprocessing = 0;
253249
shellPath = /bin/sh;
254250
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNSentryCocoaTesterTests/Pods-RNSentryCocoaTesterTests-resources.sh\"\n";
@@ -285,7 +281,7 @@
285281
ALWAYS_SEARCH_USER_PATHS = NO;
286282
CLANG_ANALYZER_NONNULL = YES;
287283
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
288-
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
284+
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
289285
CLANG_ENABLE_MODULES = YES;
290286
CLANG_ENABLE_OBJC_ARC = YES;
291287
CLANG_ENABLE_OBJC_WEAK = YES;
@@ -334,8 +330,14 @@
334330
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
335331
MTL_FAST_MATH = YES;
336332
ONLY_ACTIVE_ARCH = YES;
333+
OTHER_LDFLAGS = (
334+
"$(inherited)",
335+
" ",
336+
);
337337
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
338338
SDKROOT = iphoneos;
339+
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
340+
USE_HERMES = false;
339341
};
340342
name = Debug;
341343
};
@@ -345,7 +347,7 @@
345347
ALWAYS_SEARCH_USER_PATHS = NO;
346348
CLANG_ANALYZER_NONNULL = YES;
347349
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
348-
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
350+
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
349351
CLANG_ENABLE_MODULES = YES;
350352
CLANG_ENABLE_OBJC_ARC = YES;
351353
CLANG_ENABLE_OBJC_WEAK = YES;
@@ -387,8 +389,13 @@
387389
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
388390
MTL_ENABLE_DEBUG_INFO = NO;
389391
MTL_FAST_MATH = YES;
392+
OTHER_LDFLAGS = (
393+
"$(inherited)",
394+
" ",
395+
);
390396
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
391397
SDKROOT = iphoneos;
398+
USE_HERMES = false;
392399
VALIDATE_PRODUCT = YES;
393400
};
394401
name = Release;
@@ -444,7 +451,7 @@
444451
"\"$(PODS_TARGET_SRCROOT)/include/\"",
445452
"\"${PODS_ROOT}/Sentry/Sources/Sentry/include\"",
446453
);
447-
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
454+
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
448455
MARKETING_VERSION = 1.0;
449456
PRODUCT_BUNDLE_IDENTIFIER = io.sentry.RNSentryCocoaTesterTests;
450457
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -511,7 +518,7 @@
511518
"\"$(PODS_TARGET_SRCROOT)/include/\"",
512519
"\"${PODS_ROOT}/Sentry/Sources/Sentry/include\"",
513520
);
514-
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
521+
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
515522
MARKETING_VERSION = 1.0;
516523
PRODUCT_BUNDLE_IDENTIFIER = io.sentry.RNSentryCocoaTesterTests;
517524
PRODUCT_NAME = "$(TARGET_NAME)";

packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryReplayOptionsTests.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,10 @@ final class RNSentryReplayOptions: XCTestCase {
148148
}
149149

150150
func assertContainsClass(classArray: [AnyClass], stringClass: String) {
151-
XCTAssertTrue(mapToObjectIdentifiers(classArray: classArray).contains(ObjectIdentifier(NSClassFromString(stringClass)!)))
151+
guard let cls = NSClassFromString(stringClass) else {
152+
return
153+
}
154+
XCTAssertTrue(mapToObjectIdentifiers(classArray: classArray).contains(ObjectIdentifier(cls)))
152155
}
153156

154157
func mapToObjectIdentifiers(classArray: [AnyClass]) -> [ObjectIdentifier] {

packages/core/jest.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module.exports = {
22
collectCoverage: true,
3-
preset: 'react-native',
3+
preset: '@react-native/jest-preset',
44
setupFilesAfterEnv: ['jest-extended/all', '<rootDir>/test/mockConsole.ts'],
55
globals: {
66
__DEV__: true,

packages/core/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@
8585
"@expo/metro-config": "~0.20.0",
8686
"@microsoft/api-extractor": "^7.58.7",
8787
"@mswjs/interceptors": "^0.25.15",
88-
"@react-native/babel-preset": "0.80.0",
88+
"@react-native/babel-preset": "0.86.0",
89+
"@react-native/jest-preset": "0.86.0",
8990
"@sentry/eslint-plugin-sdk": "10.59.0",
9091
"@sentry/typescript": "10.59.0",
9192
"@sentry/wizard": "6.12.0",
@@ -106,12 +107,12 @@
106107
"jest-environment-jsdom": "^29.6.2",
107108
"jest-extended": "^4.0.2",
108109
"madge": "^6.1.0",
109-
"metro": "0.83.1",
110+
"metro": "0.84.4",
110111
"oxfmt": "^0.42.0",
111112
"oxlint": "^1.56.0",
112113
"oxlint-tsgolint": "^0.17.4",
113114
"react": "19.1.0",
114-
"react-native": "0.80.1",
115+
"react-native": "0.86.0",
115116
"react-test-renderer": "19.1.0",
116117
"rimraf": "^4.1.1",
117118
"ts-jest": "^29.3.1",

packages/core/src/js/tools/metroMiddleware.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ export const withSentryMiddleware = (config: InputConfigT): InputConfigT => {
149149
const allowedRoots = [projectRoot, ...watchFolders];
150150

151151
const originalEnhanceMiddleware = config.server.enhanceMiddleware;
152-
config.server.enhanceMiddleware = (middleware, server) => {
152+
// @ts-expect-error enhanceMiddleware is typed read only in metro 0.84+
153+
config.server.enhanceMiddleware = (middleware: Middleware, server: unknown) => {
153154
const sentryMiddleware = createSentryMetroMiddleware(middleware, allowedRoots);
154155
return originalEnhanceMiddleware ? originalEnhanceMiddleware(sentryMiddleware, server) : sentryMiddleware;
155156
};

packages/core/src/js/tools/metroconfig.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ export function withSentryFramesCollapsed(config: MetroConfig): MetroConfig {
437437

438438
const customizeFrame = (frame: MetroFrame): MetroCustomizeFrameReturnValue => {
439439
const originalOrSentryCustomizeFrame = (
440-
originalCustomization: MetroCustomizeFrame | undefined,
440+
originalCustomization: MetroCustomizeFrame | null | undefined,
441441
): MetroCustomizeFrame => ({
442442
...originalCustomization,
443443
collapse: originalCustomization?.collapse || collapseSentryInternalFrames(frame),

packages/core/src/js/tools/sentryMetroSerializer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export function unstableBeforeAssetSerializationDebugIdPlugin({
5757
export const createSentryMetroSerializer = (customSerializer?: MetroSerializer): MetroSerializer => {
5858
const serializer = customSerializer || createDefaultMetroSerializer();
5959
return async function (entryPoint, preModules, graph, options) {
60-
if (graph.transformOptions.hot) {
60+
if ('hot' in graph.transformOptions ? graph.transformOptions.hot : graph.transformOptions.dev) {
6161
return serializer(entryPoint, preModules, graph, options);
6262
}
6363

packages/core/src/js/tools/sentryOptionsSerializer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export function withSentryOptionsFromFile(config: MetroConfig, optionsFile: stri
6464
});
6565
}
6666

67+
// @ts-expect-error customSerializer is typed read only in metro 0.84+
6768
config.serializer.customSerializer = sentryOptionsSerializer;
6869
return config;
6970
}

packages/core/src/js/tools/vendor/metro/utils.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,13 @@ export const createDefaultMetroSerializer = (): MetroSerializer => {
115115
return (entryPoint, preModules, graph, options) => {
116116
// baseJSBundle assigns IDs to modules in a consistent order
117117
let bundle = baseJSBundle(entryPoint, preModules, graph, options);
118-
if (options.sentryBundleCallback && !graph.transformOptions.hot) {
118+
const isHot = 'hot' in graph.transformOptions ? graph.transformOptions.hot : graph.transformOptions.dev;
119+
if (options.sentryBundleCallback && !isHot) {
119120
bundle = options.sentryBundleCallback(bundle);
120121
}
121122
const { code } = bundleToString(bundle);
122-
if (graph.transformOptions.hot) {
123-
// Hot means running in dev server, sourcemaps are generated on demand
123+
if (isHot) {
124+
// Hot/dev means running in dev server, sourcemaps are generated on demand
124125
return code;
125126
}
126127

0 commit comments

Comments
 (0)