Skip to content

Commit a2c0a2f

Browse files
sjchmielaKudo
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 9d9b5fe commit a2c0a2f

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

React/CxxBridge/RCTCxxBridge.mm

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

React/CxxBridge/RCTCxxBridgeDelegate.h

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

3342
@end

0 commit comments

Comments
 (0)