[ReactNative] Fix racing condition on RCTDataManager

This commit is contained in:
Tadeu Zagallo 2015-06-11 10:43:29 -07:00 committed by Spencer Ahrens
parent 7b7e0bf881
commit 6aea50d6f8
1 changed files with 46 additions and 32 deletions

View File

@ -202,6 +202,7 @@ typedef void (^RCTDataLoaderCallback)(NSData *data, NSString *MIMEType, NSError
{
NSInteger _currentRequestID;
NSMapTable *_activeRequests;
dispatch_queue_t _methodQueue;
}
@synthesize bridge = _bridge;
@ -212,6 +213,7 @@ RCT_EXPORT_MODULE()
{
if ((self = [super init])) {
_currentRequestID = 0;
_methodQueue = dispatch_queue_create("com.facebook.React.RCTDataManager", DISPATCH_QUEUE_SERIAL);
_activeRequests = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory
valueOptions:NSPointerFunctionsStrongMemory
capacity:0];
@ -219,6 +221,11 @@ RCT_EXPORT_MODULE()
return self;
}
- (dispatch_queue_t)methodQueue
{
return _methodQueue;
}
- (void)buildRequest:(NSDictionary *)query
responseSender:(RCTResponseSenderBlock)responseSender
{
@ -381,55 +388,62 @@ RCT_EXPORT_MODULE()
- (void)URLRequest:(id)requestToken didReceiveResponse:(NSURLResponse *)response
{
RCTActiveURLRequest *request = [_activeRequests objectForKey:requestToken];
RCTAssert(request != nil, @"Unrecognized request token: %@", requestToken);
dispatch_async(_methodQueue, ^{
RCTActiveURLRequest *request = [_activeRequests objectForKey:requestToken];
RCTAssert(request != nil, @"Unrecognized request token: %@", requestToken);
request.response = response;
request.response = response;
NSHTTPURLResponse *httpResponse = nil;
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
// Might be a local file request
httpResponse = (NSHTTPURLResponse *)response;
}
NSHTTPURLResponse *httpResponse = nil;
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
// Might be a local file request
httpResponse = (NSHTTPURLResponse *)response;
}
NSArray *responseJSON = @[request.requestID,
@(httpResponse.statusCode ?: 200),
httpResponse.allHeaderFields ?: @{},
];
NSArray *responseJSON = @[request.requestID,
@(httpResponse.statusCode ?: 200),
httpResponse.allHeaderFields ?: @{},
];
[_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkResponse"
body:responseJSON];
[_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkResponse"
body:responseJSON];
});
}
- (void)URLRequest:(id)requestToken didReceiveData:(NSData *)data
{
RCTActiveURLRequest *request = [_activeRequests objectForKey:requestToken];
RCTAssert(request != nil, @"Unrecognized request token: %@", requestToken);
dispatch_async(_methodQueue, ^{
RCTActiveURLRequest *request = [_activeRequests objectForKey:requestToken];
RCTAssert(request != nil, @"Unrecognized request token: %@", requestToken);
if (request.incrementalUpdates) {
[self sendData:data forRequestToken:requestToken];
} else {
[request.data appendData:data];
}
if (request.incrementalUpdates) {
[self sendData:data forRequestToken:requestToken];
} else {
[request.data appendData:data];
}
});
}
- (void)URLRequest:(id)requestToken didCompleteWithError:(NSError *)error
{
RCTActiveURLRequest *request = [_activeRequests objectForKey:requestToken];
RCTAssert(request != nil, @"Unrecognized request token: %@", requestToken);
dispatch_async(_methodQueue, ^{
RCTActiveURLRequest *request = [_activeRequests objectForKey:requestToken];
RCTAssert(request != nil, @"Unrecognized request token: %@", requestToken);
if (!request.incrementalUpdates) {
[self sendData:request.data forRequestToken:requestToken];
}
if (!request.incrementalUpdates) {
[self sendData:request.data forRequestToken:requestToken];
}
NSArray *responseJSON = @[request.requestID,
error.localizedDescription ?: [NSNull null]
];
NSArray *responseJSON = @[
request.requestID,
error.localizedDescription ?: [NSNull null],
];
[_bridge.eventDispatcher sendDeviceEventWithName:@"didCompleteNetworkResponse"
body:responseJSON];
[_bridge.eventDispatcher sendDeviceEventWithName:@"didCompleteNetworkResponse"
body:responseJSON];
[_activeRequests removeObjectForKey:requestToken];
[_activeRequests removeObjectForKey:requestToken];
});
}
#pragma mark - JS API