Add ability to customize error messages and stacks within the iOS redbox
Reviewed By: javache Differential Revision: D3517605 fbshipit-source-id: a2efba80bbe1f6c74bf4e01f7807389962cb2463
This commit is contained in:
parent
83336130ef
commit
9d2e6a2f8a
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class RCTErrorInfo;
|
||||
|
||||
/**
|
||||
* Provides an interface to customize React Native error messages and stack
|
||||
* traces from exceptions.
|
||||
*/
|
||||
@protocol RCTErrorCustomizer <NSObject>
|
||||
|
||||
/**
|
||||
* Customizes the given error, returning the passed info argument if no
|
||||
* customization is required.
|
||||
*/
|
||||
- (nonnull RCTErrorInfo *)customizeErrorInfo:(nonnull RCTErrorInfo *)info;
|
||||
@end
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class RCTJSStackFrame;
|
||||
|
||||
/**
|
||||
* An ObjC wrapper for React Native errors.
|
||||
*/
|
||||
@interface RCTErrorInfo : NSObject
|
||||
@property (nonatomic, copy, readonly) NSString *errorMessage;
|
||||
@property (nonatomic, copy, readonly) NSArray<RCTJSStackFrame *> *stack;
|
||||
|
||||
|
||||
- (instancetype)initWithErrorMessage:(NSString *)errorMessage
|
||||
stack:(NSArray<RCTJSStackFrame *> *)stack;
|
||||
|
||||
@end
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "RCTErrorInfo.h"
|
||||
|
||||
#import "RCTJSStackFrame.h"
|
||||
|
||||
@implementation RCTErrorInfo
|
||||
|
||||
- (instancetype)initWithErrorMessage:(NSString *)errorMessage
|
||||
stack:(NSArray<RCTJSStackFrame *> *)stack {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_errorMessage = [errorMessage copy];
|
||||
_stack = [stack copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
|
@ -11,9 +11,11 @@
|
|||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTBridgeModule.h"
|
||||
#import "RCTErrorCustomizer.h"
|
||||
|
||||
@interface RCTRedBox : NSObject <RCTBridgeModule>
|
||||
|
||||
- (void)registerErrorCustomizer:(id<RCTErrorCustomizer>)errorCustomizer;
|
||||
- (void)showError:(NSError *)error;
|
||||
- (void)showErrorMessage:(NSString *)message;
|
||||
- (void)showErrorMessage:(NSString *)message withDetails:(NSString *)details;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#import "RCTBridge.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTDefines.h"
|
||||
#import "RCTErrorInfo.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "RCTJSStackFrame.h"
|
||||
|
||||
|
@ -314,12 +315,42 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
|||
@implementation RCTRedBox
|
||||
{
|
||||
RCTRedBoxWindow *_window;
|
||||
NSMutableArray<id<RCTErrorCustomizer>> *_errorCustomizers;
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (void)registerErrorCustomizer:(id<RCTErrorCustomizer>)errorCustomizer
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (!self->_errorCustomizers) {
|
||||
self->_errorCustomizers = [NSMutableArray array];
|
||||
}
|
||||
if (![self->_errorCustomizers containsObject:errorCustomizer]) {
|
||||
[self->_errorCustomizers addObject:errorCustomizer];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// WARNING: Should only be called from the main thread/dispatch queue.
|
||||
- (RCTErrorInfo *)_customizeError:(RCTErrorInfo *)error
|
||||
{
|
||||
RCTAssertMainQueue();
|
||||
|
||||
if (!self->_errorCustomizers) {
|
||||
return error;
|
||||
}
|
||||
for (id<RCTErrorCustomizer> customizer in self->_errorCustomizers) {
|
||||
RCTErrorInfo *newInfo = [customizer customizeErrorInfo:error];
|
||||
if (newInfo) {
|
||||
error = newInfo;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
- (void)showError:(NSError *)error
|
||||
{
|
||||
[self showErrorMessage:error.localizedDescription withDetails:error.localizedFailureReason];
|
||||
|
@ -367,7 +398,12 @@ RCT_EXPORT_MODULE()
|
|||
self->_window = [[RCTRedBoxWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
self->_window.actionDelegate = self;
|
||||
}
|
||||
[self->_window showErrorMessage:message withStack:stack isUpdate:isUpdate];
|
||||
RCTErrorInfo *errorInfo = [[RCTErrorInfo alloc] initWithErrorMessage:message
|
||||
stack:stack];
|
||||
errorInfo = [self _customizeError:errorInfo];
|
||||
[self->_window showErrorMessage:errorInfo.errorMessage
|
||||
withStack:errorInfo.stack
|
||||
isUpdate:isUpdate];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -422,6 +458,7 @@ RCT_EXPORT_METHOD(dismiss)
|
|||
@implementation RCTRedBox
|
||||
|
||||
+ (NSString *)moduleName { return nil; }
|
||||
- (void)registerErrorCustomizer:(id<RCTErrorCustomizer>)errorCustomizer {}
|
||||
- (void)showError:(NSError *)message {}
|
||||
- (void)showErrorMessage:(NSString *)message {}
|
||||
- (void)showErrorMessage:(NSString *)message withDetails:(NSString *)details {}
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
352DCFF01D19F4C20056D623 /* RCTI18nUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 352DCFEF1D19F4C20056D623 /* RCTI18nUtil.m */; };
|
||||
391E86A41C623EC800009732 /* RCTTouchEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 391E86A21C623EC800009732 /* RCTTouchEvent.m */; };
|
||||
3D1E68DB1CABD13900DD7465 /* RCTDisplayLink.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D1E68D91CABD13900DD7465 /* RCTDisplayLink.m */; };
|
||||
3EDCA8A51D3591E700450C31 /* RCTErrorInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */; };
|
||||
58114A161AAE854800E7D092 /* RCTPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A131AAE854800E7D092 /* RCTPicker.m */; };
|
||||
58114A171AAE854800E7D092 /* RCTPickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A151AAE854800E7D092 /* RCTPickerManager.m */; };
|
||||
58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A4E1AAE93D500E7D092 /* RCTAsyncLocalStorage.m */; };
|
||||
|
@ -274,6 +275,9 @@
|
|||
3D1E68D91CABD13900DD7465 /* RCTDisplayLink.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDisplayLink.m; sourceTree = "<group>"; };
|
||||
3DB910701C74B21600838BBE /* RCTWebSocketProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTWebSocketProxy.h; sourceTree = "<group>"; };
|
||||
3DB910711C74B21600838BBE /* RCTWebSocketProxyDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTWebSocketProxyDelegate.h; sourceTree = "<group>"; };
|
||||
3EDCA8A21D3591E700450C31 /* RCTErrorCustomizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTErrorCustomizer.h; sourceTree = "<group>"; };
|
||||
3EDCA8A31D3591E700450C31 /* RCTErrorInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTErrorInfo.h; sourceTree = "<group>"; };
|
||||
3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTErrorInfo.m; sourceTree = "<group>"; };
|
||||
58114A121AAE854800E7D092 /* RCTPicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPicker.h; sourceTree = "<group>"; };
|
||||
58114A131AAE854800E7D092 /* RCTPicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPicker.m; sourceTree = "<group>"; };
|
||||
58114A141AAE854800E7D092 /* RCTPickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPickerManager.h; sourceTree = "<group>"; };
|
||||
|
@ -554,6 +558,9 @@
|
|||
83CBBA491A601E3B00E9B192 /* Base */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3EDCA8A21D3591E700450C31 /* RCTErrorCustomizer.h */,
|
||||
3EDCA8A31D3591E700450C31 /* RCTErrorInfo.h */,
|
||||
3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */,
|
||||
68EFE4ED1CF6EB3900A1DE13 /* RCTBundleURLProvider.m */,
|
||||
68EFE4EC1CF6EB3000A1DE13 /* RCTBundleURLProvider.h */,
|
||||
83CBBA4A1A601E3B00E9B192 /* RCTAssert.h */,
|
||||
|
@ -755,6 +762,7 @@
|
|||
14C2CA741B3AC64300E6CBB2 /* RCTModuleData.m in Sources */,
|
||||
142014191B32094000CC17BA /* RCTPerformanceLogger.m in Sources */,
|
||||
83CBBA981A6020BB00E9B192 /* RCTTouchHandler.m in Sources */,
|
||||
3EDCA8A51D3591E700450C31 /* RCTErrorInfo.m in Sources */,
|
||||
83CBBA521A601E3B00E9B192 /* RCTLog.m in Sources */,
|
||||
13B0801D1A69489C00A75B9A /* RCTNavItemManager.m in Sources */,
|
||||
13A6E20E1C19AA0C00845B82 /* RCTParserUtils.m in Sources */,
|
||||
|
|
Loading…
Reference in New Issue