diff --git a/RNTester/RNTesterUnitTests/RCTMultipartStreamReaderTests.m b/RNTester/RNTesterUnitTests/RCTMultipartStreamReaderTests.m index c92a505a9ec..20df842757a 100644 --- a/RNTester/RNTesterUnitTests/RCTMultipartStreamReaderTests.m +++ b/RNTester/RNTesterUnitTests/RCTMultipartStreamReaderTests.m @@ -31,12 +31,12 @@ NSInputStream *inputStream = [NSInputStream inputStreamWithData:[response dataUsingEncoding:NSUTF8StringEncoding]]; RCTMultipartStreamReader *reader = [[RCTMultipartStreamReader alloc] initWithInputStream:inputStream boundary:@"sample_boundary"]; __block NSInteger count = 0; - BOOL success = [reader readAllPartsWithCompletionCallback:^(NSDictionary *headers, NSData *content, BOOL done) { + BOOL success = [reader readAllParts:^(NSDictionary *headers, NSData *content, BOOL done) { XCTAssertTrue(done); XCTAssertEqualObjects(headers[@"Content-Type"], @"application/json; charset=utf-8"); XCTAssertEqualObjects([[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding], @"{}"); count++; - } progressCallback: nil]; + }]; XCTAssertTrue(success); XCTAssertEqual(count, 1); } @@ -56,13 +56,13 @@ NSInputStream *inputStream = [NSInputStream inputStreamWithData:[response dataUsingEncoding:NSUTF8StringEncoding]]; RCTMultipartStreamReader *reader = [[RCTMultipartStreamReader alloc] initWithInputStream:inputStream boundary:@"sample_boundary"]; __block NSInteger count = 0; - BOOL success = [reader readAllPartsWithCompletionCallback:^(__unused NSDictionary *headers, NSData *content, BOOL done) { + BOOL success = [reader readAllParts:^(__unused NSDictionary *headers, NSData *content, BOOL done) { count++; XCTAssertEqual(done, count == 3); NSString *expectedBody = [NSString stringWithFormat:@"%ld", (long)count]; NSString *actualBody = [[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding]; XCTAssertEqualObjects(actualBody, expectedBody); - } progressCallback:nil]; + }]; XCTAssertTrue(success); XCTAssertEqual(count, 3); } @@ -73,9 +73,9 @@ NSInputStream *inputStream = [NSInputStream inputStreamWithData:[response dataUsingEncoding:NSUTF8StringEncoding]]; RCTMultipartStreamReader *reader = [[RCTMultipartStreamReader alloc] initWithInputStream:inputStream boundary:@"sample_boundary"]; __block NSInteger count = 0; - BOOL success = [reader readAllPartsWithCompletionCallback:^(__unused NSDictionary *headers, __unused NSData *content, __unused BOOL done) { + BOOL success = [reader readAllParts:^(__unused NSDictionary *headers, __unused NSData *content, __unused BOOL done) { count++; - } progressCallback:nil]; + }]; XCTAssertFalse(success); XCTAssertEqual(count, 0); } @@ -93,9 +93,9 @@ NSInputStream *inputStream = [NSInputStream inputStreamWithData:[response dataUsingEncoding:NSUTF8StringEncoding]]; RCTMultipartStreamReader *reader = [[RCTMultipartStreamReader alloc] initWithInputStream:inputStream boundary:@"sample_boundary"]; __block NSInteger count = 0; - BOOL success = [reader readAllPartsWithCompletionCallback:^(__unused NSDictionary *headers, __unused NSData *content, __unused BOOL done) { + BOOL success = [reader readAllParts:^(__unused NSDictionary *headers, __unused NSData *content, __unused BOOL done) { count++; - } progressCallback:nil]; + }]; XCTAssertFalse(success); XCTAssertEqual(count, 1); } diff --git a/React/Base/RCTJavaScriptLoader.mm b/React/Base/RCTJavaScriptLoader.mm index 4330e4e78b5..cbc686d9150 100755 --- a/React/Base/RCTJavaScriptLoader.mm +++ b/React/Base/RCTJavaScriptLoader.mm @@ -198,6 +198,7 @@ static void attemptAsynchronousLoadOfBundleAtURL(NSURL *scriptURL, RCTSourceLoad return; } + RCTMultipartDataTask *task = [[RCTMultipartDataTask alloc] initWithURL:scriptURL partHandler:^(NSInteger statusCode, NSDictionary *headers, NSData *data, NSError *error, BOOL done) { if (!done) { if (onProgress) { @@ -260,11 +261,6 @@ static void attemptAsynchronousLoadOfBundleAtURL(NSURL *scriptURL, RCTSourceLoad } onComplete(nil, data, data.length); - } progressHandler:^(NSDictionary *headers, NSNumber *loaded, NSNumber *total) { - // Only care about download progress events for the javascript bundle part. - if ([headers[@"Content-Type"] isEqualToString:@"application/javascript"]) { - onProgress(progressEventFromDownloadProgress(loaded, total)); - } }]; [task startTask]; @@ -291,16 +287,6 @@ static RCTLoadingProgress *progressEventFromData(NSData *rawData) return progress; } -static RCTLoadingProgress *progressEventFromDownloadProgress(NSNumber *total, NSNumber *done) -{ - RCTLoadingProgress *progress = [RCTLoadingProgress new]; - progress.status = @"Downloading JavaScript bundle"; - // Progress values are in bytes transform them to kilobytes for smaller numbers. - progress.done = done != nil ? @([done integerValue] / 1024) : nil; - progress.total = total != nil ? @([total integerValue] / 1024) : nil; - return progress; -} - static NSDictionary *userInfoForRawResponse(NSString *rawText) { NSDictionary *parsedResponse = RCTJSONParse(rawText, nil); diff --git a/React/Base/RCTMultipartDataTask.h b/React/Base/RCTMultipartDataTask.h index 25f559e3d52..0d650b0d6af 100644 --- a/React/Base/RCTMultipartDataTask.h +++ b/React/Base/RCTMultipartDataTask.h @@ -15,10 +15,7 @@ typedef void (^RCTMultipartDataTaskCallback)(NSInteger statusCode, NSDictionary @interface RCTMultipartDataTask : NSObject -- (instancetype)initWithURL:(NSURL *)url - partHandler:(RCTMultipartDataTaskCallback)partHandler - progressHandler:(RCTMultipartProgressCallback)progressHandler; - +- (instancetype)initWithURL:(NSURL *)url partHandler:(RCTMultipartDataTaskCallback)partHandler; - (void)startTask; @end diff --git a/React/Base/RCTMultipartDataTask.m b/React/Base/RCTMultipartDataTask.m index 6ca63f3c4d8..27feaffbb1e 100644 --- a/React/Base/RCTMultipartDataTask.m +++ b/React/Base/RCTMultipartDataTask.m @@ -30,21 +30,17 @@ static BOOL isStreamTaskSupported() { @implementation RCTMultipartDataTask { NSURL *_url; RCTMultipartDataTaskCallback _partHandler; - RCTMultipartProgressCallback _progressHandler; NSInteger _statusCode; NSDictionary *_headers; NSString *_boundary; NSMutableData *_data; } -- (instancetype)initWithURL:(NSURL *)url - partHandler:(RCTMultipartDataTaskCallback)partHandler - progressHandler:(RCTMultipartProgressCallback)progressHandler +- (instancetype)initWithURL:(NSURL *)url partHandler:(RCTMultipartDataTaskCallback)partHandler { if (self = [super init]) { _url = url; _partHandler = [partHandler copy]; - _progressHandler = [progressHandler copy]; } return self; } @@ -121,9 +117,9 @@ didBecomeInputStream:(NSInputStream *)inputStream _partHandler = nil; NSInteger statusCode = _statusCode; - BOOL completed = [reader readAllPartsWithCompletionCallback:^(NSDictionary *headers, NSData *content, BOOL done) { + BOOL completed = [reader readAllParts:^(NSDictionary *headers, NSData *content, BOOL done) { partHandler(statusCode, headers, content, nil, done); - } progressCallback:_progressHandler]; + }]; if (!completed) { partHandler(statusCode, nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:nil], YES); } diff --git a/React/Base/RCTMultipartStreamReader.h b/React/Base/RCTMultipartStreamReader.h index 30ffe5726d9..ab77bd1ae85 100644 --- a/React/Base/RCTMultipartStreamReader.h +++ b/React/Base/RCTMultipartStreamReader.h @@ -10,7 +10,6 @@ #import typedef void (^RCTMultipartCallback)(NSDictionary *headers, NSData *content, BOOL done); -typedef void (^RCTMultipartProgressCallback)(NSDictionary *headers, NSNumber *loaded, NSNumber *total); // RCTMultipartStreamReader can be used to parse responses with Content-Type: multipart/mixed @@ -18,7 +17,6 @@ typedef void (^RCTMultipartProgressCallback)(NSDictionary *headers, NSNumber *lo @interface RCTMultipartStreamReader : NSObject - (instancetype)initWithInputStream:(NSInputStream *)stream boundary:(NSString *)boundary; -- (BOOL)readAllPartsWithCompletionCallback:(RCTMultipartCallback)callback - progressCallback:(RCTMultipartProgressCallback)progressCallback; +- (BOOL)readAllParts:(RCTMultipartCallback)callback; @end diff --git a/React/Base/RCTMultipartStreamReader.m b/React/Base/RCTMultipartStreamReader.m index 6f4c5b04679..87b85c65e82 100644 --- a/React/Base/RCTMultipartStreamReader.m +++ b/React/Base/RCTMultipartStreamReader.m @@ -9,14 +9,11 @@ #import "RCTMultipartStreamReader.h" -#import - #define CRLF @"\r\n" @implementation RCTMultipartStreamReader { __strong NSInputStream *_stream; __strong NSString *_boundary; - CFTimeInterval _lastDownloadProgress; } - (instancetype)initWithInputStream:(NSInputStream *)stream boundary:(NSString *)boundary @@ -24,7 +21,6 @@ if (self = [super init]) { _stream = stream; _boundary = boundary; - _lastDownloadProgress = CACurrentMediaTime(); } return self; } @@ -46,17 +42,12 @@ return headers; } -- (void)emitChunk:(NSData *)data headers:(NSDictionary *)headers callback:(RCTMultipartCallback)callback done:(BOOL)done +- (void)emitChunk:(NSData *)data callback:(RCTMultipartCallback)callback done:(BOOL)done { NSData *marker = [CRLF CRLF dataUsingEncoding:NSUTF8StringEncoding]; NSRange range = [data rangeOfData:marker options:0 range:NSMakeRange(0, data.length)]; if (range.location == NSNotFound) { callback(nil, data, done); - } else if (headers != nil) { - // If headers were parsed already just use that to avoid doing it twice. - NSInteger bodyStart = range.location + marker.length; - NSData *bodyData = [data subdataWithRange:NSMakeRange(bodyStart, data.length - bodyStart)]; - callback(headers, bodyData, done); } else { NSData *headersData = [data subdataWithRange:NSMakeRange(0, range.location)]; NSInteger bodyStart = range.location + marker.length; @@ -65,26 +56,7 @@ } } -- (void)emitProgress:(NSDictionary *)headers - contentLength:(NSUInteger)contentLength - final:(BOOL)final - callback:(RCTMultipartProgressCallback)callback -{ - if (headers == nil) { - return; - } - // Throttle progress events so we don't send more that around 60 per second. - CFTimeInterval currentTime = CACurrentMediaTime(); - - NSUInteger headersContentLength = headers[@"Content-Length"] != nil ? [headers[@"Content-Length"] unsignedIntValue] : 0; - if (callback && (currentTime - _lastDownloadProgress > 0.016 || final)) { - _lastDownloadProgress = currentTime; - callback(headers, @(headersContentLength), @(contentLength)); - } -} - -- (BOOL)readAllPartsWithCompletionCallback:(RCTMultipartCallback)callback - progressCallback:(RCTMultipartProgressCallback)progressCallback +- (BOOL)readAllParts:(RCTMultipartCallback)callback { NSInteger chunkStart = 0; NSInteger bytesSeen = 0; @@ -92,8 +64,6 @@ NSData *delimiter = [[NSString stringWithFormat:@"%@--%@%@", CRLF, _boundary, CRLF] dataUsingEncoding:NSUTF8StringEncoding]; NSData *closeDelimiter = [[NSString stringWithFormat:@"%@--%@--%@", CRLF, _boundary, CRLF] dataUsingEncoding:NSUTF8StringEncoding]; NSMutableData *content = [[NSMutableData alloc] initWithCapacity:1]; - NSDictionary *currentHeaders = nil; - NSUInteger currentHeadersLength = 0; const NSUInteger bufferLen = 4 * 1024; uint8_t buffer[bufferLen]; @@ -105,8 +75,6 @@ // to allow for the edge case when the delimiter is cut by read call NSInteger searchStart = MAX(bytesSeen - (NSInteger)closeDelimiter.length, chunkStart); NSRange remainingBufferRange = NSMakeRange(searchStart, content.length - searchStart); - - // Check for delimiters. NSRange range = [content rangeOfData:delimiter options:0 range:remainingBufferRange]; if (range.location == NSNotFound) { isCloseDelimiter = YES; @@ -114,23 +82,6 @@ } if (range.location == NSNotFound) { - if (currentHeaders == nil) { - // Check for the headers delimiter. - NSData *headersMarker = [CRLF CRLF dataUsingEncoding:NSUTF8StringEncoding]; - NSRange headersRange = [content rangeOfData:headersMarker options:0 range:remainingBufferRange]; - if (headersRange.location != NSNotFound) { - NSData *headersData = [content subdataWithRange:NSMakeRange(chunkStart, headersRange.location - chunkStart)]; - currentHeadersLength = headersData.length; - currentHeaders = [self parseHeaders:headersData]; - } - } else { - // When headers are loaded start sending progress callbacks. - [self emitProgress:currentHeaders - contentLength:content.length - currentHeadersLength - final:NO - callback:progressCallback]; - } - bytesSeen = content.length; NSInteger bytesRead = [_stream read:buffer maxLength:bufferLen]; if (bytesRead <= 0 || _stream.streamError) { @@ -147,13 +98,7 @@ // Ignore preamble if (chunkStart > 0) { NSData *chunk = [content subdataWithRange:NSMakeRange(chunkStart, length)]; - [self emitProgress:currentHeaders - contentLength:chunk.length - currentHeadersLength - final:YES - callback:progressCallback]; - [self emitChunk:chunk headers:currentHeaders callback:callback done:isCloseDelimiter]; - currentHeaders = nil; - currentHeadersLength = 0; + [self emitChunk:chunk callback:callback done:isCloseDelimiter]; } if (isCloseDelimiter) {