njs_promise_host_rejection_tracker(njs_vm_t *vm, njs_promise_t *promise,
    njs_promise_rejection_type_t operation)
{
    uint32_t            i, length;
    njs_value_t         *value;
    njs_promise_data_t  *data;

    if (vm->options.unhandled_rejection
        == NJS_VM_OPT_UNHANDLED_REJECTION_IGNORE)
    {
        return NJS_OK;
    }

    if (vm->promise_reason == NULL) {
        vm->promise_reason = njs_array_alloc(vm, 1, 0, NJS_ARRAY_SPARE);
        if (njs_slow_path(vm->promise_reason == NULL)) {
            return NJS_ERROR;
        }
    }

    data = njs_data(&promise->value);

    if (operation == NJS_PROMISE_REJECT) {
        if (vm->promise_reason != NULL) {
            return njs_array_add(vm, vm->promise_reason, &data->result);
        }

    } else {
        value = vm->promise_reason->start;
        length = vm->promise_reason->length;

        for (i = 0; i < length; i++) {
            if (njs_values_same(&value[i], &data->result)) {
                length--;

                if (i < length) {
                    memmove(&value[i], &value[i + 1],
                            sizeof(njs_value_t) * (length - i));
                }

                break;
            }
        }

        vm->promise_reason->length = length;
    }

    return NJS_OK;
}
njs_promise_host_rejection_tracker(njs_vm_t *vm, njs_promise_t *promise,
    njs_promise_rejection_type_t operation)
{
    uint32_t            i, length;
    njs_value_t         *value;
    njs_promise_data_t  *data;

    if (vm->options.unhandled_rejection
        == NJS_VM_OPT_UNHANDLED_REJECTION_IGNORE)
    {
        return NJS_OK;
    }

    if (vm->promise_reason == NULL) {
        vm->promise_reason = njs_array_alloc(vm, 1, 0, NJS_ARRAY_SPARE);
        if (njs_slow_path(vm->promise_reason == NULL)) {
            return NJS_ERROR;
        }
    }

    data = njs_data(&promise->value);

    if (operation == NJS_PROMISE_REJECT) {
        if (vm->promise_reason != NULL) {
            return njs_array_add(vm, vm->promise_reason, &data->result);
        }

    } else {
        value = vm->promise_reason->start;
        length = vm->promise_reason->length;

        for (i = 0; i < length; i++) {
            if (njs_values_same(&value[i], &data->result)) {
                length--;

                if (i < length) {
                    memmove(&value[i], &value[i + 1],
                            sizeof(njs_value_t) * (length - i));
                }

                break;
            }
        }

        vm->promise_reason->length = length;
    }

    return NJS_OK;
}