Skip to content

Commit c733ee8

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 <sjchmiela@gmail.com> Date: Thu Aug 20 19:05:55 2020 +0200 Make RCTCxxBridgeDelegate not care about return value of jsExecutorFactoryForBridge commit d1dd984 Author: Stanisław Chmiela <sjchmiela@gmail.com> 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 <lukasz.kosmaty@swmansion.com> 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 <kudo@expo.io> Date: Tue Aug 17 19:17:48 2021 +0800 support hermes for our RCTCxxBridge patch (#26)
1 parent a349b13 commit c733ee8

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