Support the new React Native C++ bridge (#1065)

* Support the new React Native C++ bridge

Fixes #1049

* address code review comments

* handle the case when the websocket executor does not exist
This commit is contained in:
Yavor Georgiev 2017-06-14 14:44:28 +02:00 committed by GitHub
parent af72770094
commit 237e1ba158
2 changed files with 56 additions and 17 deletions

View File

@ -1,3 +1,14 @@
vNext Release notes (TBD)
=============================================================
### Breaking changes
* None
### Enhancements
* None
### Bug fixes
* Fix crash when used with the React Native C++ bridge
1.3.1 Release notes (2017-5-18)
=============================================================
### Breaking changes

View File

@ -49,6 +49,12 @@ using namespace realm::rpc;
- (JSContext *)context;
@end
// the part of the RCTCxxBridge private class we care about
@interface RCTBridge (RCTCxxBridge)
- (JSGlobalContextRef)jsContextRef;
- (void)executeBlockOnJavaScriptThread:(dispatch_block_t)block;
@end
extern "C" JSGlobalContextRef RealmReactGetJSGlobalContextForExecutor(id executor, bool create) {
Ivar contextIvar = class_getInstanceVariable([executor class], "_context");
if (!contextIvar) {
@ -265,33 +271,9 @@ RCT_REMAP_METHOD(emit, emitEvent:(NSString *)eventName withObject:(id)object) {
[self performSelectorOnMainThread:@selector(invalidate) withObject:nil waitUntilDone:YES];
}
- (void)setBridge:(RCTBridge *)bridge {
_bridge = bridge;
static __weak RealmReact *s_currentModule = nil;
[s_currentModule invalidate];
s_currentModule = self;
id<RCTJavaScriptExecutor> executor = [bridge valueForKey:@"javaScriptExecutor"];
if ([executor isKindOfClass:NSClassFromString(@"RCTWebSocketExecutor")]) {
#if DEBUG
[self startRPC];
#else
@throw [NSException exceptionWithName:@"Invalid Executor" reason:@"Chrome debug mode not supported in Release builds" userInfo:nil];
#endif
}
else {
__weak __typeof__(self) weakSelf = self;
__weak __typeof__(executor) weakExecutor = executor;
[executor executeBlockOnJavaScriptQueue:^{
__typeof__(self) self = weakSelf;
__typeof__(executor) executor = weakExecutor;
if (!self || !executor) {
return;
}
typedef JSGlobalContextRef (^JSContextRefExtractor)();
void _initializeOnJSThread(JSContextRefExtractor jsContextExtractor) {
// Make sure the previous JS thread is completely finished before continuing.
static __weak NSThread *s_currentJSThread;
while (s_currentJSThread && !s_currentJSThread.finished) {
@ -302,8 +284,54 @@ RCT_REMAP_METHOD(emit, emitEvent:(NSString *)eventName withObject:(id)object) {
// Close all cached Realms from the previous JS thread.
realm::_impl::RealmCoordinator::clear_all_caches();
JSGlobalContextRef ctx = RealmReactGetJSGlobalContextForExecutor(executor, true);
RJSInitializeInContext(ctx);
RJSInitializeInContext(jsContextExtractor());
}
- (void)setBridge:(RCTBridge *)bridge {
_bridge = bridge;
static __weak RealmReact *s_currentModule = nil;
[s_currentModule invalidate];
s_currentModule = self;
if (objc_lookUpClass("RCTWebSocketExecutor") && [bridge executorClass] == objc_lookUpClass("RCTWebSocketExecutor")) {
#if DEBUG
[self startRPC];
#else
@throw [NSException exceptionWithName:@"Invalid Executor" reason:@"Chrome debug mode not supported in Release builds" userInfo:nil];
#endif
} else if ([bridge isKindOfClass:objc_lookUpClass("RCTCxxBridge")]) {
// probe for the new C++ bridge in React Native 0.45+
__weak __typeof__(self) weakSelf = self;
__weak __typeof__(bridge) weakBridge = bridge;
[bridge executeBlockOnJavaScriptThread:^{
__typeof__(self) self = weakSelf;
__typeof__(bridge) bridge = weakBridge;
if (!self || !bridge) {
return;
}
_initializeOnJSThread(^{
return [bridge jsContextRef];
});
}];
return;
} else { // React Native 0.44 and older
id<RCTJavaScriptExecutor> executor = [bridge valueForKey:@"javaScriptExecutor"];
__weak __typeof__(self) weakSelf = self;
__weak __typeof__(executor) weakExecutor = executor;
[executor executeBlockOnJavaScriptQueue:^{
__typeof__(self) self = weakSelf;
__typeof__(executor) executor = weakExecutor;
if (!self || !executor) {
return;
}
_initializeOnJSThread(^ {
return RealmReactGetJSGlobalContextForExecutor(executor, true);
});
}];
}
}