diff --git a/packages/react-native/Libraries/Network/RCTFileRequestHandler.mm b/packages/react-native/Libraries/Network/RCTFileRequestHandler.mm index 19d025c51e19df..3d12ac637ec0c5 100644 --- a/packages/react-native/Libraries/Network/RCTFileRequestHandler.mm +++ b/packages/react-native/Libraries/Network/RCTFileRequestHandler.mm @@ -25,8 +25,14 @@ @implementation RCTFileRequestHandler { - (void)invalidate { - [_fileQueue cancelAllOperations]; - _fileQueue = nil; + if (_fileQueue) { + for (NSOperation *operation in _fileQueue.operations) { + if ([operation isKindOfClass:[NSOperation class]] && !operation.isCancelled && !operation.isFinished) { + [operation cancel]; + } + } + _fileQueue = nil; + } } - (BOOL)canHandleRequest:(NSURLRequest *)request diff --git a/packages/react-native/React/CxxBridge/RCTCxxBridge.mm b/packages/react-native/React/CxxBridge/RCTCxxBridge.mm index 044862f821c2a2..bbcf3fee076b09 100644 --- a/packages/react-native/React/CxxBridge/RCTCxxBridge.mm +++ b/packages/react-native/React/CxxBridge/RCTCxxBridge.mm @@ -1189,86 +1189,88 @@ - (void)dispatchBlock:(dispatch_block_t)block queue:(dispatch_queue_t)queue - (void)invalidate { - if (_didInvalidate) { - return; - } + RCTExecuteOnMainQueue(^{ + if (_didInvalidate) { + return; + } - RCTAssertMainQueue(); - RCTLogInfo(@"Invalidating %@ (parent: %@, executor: %@)", self, _parentBridge, [self executorClass]); + RCTAssertMainQueue(); + RCTLogInfo(@"Invalidating %@ (parent: %@, executor: %@)", self, _parentBridge, [self executorClass]); - if (self->_reactInstance) { - // Do this synchronously on the main thread to fulfil unregisterFromInspector's - // requirements. - self->_reactInstance->unregisterFromInspector(); - } + if (self->_reactInstance) { + // Do this synchronously on the main thread to fulfil unregisterFromInspector's + // requirements. + self->_reactInstance->unregisterFromInspector(); + } - _loading = NO; - _valid = NO; - _didInvalidate = YES; - _moduleRegistryCreated = NO; + _loading = NO; + _valid = NO; + _didInvalidate = YES; + _moduleRegistryCreated = NO; - if ([RCTBridge currentBridge] == self) { - [RCTBridge setCurrentBridge:nil]; - } + if ([RCTBridge currentBridge] == self) { + [RCTBridge setCurrentBridge:nil]; + } - // Stop JS instance and message thread - [self ensureOnJavaScriptThread:^{ - [self->_displayLink invalidate]; - self->_displayLink = nil; + // Stop JS instance and message thread + [self ensureOnJavaScriptThread:^{ + [self->_displayLink invalidate]; + self->_displayLink = nil; - if (RCTProfileIsProfiling()) { - RCTProfileUnhookModules(self); - } + if (RCTProfileIsProfiling()) { + RCTProfileUnhookModules(self); + } - // Invalidate modules + // Invalidate modules - [[NSNotificationCenter defaultCenter] postNotificationName:RCTBridgeWillInvalidateModulesNotification - object:self->_parentBridge - userInfo:@{@"bridge" : self}]; + [[NSNotificationCenter defaultCenter] postNotificationName:RCTBridgeWillInvalidateModulesNotification + object:self->_parentBridge + userInfo:@{@"bridge" : self}]; - // We're on the JS thread (which we'll be suspending soon), so no new calls will be made to native modules after - // this completes. We must ensure all previous calls were dispatched before deallocating the instance (and module - // wrappers) or we may have invalid pointers still in flight. - dispatch_group_t moduleInvalidation = dispatch_group_create(); - for (RCTModuleData *moduleData in self->_moduleDataByID) { - // Be careful when grabbing an instance here, we don't want to instantiate - // any modules just to invalidate them. - if (![moduleData hasInstance]) { - continue; - } + // We're on the JS thread (which we'll be suspending soon), so no new calls will be made to native modules after + // this completes. We must ensure all previous calls were dispatched before deallocating the instance (and module + // wrappers) or we may have invalid pointers still in flight. + dispatch_group_t moduleInvalidation = dispatch_group_create(); + for (RCTModuleData *moduleData in self->_moduleDataByID) { + // Be careful when grabbing an instance here, we don't want to instantiate + // any modules just to invalidate them. + if (![moduleData hasInstance]) { + continue; + } - if ([moduleData.instance respondsToSelector:@selector(invalidate)]) { - dispatch_group_enter(moduleInvalidation); - [self - dispatchBlock:^{ - [(id)moduleData.instance invalidate]; - dispatch_group_leave(moduleInvalidation); - } - queue:moduleData.methodQueue]; + if ([moduleData.instance respondsToSelector:@selector(invalidate)]) { + dispatch_group_enter(moduleInvalidation); + [self + dispatchBlock:^{ + [(id)moduleData.instance invalidate]; + dispatch_group_leave(moduleInvalidation); + } + queue:moduleData.methodQueue]; + } + [moduleData invalidate]; } - [moduleData invalidate]; - } - if (dispatch_group_wait(moduleInvalidation, dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC))) { - RCTLogError(@"Timed out waiting for modules to be invalidated"); - } + if (dispatch_group_wait(moduleInvalidation, dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC))) { + RCTLogError(@"Timed out waiting for modules to be invalidated"); + } - [[NSNotificationCenter defaultCenter] postNotificationName:RCTBridgeDidInvalidateModulesNotification - object:self->_parentBridge - userInfo:@{@"bridge" : self}]; + [[NSNotificationCenter defaultCenter] postNotificationName:RCTBridgeDidInvalidateModulesNotification + object:self->_parentBridge + userInfo:@{@"bridge" : self}]; - self->_reactInstance.reset(); - self->_jsMessageThread.reset(); + self->_reactInstance.reset(); + self->_jsMessageThread.reset(); - self->_moduleDataByName = nil; - self->_moduleDataByID = nil; - self->_moduleClassesByID = nil; - self->_pendingCalls = nil; + self->_moduleDataByName = nil; + self->_moduleDataByID = nil; + self->_moduleClassesByID = nil; + self->_pendingCalls = nil; - [self->_jsThread cancel]; - self->_jsThread = nil; - CFRunLoopStop(CFRunLoopGetCurrent()); - }]; + [self->_jsThread cancel]; + self->_jsThread = nil; + CFRunLoopStop(CFRunLoopGetCurrent()); + }]; + }); } - (void)logMessage:(NSString *)message level:(NSString *)level