[ReactNative] Maintain order of bridge calls
Summary:
When bridge calls are made, they should be dispatched to their
destination GCD queue in the same order they were made. (It
looks like this invariant broke in 336e18d
, which caused call
order to depend on the iteration of `NSMapTable` keys
whenever there are calls to multiple modules that share a queue)
Fixes #1941 (in which RCTUIManager createView addUIBlock
blocks were sometimes running after other blocks that depended
on them)
I'm a react-native/iOS/objc newbie, so please excuse any
ignorance this commit may well contain :)
Closes https://github.com/facebook/react-native/pull/2488
Github Author: Ted Suzman <ted@suzman.net>
This commit is contained in:
parent
1ff22b7b9c
commit
2b3a4bd27d
|
@ -664,22 +664,23 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||||
// verify that class has been registered
|
// verify that class has been registered
|
||||||
(void)_modulesByName[moduleData.name];
|
(void)_modulesByName[moduleData.name];
|
||||||
}
|
}
|
||||||
NSMutableOrderedSet *set = [buckets objectForKey:moduleData];
|
id queue = [moduleData queue];
|
||||||
|
NSMutableOrderedSet *set = [buckets objectForKey:queue];
|
||||||
if (!set) {
|
if (!set) {
|
||||||
set = [NSMutableOrderedSet new];
|
set = [NSMutableOrderedSet new];
|
||||||
[buckets setObject:set forKey:moduleData];
|
[buckets setObject:set forKey:queue];
|
||||||
}
|
}
|
||||||
[set addObject:@(i)];
|
[set addObject:@(i)];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (RCTModuleData *moduleData in buckets) {
|
for (id queue in buckets) {
|
||||||
RCTProfileBeginFlowEvent();
|
RCTProfileBeginFlowEvent();
|
||||||
|
|
||||||
[moduleData dispatchBlock:^{
|
dispatch_block_t block = ^{
|
||||||
RCTProfileEndFlowEvent();
|
RCTProfileEndFlowEvent();
|
||||||
RCTProfileBeginEvent(0, RCTCurrentThreadName(), nil);
|
RCTProfileBeginEvent(0, RCTCurrentThreadName(), nil);
|
||||||
|
|
||||||
NSOrderedSet *calls = [buckets objectForKey:moduleData];
|
NSOrderedSet *calls = [buckets objectForKey:queue];
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
for (NSNumber *indexObj in calls) {
|
for (NSNumber *indexObj in calls) {
|
||||||
NSUInteger index = indexObj.unsignedIntegerValue;
|
NSUInteger index = indexObj.unsignedIntegerValue;
|
||||||
|
@ -693,7 +694,13 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||||
RCTProfileEndEvent(0, @"objc_call,dispatch_async", @{
|
RCTProfileEndEvent(0, @"objc_call,dispatch_async", @{
|
||||||
@"calls": @(calls.count),
|
@"calls": @(calls.count),
|
||||||
});
|
});
|
||||||
}];
|
};
|
||||||
|
|
||||||
|
if (queue == RCTJSThread) {
|
||||||
|
[_javaScriptExecutor executeBlockOnJavaScriptQueue:block];
|
||||||
|
} else if (queue) {
|
||||||
|
dispatch_async(queue, block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: batchDidComplete is only used by RCTUIManager - can we eliminate this special case?
|
// TODO: batchDidComplete is only used by RCTUIManager - can we eliminate this special case?
|
||||||
|
|
Loading…
Reference in New Issue