@@ -301,6 +301,7 @@ - (void)start
301
301
[self registerExtraModules ];
302
302
// Initialize all native modules that cannot be loaded lazily
303
303
(void )[self _initializeModules: RCTGetModuleClasses () withDispatchGroup: prepareBridge lazilyDiscovered: NO ];
304
+ [self registerExtraLazyModules ];
304
305
305
306
[_performanceLogger markStopForTag: RCTPLNativeModuleInit];
306
307
@@ -600,6 +601,57 @@ - (void)registerExtraModules
600
601
RCT_PROFILE_END_EVENT (RCTProfileTagAlways, @" " );
601
602
}
602
603
604
+ - (void )registerExtraLazyModules
605
+ {
606
+ #if RCT_DEBUG
607
+ // This is debug-only and only when Chrome is attached, since it expects all modules to be already
608
+ // available on start up. Otherwise, we can let the lazy module discovery to load them on demand.
609
+ Class executorClass = [_parentBridge executorClass ];
610
+ if (executorClass && [NSStringFromClass (executorClass) isEqualToString: @" RCTWebSocketExecutor" ]) {
611
+ NSDictionary <NSString *, Class > *moduleClasses = nil ;
612
+ if ([self .delegate respondsToSelector: @selector (extraLazyModuleClassesForBridge: )]) {
613
+ moduleClasses = [self .delegate extraLazyModuleClassesForBridge: _parentBridge];
614
+ }
615
+
616
+ if (!moduleClasses) {
617
+ return ;
618
+ }
619
+
620
+ // This logic is mostly copied from `registerModulesForClasses:`, but with one difference:
621
+ // we must use the names provided by the delegate method here.
622
+ for (NSString *moduleName in moduleClasses) {
623
+ Class moduleClass = moduleClasses[moduleName];
624
+ if (RCTJSINativeModuleEnabled () && [moduleClass conformsToProtocol: @protocol (RCTJSINativeModule)]) {
625
+ continue ;
626
+ }
627
+
628
+ // Check for module name collisions
629
+ RCTModuleData *moduleData = _moduleDataByName[moduleName];
630
+ if (moduleData) {
631
+ if (moduleData.hasInstance ) {
632
+ // Existing module was preregistered, so it takes precedence
633
+ continue ;
634
+ } else if ([moduleClass new ] == nil ) {
635
+ // The new module returned nil from init, so use the old module
636
+ continue ;
637
+ } else if ([moduleData.moduleClass new ] != nil ) {
638
+ // Both modules were non-nil, so it's unclear which should take precedence
639
+ RCTLogError (@" Attempted to register RCTBridgeModule class %@ for the "
640
+ " name '%@ ', but name was already registered by class %@ " ,
641
+ moduleClass, moduleName, moduleData.moduleClass );
642
+ }
643
+ }
644
+
645
+ moduleData = [[RCTModuleData alloc ] initWithModuleClass: moduleClass bridge: self ];
646
+
647
+ _moduleDataByName[moduleName] = moduleData;
648
+ [_moduleClassesByID addObject: moduleClass];
649
+ [_moduleDataByID addObject: moduleData];
650
+ }
651
+ }
652
+ #endif
653
+ }
654
+
603
655
- (NSArray <RCTModuleData *> *)_initializeModules : (NSArray <id<RCTBridgeModule>> *)modules
604
656
withDispatchGroup : (dispatch_group_t )dispatchGroup
605
657
lazilyDiscovered : (BOOL )lazilyDiscovered
0 commit comments