diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index e0ab9f68446fdd..d82d7da2c0b94c 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -334,9 +334,28 @@ - (void)start // Prepare executor factory (shared_ptr for copy into block) std::shared_ptr executorFactory; if (!self.executorClass) { - if ([self.delegate respondsToSelector:@selector(jsExecutorFactoryForBridge:)]) { - id cxxDelegate = (id)self.delegate; - executorFactory = std::make_shared(*reinterpret_cast([cxxDelegate jsExecutorFactoryForBridge:self])); + SEL jsExecutorFactoryForBridgeSEL = @selector(jsExecutorFactoryForBridge:); + if ([self.delegate respondsToSelector:jsExecutorFactoryForBridgeSEL]) { + // Normally, `RCTCxxBridgeDelegate` protocol uses `std::unique_ptr` to return the js executor object. + // However, we needed to change the signature of `jsExecutorFactoryForBridge` to return `void *` instead. See https://github.com/expo/expo/pull/9862. + // This change works great in Expo Go because we have full control over modules initialization, + // but if someone is using our fork in the bare app, crashes may occur (`EXC_BAD_ACCESS`). + // To fix it, we need to get the return type of `jsExecutorFactoryForBridge` and handle two cases: + // - method returns `void *` + // - method returns `std::unique_ptr` + Method m = class_getInstanceMethod([self.delegate class], jsExecutorFactoryForBridgeSEL); + char returnType[128]; + method_getReturnType(m, returnType, sizeof(returnType)); + + if(strcmp(returnType, @encode(void *)) == 0) { + // `jsExecutorFactoryForBridge` returns `void *` + id cxxDelegate = (id)self.delegate; + executorFactory = std::make_shared(*reinterpret_cast([cxxDelegate jsExecutorFactoryForBridge:self])); + } else { + // `jsExecutorFactoryForBridge` returns `std::unique_ptr` + id cxxDelegate = (id)self.delegate; + executorFactory = [cxxDelegate jsExecutorFactoryForBridge:self]; + } } if (!executorFactory) { executorFactory = std::make_shared(nullptr); diff --git a/React/CxxBridge/RCTCxxBridgeDelegate.h b/React/CxxBridge/RCTCxxBridgeDelegate.h index 8e19f3f4208302..d6f55f9e5b8c05 100644 --- a/React/CxxBridge/RCTCxxBridgeDelegate.h +++ b/React/CxxBridge/RCTCxxBridgeDelegate.h @@ -31,3 +31,12 @@ class JSExecutorFactory; - (void *)jsExecutorFactoryForBridge:(RCTBridge *)bridge; @end + +@protocol RCTCxxBridgeTurboModuleDelegate + +/** + * The RCTCxxBridgeDelegate used outside of the Expo Go. + */ +- (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge; + +@end