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:
Ramanpreet Nara 2020-09-17 13:52:44 -07:00 коммит произвёл Facebook GitHub Bot
Родитель ee38751975
Коммит 9b76e217bb
1 изменённых файлов: 12 добавлений и 8 удалений

Просмотреть файл

@ -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);
})