njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq)
{
    njs_int_t          ret;
    njs_value_t        *value;
    njs_object_t       *object;
    njs_function_t     *function;
    njs_object_prop_t  *prop, *shared;

    prop = njs_mp_align(vm->mem_pool, sizeof(njs_value_t),
                        sizeof(njs_object_prop_t));
    if (njs_slow_path(prop == NULL)) {
        njs_memory_error(vm);
        return NJS_ERROR;
    }

    shared = pq->lhq.value;
    *prop = *shared;

    pq->lhq.replace = 0;
    pq->lhq.value = prop;
    pq->lhq.pool = vm->mem_pool;

    ret = njs_lvlhsh_insert(&pq->prototype->hash, &pq->lhq);
    if (njs_slow_path(ret != NJS_OK)) {
        njs_internal_error(vm, "lvlhsh insert failed");
        return NJS_ERROR;
    }

    if (njs_is_accessor_descriptor(prop)) {
        if (njs_is_function(&prop->getter)) {
            function = njs_function_value_copy(vm, &prop->getter);
            if (njs_slow_path(function == NULL)) {
                return NJS_ERROR;
            }

            if (njs_is_function(&prop->setter)
                && function->native && njs_function(&prop->setter)->native
                && function->u.native == njs_function(&prop->setter)->u.native)
            {
                prop->setter = prop->getter;
                return NJS_OK;
            }
        }

        if (njs_is_function(&prop->setter)) {
            function = njs_function_value_copy(vm, &prop->setter);
            if (njs_slow_path(function == NULL)) {
                return NJS_ERROR;
            }
        }

        return NJS_OK;
    }

    value = &prop->value;

    switch (value->type) {
    case NJS_OBJECT:
    case NJS_OBJECT_VALUE:
        object = njs_object_value_copy(vm, value);
        if (njs_slow_path(object == NULL)) {
            return NJS_ERROR;
        }

        value->data.u.object = object;
        return NJS_OK;

    case NJS_FUNCTION:
        function = njs_function_value_copy(vm, &prop->value);
        if (njs_slow_path(function == NULL)) {
            return NJS_ERROR;
        }

        return njs_function_name_set(vm, function, &prop->name, NULL);

    default:
        break;
    }

    return NJS_OK;
}
njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq)
{
    njs_int_t          ret;
    njs_value_t        *value;
    njs_object_t       *object;
    njs_function_t     *function;
    njs_object_prop_t  *prop, *shared;

    prop = njs_mp_align(vm->mem_pool, sizeof(njs_value_t),
                        sizeof(njs_object_prop_t));
    if (njs_slow_path(prop == NULL)) {
        njs_memory_error(vm);
        return NJS_ERROR;
    }

    shared = pq->lhq.value;
    *prop = *shared;

    pq->lhq.replace = 0;
    pq->lhq.value = prop;
    pq->lhq.pool = vm->mem_pool;

    ret = njs_lvlhsh_insert(&pq->prototype->hash, &pq->lhq);
    if (njs_slow_path(ret != NJS_OK)) {
        njs_internal_error(vm, "lvlhsh insert failed");
        return NJS_ERROR;
    }

    if (njs_is_accessor_descriptor(prop)) {
        if (njs_is_function(&prop->getter)) {
            function = njs_function_value_copy(vm, &prop->getter);
            if (njs_slow_path(function == NULL)) {
                return NJS_ERROR;
            }

            if (njs_is_function(&prop->setter)
                && function->native && njs_function(&prop->setter)->native
                && function->u.native == njs_function(&prop->setter)->u.native)
            {
                prop->setter = prop->getter;
                return NJS_OK;
            }
        }

        if (njs_is_function(&prop->setter)) {
            function = njs_function_value_copy(vm, &prop->setter);
            if (njs_slow_path(function == NULL)) {
                return NJS_ERROR;
            }
        }

        return NJS_OK;
    }

    value = &prop->value;

    switch (value->type) {
    case NJS_OBJECT:
    case NJS_OBJECT_VALUE:
        object = njs_object_value_copy(vm, value);
        if (njs_slow_path(object == NULL)) {
            return NJS_ERROR;
        }

        value->data.u.object = object;
        return NJS_OK;

    case NJS_FUNCTION:
        function = njs_function_value_copy(vm, &prop->value);
        if (njs_slow_path(function == NULL)) {
            return NJS_ERROR;
        }

        return njs_function_name_set(vm, function, &prop->name, NULL);

    default:
        break;
    }

    return NJS_OK;
}