Fabric iOS: ask the bridge to queue async callback for the RuntimeExecutor

Summary:
In the case where the first rootView we load enables Fabric, the UIManagerBinding ended up calling AppRegistry (JS) too early, before the bridge was fully ready. This means AppRegistry wasn't set up yet, causing redbox.

To fix this, RuntimeExecutor impl should ask the bridge to queue the callback instead of asking the MessageQueueThread directly. MessageQueueThread only works well IFF the bridge is alive, but it has no knowledge about whether the bridge is alive or not. To support this, we add `invokeAsync` impl to the RCTCxxBridge.

Reviewed By: JoshuaGross

Differential Revision: D14868547

fbshipit-source-id: 3b3f2b9150e930b4a2c71012242305241fc6dbed
This commit is contained in:
Kevin Gozali
2019-04-10 11:00:50 -07:00
committed by Facebook Github Bot
parent 0df3cde152
commit 6aa896896f
2 changed files with 20 additions and 6 deletions

View File

@@ -1412,4 +1412,17 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
return _reactInstance->getJavaScriptContext();
}
- (void)invokeAsync:(std::function<void()>&&)func
{
__block auto retainedFunc = std::move(func);
__weak __typeof(self) weakSelf = self;
[self _runAfterLoad:^{
__strong __typeof(self) strongSelf = weakSelf;
if (strongSelf->_reactInstance == nullptr) {
return;
}
strongSelf->_reactInstance->invokeAsync(std::move(retainedFunc));
}];
}
@end

View File

@@ -39,6 +39,7 @@ using namespace facebook::react;
@interface RCTBridge ()
- (std::shared_ptr<facebook::react::MessageQueueThread>)jsMessageThread;
- (void)invokeAsync:(std::function<void()> &&)func;
@end
@interface RCTSurfacePresenter () <RCTSchedulerDelegate, RCTMountingManagerDelegate>
@@ -220,12 +221,12 @@ using namespace facebook::react;
auto runtime = (facebook::jsi::Runtime *)((RCTCxxBridge *)_batchedBridge).runtime;
RuntimeExecutor runtimeExecutor =
[runtime, messageQueueThread](std::function<void(facebook::jsi::Runtime &runtime)> &&callback) {
messageQueueThread->runOnQueue([runtime, callback = std::move(callback)]() {
callback(*runtime);
});
};
RuntimeExecutor runtimeExecutor = [self, runtime](std::function<void(facebook::jsi::Runtime & runtime)> &&callback) {
// For now, ask the bridge to queue the callback asynchronously to ensure that
// it's not invoked too early, e.g. before the bridge is fully ready.
// Revisit this after Fabric/TurboModule is fully rolled out.
[((RCTCxxBridge *)_batchedBridge) invokeAsync:[runtime, callback = std::move(callback)]() { callback(*runtime); }];
};
EventBeatFactory synchronousBeatFactory = [runtimeExecutor]() {
return std::make_unique<MainRunLoopEventBeat>(runtimeExecutor);