Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Examples/UIExplorer/UIExplorerUnitTests/RCTJSONTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,25 @@ - (void)testEncodingString
XCTAssertEqualObjects(json, RCTJSONStringify(text, NULL));
}

- (void)testEncodingNSError
{
NSError *underlyingError = [NSError errorWithDomain:@"underlyingDomain" code:421 userInfo:nil];
NSError *err = [NSError errorWithDomain:@"domain" code:68 userInfo:@{@"NSUnderlyingError": underlyingError}];

// An assertion on the full object would be too brittle since it contains an iOS stack trace
// so we are relying on the behavior of RCTJSONParse, which is tested below.
NSDictionary<NSString *, id> *jsonObject = RCTJSErrorFromNSError(err);
NSString *jsonString = RCTJSONStringify(jsonObject, NULL);
NSDictionary<NSString *, id> *json = RCTJSONParse(jsonString, NULL);
XCTAssertEqualObjects(json[@"code"], @"EDOMAIN68");
XCTAssertEqualObjects(json[@"message"], @"The operation couldn’t be completed. (domain error 68.)");
XCTAssertEqualObjects(json[@"domain"], @"domain");
XCTAssertEqualObjects(json[@"userInfo"][@"NSUnderlyingError"][@"code"], @"421");
XCTAssertEqualObjects(json[@"userInfo"][@"NSUnderlyingError"][@"message"], @"underlying error");
XCTAssertEqualObjects(json[@"userInfo"][@"NSUnderlyingError"][@"domain"], @"underlyingDomain");
}


- (void)testDecodingObject
{
NSDictionary<NSString *, id> *obj = @{@"foo": @"bar"};
Expand Down
12 changes: 11 additions & 1 deletion React/Base/RCTUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -413,18 +413,28 @@ BOOL RCTClassOverridesInstanceMethod(Class cls, SEL selector)
{
NSString *errorMessage;
NSArray<NSString *> *stackTrace = [NSThread callStackSymbols];
NSMutableDictionary *userInfo;
NSMutableDictionary<NSString *, id> *errorInfo =
[NSMutableDictionary dictionaryWithObject:stackTrace forKey:@"nativeStackIOS"];

if (error) {
errorMessage = error.localizedDescription ?: @"Unknown error from a native module";
errorInfo[@"domain"] = error.domain ?: RCTErrorDomain;
if (error.userInfo) {
userInfo = [error.userInfo mutableCopy];
if (userInfo != nil && userInfo[NSUnderlyingErrorKey] != nil) {
NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey];
NSString *underlyingCode = [NSString stringWithFormat:@"%d", (int)underlyingError.code];
userInfo[NSUnderlyingErrorKey] = RCTJSErrorFromCodeMessageAndNSError(underlyingCode, @"underlying error", underlyingError);
}
}
} else {
errorMessage = @"Unknown error from a native module";
errorInfo[@"domain"] = RCTErrorDomain;
userInfo = nil;
}
errorInfo[@"code"] = code ?: RCTErrorUnspecified;
errorInfo[@"userInfo"] = RCTNullIfNil(error.userInfo);
errorInfo[@"userInfo"] = RCTNullIfNil(userInfo);

// Allow for explicit overriding of the error message
errorMessage = message ?: errorMessage;
Expand Down