njs_promise_prototype_finally(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
    njs_index_t unused)
{
    njs_int_t              ret;
    njs_value_t            *promise, *finally, constructor, arguments[2];
    njs_function_t         *function;
    njs_promise_context_t  *context;

    promise = njs_argument(args, 0);

    if (njs_slow_path(!njs_is_object(promise))) {
        njs_type_error(vm, "required a object");
        return NJS_ERROR;
    }

    finally = njs_arg(args, nargs, 1);

    function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
    function->u.native = njs_promise_constructor;

    njs_set_function(&constructor, function);

    ret = njs_value_species_constructor(vm, promise, &constructor,
                                        &constructor);
    if (njs_slow_path(ret != NJS_OK)) {
        return ret;
    }

    if (!njs_is_function(finally)) {
        arguments[0] = *finally;
        arguments[1] = *finally;

        return njs_promise_invoke_then(vm, promise, arguments, 2);
    }

    function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
    if (njs_slow_path(function == NULL)) {
        return NJS_ERROR;
    }

    function->u.native = njs_promise_then_finally_function;
    function->args_count = 1;

    context = function->context;
    context->constructor = constructor;
    context->finally = *finally;
    context->handler = njs_promise_then_finally_return;

    njs_set_function(&arguments[0], function);

    function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
    if (njs_slow_path(function == NULL)) {
        njs_mp_free(vm->mem_pool, njs_function(&arguments[0]));
        return NJS_ERROR;
    }

    function->u.native = njs_promise_then_finally_function;
    function->args_count = 1;

    context = function->context;
    context->constructor = constructor;
    context->finally = *finally;
    context->handler = njs_promise_catch_finally_return;

    njs_set_function(&arguments[1], function);

    return njs_promise_invoke_then(vm, promise, arguments, 2);
}
njs_promise_prototype_finally(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
    njs_index_t unused)
{
    njs_int_t              ret;
    njs_value_t            *promise, *finally, constructor, arguments[2];
    njs_function_t         *function;
    njs_promise_context_t  *context;

    promise = njs_argument(args, 0);

    if (njs_slow_path(!njs_is_object(promise))) {
        njs_type_error(vm, "required a object");
        return NJS_ERROR;
    }

    finally = njs_arg(args, nargs, 1);

    function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
    function->u.native = njs_promise_constructor;

    njs_set_function(&constructor, function);

    ret = njs_value_species_constructor(vm, promise, &constructor,
                                        &constructor);
    if (njs_slow_path(ret != NJS_OK)) {
        return ret;
    }

    if (!njs_is_function(finally)) {
        arguments[0] = *finally;
        arguments[1] = *finally;

        return njs_promise_invoke_then(vm, promise, arguments, 2);
    }

    function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
    if (njs_slow_path(function == NULL)) {
        return NJS_ERROR;
    }

    function->u.native = njs_promise_then_finally_function;
    function->args_count = 1;

    context = function->context;
    context->constructor = constructor;
    context->finally = *finally;
    context->handler = njs_promise_then_finally_return;

    njs_set_function(&arguments[0], function);

    function = njs_promise_create_function(vm, sizeof(njs_promise_context_t));
    if (njs_slow_path(function == NULL)) {
        njs_mp_free(vm->mem_pool, njs_function(&arguments[0]));
        return NJS_ERROR;
    }

    function->u.native = njs_promise_then_finally_function;
    function->args_count = 1;

    context = function->context;
    context->constructor = constructor;
    context->finally = *finally;
    context->handler = njs_promise_catch_finally_return;

    njs_set_function(&arguments[1], function);

    return njs_promise_invoke_then(vm, promise, arguments, 2);
}