in source/module.c [302:381]
static void s_handle_failed_callback(napi_env env, napi_value function, napi_status reason) {
/* Figure out if there's an exception pending, if so, no callbacks will ever succeed again until it's cleared */
bool pending_exception = reason == napi_pending_exception;
AWS_NAPI_ENSURE(env, napi_is_exception_pending(env, &pending_exception));
/* if there's no pending exception, but failure occurred, log what we can find and get out */
if (!pending_exception) {
const napi_extended_error_info *node_error_info = NULL;
AWS_NAPI_ENSURE(env, napi_get_last_error_info(env, &node_error_info));
AWS_NAPI_LOGF_ERROR(
"Extended error info: engine_error_code=%u error_code=%s error_message=%s",
node_error_info->engine_error_code,
aws_napi_status_to_str(node_error_info->error_code),
node_error_info->error_message);
return;
}
/* get the current exception and report it, and clear it so that execution can continue */
napi_value node_exception = NULL;
AWS_NAPI_ENSURE(env, napi_get_and_clear_last_exception(env, &node_exception));
/* figure out what the exception is */
bool is_error = false;
AWS_NAPI_ENSURE(env, napi_is_error(env, node_exception, &is_error));
/*
* Convert the function to a string. If it's a lambda, this will produce the source of the lambda, if
* it's a class function or free function, it will produce the name
*/
napi_value node_function_str = NULL;
AWS_NAPI_ENSURE(env, napi_coerce_to_string(env, function, &node_function_str));
struct aws_string *function_str = aws_string_new_from_napi(env, node_function_str);
if (function_str) {
AWS_NAPI_LOGF_ERROR("Calling %s", aws_string_c_str(function_str));
}
/* If it's an Error, extract info from it and log it */
if (is_error) {
/* get the Error.message field */
napi_value node_message = NULL;
AWS_NAPI_ENSURE(env, napi_get_named_property(env, node_exception, "message", &node_message));
/* extract and log the message */
struct aws_string *message = aws_string_new_from_napi(env, node_message);
if (message) {
AWS_NAPI_LOGF_ERROR("Error: %s", aws_string_bytes(message));
aws_string_destroy(message);
} else {
AWS_NAPI_LOGF_ERROR("aws_string_new_from_napi(exception.message) failed");
return;
}
/* get the Error.stack field */
napi_value node_stack = NULL;
AWS_NAPI_ENSURE(env, napi_get_named_property(env, node_exception, "stack", &node_stack));
/* extract and log the stack trace */
struct aws_string *stacktrace = aws_string_new_from_napi(env, node_stack);
if (stacktrace) {
AWS_NAPI_LOGF_ERROR("Stack:\n%s", aws_string_bytes(stacktrace));
aws_string_destroy(stacktrace);
} else {
AWS_NAPI_LOGF_ERROR("aws_string_new_from_napi(exception.stack) failed");
return;
}
/* the Error has been reported and cleared, that's all we can do */
return;
}
/* The last thing thrown was some other sort of object/primitive, so convert it to a string and log it */
napi_value node_error_str = NULL;
AWS_NAPI_ENSURE(env, napi_coerce_to_string(env, node_exception, &node_error_str));
struct aws_string *error_str = aws_string_new_from_napi(env, node_error_str);
if (error_str) {
AWS_NAPI_LOGF_ERROR("Error: %s", aws_string_bytes(error_str));
} else {
AWS_NAPI_LOGF_ERROR("aws_string_new_from_napi(ToString(exception)) failed");
return;
}
}