From 0c5f279c9df869db2afb3e1d92a54e6d930551ad Mon Sep 17 00:00:00 2001 From: Dave Miller Date: Tue, 19 Jan 2016 12:19:47 -0800 Subject: [PATCH] Standardize Error objects for Promises Summary: public Promises are coming. And as part of it, we are standardizing the error objects that will be returned. This puts the code in place on the Android side to always send the proper error format. It will be an error object like this { code : "E_SOME_ERROR_CODE_DEFINED_BY_MODULE", // Meant to be machine parseable message : "Human readable message", nativeError : {} // Some representation of the underlying error (Exception or NSError) , still figuring out exactly, but hopefully something with stack info } Reviewed By: nicklockwood Differential Revision: D2840128 fb-gh-sync-id: 174d620e2beb53e1fc14161a10fd0479218d98a6 --- Libraries/RCTTest/RCTTestModule.m | 2 +- React/Base/RCTBridgeModule.h | 2 +- React/Base/RCTModuleMethod.m | 4 ++-- React/Base/RCTUtils.h | 4 ++++ React/Base/RCTUtils.m | 17 +++++++++++++---- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Libraries/RCTTest/RCTTestModule.m b/Libraries/RCTTest/RCTTestModule.m index 0692543e7..a889b8522 100644 --- a/Libraries/RCTTest/RCTTestModule.m +++ b/Libraries/RCTTest/RCTTestModule.m @@ -62,7 +62,7 @@ RCT_REMAP_METHOD(shouldResolve, shouldResolve_resolve:(RCTPromiseResolveBlock)re RCT_REMAP_METHOD(shouldReject, shouldReject_resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) { - reject(nil); + reject(nil, nil, nil); } RCT_EXPORT_METHOD(markTestCompleted) diff --git a/React/Base/RCTBridgeModule.h b/React/Base/RCTBridgeModule.h index 39c7acad4..067ecb492 100644 --- a/React/Base/RCTBridgeModule.h +++ b/React/Base/RCTBridgeModule.h @@ -37,7 +37,7 @@ typedef void (^RCTPromiseResolveBlock)(id result); * The error may be nil but it is preferable to pass an NSError object for more * precise error messages. */ -typedef void (^RCTPromiseRejectBlock)(NSError *error); +typedef void (^RCTPromiseRejectBlock)(NSString *code, NSString *message, NSError *error); /** * This constant can be returned from +methodQueue to force module diff --git a/React/Base/RCTModuleMethod.m b/React/Base/RCTModuleMethod.m index 8f54f2d9e..0a6cd9390 100644 --- a/React/Base/RCTModuleMethod.m +++ b/React/Base/RCTModuleMethod.m @@ -335,8 +335,8 @@ SEL RCTParseMethodSignature(NSString *methodSignature, NSArray *RCTMakeError(NSString *message, id toStringify, NSDictionary *extraData); RCT_EXTERN NSDictionary *RCTMakeAndLogError(NSString *message, id toStringify, NSDictionary *extraData); RCT_EXTERN NSDictionary *RCTJSErrorFromNSError(NSError *error); +RCT_EXTERN NSDictionary *RCTJSErrorFromCodeMessageAndNSError(NSString *code, NSString *message, NSError *error); + +// The default error code that will be sent in the .code value of the Error object to js +RCT_EXTERN NSString *const RCTErrorUnspecified; // Returns YES if React is running in a test environment RCT_EXTERN BOOL RCTRunningInTestEnvironment(void); diff --git a/React/Base/RCTUtils.m b/React/Base/RCTUtils.m index e6ebdb806..cf0d8b8b0 100644 --- a/React/Base/RCTUtils.m +++ b/React/Base/RCTUtils.m @@ -21,6 +21,8 @@ #import "RCTLog.h" +NSString *const RCTErrorUnspecified = @"EUNSPECIFIED"; + NSString *RCTJSONStringify(id jsonObject, NSError **error) { static SEL JSONKitSelector = NULL; @@ -313,27 +315,34 @@ NSDictionary *RCTMakeAndLogError(NSString *message, id toStringi return error; } -// TODO: Can we just replace RCTMakeError with this function instead? NSDictionary *RCTJSErrorFromNSError(NSError *error) +{ + return RCTJSErrorFromCodeMessageAndNSError(RCTErrorUnspecified, nil, error); +} + +// TODO: Can we just replace RCTMakeError with this function instead? +NSDictionary *RCTJSErrorFromCodeMessageAndNSError(NSString *code, NSString *message, NSError *error) { NSString *errorMessage; NSArray *stackTrace = [NSThread callStackSymbols]; NSMutableDictionary *errorInfo = - [NSMutableDictionary dictionaryWithObject:stackTrace forKey:@"nativeStackIOS"]; + [NSMutableDictionary dictionaryWithObject:stackTrace forKey:@"nativeStackIOS"]; if (error) { errorMessage = error.localizedDescription ?: @"Unknown error from a native module"; errorInfo[@"domain"] = error.domain ?: RCTErrorDomain; - errorInfo[@"code"] = @(error.code); } else { errorMessage = @"Unknown error from a native module"; errorInfo[@"domain"] = RCTErrorDomain; - errorInfo[@"code"] = @-1; } + errorInfo[@"code"] = code ?: RCTErrorUnspecified; + // Allow for explicit overriding of the error message + errorMessage = message ?: errorMessage; return RCTMakeError(errorMessage, nil, errorInfo); } + BOOL RCTRunningInTestEnvironment(void) { static BOOL isTestEnvironment = NO;