diff --git a/React/Base/RCTBatchedBridge.m b/React/Base/RCTBatchedBridge.m index 49c4dcb7c..b574d62be 100644 --- a/React/Base/RCTBatchedBridge.m +++ b/React/Base/RCTBatchedBridge.m @@ -342,6 +342,12 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void); } } + for (RCTModuleData *moduleData in _moduleDataByID) { + if (moduleData.hasInstance) { + [moduleData gatherConstants]; + } + } + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" diff --git a/React/Base/RCTModuleData.h b/React/Base/RCTModuleData.h index ec922c804..6d5b00c7a 100644 --- a/React/Base/RCTModuleData.h +++ b/React/Base/RCTModuleData.h @@ -37,6 +37,14 @@ */ - (void)finishSetupForInstance; +/** + * Calls `constantsToExport` on the module and stores the result. Note that + * this will init the module if it has not already been created. This method + * can be called on any thread, but may block the main thread briefly if the + * module implements `constantsToExport`. + */ +- (void)gatherConstants; + @property (nonatomic, strong, readonly) Class moduleClass; @property (nonatomic, copy, readonly) NSString *name; diff --git a/React/Base/RCTModuleData.m b/React/Base/RCTModuleData.m index 78ef8471e..5175fb16d 100644 --- a/React/Base/RCTModuleData.m +++ b/React/Base/RCTModuleData.m @@ -80,11 +80,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init); [[NSNotificationCenter defaultCenter] postNotificationName:RCTDidInitializeModuleNotification object:_bridge userInfo:@{@"module": _instance}]; - - if (RCTClassOverridesInstanceMethod(_moduleClass, @selector(constantsToExport))) { - RCTAssertMainThread(); - _constantsToExport = [_instance constantsToExport]; - } } } @@ -140,7 +135,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init); [_instanceLock unlock]; [self finishSetupForInstance]; - return _instance; } @@ -185,10 +179,23 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init); return _methods; } +- (void)gatherConstants +{ + if (!_constantsToExport) { + if (RCTClassOverridesInstanceMethod(_moduleClass, @selector(constantsToExport))) { + RCTAssert(_instance, @"constantsToExport called before instance created."); + RCTExecuteOnMainThread(^{ + _constantsToExport = [_instance constantsToExport] ?: @{}; + }, YES); + } else { + _constantsToExport = @{}; + } + } +} + - (NSArray *)config { __block NSDictionary *constants = _constantsToExport; - _constantsToExport = nil; // Not needed any more if (constants.count == 0 && self.methods.count == 0) { return (id)kCFNull; // Nothing to export