mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Execute sync methods on JS thread
Summary: There are two ways to make a NativeModule method execute synchronously: - Declare the NativeModule method to be synchronous (i.e: use `RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD`). - Make the NativeModule synchronous (i.e: make its method queue `RCTJSThread`). This way, all its methods are synchronous. `RCTNativeModule` executes all synchronous methods on the JS thread: - Executing an async methods on a sync module: https://git.io/JfRPj - Executing a sync method: https://git.io/JfRXe However, in TurboModules we block the JS thread, execute the method on the NativeModule's method queue, and then unblock the JS thread. While this approach is thread-safe, and arguably the correct way to dispatch sync methods, it's also much slower than the alternative. Therefore, this diff migrates the legacy behaviour to the TurboModule system. ## Special Case: getConstants() When an ObjC NativeModule requires main queue setup, and it exports constants, we execute its `constantsToExport` method on the main queue (see: [RCTModuleData gatherConstants](https://github.com/facebook/react-native/blob/c8d678abcf93fd3f6daf4bebfdf25937995c1fdf/React/Base/RCTModuleData.mm#L392-L402)). I replicated this behaviour with TurboModules. Changelog: [iOS][Fixed] - Execute ObjC TurboModule async method calls on JS thread for sync modules Reviewed By: fkgozali Differential Revision: D21602096 fbshipit-source-id: 42d07b7ad000abeac27091dc3ec440e3836d2eae
This commit is contained in:
committed by
Facebook GitHub Bot
parent
d7ac21cec5
commit
976f51abd9
@@ -40,7 +40,6 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule {
|
||||
id<RCTTurboModule> instance;
|
||||
std::shared_ptr<CallInvoker> jsInvoker;
|
||||
std::shared_ptr<CallInvoker> nativeInvoker;
|
||||
// Does the NativeModule dispatch async methods to the JS thread?
|
||||
bool isSyncModule;
|
||||
};
|
||||
|
||||
@@ -61,16 +60,20 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule {
|
||||
void setMethodArgConversionSelector(NSString *methodName, int argIndex, NSString *fnName);
|
||||
|
||||
private:
|
||||
// Does the NativeModule dispatch async methods to the JS thread?
|
||||
const bool isSyncModule_;
|
||||
|
||||
/**
|
||||
* TODO(ramanpreet):
|
||||
* Investigate an optimization that'll let us get rid of this NSMutableDictionary.
|
||||
*/
|
||||
NSMutableDictionary<NSString *, NSMutableArray *> *methodArgConversionSelectors_;
|
||||
NSDictionary<NSString *, NSArray<NSString *> *> *methodArgumentTypeNames_;
|
||||
const bool isSyncModule_;
|
||||
bool isMethodSync(TurboModuleMethodValueKind returnType);
|
||||
NSString *getArgumentTypeName(NSString *methodName, int argIndex);
|
||||
|
||||
bool isMethodSync(TurboModuleMethodValueKind returnType);
|
||||
BOOL hasMethodArgConversionSelector(NSString *methodName, int argIndex);
|
||||
SEL getMethodArgConversionSelector(NSString *methodName, int argIndex);
|
||||
NSString *getArgumentTypeName(NSString *methodName, int argIndex);
|
||||
NSInvocation *getMethodInvocation(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind returnType,
|
||||
@@ -86,9 +89,6 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule {
|
||||
NSInvocation *inv,
|
||||
NSMutableArray *retainedObjectsForInvocation);
|
||||
|
||||
BOOL hasMethodArgConversionSelector(NSString *methodName, int argIndex);
|
||||
SEL getMethodArgConversionSelector(NSString *methodName, int argIndex);
|
||||
|
||||
using PromiseInvocationBlock = void (^)(RCTPromiseResolveBlock resolveWrapper, RCTPromiseRejectBlock rejectWrapper);
|
||||
jsi::Value
|
||||
createPromise(jsi::Runtime &runtime, std::shared_ptr<react::CallInvoker> jsInvoker, PromiseInvocationBlock invoke);
|
||||
|
||||
@@ -361,7 +361,7 @@ jsi::Value ObjCTurboModule::performMethodInvocation(
|
||||
};
|
||||
|
||||
if (wasMethodSync) {
|
||||
nativeInvoker_->invokeSync([block]() -> void { block(); });
|
||||
block();
|
||||
} else {
|
||||
asyncCallCounter = getUniqueId();
|
||||
TurboModulePerfLogger::asyncMethodCallDispatch(moduleName, methodName);
|
||||
|
||||
Reference in New Issue
Block a user