static void s_handle_failed_callback()

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;
    }
}