@@ -113,27 +113,26 @@ - (instancetype)initWithParentBridge:(RCTBridge *)bridge
113113
114114- (void )start
115115{
116- __weak RCTBatchedBridge *weakSelf = self;
117-
118- __block NSString *sourceCode;
119- __block NSString *config;
120-
121116 dispatch_queue_t bridgeQueue = dispatch_queue_create (" com.facebook.react.RCTBridgeQueue" , DISPATCH_QUEUE_CONCURRENT);
122- dispatch_group_t initModulesAndLoadSource = dispatch_group_create ();
123117
118+ dispatch_group_t initModulesAndLoadSource = dispatch_group_create ();
124119 dispatch_group_enter (initModulesAndLoadSource);
125- [weakSelf loadSource: ^(NSError *error, NSString *source) {
126- if (error) {
127- RCTLogError (@" %@ " , error);
128- } else {
129- sourceCode = source;
130- }
131-
120+ __block NSString *sourceCode;
121+ [self loadSource: ^(NSError *error, NSString *source) {
122+ sourceCode = source;
132123 dispatch_group_leave (initModulesAndLoadSource);
133124 }];
134125
126+ // Synchronously initialize all native modules
135127 [self initModules ];
136128
129+ if (RCTProfileIsProfiling ()) {
130+ // Depends on moduleDataByID being loaded
131+ RCTProfileHookModules (self);
132+ }
133+
134+ __weak RCTBatchedBridge *weakSelf = self;
135+ __block NSString *config;
137136 dispatch_group_enter (initModulesAndLoadSource);
138137 dispatch_async (bridgeQueue, ^{
139138 dispatch_group_t setupJSExecutorAndModuleConfig = dispatch_group_create ();
@@ -144,16 +143,16 @@ - (void)start
144143 dispatch_group_async (setupJSExecutorAndModuleConfig, bridgeQueue, ^{
145144 if (weakSelf.isValid ) {
146145 config = [weakSelf moduleConfig ];
147-
148- if (RCTProfileIsProfiling ()) {
149- RCTProfileHookModules (weakSelf);
150- }
151146 }
152147 });
153148
154149 dispatch_group_notify (setupJSExecutorAndModuleConfig, bridgeQueue, ^{
155- [weakSelf injectJSONConfiguration: config onComplete: ^(__unused NSError *error) {}];
156-
150+ // We're not waiting for this complete to leave the dispatch group, since
151+ // injectJSONConfiguration and executeSourceCode will schedule operations on the
152+ // same queue anyway.
153+ [weakSelf injectJSONConfiguration: config onComplete: ^(__unused NSError *error) {
154+ RCTPerformanceLoggerEnd (RCTPLNativeModuleInit);
155+ }];
157156 dispatch_group_leave (initModulesAndLoadSource);
158157 });
159158 });
@@ -167,51 +166,52 @@ - (void)start
167166
168167- (void )loadSource : (RCTSourceLoadBlock)_onSourceLoad
169168{
170- RCTPerformanceLoggerStart (RCTPLScriptDownload);
171- int cookie = RCTProfileBeginAsyncEvent (0 , @" JavaScript download" , nil );
172-
173- RCTSourceLoadBlock onSourceLoad = ^(NSError *error, NSString *source) {
174- RCTPerformanceLoggerEnd (RCTPLScriptDownload);
175- RCTProfileEndAsyncEvent (0 , @" init,download" , cookie, @" JavaScript download" , nil );
176-
177- if (error) {
178- NSArray *stack = [error userInfo ][@" stack" ];
179- if (stack) {
180- [self .redBox showErrorMessage: error.localizedDescription
181- withStack: stack];
182- } else {
183- [self .redBox showErrorMessage: error.localizedDescription
184- withDetails: error.localizedFailureReason];
185- }
169+ RCTPerformanceLoggerStart (RCTPLScriptDownload);
170+ int cookie = RCTProfileBeginAsyncEvent (0 , @" JavaScript download" , nil );
186171
187- NSDictionary *userInfo = @{@" bridge" : self, @" error" : error};
188- [[NSNotificationCenter defaultCenter ] postNotificationName: RCTJavaScriptDidFailToLoadNotification
189- object: _parentBridge
190- userInfo: userInfo];
191- }
172+ RCTSourceLoadBlock onSourceLoad = ^(NSError *error, NSString *source) {
173+ RCTProfileEndAsyncEvent (0 , @" init,download" , cookie, @" JavaScript download" , nil );
174+ RCTPerformanceLoggerEnd (RCTPLScriptDownload);
192175
193- _onSourceLoad (error, source);
194- };
176+ if (error) {
177+ NSArray *stack = [error userInfo ][@" stack" ];
178+ if (stack) {
179+ [self .redBox showErrorMessage: error.localizedDescription
180+ withStack: stack];
181+ } else {
182+ [self .redBox showErrorMessage: error.localizedDescription
183+ withDetails: error.localizedFailureReason];
184+ }
195185
196- if ([self .delegate respondsToSelector: @selector (loadSourceForBridge:withBlock: )]) {
197- [self .delegate loadSourceForBridge: _parentBridge withBlock: onSourceLoad];
198- } else if (self.bundleURL ) {
199- [RCTJavaScriptLoader loadBundleAtURL: self .bundleURL onComplete: onSourceLoad];
200- } else {
201- // Allow testing without a script
202- dispatch_async (dispatch_get_main_queue (), ^{
203- _loading = NO ;
204- [[NSNotificationCenter defaultCenter ] postNotificationName: RCTJavaScriptDidLoadNotification
205- object: _parentBridge
206- userInfo: @{ @" bridge" : self }];
207- });
208- onSourceLoad (nil , nil );
186+ NSDictionary *userInfo = @{@" bridge" : self, @" error" : error};
187+ [[NSNotificationCenter defaultCenter ] postNotificationName: RCTJavaScriptDidFailToLoadNotification
188+ object: _parentBridge
189+ userInfo: userInfo];
209190 }
191+
192+ _onSourceLoad (error, source);
193+ };
194+
195+ if ([self .delegate respondsToSelector: @selector (loadSourceForBridge:withBlock: )]) {
196+ [self .delegate loadSourceForBridge: _parentBridge withBlock: onSourceLoad];
197+ } else if (self.bundleURL ) {
198+ [RCTJavaScriptLoader loadBundleAtURL: self .bundleURL onComplete: onSourceLoad];
199+ } else {
200+ // Allow testing without a script
201+ dispatch_async (dispatch_get_main_queue (), ^{
202+ _loading = NO ;
203+ [[NSNotificationCenter defaultCenter ] postNotificationName: RCTJavaScriptDidLoadNotification
204+ object: _parentBridge
205+ userInfo: @{ @" bridge" : self }];
206+ });
207+ onSourceLoad (nil , nil );
208+ }
210209}
211210
212211- (void )initModules
213212{
214213 RCTAssertMainThread ();
214+ RCTPerformanceLoggerStart (RCTPLNativeModuleInit);
215215
216216 // Register passed-in module instances
217217 NSMutableDictionary *preregisteredModules = [NSMutableDictionary new ];
@@ -266,7 +266,6 @@ - (void)initModules
266266 _javaScriptExecutor = _modulesByName[RCTBridgeModuleNameForClass (self .executorClass)];
267267
268268 for (id <RCTBridgeModule> module in _modulesByName.allValues ) {
269-
270269 // Bridge must be set before moduleData is set up, as methodQueue
271270 // initialization requires it (View Managers get their queue by calling
272271 // self.bridge.uiManager.methodQueue)
@@ -288,7 +287,6 @@ - (void)initModules
288287- (void )setupExecutor
289288{
290289 [_javaScriptExecutor setUp ];
291-
292290}
293291
294292- (NSString *)moduleConfig
@@ -309,7 +307,7 @@ - (NSString *)moduleConfig
309307- (void )injectJSONConfiguration : (NSString *)configJSON
310308 onComplete : (void (^)(NSError *))onComplete
311309{
312- if (!self.isValid ) {
310+ if (!self.valid ) {
313311 return ;
314312 }
315313
@@ -325,9 +323,7 @@ - (void)injectJSONConfiguration:(NSString *)configJSON
325323
326324- (void )executeSourceCode : (NSString *)sourceCode
327325{
328- _loading = NO ;
329-
330- if (!self.isValid || !_javaScriptExecutor) {
326+ if (!self.valid || !_javaScriptExecutor) {
331327 return ;
332328 }
333329
@@ -336,22 +332,23 @@ - (void)executeSourceCode:(NSString *)sourceCode
336332 sourceCodeModule.scriptText = sourceCode;
337333
338334 [self enqueueApplicationScript: sourceCode url: self .bundleURL onComplete: ^(NSError *loadError) {
339-
340335 if (loadError) {
341336 [self .redBox showError: loadError];
342337 return ;
343338 }
344339
345- /* *
346- * Register the display link to start sending js calls after everything
347- * is setup
348- */
340+ // Register the display link to start sending js calls after everything is setup
349341 NSRunLoop *targetRunLoop = [_javaScriptExecutor isKindOfClass: [RCTContextExecutor class ]] ? [NSRunLoop currentRunLoop ] : [NSRunLoop mainRunLoop ];
350342 [_jsDisplayLink addToRunLoop: targetRunLoop forMode: NSRunLoopCommonModes ];
351343
352- [[NSNotificationCenter defaultCenter ] postNotificationName: RCTJavaScriptDidLoadNotification
353- object: _parentBridge
354- userInfo: @{ @" bridge" : self }];
344+ // Perform the state update and notification on the main thread, so we can't run into
345+ // timing issues with RCTRootView
346+ dispatch_async (dispatch_get_main_queue (), ^{
347+ _loading = NO ;
348+ [[NSNotificationCenter defaultCenter ] postNotificationName: RCTJavaScriptDidLoadNotification
349+ object: _parentBridge
350+ userInfo: @{ @" bridge" : self }];
351+ });
355352 }];
356353}
357354
@@ -420,12 +417,13 @@ - (NSDictionary *)modules
420417
421418- (void )invalidate
422419{
423- if (!self.isValid ) {
420+ if (!self.valid ) {
424421 return ;
425422 }
426423
427424 RCTAssertMainThread ();
428425
426+ _loading = NO ;
429427 _valid = NO ;
430428 if ([RCTBridge currentBridge ] == self) {
431429 [RCTBridge setCurrentBridge: nil ];
0 commit comments