Skip to content

Commit

Permalink
Attach js_extra_data to JS errors on iOS
Browse files Browse the repository at this point in the history
Summary:
Changelog:
[iOS][Fixed] - Expose the extraData dict attached to JavaScript errors to the native ExceptionManager on iOS, similar to Android

Attaching the `extraData` dict to JavaScript crash reports is something that was done for Android only in 2019 (D16133080 (3a825c0)), and somehow we never really got around to adding it in iOS. This diff finally adds the capability to iOS as well. `extraData` can be used to attach various bits of data to a crash report for better debugging and categorization. As with the Android implementation, `extraData` is not attached if the `reportException` API is not used.

Reviewed By: dmitryrykun

Differential Revision: D35743658

fbshipit-source-id: de4060cb6e514db1d85907441a8962f98e9b8392
  • Loading branch information
GijsWeterings authored and facebook-github-bot committed Apr 25, 2022
1 parent 4f855c8 commit a65ae8e
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 11 deletions.
5 changes: 5 additions & 0 deletions React/Base/RCTAssert.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ RCT_EXTERN NSString *const RCTObjCStackTraceKey;
*/
RCT_EXTERN NSString *const RCTFatalExceptionName;

/**
* Stringified JSON object containing extra data to attach to the error from JavaScript.
*/
RCT_EXTERN NSString *const RCTJSExtraDataKey;

/**
* A block signature to be used for custom assertion handling.
*/
Expand Down
1 change: 1 addition & 0 deletions React/Base/RCTAssert.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
NSString *const RCTObjCStackTraceKey = @"RCTObjCStackTraceKey";
NSString *const RCTFatalExceptionName = @"RCTFatalException";
NSString *const RCTUntruncatedMessageKey = @"RCTUntruncatedMessageKey";
NSString *const RCTJSExtraDataKey = @"RCTJSExtraDataKey";

static NSString *const RCTAssertFunctionStack = @"RCTAssertFunctionStack";

Expand Down
6 changes: 4 additions & 2 deletions React/CoreModules/RCTExceptionsManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ NS_ASSUME_NONNULL_BEGIN

- (void)handleSoftJSExceptionWithMessage:(nullable NSString *)message
stack:(nullable NSArray *)stack
exceptionId:(NSNumber *)exceptionId;
exceptionId:(NSNumber *)exceptionId
extraDataAsJSON:(nullable NSString *)extraDataAsJSON;
- (void)handleFatalJSExceptionWithMessage:(nullable NSString *)message
stack:(nullable NSArray *)stack
exceptionId:(NSNumber *)exceptionId;
exceptionId:(NSNumber *)exceptionId
extraDataAsJSON:(nullable NSString *)extraDataAsJSON;

@optional
- (void)updateJSExceptionWithMessage:(nullable NSString *)message
Expand Down
30 changes: 21 additions & 9 deletions React/CoreModules/RCTExceptionsManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,35 @@ - (instancetype)initWithDelegate:(id<RCTExceptionsManagerDelegate>)delegate
return self;
}

- (void)reportSoft:(NSString *)message stack:(NSArray<NSDictionary *> *)stack exceptionId:(double)exceptionId
- (void)reportSoft:(NSString *)message
stack:(NSArray<NSDictionary *> *)stack
exceptionId:(double)exceptionId
extraDataAsJSON:(nullable NSString *)extraDataAsJSON
{
RCTRedBox *redbox = [_moduleRegistry moduleForName:"RedBox"];
[redbox showErrorMessage:message withStack:stack errorCookie:(int)exceptionId];

if (_delegate) {
[_delegate handleSoftJSExceptionWithMessage:message
stack:stack
exceptionId:[NSNumber numberWithDouble:exceptionId]];
exceptionId:[NSNumber numberWithDouble:exceptionId]
extraDataAsJSON:extraDataAsJSON];
}
}

- (void)reportFatal:(NSString *)message stack:(NSArray<NSDictionary *> *)stack exceptionId:(double)exceptionId
- (void)reportFatal:(NSString *)message
stack:(NSArray<NSDictionary *> *)stack
exceptionId:(double)exceptionId
extraDataAsJSON:(nullable NSString *)extraDataAsJSON
{
RCTRedBox *redbox = [_moduleRegistry moduleForName:"RedBox"];
[redbox showErrorMessage:message withStack:stack errorCookie:(int)exceptionId];

if (_delegate) {
[_delegate handleFatalJSExceptionWithMessage:message
stack:stack
exceptionId:[NSNumber numberWithDouble:exceptionId]];
exceptionId:[NSNumber numberWithDouble:exceptionId]
extraDataAsJSON:extraDataAsJSON];
}

static NSUInteger reloadRetries = 0;
Expand All @@ -64,7 +72,8 @@ - (void)reportFatal:(NSString *)message stack:(NSArray<NSDictionary *> *)stack e
RCTTriggerReloadCommandListeners(@"JS Crash Reload");
} else if (!RCT_DEV) {
NSString *description = [@"Unhandled JS Exception: " stringByAppendingString:message];
NSDictionary *errorInfo = @{NSLocalizedDescriptionKey : description, RCTJSStackTraceKey : stack};
NSDictionary *errorInfo =
@{NSLocalizedDescriptionKey : description, RCTJSStackTraceKey : stack, RCTJSExtraDataKey : extraDataAsJSON};
RCTFatal([NSError errorWithDomain:RCTErrorDomain code:0 userInfo:errorInfo]);
}
}
Expand All @@ -74,15 +83,15 @@ - (void)reportFatal:(NSString *)message stack:(NSArray<NSDictionary *> *)stack e
: (NSArray<NSDictionary *> *)stack exceptionId
: (double)exceptionId)
{
[self reportSoft:message stack:stack exceptionId:exceptionId];
[self reportSoft:message stack:stack exceptionId:exceptionId extraDataAsJSON:nil];
}

RCT_EXPORT_METHOD(reportFatalException
: (NSString *)message stack
: (NSArray<NSDictionary *> *)stack exceptionId
: (double)exceptionId)
{
[self reportFatal:message stack:stack exceptionId:exceptionId];
[self reportFatal:message stack:stack exceptionId:exceptionId extraDataAsJSON:nil];
}

RCT_EXPORT_METHOD(updateExceptionMessage
Expand Down Expand Up @@ -131,10 +140,13 @@ - (void)reportFatal:(NSString *)message stack:(NSArray<NSDictionary *> *)stack e
[stackArray addObject:frameDict];
}

NSDictionary *extraData = (NSDictionary *)data.extraData();
NSString *extraDataAsJSON = RCTJSONStringify(extraData, NULL);

if (data.isFatal()) {
[self reportFatal:message stack:stackArray exceptionId:exceptionId];
[self reportFatal:message stack:stackArray exceptionId:exceptionId extraDataAsJSON:extraDataAsJSON];
} else {
[self reportSoft:message stack:stackArray exceptionId:exceptionId];
[self reportSoft:message stack:stackArray exceptionId:exceptionId extraDataAsJSON:extraDataAsJSON];
}
}

Expand Down

0 comments on commit a65ae8e

Please sign in to comment.