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:
parent
af72770094
commit
237e1ba158
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -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)
|
1.3.1 Release notes (2017-5-18)
|
||||||
=============================================================
|
=============================================================
|
||||||
### Breaking changes
|
### Breaking changes
|
||||||
|
|
|
@ -49,6 +49,12 @@ using namespace realm::rpc;
|
||||||
- (JSContext *)context;
|
- (JSContext *)context;
|
||||||
@end
|
@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) {
|
extern "C" JSGlobalContextRef RealmReactGetJSGlobalContextForExecutor(id executor, bool create) {
|
||||||
Ivar contextIvar = class_getInstanceVariable([executor class], "_context");
|
Ivar contextIvar = class_getInstanceVariable([executor class], "_context");
|
||||||
if (!contextIvar) {
|
if (!contextIvar) {
|
||||||
|
@ -265,6 +271,22 @@ RCT_REMAP_METHOD(emit, emitEvent:(NSString *)eventName withObject:(id)object) {
|
||||||
[self performSelectorOnMainThread:@selector(invalidate) withObject:nil waitUntilDone:YES];
|
[self performSelectorOnMainThread:@selector(invalidate) withObject:nil waitUntilDone:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
[NSThread sleepForTimeInterval:0.1];
|
||||||
|
}
|
||||||
|
s_currentJSThread = [NSThread currentThread];
|
||||||
|
|
||||||
|
// Close all cached Realms from the previous JS thread.
|
||||||
|
realm::_impl::RealmCoordinator::clear_all_caches();
|
||||||
|
|
||||||
|
RJSInitializeInContext(jsContextExtractor());
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setBridge:(RCTBridge *)bridge {
|
- (void)setBridge:(RCTBridge *)bridge {
|
||||||
_bridge = bridge;
|
_bridge = bridge;
|
||||||
|
|
||||||
|
@ -272,16 +294,31 @@ RCT_REMAP_METHOD(emit, emitEvent:(NSString *)eventName withObject:(id)object) {
|
||||||
[s_currentModule invalidate];
|
[s_currentModule invalidate];
|
||||||
s_currentModule = self;
|
s_currentModule = self;
|
||||||
|
|
||||||
id<RCTJavaScriptExecutor> executor = [bridge valueForKey:@"javaScriptExecutor"];
|
if (objc_lookUpClass("RCTWebSocketExecutor") && [bridge executorClass] == objc_lookUpClass("RCTWebSocketExecutor")) {
|
||||||
|
|
||||||
if ([executor isKindOfClass:NSClassFromString(@"RCTWebSocketExecutor")]) {
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
[self startRPC];
|
[self startRPC];
|
||||||
#else
|
#else
|
||||||
@throw [NSException exceptionWithName:@"Invalid Executor" reason:@"Chrome debug mode not supported in Release builds" userInfo:nil];
|
@throw [NSException exceptionWithName:@"Invalid Executor" reason:@"Chrome debug mode not supported in Release builds" userInfo:nil];
|
||||||
#endif
|
#endif
|
||||||
}
|
} else if ([bridge isKindOfClass:objc_lookUpClass("RCTCxxBridge")]) {
|
||||||
else {
|
// 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__(self) weakSelf = self;
|
||||||
__weak __typeof__(executor) weakExecutor = executor;
|
__weak __typeof__(executor) weakExecutor = executor;
|
||||||
|
|
||||||
|
@ -292,18 +329,9 @@ RCT_REMAP_METHOD(emit, emitEvent:(NSString *)eventName withObject:(id)object) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the previous JS thread is completely finished before continuing.
|
_initializeOnJSThread(^ {
|
||||||
static __weak NSThread *s_currentJSThread;
|
return RealmReactGetJSGlobalContextForExecutor(executor, true);
|
||||||
while (s_currentJSThread && !s_currentJSThread.finished) {
|
});
|
||||||
[NSThread sleepForTimeInterval:0.1];
|
|
||||||
}
|
|
||||||
s_currentJSThread = [NSThread currentThread];
|
|
||||||
|
|
||||||
// Close all cached Realms from the previous JS thread.
|
|
||||||
realm::_impl::RealmCoordinator::clear_all_caches();
|
|
||||||
|
|
||||||
JSGlobalContextRef ctx = RealmReactGetJSGlobalContextForExecutor(executor, true);
|
|
||||||
RJSInitializeInContext(ctx);
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue