njs_descriptor_prop(njs_vm_t *vm, njs_object_prop_t *prop,
    const njs_value_t *desc)
{
    njs_int_t           ret;
    njs_bool_t          data, accessor;
    njs_value_t         value;
    njs_lvlhsh_query_t  lhq;

    static const njs_value_t  get_string = njs_string("get");

    if (!njs_is_object(desc)) {
        njs_type_error(vm, "property descriptor must be an object");
        return NJS_ERROR;
    }

    data = 0;
    accessor = 0;

    njs_object_property_init(&lhq, &get_string, NJS_GET_HASH);

    ret = njs_object_property(vm, desc, &lhq, &value);

    if (njs_slow_path(ret == NJS_ERROR)) {
        return NJS_ERROR;
    }

    if (ret == NJS_OK) {
        if (njs_is_defined(&value) && !njs_is_function(&value)) {
            njs_type_error(vm, "Getter must be a function");
            return NJS_ERROR;
        }

        accessor = 1;
        prop->getter = value;

    } else {
        /* NJS_DECLINED */
        njs_set_invalid(&prop->getter);
    }

    lhq.key = njs_str_value("set");
    lhq.key_hash = NJS_SET_HASH;

    ret = njs_object_property(vm, desc, &lhq, &value);

    if (njs_slow_path(ret == NJS_ERROR)) {
        return ret;
    }

    if (ret == NJS_OK) {
        if (njs_is_defined(&value) && !njs_is_function(&value)) {
            njs_type_error(vm, "Setter must be a function");
            return NJS_ERROR;
        }

        accessor = 1;
        prop->setter = value;

    } else {
        /* NJS_DECLINED */
        njs_set_invalid(&prop->setter);
    }

    lhq.key = njs_str_value("value");
    lhq.key_hash = NJS_VALUE_HASH;

    ret = njs_object_property(vm, desc, &lhq, &value);

    if (njs_slow_path(ret == NJS_ERROR)) {
        return ret;
    }

    if (ret == NJS_OK) {
        data = 1;
        prop->value = value;
    }

    lhq.key = njs_str_value("writable");
    lhq.key_hash = NJS_WRITABABLE_HASH;

    ret = njs_object_property(vm, desc, &lhq, &value);

    if (njs_slow_path(ret == NJS_ERROR)) {
        return ret;
    }

    if (ret == NJS_OK) {
        data = 1;
        prop->writable = njs_is_true(&value);
    }

    lhq.key = njs_str_value("enumerable");
    lhq.key_hash = NJS_ENUMERABLE_HASH;

    ret = njs_object_property(vm, desc, &lhq, &value);

    if (njs_slow_path(ret == NJS_ERROR)) {
        return ret;
    }

    if (ret == NJS_OK) {
        prop->enumerable = njs_is_true(&value);
    }

    lhq.key = njs_str_value("configurable");
    lhq.key_hash = NJS_CONFIGURABLE_HASH;

    ret = njs_object_property(vm, desc, &lhq, &value);

    if (njs_slow_path(ret == NJS_ERROR)) {
        return ret;
    }

    if (ret == NJS_OK) {
        prop->configurable = njs_is_true(&value);
    }

    if (accessor && data) {
        njs_type_error(vm, "Cannot both specify accessors "
                           "and a value or writable attribute");
        return NJS_ERROR;
    }

    return NJS_OK;
}
njs_descriptor_prop(njs_vm_t *vm, njs_object_prop_t *prop,
    const njs_value_t *desc)
{
    njs_int_t           ret;
    njs_bool_t          data, accessor;
    njs_value_t         value;
    njs_lvlhsh_query_t  lhq;

    static const njs_value_t  get_string = njs_string("get");

    if (!njs_is_object(desc)) {
        njs_type_error(vm, "property descriptor must be an object");
        return NJS_ERROR;
    }

    data = 0;
    accessor = 0;

    njs_object_property_init(&lhq, &get_string, NJS_GET_HASH);

    ret = njs_object_property(vm, desc, &lhq, &value);

    if (njs_slow_path(ret == NJS_ERROR)) {
        return NJS_ERROR;
    }

    if (ret == NJS_OK) {
        if (njs_is_defined(&value) && !njs_is_function(&value)) {
            njs_type_error(vm, "Getter must be a function");
            return NJS_ERROR;
        }

        accessor = 1;
        prop->getter = value;

    } else {
         
        njs_set_invalid(&prop->getter);
    }

    lhq.key = njs_str_value("set");
    lhq.key_hash = NJS_SET_HASH;

    ret = njs_object_property(vm, desc, &lhq, &value);

    if (njs_slow_path(ret == NJS_ERROR)) {
        return ret;
    }

    if (ret == NJS_OK) {
        if (njs_is_defined(&value) && !njs_is_function(&value)) {
            njs_type_error(vm, "Setter must be a function");
            return NJS_ERROR;
        }

        accessor = 1;
        prop->setter = value;

    } else {
         
        njs_set_invalid(&prop->setter);
    }

    lhq.key = njs_str_value("value");
    lhq.key_hash = NJS_VALUE_HASH;

    ret = njs_object_property(vm, desc, &lhq, &value);

    if (njs_slow_path(ret == NJS_ERROR)) {
        return ret;
    }

    if (ret == NJS_OK) {
        data = 1;
        prop->value = value;
    }

    lhq.key = njs_str_value("writable");
    lhq.key_hash = NJS_WRITABABLE_HASH;

    ret = njs_object_property(vm, desc, &lhq, &value);

    if (njs_slow_path(ret == NJS_ERROR)) {
        return ret;
    }

    if (ret == NJS_OK) {
        data = 1;
        prop->writable = njs_is_true(&value);
    }

    lhq.key = njs_str_value("enumerable");
    lhq.key_hash = NJS_ENUMERABLE_HASH;

    ret = njs_object_property(vm, desc, &lhq, &value);

    if (njs_slow_path(ret == NJS_ERROR)) {
        return ret;
    }

    if (ret == NJS_OK) {
        prop->enumerable = njs_is_true(&value);
    }

    lhq.key = njs_str_value("configurable");
    lhq.key_hash = NJS_CONFIGURABLE_HASH;

    ret = njs_object_property(vm, desc, &lhq, &value);

    if (njs_slow_path(ret == NJS_ERROR)) {
        return ret;
    }

    if (ret == NJS_OK) {
        prop->configurable = njs_is_true(&value);
    }

    if (accessor && data) {
        njs_type_error(vm, "Cannot both specify accessors "
                           "and a value or writable attribute");
        return NJS_ERROR;
    }

    return NJS_OK;
}