From d7a0c44590bcf3fb9d055aeae3391d5bcd7e21be Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Tue, 13 Nov 2018 20:09:21 -0800 Subject: [PATCH] iOS: add moduleForNameForcedLoad: to lookup modules by name and force load them Summary: Some module classes may not be loaded yet, so looking up via classes may not always give the correct instance. This diff added a new lookup method that delegate to the bridge delegate to force load the modules as needed. The existing moduleForName: method was left untouched because it's solely used by RCTUIManager at the moment. Reviewed By: dshahidehpour Differential Revision: D13033876 fbshipit-source-id: 4082fcd68498004f678b4b95adc82b5b134fefdf --- React/Base/RCTBridge.h | 4 ++++ React/Base/RCTBridge.m | 5 +++++ React/CxxBridge/RCTCxxBridge.mm | 36 +++++++++++++++++++++++---------- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/React/Base/RCTBridge.h b/React/Base/RCTBridge.h index 3af1a1976..b1ed41cdc 100644 --- a/React/Base/RCTBridge.h +++ b/React/Base/RCTBridge.h @@ -151,8 +151,12 @@ RCT_EXTERN void RCTEnableJSINativeModule(BOOL enabled); * lazily instantiated, so calling these methods for the first time with a given * module name/class may cause the class to be sychronously instantiated, * potentially blocking both the calling thread and main thread for a short time. + * + * Note: This method does NOT lazily load the particular module if it's not yet loaded. */ - (id)moduleForName:(NSString *)moduleName; +- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad; +// Note: This method lazily load the module as necessary. - (id)moduleForClass:(Class)moduleClass; /** diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index a8a79a945..22c9a07d5 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -241,6 +241,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) return [self.batchedBridge moduleForName:moduleName]; } +- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad +{ + return [self.batchedBridge moduleForName:moduleName lazilyLoadIfNecessary:lazilyLoad]; +} + - (id)moduleForClass:(Class)moduleClass { id module = [self.batchedBridge moduleForClass:moduleClass]; diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 9f42541df..79990b762 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -439,6 +439,30 @@ struct RCTInstanceCallback : public InstanceCallback { return _moduleDataByName[moduleName].instance; } +- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad +{ + if (!lazilyLoad) { + return [self moduleForName:moduleName]; + } + + RCTModuleData *moduleData = _moduleDataByName[moduleName]; + if (moduleData) { + return moduleData.instance; + } + + // Module may not be loaded yet, so attempt to force load it here. + const BOOL result = [self.delegate respondsToSelector:@selector(bridge:didNotFindModule:)] && + [self.delegate bridge:self didNotFindModule:moduleName]; + if (result) { + // Try again. + moduleData = _moduleDataByName[moduleName]; + } else { + RCTLogError(@"Unable to find module for %@", moduleName); + } + + return moduleData.instance; +} + - (BOOL)moduleIsInitialized:(Class)moduleClass { return _moduleDataByName[RCTBridgeModuleNameForClass(moduleClass)].hasInstance; @@ -446,17 +470,7 @@ struct RCTInstanceCallback : public InstanceCallback { - (id)moduleForClass:(Class)moduleClass { - NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass); - RCTModuleData *moduleData = _moduleDataByName[moduleName]; - if (moduleData) { - return moduleData.instance; - } - - // Module may not be loaded yet, so attempt to force load it here. - RCTAssert([moduleClass conformsToProtocol:@protocol(RCTBridgeModule)], @"Asking for a NativeModule that doesn't conform to RCTBridgeModule: %@", NSStringFromClass(moduleClass)); - [self registerAdditionalModuleClasses:@[moduleClass]]; - - return _moduleDataByName[moduleName].instance; + return [self moduleForName:RCTBridgeModuleNameForClass(moduleClass) lazilyLoadIfNecessary:YES]; } - (std::shared_ptr)_buildModuleRegistryUnlocked