Skip to content

Commit

Permalink
misc: Add linked errors examples to the sample apps (#3549)
Browse files Browse the repository at this point in the history
* Fix native linked errors execution order

* fix lint

* Add integrations execution order tests

* Add jest extended types and linkedErrors order tests

* Add changelog

* remove empty test

* fix native linked errors async calls

* fix native async calls ios

* fix old arch build

* feat: Add linked errors examples to the sample apps

* fix sample lint

* remove unused header file
  • Loading branch information
krystofwoldrich authored Feb 15, 2024
1 parent deebf78 commit bc4b9f6
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 15 deletions.
8 changes: 8 additions & 0 deletions samples/expo/app/(tabs)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ export default function TabOneScreen() {
Sentry.captureException(new Error('Captured exception'));
}}
/>
<Button
title="Capture exception with cause"
onPress={() => {
const error = new Error('Captured exception')
error.cause = new Error('Cause of captured exception')
Sentry.captureException(error);
}}
/>
<Button
title="Uncaught Thrown Error"
onPress={() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,16 @@ import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.flipper.ReactNativeFlipper
import com.facebook.soloader.SoLoader
import io.sentry.react.RNSentryPackage

class MainApplication : Application(), ReactApplication {
class MainApplication() : Application(), ReactApplication {
override val reactNativeHost: ReactNativeHost =
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> {
val packages: MutableList<ReactPackage> = PackageList(this).packages
packages.add(SamplePackage())
// Packages that cannot be auto linked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
for (pkg in packages) {
if (pkg is RNSentryPackage) {
return packages
}
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
add(SamplePackage())
add(TurboSamplePackage())
}
packages.add(RNSentryPackage())
return packages
}

override fun getJSMainModuleName(): String = "index"
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
Expand All @@ -47,4 +39,4 @@ class MainApplication : Application(), ReactApplication {
}
ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.samplenewarchitecture

import com.facebook.fbreact.specs.NativePlatformSampleModuleSpec
import com.facebook.react.bridge.ReactApplicationContext

class NativePlatformSampleModule(reactContext: ReactApplicationContext) : NativePlatformSampleModuleSpec(reactContext) {

override fun getName() = NAME

override fun crashOrString(): String {
throw RuntimeException("JVM Crash in NativePlatformSampleModule.crashOrString()")
}

companion object {
const val NAME = "NativePlatformSampleModule"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.samplenewarchitecture

import com.facebook.react.TurboReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.model.ReactModuleInfo
import com.facebook.react.module.model.ReactModuleInfoProvider
import org.jetbrains.annotations.Nullable

class TurboSamplePackage : TurboReactPackage() {
@Nullable
override fun getModule(
name: String,
reactApplicationContext: ReactApplicationContext
): NativeModule? {
return if (name == NativePlatformSampleModule.NAME) {
NativePlatformSampleModule(reactApplicationContext)
} else {
null
}
}

override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
return ReactModuleInfoProvider {
val moduleInfos: MutableMap<String, ReactModuleInfo> =
HashMap()
moduleInfos[NativePlatformSampleModule.NAME] = ReactModuleInfo(
NativePlatformSampleModule.NAME,
NativePlatformSampleModule.NAME,
false, // canOverrideExistingModule
false, // needsEagerInit
true, // hasConstants
false, // isCxxModule
true // isTurboModule
)
moduleInfos
}
}
}
6 changes: 6 additions & 0 deletions samples/react-native/android/app/src/main/jni/OnLoad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
// }
// }

#include <AppSpecs.h>
#include <DefaultComponentsRegistry.h>
#include <DefaultTurboModuleManagerDelegate.h>
#include <fbjni/fbjni.h>
Expand Down Expand Up @@ -73,6 +74,11 @@ std::shared_ptr<TurboModule> javaModuleProvider(
// }
// return rncore_ModuleProvider(moduleName, params);

auto module = AppSpecs_ModuleProvider(name, params);
if (module != nullptr) {
return module;
}

// By default we just use the module providers autolinked by RN CLI
return rncli_ModuleProvider(name, params);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
338BBBC82B614FA10035844C /* NativePlatformSampleModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 338BBBC62B614FA10035844C /* NativePlatformSampleModule.mm */; };
33E2D62A29A7719600B5042B /* RCTAssetsModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 33E2D62829A7719600B5042B /* RCTAssetsModule.m */; };
7699B88040F8A987B510C191 /* libPods-sampleNewArchitecture-sampleNewArchitectureTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-sampleNewArchitecture-sampleNewArchitectureTests.a */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
Expand All @@ -38,6 +39,8 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = sampleNewArchitecture/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = sampleNewArchitecture/main.m; sourceTree = "<group>"; };
19F6CBCC0A4E27FBF8BF4A61 /* libPods-sampleNewArchitecture-sampleNewArchitectureTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-sampleNewArchitecture-sampleNewArchitectureTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
338BBBC62B614FA10035844C /* NativePlatformSampleModule.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NativePlatformSampleModule.mm; path = sampleNewArchitecture/NativePlatformSampleModule.mm; sourceTree = "<group>"; };
338BBBC72B614FA10035844C /* NativePlatformSampleModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativePlatformSampleModule.h; path = sampleNewArchitecture/NativePlatformSampleModule.h; sourceTree = "<group>"; };
33E2D62829A7719600B5042B /* RCTAssetsModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RCTAssetsModule.m; path = sampleNewArchitecture/RCTAssetsModule.m; sourceTree = "<group>"; };
33E2D62929A7719600B5042B /* RCTAssetsModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTAssetsModule.h; path = sampleNewArchitecture/RCTAssetsModule.h; sourceTree = "<group>"; };
3B4392A12AC88292D35C810B /* Pods-sampleNewArchitecture.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-sampleNewArchitecture.debug.xcconfig"; path = "Target Support Files/Pods-sampleNewArchitecture/Pods-sampleNewArchitecture.debug.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -89,6 +92,8 @@
13B07FAE1A68108700A75B9A /* sampleNewArchitecture */ = {
isa = PBXGroup;
children = (
338BBBC72B614FA10035844C /* NativePlatformSampleModule.h */,
338BBBC62B614FA10035844C /* NativePlatformSampleModule.mm */,
33E2D62929A7719600B5042B /* RCTAssetsModule.h */,
33E2D62829A7719600B5042B /* RCTAssetsModule.m */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
Expand Down Expand Up @@ -416,6 +421,7 @@
files = (
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
338BBBC82B614FA10035844C /* NativePlatformSampleModule.mm in Sources */,
33E2D62A29A7719600B5042B /* RCTAssetsModule.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -601,6 +607,7 @@
"-DFOLLY_NO_CONFIG",
"-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1",
" ",
);
OTHER_LDFLAGS = (
"$(inherited)",
Expand Down Expand Up @@ -673,6 +680,7 @@
"-DFOLLY_NO_CONFIG",
"-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1",
" ",
);
OTHER_LDFLAGS = (
"$(inherited)",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#import <Foundation/Foundation.h>

#ifdef RCT_NEW_ARCH_ENABLED
#import <AppSpecs/AppSpecs.h>

@interface NativePlatformSampleModule : NSObject <NativePlatformSampleModuleSpec>

@end
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#import "NativePlatformSampleModule.h"

#ifdef RCT_NEW_ARCH_ENABLED

@implementation NativePlatformSampleModule

RCT_EXPORT_MODULE();

// Thanks to this guard, we won't compile this code when we build for the old architecture.
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params {
return std::make_shared<facebook::react::NativePlatformSampleModuleSpecJSI>(params);
}

- (NSString *)crashOrString {
NSObject * nilObject = NULL;
NSArray * _ = @[nilObject];
return @"NEVER RETURNED";
}

@end

#endif
26 changes: 26 additions & 0 deletions samples/react-native/src/Screens/ErrorsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { StackNavigationProp } from '@react-navigation/stack';
import { UserFeedbackModal } from '../components/UserFeedbackModal';
import { FallbackRender } from '@sentry/react';
import NativeSampleModule from '../../tm/NativeSampleModule';
import NativePlatformSampleModule from '../../tm/NativePlatformSampleModule';
import { timestampInSeconds } from '@sentry/utils';

const { AssetsModule, CppModule, CrashModule } = NativeModules;
Expand Down Expand Up @@ -77,6 +78,16 @@ const ErrorsScreen = (_props: Props) => {
Sentry.captureException(new Error('Captured exception'));
}}
/>
<Button
title="Capture exception with cause"
onPress={() => {
const error = new Error('Captured exception');
(error as { cause?: unknown }).cause = new Error(
'Cause of captured exception',
);
Sentry.captureException(error);
}}
/>
<Button
title="Uncaught Thrown Error"
onPress={() => {
Expand Down Expand Up @@ -127,6 +138,21 @@ const ErrorsScreen = (_props: Props) => {
NativeSampleModule?.crash();
}}
/>
<Button
title="Catch Turbo Crash or String"
onPress={() => {
if (!NativePlatformSampleModule) {
throw new Error(
'NativePlatformSampleModule is not available. Build the application with the New Architecture enabled.',
);
}
try {
NativePlatformSampleModule?.crashOrString();
} catch (e) {
Sentry.captureException(e);
}
}}
/>
{Platform.OS === 'android' && (
<>
<Button
Expand Down
8 changes: 8 additions & 0 deletions samples/react-native/tm/NativePlatformSampleModule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';

export interface Spec extends TurboModule {
crashOrString(): string;
}

export default TurboModuleRegistry.get<Spec>('NativePlatformSampleModule');

0 comments on commit bc4b9f6

Please sign in to comment.