diff --git a/React/Base/RCTBatchedBridge.m b/React/Base/RCTBatchedBridge.m index 21d35a6e1..9aba7f9ff 100644 --- a/React/Base/RCTBatchedBridge.m +++ b/React/Base/RCTBatchedBridge.m @@ -29,6 +29,9 @@ [[[NSThread currentThread] name] isEqualToString:@"com.facebook.React.JavaScript"], \ @"This method must be called on JS thread") +/** + * Used by RKAnalyticsCPULogger + */ NSString *const RCTEnqueueNotification = @"RCTEnqueueNotification"; NSString *const RCTDequeueNotification = @"RCTDequeueNotification"; @@ -90,9 +93,9 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void); [RCTBridge setCurrentBridge:self]; - [[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptWillStartLoadingNotification - object:self - userInfo:@{ @"bridge": self }]; + [[NSNotificationCenter defaultCenter] + postNotificationName:RCTJavaScriptWillStartLoadingNotification + object:_parentBridge userInfo:@{@"bridge": self}]; [self start]; } @@ -208,9 +211,9 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void); // Allow testing without a script dispatch_async(dispatch_get_main_queue(), ^{ [self didFinishLoading]; - [[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidLoadNotification - object:_parentBridge - userInfo:@{ @"bridge": self }]; + [[NSNotificationCenter defaultCenter] + postNotificationName:RCTJavaScriptDidLoadNotification + object:_parentBridge userInfo:@{@"bridge": self}]; }); onSourceLoad(nil, nil); } @@ -331,8 +334,15 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void); } } - [[NSNotificationCenter defaultCenter] postNotificationName:RCTDidCreateNativeModules - object:self]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + + [[NSNotificationCenter defaultCenter] + postNotificationName:RCTDidCreateNativeModules + object:self userInfo:@{@"bridge": self}]; + +#pragma clang diagnostic pop + RCTPerformanceLoggerEnd(RCTPLNativeModuleInit); } @@ -429,10 +439,9 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void); // timing issues with RCTRootView dispatch_async(dispatch_get_main_queue(), ^{ [self didFinishLoading]; - - [[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidLoadNotification - object:_parentBridge - userInfo:@{ @"bridge": self }]; + [[NSNotificationCenter defaultCenter] + postNotificationName:RCTJavaScriptDidLoadNotification + object:_parentBridge userInfo:@{@"bridge": self}]; }); }]; } @@ -457,9 +466,10 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void); _loading = NO; - [[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidFailToLoadNotification - object:_parentBridge - userInfo:@{@"bridge": self, @"error": error}]; + [[NSNotificationCenter defaultCenter] + postNotificationName:RCTJavaScriptDidFailToLoadNotification + object:_parentBridge userInfo:@{@"bridge": self, @"error": error}]; + RCTFatal(error); } @@ -715,7 +725,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR { RCTAssertJSThread(); - [[NSNotificationCenter defaultCenter] postNotificationName:RCTEnqueueNotification object:nil userInfo:nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:RCTEnqueueNotification object:self userInfo:nil]; RCTJavaScriptCallback processResponse = ^(id json, NSError *error) { if (error) { @@ -725,7 +735,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR if (!self.isValid) { return; } - [[NSNotificationCenter defaultCenter] postNotificationName:RCTDequeueNotification object:nil userInfo:nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:RCTDequeueNotification object:self userInfo:nil]; [self handleBuffer:json batchEnded:YES]; }; @@ -740,7 +750,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR { RCTAssertJSThread(); - [[NSNotificationCenter defaultCenter] postNotificationName:RCTEnqueueNotification object:nil userInfo:nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:RCTEnqueueNotification object:self userInfo:nil]; RCTJavaScriptCallback processResponse = ^(id json, NSError *error) { if (error) { @@ -750,7 +760,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR if (!self.isValid) { return; } - [[NSNotificationCenter defaultCenter] postNotificationName:RCTDequeueNotification object:nil userInfo:nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:RCTDequeueNotification object:self userInfo:nil]; [self handleBuffer:json batchEnded:YES]; }; diff --git a/React/Base/RCTBridge.h b/React/Base/RCTBridge.h index f341b75aa..a67176e9c 100644 --- a/React/Base/RCTBridge.h +++ b/React/Base/RCTBridge.h @@ -25,24 +25,28 @@ RCT_EXTERN NSString *const RCTReloadNotification; /** - * This notification fires when the bridge starts loading. + * This notification fires when the bridge starts loading the JS bundle. */ RCT_EXTERN NSString *const RCTJavaScriptWillStartLoadingNotification; /** - * This notification fires when the bridge has finished loading. + * This notification fires when the bridge has finished loading the JS bundle. */ RCT_EXTERN NSString *const RCTJavaScriptDidLoadNotification; /** - * This notification fires when the bridge failed to load. + * This notification fires when the bridge failed to load the JS bundle. The + * `error` key can be used to determine the error that occured. */ RCT_EXTERN NSString *const RCTJavaScriptDidFailToLoadNotification; /** - * This notification fires when the bridge created all registered native modules + * This notification fires each time a native module is instantiated. The + * `module` key will contain a reference to the newly-created module instance. + * Note that this notification may be fired before the module is available via + * the `[bridge moduleForClass:]` method. */ -RCT_EXTERN NSString *const RCTDidCreateNativeModules; +RCT_EXTERN NSString *const RCTDidInitializeModuleNotification; /** * This block can be used to instantiate modules that require additional @@ -171,10 +175,28 @@ RCT_EXTERN BOOL RCTBridgeModuleClassIsRegistered(Class); @end /** - * These properties and methods are deprecated and should not be used + * These features are deprecated and should not be used. */ @interface RCTBridge (Deprecated) +/** + * This notification used to fire after all native modules has been initialized, + * but now that native modules are instantiated lazily on demand, its original + * purpose is meaningless. + * + * If you need to access a module, you can do so as soon as the bridge has been + * initialized, by calling `[bridge moduleForClass:]`. If you need to know when + * an individual module has been instantiated, use the `RCTDidInitializeModule` + * notification instead. + */ +RCT_EXTERN NSString *const RCTDidCreateNativeModules +__deprecated_msg("Use RCTDidInitializeModule to observe init of individual modules"); + +/** + * Accessing the modules property causes all modules to be eagerly initialized, + * which stalls the main thread. Use moduleClasses to enumerate through modules + * without causing them to be instantiated. + */ @property (nonatomic, copy, readonly) NSDictionary *modules __deprecated_msg("Use moduleClasses and/or moduleForName: instead"); diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index 1dfac45b3..6ba6b5c36 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -22,7 +22,7 @@ NSString *const RCTReloadNotification = @"RCTReloadNotification"; NSString *const RCTJavaScriptWillStartLoadingNotification = @"RCTJavaScriptWillStartLoadingNotification"; NSString *const RCTJavaScriptDidLoadNotification = @"RCTJavaScriptDidLoadNotification"; NSString *const RCTJavaScriptDidFailToLoadNotification = @"RCTJavaScriptDidFailToLoadNotification"; -NSString *const RCTDidCreateNativeModules = @"RCTDidCreateNativeModules"; +NSString *const RCTDidInitializeModuleNotification = @"RCTDidInitializeModuleNotification"; @interface RCTBatchedBridge : RCTBridge @@ -213,10 +213,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) [commands registerKeyCommandWithInput:@"r" modifierFlags:UIKeyModifierCommand action:^(__unused UIKeyCommand *command) { - [[NSNotificationCenter defaultCenter] postNotificationName:RCTReloadNotification - object:nil - userInfo:nil]; - }]; + [[NSNotificationCenter defaultCenter] postNotificationName:RCTReloadNotification + object:nil + userInfo:nil]; + }]; #endif } @@ -305,6 +305,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) @implementation RCTBridge(Deprecated) +NSString *const RCTDidCreateNativeModules = @"RCTDidCreateNativeModules"; + - (NSDictionary *)modules { return self.batchedBridge.modules; diff --git a/React/Base/RCTModuleData.m b/React/Base/RCTModuleData.m index d247f532f..9b28cd657 100644 --- a/React/Base/RCTModuleData.m +++ b/React/Base/RCTModuleData.m @@ -79,6 +79,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init); - (void)setBridgeForInstance:(RCTBridge *)bridge { + _bridge = bridge; if ([_instance respondsToSelector:@selector(bridge)]) { @try { [(id)_instance setValue:bridge forKey:@"bridge"]; @@ -198,6 +199,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init); } } } + + // Needs to be sent after bridge has been set for all module instances. + // Makes sense to put it here, since the same rules apply for methodQueue. + [[NSNotificationCenter defaultCenter] + postNotificationName:RCTDidInitializeModuleNotification + object:_bridge userInfo:@{@"module": _instance}]; } return _methodQueue; } diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m index 46c991e3c..bf1c2ee59 100644 --- a/React/Modules/RCTUIManager.m +++ b/React/Modules/RCTUIManager.m @@ -347,7 +347,7 @@ extern NSString *RCTBridgeModuleNameForClass(Class cls); [[NSNotificationCenter defaultCenter] postNotificationName:RCTUIManagerDidRegisterRootViewNotification object:self - userInfo:@{ RCTUIManagerRootViewKey: rootView }]; + userInfo:@{RCTUIManagerRootViewKey: rootView}]; } - (UIView *)viewForReactTag:(NSNumber *)reactTag @@ -695,7 +695,7 @@ RCT_EXPORT_METHOD(removeRootView:(nonnull NSNumber *)rootReactTag) [[NSNotificationCenter defaultCenter] postNotificationName:RCTUIManagerDidRemoveRootViewNotification object:uiManager - userInfo:@{ RCTUIManagerRootViewKey: rootView }]; + userInfo:@{RCTUIManagerRootViewKey: rootView}]; }]; } diff --git a/React/Profiler/RCTProfile.m b/React/Profiler/RCTProfile.m index 9cc0ae1d9..122dcbe8f 100644 --- a/React/Profiler/RCTProfile.m +++ b/React/Profiler/RCTProfile.m @@ -403,7 +403,7 @@ void RCTProfileInit(RCTBridge *bridge) forMode:NSRunLoopCommonModes]; [[NSNotificationCenter defaultCenter] postNotificationName:RCTProfileDidStartProfiling - object:nil]; + object:bridge]; } void RCTProfileEnd(RCTBridge *bridge, void (^callback)(NSString *)) @@ -417,7 +417,7 @@ void RCTProfileEnd(RCTBridge *bridge, void (^callback)(NSString *)) OSAtomicAnd32Barrier(0, &RCTProfileProfiling); [[NSNotificationCenter defaultCenter] postNotificationName:RCTProfileDidEndProfiling - object:nil]; + object:bridge]; [RCTProfileDisplayLink invalidate]; RCTProfileDisplayLink = nil;