[Loader] Post a notification when the JS fails to load

Summary:
This provides a way to get notified when a bridge fails to load JS, allowing apps to handle the error.

Closes https://github.com/facebook/react-native/pull/1085
Github Author: James Ide <ide@jameside.com>

Test Plan: run the UIExplorer app with the packager server not running, and verify that the notification is posted.
This commit is contained in:
James Ide 2015-05-07 04:29:31 -07:00
parent 205c22b915
commit b8bf4d0957
2 changed files with 17 additions and 2 deletions

View File

@ -28,6 +28,11 @@ extern NSString *const RCTReloadNotification;
*/ */
extern NSString *const RCTJavaScriptDidLoadNotification; extern NSString *const RCTJavaScriptDidLoadNotification;
/**
* This notification fires when the bridge failed to load.
*/
extern NSString *const RCTJavaScriptDidFailToLoadNotification;
/** /**
* This block can be used to instantiate modules that require additional * This block can be used to instantiate modules that require additional
* init parameters, or additional configuration prior to being used. * init parameters, or additional configuration prior to being used.

View File

@ -31,6 +31,7 @@
NSString *const RCTReloadNotification = @"RCTReloadNotification"; NSString *const RCTReloadNotification = @"RCTReloadNotification";
NSString *const RCTJavaScriptDidLoadNotification = @"RCTJavaScriptDidLoadNotification"; NSString *const RCTJavaScriptDidLoadNotification = @"RCTJavaScriptDidLoadNotification";
NSString *const RCTJavaScriptDidFailToLoadNotification = @"RCTJavaScriptDidFailToLoadNotification";
dispatch_queue_t const RCTJSThread = nil; dispatch_queue_t const RCTJSThread = nil;
@ -1082,16 +1083,18 @@ RCT_BRIDGE_WARN(_invokeAndProcessModule:(NSString *)module method:(NSString *)me
RCTJavaScriptLoader *loader = [[RCTJavaScriptLoader alloc] initWithBridge:self]; RCTJavaScriptLoader *loader = [[RCTJavaScriptLoader alloc] initWithBridge:self];
[loader loadBundleAtURL:bundleURL onComplete:^(NSError *error, NSString *script) { [loader loadBundleAtURL:bundleURL onComplete:^(NSError *error, NSString *script) {
_loading = NO; _loading = NO;
if (!self.isValid) { if (!self.isValid) {
return; return;
} }
RCTSourceCode *sourceCodeModule = self.modules[RCTBridgeModuleNameForClass([RCTSourceCode class])]; RCTSourceCode *sourceCodeModule = self.modules[RCTBridgeModuleNameForClass([RCTSourceCode class])];
sourceCodeModule.scriptURL = bundleURL; sourceCodeModule.scriptURL = bundleURL;
sourceCodeModule.scriptText = script; sourceCodeModule.scriptText = script;
if (error != nil) { if (error) {
NSArray *stack = [[error userInfo] objectForKey:@"stack"]; NSArray *stack = [error userInfo][@"stack"];
if (stack) { if (stack) {
[[RCTRedBox sharedInstance] showErrorMessage:[error localizedDescription] [[RCTRedBox sharedInstance] showErrorMessage:[error localizedDescription]
withStack:stack]; withStack:stack];
@ -1100,10 +1103,17 @@ RCT_BRIDGE_WARN(_invokeAndProcessModule:(NSString *)module method:(NSString *)me
withDetails:[error localizedFailureReason]]; withDetails:[error localizedFailureReason]];
} }
NSDictionary *userInfo = @{@"error": error};
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidFailToLoadNotification
object:self
userInfo:userInfo];
} else { } else {
[self enqueueApplicationScript:script url:bundleURL onComplete:^(NSError *loadError) { [self enqueueApplicationScript:script url:bundleURL onComplete:^(NSError *loadError) {
if (!loadError) { if (!loadError) {
/** /**
* Register the display link to start sending js calls after everything * Register the display link to start sending js calls after everything
* is setup * is setup