Skip to content

Commit

Permalink
[ReactNative] Maintain order of bridge calls
Browse files Browse the repository at this point in the history
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 facebook#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 facebook#2488
Github Author: Ted Suzman <[email protected]>
  • Loading branch information
RoboTeddy authored and Tj committed Nov 9, 2015
1 parent 010caf1 commit 7988a37
Showing 1 changed file with 13 additions and 6 deletions.
19 changes: 13 additions & 6 deletions React/Base/RCTBatchedBridge.m
Original file line number Diff line number Diff line change
Expand Up @@ -664,22 +664,23 @@ - (void)_handleBuffer:(id)buffer
// verify that class has been registered
(void)_modulesByName[moduleData.name];
}
NSMutableOrderedSet *set = [buckets objectForKey:moduleData];
id queue = [moduleData queue];
NSMutableOrderedSet *set = [buckets objectForKey:queue];
if (!set) {
set = [NSMutableOrderedSet new];
[buckets setObject:set forKey:moduleData];
[buckets setObject:set forKey:queue];
}
[set addObject:@(i)];
}

for (RCTModuleData *moduleData in buckets) {
for (id queue in buckets) {
RCTProfileBeginFlowEvent();

[moduleData dispatchBlock:^{
dispatch_block_t block = ^{
RCTProfileEndFlowEvent();
RCTProfileBeginEvent(0, RCTCurrentThreadName(), nil);

NSOrderedSet *calls = [buckets objectForKey:moduleData];
NSOrderedSet *calls = [buckets objectForKey:queue];
@autoreleasepool {
for (NSNumber *indexObj in calls) {
NSUInteger index = indexObj.unsignedIntegerValue;
Expand All @@ -693,7 +694,13 @@ - (void)_handleBuffer:(id)buffer
RCTProfileEndEvent(0, @"objc_call,dispatch_async", @{
@"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?
Expand Down

0 comments on commit 7988a37

Please sign in to comment.