Allow serializing underlying NSError objects, closes #10506
Summary: Explain the **motivation** for making this change. What existing problem does the pull request solve? See https://github.com/facebook/react-native/issues/10506. A native `NSError` with `NSUnderlyingErrorKey` set causes a JSON stringify error from the websocket dispatcher if remote debugging is enabled. **Test plan (required)** I'm not familiar with the react native testing framework. Happy to add a test for this if someone can point me to where this part of the codebase is exercised :) I did some spot checks with nil user dictionaries and nil underlying errors here. The case that this solves is testable using https://github.com/superseriouscompany/react-native-error-repro, specifically: ```objective-c NSError *underlyingError = [NSError errorWithDomain:@"underlyingDomain" code:421 userInfo:nil]; NSError *err = [NSError errorWithDomain:@"domain" code:68 userInfo:@{@"NSUnderlyingError": underlyingError}]; reject(@"foo", @"bar", err); ``` Closes https://github.com/facebook/react-native/pull/10507 Differential Revision: D4080802 Pulled By: lacker fbshipit-source-id: 93a41d9e9a710e406a6ccac214a5617271b4bede
This commit is contained in:
parent
f64538943e
commit
c144bbfb7e
|
@ -42,6 +42,25 @@
|
|||
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"};
|
||||
|
|
|
@ -413,18 +413,28 @@ NSDictionary<NSString *, id> *RCTJSErrorFromCodeMessageAndNSError(NSString *code
|
|||
{
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue