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
This commit is contained in:
Dave Miller 2016-01-19 12:19:47 -08:00 committed by facebook-github-bot-5
parent 554292d304
commit 0c5f279c9d
5 changed files with 21 additions and 8 deletions

View File

@ -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)

View File

@ -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

View File

@ -335,8 +335,8 @@ SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument
return NO;
}
RCT_BLOCK_ARGUMENT(^(NSError *error) {
NSDictionary *errorJSON = RCTJSErrorFromNSError(error);
RCT_BLOCK_ARGUMENT(^(NSString *code, NSString *message, NSError *error) {
NSDictionary *errorJSON = RCTJSErrorFromCodeMessageAndNSError(code, message, error);
[bridge enqueueCallback:json args:@[errorJSON]];
});
)

View File

@ -52,6 +52,10 @@ RCT_EXTERN BOOL RCTClassOverridesInstanceMethod(Class cls, SEL selector);
RCT_EXTERN NSDictionary<NSString *, id> *RCTMakeError(NSString *message, id toStringify, NSDictionary<NSString *, id> *extraData);
RCT_EXTERN NSDictionary<NSString *, id> *RCTMakeAndLogError(NSString *message, id toStringify, NSDictionary<NSString *, id> *extraData);
RCT_EXTERN NSDictionary<NSString *, id> *RCTJSErrorFromNSError(NSError *error);
RCT_EXTERN NSDictionary<NSString *, id> *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);

View File

@ -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<NSString *, id> *RCTMakeAndLogError(NSString *message, id toStringi
return error;
}
// TODO: Can we just replace RCTMakeError with this function instead?
NSDictionary<NSString *, id> *RCTJSErrorFromNSError(NSError *error)
{
return RCTJSErrorFromCodeMessageAndNSError(RCTErrorUnspecified, nil, error);
}
// TODO: Can we just replace RCTMakeError with this function instead?
NSDictionary<NSString *, id> *RCTJSErrorFromCodeMessageAndNSError(NSString *code, NSString *message, NSError *error)
{
NSString *errorMessage;
NSArray<NSString *> *stackTrace = [NSThread callStackSymbols];
NSMutableDictionary<NSString *, id> *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;