From e94f2c362581c72e56a5436a2b9e67ca57901bda Mon Sep 17 00:00:00 2001 From: Peter Argany Date: Wed, 21 Aug 2019 14:28:16 -0700 Subject: [PATCH] Adhere to main queue requirements of native modules Summary: Certain turbomodules set `requiresMainQueueSetup` to true. This is b/c they use some fancy APIs in setup that need main queue. TurboModuleManager mostly adhered to this restriction, the only case it didn't is when setting bridge. There is possibility that this happens on JS thread, which would crash the app for these certain TM. This diff fixes that. Reviewed By: RSNara Differential Revision: D16921644 fbshipit-source-id: 69b2410550360d3ccb03c0b71fb7dfccb889eda4 --- .../core/platform/ios/RCTTurboModuleManager.mm | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm b/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm index 3cb73b54c0..f3273629fd 100644 --- a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm +++ b/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm @@ -284,6 +284,10 @@ static Class getFallbackClassFromName(const char *name) */ @try { /** + * If module requiresMainQueueSetup, dispatch to main queue. Bridge setup + * may call APIs which are main queue only, which crash if called from + * JS thread. + * * RCTBridgeModule declares the bridge property as readonly. * Therefore, when authors of NativeModules synthesize the bridge * via @synthesize bridge = bridge;, the ObjC runtime generates @@ -291,7 +295,16 @@ static Class getFallbackClassFromName(const char *name) * generated, so we have have to rely on the KVC API of ObjC to set * the bridge property of these NativeModules. */ - [(id)module setValue:_bridge forKey:@"bridge"]; + if ([[module class] respondsToSelector:@selector(requiresMainQueueSetup)] && + [[module class] requiresMainQueueSetup]) { + __weak __typeof(self) weakSelf = self; + dispatch_async(dispatch_get_main_queue(), ^{ + __strong __typeof(self) strongSelf = weakSelf; + [(id)module setValue:strongSelf->_bridge forKey:@"bridge"]; + }); + } else { + [(id)module setValue:_bridge forKey:@"bridge"]; + } } @catch (NSException *exception) { RCTLogError( @"%@ has no setter or ivar for its bridge, which is not "