Skip to content

Commit fe93239

Browse files
sjchmielaalanjhughes
authored andcommitted
[ios] Support custom js executor
This is a squashed commit from the following changes: commit c1c976f Author: Stanisław Chmiela <[email protected]> Date: Thu Aug 20 19:05:55 2020 +0200 Make RCTCxxBridgeDelegate not care about return value of jsExecutorFactoryForBridge commit d1dd984 Author: Stanisław Chmiela <[email protected]> Date: Thu Aug 20 19:06:13 2020 +0200 Make RCTCxxBridge not care about the actual protocol implemented, only the method used commit efd22a8 Author: Łukasz Kosmaty <[email protected]> Date: Tue Mar 9 00:36:25 2021 +0100 [ios] Fix `EXC_BAD_ACCESS` in start method of `RCTCxxBridge` (#25) commit 0e9b4f9 Author: Kudo Chien <[email protected]> Date: Tue Aug 17 19:17:48 2021 +0800 support hermes for our RCTCxxBridge patch (#26)
1 parent 6c97c6e commit fe93239

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

packages/react-native/React/CxxBridge/RCTCxxBridge.mm

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,9 +432,28 @@ - (void)start
432432
// Prepare executor factory (shared_ptr for copy into block)
433433
std::shared_ptr<JSExecutorFactory> executorFactory;
434434
if (!self.executorClass) {
435-
if ([self.delegate conformsToProtocol:@protocol(RCTCxxBridgeDelegate)]) {
436-
id<RCTCxxBridgeDelegate> cxxDelegate = (id<RCTCxxBridgeDelegate>)self.delegate;
437-
executorFactory = [cxxDelegate jsExecutorFactoryForBridge:self];
435+
SEL jsExecutorFactoryForBridgeSEL = @selector(jsExecutorFactoryForBridge:);
436+
if ([self.delegate respondsToSelector:jsExecutorFactoryForBridgeSEL]) {
437+
// Normally, `RCTCxxBridgeDelegate` protocol uses `std::unique_ptr` to return the js executor object.
438+
// However, we needed to change the signature of `jsExecutorFactoryForBridge` to return `void *` instead. See https://github.com/expo/expo/pull/9862.
439+
// This change works great in Expo Go because we have full control over modules initialization,
440+
// but if someone is using our fork in the bare app, crashes may occur (`EXC_BAD_ACCESS`).
441+
// To fix it, we need to get the return type of `jsExecutorFactoryForBridge` and handle two cases:
442+
// - method returns `void *`
443+
// - method returns `std::unique_ptr<JSExecutorFactory>`
444+
Method m = class_getInstanceMethod([self.delegate class], jsExecutorFactoryForBridgeSEL);
445+
char returnType[128];
446+
method_getReturnType(m, returnType, sizeof(returnType));
447+
448+
if(strcmp(returnType, @encode(void *)) == 0) {
449+
// `jsExecutorFactoryForBridge` returns `void *`
450+
id<RCTCxxBridgeDelegate> cxxDelegate = (id<RCTCxxBridgeDelegate>)self.delegate;
451+
executorFactory.reset(reinterpret_cast<JSExecutorFactory *>([cxxDelegate jsExecutorFactoryForBridge:self]));
452+
} else {
453+
// `jsExecutorFactoryForBridge` returns `std::unique_ptr<JSExecutorFactory>`
454+
id<RCTCxxBridgeTurboModuleDelegate> cxxDelegate = (id<RCTCxxBridgeTurboModuleDelegate>)self.delegate;
455+
executorFactory = [cxxDelegate jsExecutorFactoryForBridge:self];
456+
}
438457
}
439458
if (!executorFactory) {
440459
auto installBindings = RCTJSIExecutorRuntimeInstaller(nullptr);

packages/react-native/React/CxxBridge/RCTCxxBridgeDelegate.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ class JSExecutorFactory;
2626
* If not implemented, or returns an empty pointer, JSIExecutorFactory
2727
* will be used with a JSCRuntime.
2828
*/
29+
- (void *)jsExecutorFactoryForBridge:(RCTBridge *)bridge;
30+
31+
@end
32+
33+
@protocol RCTCxxBridgeTurboModuleDelegate <RCTBridgeDelegate>
34+
35+
/**
36+
* The RCTCxxBridgeDelegate used outside of the Expo Go.
37+
*/
2938
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge;
3039

3140
@end

0 commit comments

Comments
 (0)