Defer calls until bridge finishes loading

Summary: @​public

When de-batching the calls from native -> JS, some calls were being dispatched
before the bridge had finished loading, which would cause lost calls when running
on the `ContextExecutor` and redbox when running in the Chrome debugger

Reviewed By: @javache

Differential Revision: D2540746

fb-gh-sync-id: ece29406648d3cbcb42cef3b32b8774ff0c15fd8
This commit is contained in:
Tadeu Zagallo 2015-10-14 09:48:00 -07:00 коммит произвёл facebook-github-bot-9
Родитель 10a9b94b9c
Коммит 529687f923
1 изменённых файлов: 24 добавлений и 4 удалений

Просмотреть файл

@ -64,6 +64,7 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
BOOL _loading;
BOOL _valid;
__weak id<RCTJavaScriptExecutor> _javaScriptExecutor;
NSMutableArray *_pendingCalls;
NSMutableArray *_moduleDataByID;
RCTModuleMap *_modulesByName;
CADisplayLink *_mainDisplayLink;
@ -87,6 +88,7 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
*/
_valid = YES;
_loading = YES;
_pendingCalls = [NSMutableArray new];
_moduleDataByID = [NSMutableArray new];
_frameUpdateObservers = [NSMutableSet new];
_jsDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_jsThreadUpdate:)];
@ -212,7 +214,7 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
} else {
// Allow testing without a script
dispatch_async(dispatch_get_main_queue(), ^{
_loading = NO;
[self didFinishLoading];
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidLoadNotification
object:_parentBridge
userInfo:@{ @"bridge": self }];
@ -382,7 +384,7 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
// Perform the state update and notification on the main thread, so we can't run into
// timing issues with RCTRootView
dispatch_async(dispatch_get_main_queue(), ^{
_loading = NO;
[self didFinishLoading];
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidLoadNotification
object:_parentBridge
userInfo:@{ @"bridge": self }];
@ -390,6 +392,18 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
}];
}
- (void)didFinishLoading
{
_loading = NO;
[_javaScriptExecutor executeBlockOnJavaScriptQueue:^{
for (NSArray *call in _pendingCalls) {
[self _actuallyInvokeAndProcessModule:call[0]
method:call[1]
arguments:call[2]];
}
}];
}
- (void)stopLoadingWithError:(NSError *)error
{
RCTAssertMainThread();
@ -625,9 +639,15 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
RCTProfileBeginEvent(0, @"enqueue_call", nil);
RCTBatchedBridge *strongSelf = weakSelf;
if (!strongSelf || !strongSelf.valid) {
return;
}
[strongSelf _actuallyInvokeAndProcessModule:module method:method arguments:args];
if (strongSelf.loading) {
[strongSelf->_pendingCalls addObject:@[module, method, args]];
} else {
[strongSelf _actuallyInvokeAndProcessModule:module method:method arguments:args];
}
}];
}