njs_promise_perform_all(njs_vm_t *vm, njs_value_t *iterator,
    njs_promise_iterator_args_t *pargs, njs_iterator_handler_t handler,
    njs_value_t *retval)
{
    int64_t       length;
    njs_int_t     ret;
    njs_value_t   argument;
    njs_object_t  *error;

    if (njs_slow_path(!njs_is_object(pargs->constructor))) {
        njs_type_error(vm, "constructor is not object");
        return NJS_ERROR;
    }

    njs_memzero(&pargs->args, sizeof(njs_iterator_args_t));

    ret = njs_object_length(vm, iterator, &length);
    if (njs_slow_path(ret != NJS_OK)) {
        return ret;
    }

    pargs->args.data = njs_array_alloc(vm, 1, length, 0);
    if (njs_slow_path(pargs->args.data == NULL)) {
        return NJS_ERROR;
    }

    pargs->remaining = njs_mp_alloc(vm->mem_pool, sizeof(uint32_t));
    if (njs_slow_path(pargs->remaining == NULL)) {
        njs_memory_error(vm);
        return NJS_ERROR;
    }

    (*pargs->remaining) = 1;

    pargs->args.value = iterator;
    pargs->args.to = length;

    ret = njs_object_iterate(vm, &pargs->args, handler);
    if (njs_slow_path(ret == NJS_ERROR)) {
        return ret;
    }

    if (--(*pargs->remaining) == 0) {
        njs_mp_free(vm->mem_pool, pargs->remaining);

        njs_set_array(&argument, pargs->args.data);

        if (handler == njs_promise_perform_any_handler) {
            error = njs_error_alloc(vm, NJS_OBJ_TYPE_AGGREGATE_ERROR,
                                    NULL, &string_any_rejected, &argument);
            if (njs_slow_path(error == NULL)) {
                return NJS_ERROR;
            }

            njs_set_object(&argument, error);
        }

        ret = njs_function_call(vm, njs_function(&pargs->capability->resolve),
                                &njs_value_undefined, &argument, 1, retval);
        if (njs_slow_path(ret == NJS_ERROR)) {
            return ret;
        }
    }

    *retval = pargs->capability->promise;

    return NJS_OK;
}
njs_promise_perform_all(njs_vm_t *vm, njs_value_t *iterator,
    njs_promise_iterator_args_t *pargs, njs_iterator_handler_t handler,
    njs_value_t *retval)
{
    int64_t       length;
    njs_int_t     ret;
    njs_value_t   argument;
    njs_object_t  *error;

    if (njs_slow_path(!njs_is_object(pargs->constructor))) {
        njs_type_error(vm, "constructor is not object");
        return NJS_ERROR;
    }

    njs_memzero(&pargs->args, sizeof(njs_iterator_args_t));

    ret = njs_object_length(vm, iterator, &length);
    if (njs_slow_path(ret != NJS_OK)) {
        return ret;
    }

    pargs->args.data = njs_array_alloc(vm, 1, length, 0);
    if (njs_slow_path(pargs->args.data == NULL)) {
        return NJS_ERROR;
    }

    pargs->remaining = njs_mp_alloc(vm->mem_pool, sizeof(uint32_t));
    if (njs_slow_path(pargs->remaining == NULL)) {
        njs_memory_error(vm);
        return NJS_ERROR;
    }

    (*pargs->remaining) = 1;

    pargs->args.value = iterator;
    pargs->args.to = length;

    ret = njs_object_iterate(vm, &pargs->args, handler);
    if (njs_slow_path(ret == NJS_ERROR)) {
        return ret;
    }

    if (--(*pargs->remaining) == 0) {
        njs_mp_free(vm->mem_pool, pargs->remaining);

        njs_set_array(&argument, pargs->args.data);

        if (handler == njs_promise_perform_any_handler) {
            error = njs_error_alloc(vm, NJS_OBJ_TYPE_AGGREGATE_ERROR,
                                    NULL, &string_any_rejected, &argument);
            if (njs_slow_path(error == NULL)) {
                return NJS_ERROR;
            }

            njs_set_object(&argument, error);
        }

        ret = njs_function_call(vm, njs_function(&pargs->capability->resolve),
                                &njs_value_undefined, &argument, 1, retval);
        if (njs_slow_path(ret == NJS_ERROR)) {
            return ret;
        }
    }

    *retval = pargs->capability->promise;

    return NJS_OK;
}