mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
aa5edca0e2
Summary: This diff migrates the usages Nullable and NonNull annotations to AndroidX instead of javax. The purpose of this change is to bring consistency in the annotations used by the core of RN Reviewed By: makovkastar Differential Revision: D16054504 fbshipit-source-id: 21d888854da088d2a14615a90d4dc058e5286b91
245 lines
7.7 KiB
Java
245 lines
7.7 KiB
Java
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
|
|
* directory of this source tree.
|
|
*/
|
|
package com.facebook.react.bridge;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
|
|
/*
|
|
* Implementation of {@link Promise} that represents a JavaScript Promise which can be passed to the
|
|
* native module as a method parameter.
|
|
*
|
|
* Methods annotated with {@link ReactMethod} that use a {@link Promise} as the last parameter
|
|
* will be marked as "promise" and will return a promise when invoked from JavaScript.
|
|
*/
|
|
public class PromiseImpl implements Promise {
|
|
// Number of stack frames to parse and return to mReject.invoke
|
|
// for ERROR_MAP_KEY_NATIVE_STACK
|
|
private static final int ERROR_STACK_FRAME_LIMIT = 50;
|
|
|
|
private static final String ERROR_DEFAULT_CODE = "EUNSPECIFIED";
|
|
private static final String ERROR_DEFAULT_MESSAGE = "Error not specified.";
|
|
|
|
// Keys for mReject's WritableMap
|
|
private static final String ERROR_MAP_KEY_CODE = "code";
|
|
private static final String ERROR_MAP_KEY_MESSAGE = "message";
|
|
private static final String ERROR_MAP_KEY_USER_INFO = "userInfo";
|
|
private static final String ERROR_MAP_KEY_NATIVE_STACK = "nativeStackAndroid";
|
|
|
|
// Keys for ERROR_MAP_KEY_NATIVE_STACK's StackFrame maps
|
|
private static final String STACK_FRAME_KEY_CLASS = "class";
|
|
private static final String STACK_FRAME_KEY_FILE = "file";
|
|
private static final String STACK_FRAME_KEY_LINE_NUMBER = "lineNumber";
|
|
private static final String STACK_FRAME_KEY_METHOD_NAME = "methodName";
|
|
|
|
private @Nullable Callback mResolve;
|
|
private @Nullable Callback mReject;
|
|
|
|
public PromiseImpl(@Nullable Callback resolve, @Nullable Callback reject) {
|
|
mResolve = resolve;
|
|
mReject = reject;
|
|
}
|
|
|
|
/**
|
|
* Successfully resolve the Promise with an optional value.
|
|
*
|
|
* @param value Object
|
|
*/
|
|
@Override
|
|
public void resolve(Object value) {
|
|
if (mResolve != null) {
|
|
mResolve.invoke(value);
|
|
mResolve = null;
|
|
mReject = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Report an error without an exception using a custom code and error message.
|
|
*
|
|
* @param code String
|
|
* @param message String
|
|
*/
|
|
@Override
|
|
public void reject(String code, String message) {
|
|
reject(code, message, /*Throwable*/ null, /*WritableMap*/ null);
|
|
}
|
|
|
|
/**
|
|
* Report an exception with a custom code.
|
|
*
|
|
* @param code String
|
|
* @param throwable Throwable
|
|
*/
|
|
@Override
|
|
public void reject(String code, Throwable throwable) {
|
|
reject(code, /*Message*/ null, throwable, /*WritableMap*/ null);
|
|
}
|
|
|
|
/**
|
|
* Report an exception with a custom code and error message.
|
|
*
|
|
* @param code String
|
|
* @param message String
|
|
* @param throwable Throwable
|
|
*/
|
|
@Override
|
|
public void reject(String code, String message, Throwable throwable) {
|
|
reject(code, message, throwable, /*WritableMap*/ null);
|
|
}
|
|
|
|
/**
|
|
* Report an exception, with default error code. Useful in catch-all scenarios where it's unclear
|
|
* why the error occurred.
|
|
*
|
|
* @param throwable Throwable
|
|
*/
|
|
@Override
|
|
public void reject(Throwable throwable) {
|
|
reject(/*Code*/ null, /*Message*/ null, throwable, /*WritableMap*/ null);
|
|
}
|
|
|
|
/* ---------------------------
|
|
* With userInfo WritableMap
|
|
* --------------------------- */
|
|
|
|
/**
|
|
* Report an exception, with default error code, with userInfo. Useful in catch-all scenarios
|
|
* where it's unclear why the error occurred.
|
|
*
|
|
* @param throwable Throwable
|
|
* @param userInfo WritableMap
|
|
*/
|
|
@Override
|
|
public void reject(Throwable throwable, WritableMap userInfo) {
|
|
reject(/*Code*/ null, /*Message*/ null, throwable, userInfo);
|
|
}
|
|
|
|
/**
|
|
* Reject with a code and userInfo WritableMap.
|
|
*
|
|
* @param code String
|
|
* @param userInfo WritableMap
|
|
*/
|
|
@Override
|
|
public void reject(String code, @NonNull WritableMap userInfo) {
|
|
reject(code, /*Message*/ null, /*Throwable*/ null, userInfo);
|
|
}
|
|
|
|
/**
|
|
* Report an exception with a custom code and userInfo.
|
|
*
|
|
* @param code String
|
|
* @param throwable Throwable
|
|
* @param userInfo WritableMap
|
|
*/
|
|
@Override
|
|
public void reject(String code, Throwable throwable, WritableMap userInfo) {
|
|
reject(code, /*Message*/ null, throwable, userInfo);
|
|
}
|
|
|
|
/**
|
|
* Report an error with a custom code, error message and userInfo, an error not caused by an
|
|
* exception.
|
|
*
|
|
* @param code String
|
|
* @param message String
|
|
* @param userInfo WritableMap
|
|
*/
|
|
@Override
|
|
public void reject(String code, String message, @NonNull WritableMap userInfo) {
|
|
reject(code, message, /*Throwable*/ null, userInfo);
|
|
}
|
|
|
|
/**
|
|
* Report an exception with a custom code, error message and userInfo.
|
|
*
|
|
* @param code String
|
|
* @param message String
|
|
* @param throwable Throwable
|
|
* @param userInfo WritableMap
|
|
*/
|
|
@Override
|
|
public void reject(
|
|
@Nullable String code,
|
|
@Nullable String message,
|
|
@Nullable Throwable throwable,
|
|
@Nullable WritableMap userInfo) {
|
|
if (mReject == null) {
|
|
mResolve = null;
|
|
return;
|
|
}
|
|
|
|
WritableNativeMap errorInfo = new WritableNativeMap();
|
|
|
|
if (code == null) {
|
|
errorInfo.putString(ERROR_MAP_KEY_CODE, ERROR_DEFAULT_CODE);
|
|
} else {
|
|
errorInfo.putString(ERROR_MAP_KEY_CODE, code);
|
|
}
|
|
|
|
// Use the custom message if provided otherwise use the throwable message.
|
|
if (message != null) {
|
|
errorInfo.putString(ERROR_MAP_KEY_MESSAGE, message);
|
|
} else if (throwable != null) {
|
|
errorInfo.putString(ERROR_MAP_KEY_MESSAGE, throwable.getMessage());
|
|
} else {
|
|
// The JavaScript side expects a map with at least an error message.
|
|
// /Libraries/BatchedBridge/NativeModules.js -> createErrorFromErrorData
|
|
// TYPE: (errorData: { message: string })
|
|
errorInfo.putString(ERROR_MAP_KEY_MESSAGE, ERROR_DEFAULT_MESSAGE);
|
|
}
|
|
|
|
// For consistency with iOS ensure userInfo key exists, even if we null it.
|
|
// iOS: /React/Base/RCTUtils.m -> RCTJSErrorFromCodeMessageAndNSError
|
|
if (userInfo != null) {
|
|
errorInfo.putMap(ERROR_MAP_KEY_USER_INFO, userInfo);
|
|
} else {
|
|
errorInfo.putNull(ERROR_MAP_KEY_USER_INFO);
|
|
}
|
|
|
|
// Attach a nativeStackAndroid array if a throwable was passed
|
|
// this matches iOS behavior - iOS adds a `nativeStackIOS` property
|
|
// iOS: /React/Base/RCTUtils.m -> RCTJSErrorFromCodeMessageAndNSError
|
|
if (throwable != null) {
|
|
StackTraceElement[] stackTrace = throwable.getStackTrace();
|
|
WritableNativeArray nativeStackAndroid = new WritableNativeArray();
|
|
|
|
// Build an an Array of StackFrames to match JavaScript:
|
|
// iOS: /Libraries/Core/Devtools/parseErrorStack.js -> StackFrame
|
|
for (int i = 0; i < stackTrace.length && i < ERROR_STACK_FRAME_LIMIT; i++) {
|
|
StackTraceElement frame = stackTrace[i];
|
|
WritableMap frameMap = new WritableNativeMap();
|
|
// NOTE: no column number exists StackTraceElement
|
|
frameMap.putString(STACK_FRAME_KEY_CLASS, frame.getClassName());
|
|
frameMap.putString(STACK_FRAME_KEY_FILE, frame.getFileName());
|
|
frameMap.putInt(STACK_FRAME_KEY_LINE_NUMBER, frame.getLineNumber());
|
|
frameMap.putString(STACK_FRAME_KEY_METHOD_NAME, frame.getMethodName());
|
|
nativeStackAndroid.pushMap(frameMap);
|
|
}
|
|
|
|
errorInfo.putArray(ERROR_MAP_KEY_NATIVE_STACK, nativeStackAndroid);
|
|
} else {
|
|
errorInfo.putArray(ERROR_MAP_KEY_NATIVE_STACK, new WritableNativeArray());
|
|
}
|
|
|
|
mReject.invoke(errorInfo);
|
|
mResolve = null;
|
|
mReject = null;
|
|
}
|
|
|
|
/* ------------
|
|
* Deprecated
|
|
* ------------ */
|
|
|
|
@Override
|
|
@Deprecated
|
|
public void reject(String message) {
|
|
reject(/*Code*/ null, message, /*Throwable*/ null, /*WritableMap*/ null);
|
|
}
|
|
}
|