Copy all blocks generated by TurboModules
Summary: The Apple documentation states: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Blocks/Articles/bxUsing.html#//apple_ref/doc/uid/TP40007502-CH5-SW1 > Typically, you shouldn’t need to copy (or retain) a block. You only need to make a copy when you expect the block to be used after destruction of the scope within which it was declared. Copying moves a block to the heap. All blocks generated in the TurboModule infra, for callbacks and promise resolve/reject handlers, can be used after the destruction of the scope within which they were declared. Therefore, let's copy them in the hopes that they mitigate T75876134. **Note:** We copy blocks before pushing them into the `retainedObjects` array in the legacy Infra as well. Context: D2559997 (71da2917e5
), D5589246 (2a6965df90
) Changelog: [Internal] Reviewed By: fkgozali Differential Revision: D23764329 fbshipit-source-id: e71360977bdff74dc570bd40f0139792860f811f
This commit is contained in:
Родитель
ee38751975
Коммит
9b76e217bb
|
@ -171,7 +171,7 @@ convertJSIFunctionToCallback(jsi::Runtime &runtime, const jsi::Function &value,
|
|||
{
|
||||
auto weakWrapper = CallbackWrapper::createWeak(value.getFunction(runtime), runtime, jsInvoker);
|
||||
BOOL __block wrapperWasCalled = NO;
|
||||
return ^(NSArray *responses) {
|
||||
RCTResponseSenderBlock callback = ^(NSArray *responses) {
|
||||
if (wrapperWasCalled) {
|
||||
throw std::runtime_error("callback arg cannot be called more than once");
|
||||
}
|
||||
|
@ -194,6 +194,8 @@ convertJSIFunctionToCallback(jsi::Runtime &runtime, const jsi::Function &value,
|
|||
|
||||
wrapperWasCalled = YES;
|
||||
};
|
||||
|
||||
return [callback copy];
|
||||
}
|
||||
|
||||
namespace facebook {
|
||||
|
@ -331,12 +333,11 @@ jsi::Value ObjCTurboModule::performMethodInvocation(
|
|||
bool wasMethodSync = isMethodSync(returnType);
|
||||
|
||||
void (^block)() = ^{
|
||||
if (!weakModule) {
|
||||
id<RCTTurboModule> strongModule = weakModule;
|
||||
if (!strongModule) {
|
||||
return;
|
||||
}
|
||||
|
||||
id<RCTTurboModule> strongModule = weakModule;
|
||||
|
||||
if (wasMethodSync) {
|
||||
TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodNameStr.c_str());
|
||||
} else {
|
||||
|
@ -635,10 +636,13 @@ jsi::Value ObjCTurboModule::invokeObjCMethod(
|
|||
runtime,
|
||||
jsInvoker_,
|
||||
^(RCTPromiseResolveBlock resolveBlock, RCTPromiseRejectBlock rejectBlock) {
|
||||
[inv setArgument:(void *)&resolveBlock atIndex:count + 2];
|
||||
[inv setArgument:(void *)&rejectBlock atIndex:count + 3];
|
||||
[retainedObjectsForInvocation addObject:resolveBlock];
|
||||
[retainedObjectsForInvocation addObject:rejectBlock];
|
||||
RCTPromiseResolveBlock resolveCopy = [resolveBlock copy];
|
||||
RCTPromiseRejectBlock rejectCopy = [rejectBlock copy];
|
||||
|
||||
[inv setArgument:(void *)&resolveCopy atIndex:count + 2];
|
||||
[inv setArgument:(void *)&rejectCopy atIndex:count + 3];
|
||||
[retainedObjectsForInvocation addObject:resolveCopy];
|
||||
[retainedObjectsForInvocation addObject:rejectCopy];
|
||||
// The return type becomes void in the ObjC side.
|
||||
performMethodInvocation(runtime, VoidKind, methodName, inv, retainedObjectsForInvocation);
|
||||
})
|
||||
|
|
Загрузка…
Ссылка в новой задаче