diff options
Diffstat (limited to 'src/njs_object_prop.c')
-rw-r--r-- | src/njs_object_prop.c | 469 |
1 files changed, 225 insertions, 244 deletions
diff --git a/src/njs_object_prop.c b/src/njs_object_prop.c index d7c55d3a..aeaeb71b 100644 --- a/src/njs_object_prop.c +++ b/src/njs_object_prop.c @@ -8,57 +8,20 @@ #include <njs_main.h> -static njs_object_prop_t *njs_object_prop_alloc2(njs_vm_t *vm, - njs_object_prop_type_t type, unsigned flags); static njs_object_prop_t *njs_descriptor_prop(njs_vm_t *vm, - const njs_value_t *desc); + const njs_value_t *desc, njs_object_prop_t *prop, + uint32_t *unset_enumerable, uint32_t *unset_configuarble, + uint32_t *enum_writable); -njs_object_prop_t * -njs_object_prop_alloc(njs_vm_t *vm, - const njs_value_t *value, uint8_t attributes) -{ - unsigned flags; - njs_object_prop_t *prop; - - switch (attributes) { - case NJS_ATTRIBUTE_FALSE: - case NJS_ATTRIBUTE_TRUE: - flags = attributes ? NJS_OBJECT_PROP_VALUE_ECW : 0; - break; - - case NJS_ATTRIBUTE_UNSET: - default: - flags = NJS_OBJECT_PROP_UNSET; - break; - } - - prop = njs_object_prop_alloc2(vm, NJS_PROPERTY, flags); - if (njs_slow_path(prop == NULL)) { - return NULL; - } - - njs_value_assign(njs_prop_value(prop), value); - - return prop; -} - - -static njs_object_prop_t * -njs_object_prop_alloc2(njs_vm_t *vm, - njs_object_prop_type_t type, unsigned flags) +void +njs_object_prop_init(njs_object_prop_t *prop, njs_object_prop_type_t type, + uint8_t flags) { - njs_object_prop_t *prop; - - 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 NULL; - } + prop->next_elt = 0; + prop->atom_id = 0; prop->type = type; - prop->enum_in_object_hash = 0; if (flags != NJS_OBJECT_PROP_UNSET) { prop->enumerable = !!(flags & NJS_OBJECT_PROP_ENUMERABLE); @@ -68,39 +31,37 @@ njs_object_prop_alloc2(njs_vm_t *vm, prop->writable = !!(flags & NJS_OBJECT_PROP_WRITABLE); } else { - prop->writable = NJS_ATTRIBUTE_UNSET; + prop->writable = 0; } } else { - prop->enumerable = NJS_ATTRIBUTE_UNSET; - prop->configurable = NJS_ATTRIBUTE_UNSET; - prop->writable = NJS_ATTRIBUTE_UNSET; + prop->enumerable = 0; + prop->configurable = 0; + prop->writable = 0; } - - return prop; } njs_int_t njs_object_property(njs_vm_t *vm, njs_object_t *object, - njs_flathsh_query_t *lhq, njs_value_t *retval) + njs_flathsh_query_t *fhq, njs_value_t *retval) { njs_int_t ret; njs_value_t value; njs_object_prop_t *prop; do { - ret = njs_flathsh_unique_find(&object->hash, lhq); + ret = njs_flathsh_unique_find(&object->hash, fhq); if (njs_fast_path(ret == NJS_OK)) { - prop = lhq->value; + prop = fhq->value; if (prop->type != NJS_WHITEOUT) { goto found; } } - ret = njs_flathsh_unique_find(&object->shared_hash, lhq); + ret = njs_flathsh_unique_find(&object->shared_hash, fhq); if (njs_fast_path(ret == NJS_OK)) { goto found; @@ -116,7 +77,7 @@ njs_object_property(njs_vm_t *vm, njs_object_t *object, found: - prop = lhq->value; + prop = fhq->value; if (njs_is_data_descriptor(prop)) { njs_value_assign(retval, njs_prop_value(prop)); @@ -140,25 +101,27 @@ njs_object_property_add(njs_vm_t *vm, njs_value_t *object, unsigned atom_id, { njs_int_t ret; njs_object_prop_t *prop; - njs_flathsh_query_t lhq; - - prop = njs_object_prop_alloc(vm, &njs_value_invalid, 1); - if (njs_slow_path(prop == NULL)) { - return NULL; - } + njs_flathsh_query_t fhq; - lhq.value = prop; - lhq.key_hash = atom_id; - lhq.replace = replace; - lhq.pool = vm->mem_pool; - lhq.proto = &njs_object_hash_proto; + fhq.key_hash = atom_id; + fhq.replace = replace; + fhq.pool = vm->mem_pool; + fhq.proto = &njs_object_hash_proto; - ret = njs_flathsh_unique_insert(njs_object_hash(object), &lhq); + ret = njs_flathsh_unique_insert(njs_object_hash(object), &fhq); if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); + njs_internal_error(vm, "flathsh insert failed"); return NULL; } + prop = fhq.value; + + prop->type = NJS_PROPERTY; + prop->enumerable = 1; + prop->configurable = 1; + prop->writable = 1; + prop->u.value = njs_value_invalid; + return prop; } @@ -170,15 +133,21 @@ njs_int_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, unsigned atom_id, njs_value_t *value, unsigned flags) { - uint32_t length, index; + uint32_t length, index, set_enumerable, set_configurable, + set_writable; njs_int_t ret; njs_array_t *array; njs_value_t key, retval; - njs_object_prop_t *prop, *prev; + njs_object_prop_t _prop; + njs_object_prop_t *prop = &_prop, *prev, *obj_prop; njs_property_query_t pq; again: + set_enumerable = 1; + set_configurable = 1; + set_writable = 1; + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 1); ret = (flags & NJS_OBJECT_PROP_CREATE) @@ -191,7 +160,8 @@ again: switch (njs_prop_type(flags)) { case NJS_OBJECT_PROP_DESCRIPTOR: - prop = njs_descriptor_prop(vm, value); + prop = njs_descriptor_prop(vm, value, prop, &set_enumerable, + &set_configurable, &set_writable); if (njs_slow_path(prop == NULL)) { return NJS_ERROR; } @@ -212,12 +182,8 @@ again: } } - prop = njs_object_prop_alloc2(vm, NJS_PROPERTY, - flags & NJS_OBJECT_PROP_VALUE_ECW); - if (njs_slow_path(prop == NULL)) { - return NJS_ERROR; - } - + njs_object_prop_init(prop, NJS_PROPERTY, + flags & NJS_OBJECT_PROP_VALUE_ECW); njs_value_assign(njs_prop_value(prop), value); break; @@ -226,11 +192,9 @@ again: default: njs_assert(njs_is_function(value)); - prop = njs_object_prop_alloc2(vm, NJS_ACCESSOR, - NJS_OBJECT_PROP_VALUE_EC); - if (njs_slow_path(prop == NULL)) { - return NJS_ERROR; - } + njs_object_prop_init(prop, NJS_ACCESSOR, NJS_OBJECT_PROP_VALUE_EC); + + set_writable = 0; if (njs_prop_type(flags) == NJS_OBJECT_PROP_GETTER) { njs_prop_getter(prop) = njs_function(value); @@ -249,9 +213,9 @@ again: set_prop: if (!njs_object(object)->extensible) { - njs_atom_string_get(vm, atom_id, &pq.lhq.key); + njs_atom_string_get(vm, atom_id, &pq.fhq.key); njs_type_error(vm, "Cannot add property \"%V\", " - "object is not extensible", &pq.lhq.key); + "object is not extensible", &pq.fhq.key); return NJS_ERROR; } @@ -283,7 +247,7 @@ set_prop: } } else { - if (prop->writable == NJS_ATTRIBUTE_UNSET) { + if (!set_writable) { prop->writable = 0; } @@ -292,35 +256,43 @@ set_prop: } } - if (prop->enumerable == NJS_ATTRIBUTE_UNSET) { + if (!set_enumerable) { prop->enumerable = 0; } - if (prop->configurable == NJS_ATTRIBUTE_UNSET) { + if (!set_configurable) { prop->configurable = 0; } - if (njs_slow_path(pq.lhq.value != NULL)) { - prev = pq.lhq.value; + if (njs_slow_path(pq.fhq.value != NULL)) { + prev = pq.fhq.value; if (njs_slow_path(prev->type == NJS_WHITEOUT)) { /* Previously deleted property. */ + prop->atom_id = prev->atom_id; + prop->next_elt = prev->next_elt; *prev = *prop; } } else { - pq.lhq.key_hash = atom_id; - pq.lhq.proto = &njs_object_hash_proto; - pq.lhq.value = prop; - pq.lhq.replace = 0; - pq.lhq.pool = vm->mem_pool; + pq.fhq.key_hash = atom_id; + pq.fhq.proto = &njs_object_hash_proto; + pq.fhq.replace = 0; + pq.fhq.pool = vm->mem_pool; - ret = njs_flathsh_unique_insert(njs_object_hash(object), &pq.lhq); + ret = njs_flathsh_unique_insert(njs_object_hash(object), &pq.fhq); if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); + njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; } + + obj_prop = pq.fhq.value; + obj_prop->enumerable = prop->enumerable; + obj_prop->configurable = prop->configurable; + obj_prop->writable = prop->writable; + obj_prop->type = prop->type; + obj_prop->u.value = prop->u.value; } return NJS_OK; @@ -328,7 +300,7 @@ set_prop: /* Updating existing prop. */ - prev = pq.lhq.value; + prev = pq.fhq.value; switch (prev->type) { case NJS_PROPERTY: @@ -340,9 +312,9 @@ set_prop: case NJS_PROPERTY_PLACE_REF: if (prev->type == NJS_PROPERTY_REF && !njs_is_accessor_descriptor(prop) - && prop->configurable != NJS_ATTRIBUTE_FALSE - && prop->enumerable != NJS_ATTRIBUTE_FALSE - && prop->writable != NJS_ATTRIBUTE_FALSE) + && (!set_configurable || prop->configurable) + && (!set_enumerable || prop->enumerable) + && (!set_writable || prop->writable)) { if (njs_is_valid(njs_prop_value(prop))) { njs_value_assign(njs_prop_ref(prev), njs_prop_value(prop)); @@ -373,9 +345,9 @@ set_prop: goto exception; } - if (prop->configurable == NJS_ATTRIBUTE_TRUE || - prop->enumerable == NJS_ATTRIBUTE_FALSE || - prop->writable == NJS_ATTRIBUTE_FALSE) + if ((set_configurable && prop->configurable) + || (set_enumerable && !prop->enumerable) + || (set_writable && !prop->writable)) { goto exception; } @@ -401,22 +373,24 @@ set_prop: if (!prev->configurable) { - if (prop->configurable == NJS_ATTRIBUTE_TRUE) { + if (prop->configurable) { goto exception; } - if (prop->enumerable != NJS_ATTRIBUTE_UNSET - && prev->enumerable != prop->enumerable) - { + if (set_enumerable && prev->enumerable != prop->enumerable) { goto exception; } } - if (njs_is_generic_descriptor(prop)) { + if (!(set_writable || njs_is_data_descriptor(prop)) + && !njs_is_accessor_descriptor(prop)) + { goto done; } - if (njs_is_data_descriptor(prev) != njs_is_data_descriptor(prop)) { + if (njs_is_data_descriptor(prev) + != (set_writable || njs_is_data_descriptor(prop))) + { if (!prev->configurable) { goto exception; } @@ -428,19 +402,19 @@ set_prop: */ if (pq.temp) { - pq.lhq.value = NULL; + pq.fhq.value = NULL; prop->configurable = prev->configurable; prop->enumerable = prev->enumerable; goto set_prop; } if (njs_is_data_descriptor(prev)) { - prev->writable = NJS_ATTRIBUTE_UNSET; + set_writable = 0; njs_prop_getter(prev) = NULL; njs_prop_setter(prev) = NULL; } else { - prev->writable = NJS_ATTRIBUTE_FALSE; + prev->writable = 0; njs_set_undefined(njs_prop_value(prev)); } @@ -448,10 +422,10 @@ set_prop: prev->type = prop->type; } else if (njs_is_data_descriptor(prev) - && njs_is_data_descriptor(prop)) + && (set_writable || njs_is_data_descriptor(prop))) { if (!prev->configurable && !prev->writable) { - if (prop->writable == NJS_ATTRIBUTE_TRUE) { + if (prop->writable) { goto exception; } @@ -483,8 +457,8 @@ set_prop: done: if (njs_slow_path(njs_is_fast_array(object) - && pq.lhq.key_hash == NJS_ATOM_STRING_length) - && prop->writable == NJS_ATTRIBUTE_FALSE) + && pq.fhq.key_hash == NJS_ATOM_STRING_length) + && (set_writable && !prop->writable)) { array = njs_array(object); length = array->length; @@ -524,7 +498,7 @@ done: } if (ret == NJS_DECLINED) { - pq.lhq.value = NULL; + pq.fhq.value = NULL; goto set_prop; } @@ -537,10 +511,10 @@ done: } else { if (njs_slow_path(njs_is_array(object) - && pq.lhq.key_hash == NJS_ATOM_STRING_length)) + && pq.fhq.key_hash == NJS_ATOM_STRING_length)) { - if (prev->configurable != NJS_ATTRIBUTE_TRUE - && prev->writable != NJS_ATTRIBUTE_TRUE + if (!prev->configurable + && !prev->writable && !njs_values_strict_equal(vm, njs_prop_value(prev), njs_prop_value(prop))) { @@ -548,7 +522,7 @@ done: return NJS_ERROR; } - if (prop->writable != NJS_ATTRIBUTE_UNSET) { + if (set_writable) { prev->writable = prop->writable; } @@ -565,15 +539,15 @@ done: * attribute of the property named P of object O to the value of the field. */ - if (prop->writable != NJS_ATTRIBUTE_UNSET) { + if (set_writable) { prev->writable = prop->writable; } - if (prop->enumerable != NJS_ATTRIBUTE_UNSET) { + if (set_enumerable) { prev->enumerable = prop->enumerable; } - if (prop->configurable != NJS_ATTRIBUTE_UNSET) { + if (set_configurable) { prev->configurable = prop->configurable; } @@ -581,8 +555,8 @@ done: exception: - njs_atom_string_get(vm, atom_id, &pq.lhq.key); - njs_type_error(vm, "Cannot redefine property: \"%V\"", &pq.lhq.key); + njs_atom_string_get(vm, atom_id, &pq.fhq.key); + njs_type_error(vm, "Cannot redefine property: \"%V\"", &pq.fhq.key); return NJS_ERROR; } @@ -598,26 +572,24 @@ njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq, 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; + shared = pq->fhq.value; - pq->lhq.replace = 0; - pq->lhq.value = prop; - pq->lhq.pool = vm->mem_pool; + pq->fhq.replace = 0; + pq->fhq.pool = vm->mem_pool; - ret = njs_flathsh_unique_insert(&proto->hash, &pq->lhq); + ret = njs_flathsh_unique_insert(&proto->hash, &pq->fhq); if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); + njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; } + prop = pq->fhq.value; + prop->enumerable = shared->enumerable; + prop->configurable = shared->configurable; + prop->writable = shared->writable; + prop->type = shared->type; + prop->u.value = shared->u.value; + if (njs_is_accessor_descriptor(prop)) { if (njs_prop_getter(prop) != NULL) { function = njs_function_copy(vm, njs_prop_getter(prop)); @@ -668,7 +640,7 @@ njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq, return NJS_ERROR; } - ret = njs_atom_to_value(vm, &prop_name, pq->lhq.key_hash); + ret = njs_atom_to_value(vm, &prop_name, pq->fhq.key_hash); if (ret != NJS_OK) { return NJS_ERROR; } @@ -684,26 +656,28 @@ njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq, static njs_object_prop_t * -njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc) +njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc, + njs_object_prop_t *prop, uint32_t *set_enumerable, + uint32_t *set_configurable, uint32_t *set_writable) { njs_int_t ret; njs_bool_t data, accessor; njs_value_t value; njs_object_t *desc_object; njs_function_t *getter, *setter; - njs_object_prop_t *prop; - njs_flathsh_query_t lhq; + njs_flathsh_query_t fhq; if (!njs_is_object(desc)) { njs_type_error(vm, "property descriptor must be an object"); return NULL; } - prop = njs_object_prop_alloc(vm, &njs_value_invalid, - NJS_ATTRIBUTE_UNSET); - if (njs_slow_path(prop == NULL)) { - return NULL; - } + njs_object_prop_init(prop, NJS_PROPERTY, NJS_OBJECT_PROP_UNSET); + *njs_prop_value(prop) = njs_value_invalid; + + *set_enumerable = 0; + *set_configurable = 0; + *set_writable = 0; data = 0; accessor = 0; @@ -711,10 +685,10 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc) setter = NJS_PROP_PTR_UNSET; desc_object = njs_object(desc); - lhq.proto = &njs_object_hash_proto; - lhq.key_hash = NJS_ATOM_STRING_get; + fhq.proto = &njs_object_hash_proto; + fhq.key_hash = NJS_ATOM_STRING_get; - ret = njs_object_property(vm, desc_object, &lhq, &value); + ret = njs_object_property(vm, desc_object, &fhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NULL; } @@ -729,9 +703,9 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc) getter = njs_is_function(&value) ? njs_function(&value) : NULL; } - lhq.key_hash = NJS_ATOM_STRING_set; + fhq.key_hash = NJS_ATOM_STRING_set; - ret = njs_object_property(vm, desc_object, &lhq, &value); + ret = njs_object_property(vm, desc_object, &fhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NULL; } @@ -746,9 +720,9 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc) setter = njs_is_function(&value) ? njs_function(&value) : NULL; } - lhq.key_hash = NJS_ATOM_STRING_value; + fhq.key_hash = NJS_ATOM_STRING_value; - ret = njs_object_property(vm, desc_object, &lhq, &value); + ret = njs_object_property(vm, desc_object, &fhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NULL; } @@ -758,9 +732,9 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc) njs_value_assign(njs_prop_value(prop), &value); } - lhq.key_hash = NJS_ATOM_STRING_writable; + fhq.key_hash = NJS_ATOM_STRING_writable; - ret = njs_object_property(vm, desc_object, &lhq, &value); + ret = njs_object_property(vm, desc_object, &fhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NULL; } @@ -768,6 +742,7 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc) if (ret == NJS_OK) { data = 1; prop->writable = njs_is_true(&value); + *set_writable = 1; } if (accessor && data) { @@ -776,26 +751,28 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc) return NULL; } - lhq.key_hash = NJS_ATOM_STRING_enumerable; + fhq.key_hash = NJS_ATOM_STRING_enumerable; - ret = njs_object_property(vm, desc_object, &lhq, &value); + ret = njs_object_property(vm, desc_object, &fhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NULL; } if (ret == NJS_OK) { prop->enumerable = njs_is_true(&value); + *set_enumerable = 1; } - lhq.key_hash = NJS_ATOM_STRING_configurable; + fhq.key_hash = NJS_ATOM_STRING_configurable; - ret = njs_object_property(vm, desc_object, &lhq, &value); + ret = njs_object_property(vm, desc_object, &fhq, &value); if (njs_slow_path(ret == NJS_ERROR)) { return NULL; } if (ret == NJS_OK) { prop->configurable = njs_is_true(&value); + *set_configurable = 1; } if (accessor) { @@ -816,7 +793,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, njs_object_t *desc; njs_object_prop_t *pr, *prop; const njs_value_t *setval; - njs_flathsh_query_t lhq; + njs_flathsh_query_t fhq; njs_property_query_t pq; njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); @@ -832,7 +809,7 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, switch (ret) { case NJS_OK: - prop = pq.lhq.value; + prop = pq.fhq.value; switch (prop->type) { case NJS_PROPERTY: @@ -872,117 +849,123 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest, return NJS_ERROR; } - lhq.proto = &njs_object_hash_proto; - lhq.replace = 0; - lhq.pool = vm->mem_pool; + fhq.proto = &njs_object_hash_proto; + fhq.replace = 0; + fhq.pool = vm->mem_pool; if (njs_is_data_descriptor(prop)) { - lhq.key_hash = NJS_ATOM_STRING_value; + fhq.key_hash = NJS_ATOM_STRING_value; - pr = njs_object_prop_alloc(vm, njs_prop_value(prop), 1); - if (njs_slow_path(pr == NULL)) { + ret = njs_flathsh_unique_insert(&desc->hash, &fhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; } - lhq.value = pr; + pr = fhq.value; - ret = njs_flathsh_unique_insert(&desc->hash, &lhq); - if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NJS_ERROR; - } + pr->type = NJS_PROPERTY; + pr->enumerable = 1; + pr->configurable = 1; + pr->writable = 1; + pr->u.value = *(njs_prop_value(prop)); - lhq.key_hash = NJS_ATOM_STRING_writable; + fhq.key_hash = NJS_ATOM_STRING_writable; setval = (prop->writable == 1) ? &njs_value_true : &njs_value_false; - pr = njs_object_prop_alloc(vm, setval, 1); - if (njs_slow_path(pr == NULL)) { + ret = njs_flathsh_unique_insert(&desc->hash, &fhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; } - lhq.value = pr; + pr = fhq.value; - ret = njs_flathsh_unique_insert(&desc->hash, &lhq); - if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NJS_ERROR; - } + pr->type = NJS_PROPERTY; + pr->enumerable = 1; + pr->configurable = 1; + pr->writable = 1; + pr->u.value = *setval; } else { - lhq.key_hash = NJS_ATOM_STRING_get; + fhq.key_hash = NJS_ATOM_STRING_get; - pr = njs_object_prop_alloc(vm, &njs_value_undefined, 1); - if (njs_slow_path(pr == NULL)) { + ret = njs_flathsh_unique_insert(&desc->hash, &fhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; } + pr = fhq.value; + + pr->type = NJS_PROPERTY; + pr->enumerable = 1; + pr->configurable = 1; + pr->writable = 1; + pr->u.value = njs_value_undefined; + if (njs_prop_getter(prop) != NULL) { njs_set_function(njs_prop_value(pr), njs_prop_getter(prop)); } - lhq.value = pr; + fhq.key_hash = NJS_ATOM_STRING_set; - ret = njs_flathsh_unique_insert(&desc->hash, &lhq); + ret = njs_flathsh_unique_insert(&desc->hash, &fhq); if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); + njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; } - lhq.key_hash = NJS_ATOM_STRING_set; + pr = fhq.value; - pr = njs_object_prop_alloc(vm, &njs_value_undefined, 1); - if (njs_slow_path(pr == NULL)) { - return NJS_ERROR; - } + pr->type = NJS_PROPERTY; + pr->enumerable = 1; + pr->configurable = 1; + pr->writable = 1; + pr->u.value = njs_value_undefined; if (njs_prop_setter(prop) != NULL) { njs_set_function(njs_prop_value(pr), njs_prop_setter(prop)); } - - lhq.value = pr; - - ret = njs_flathsh_unique_insert(&desc->hash, &lhq); - if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NJS_ERROR; - } } - lhq.key_hash = NJS_ATOM_STRING_enumerable; + fhq.key_hash = NJS_ATOM_STRING_enumerable; setval = (prop->enumerable == 1) ? &njs_value_true : &njs_value_false; - pr = njs_object_prop_alloc(vm, setval, 1); - if (njs_slow_path(pr == NULL)) { + ret = njs_flathsh_unique_insert(&desc->hash, &fhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; } - lhq.value = pr; + pr = fhq.value; - ret = njs_flathsh_unique_insert(&desc->hash, &lhq); - if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NJS_ERROR; - } + pr->type = NJS_PROPERTY; + pr->enumerable = 1; + pr->configurable = 1; + pr->writable = 1; + pr->u.value = *setval; - lhq.key_hash = NJS_ATOM_STRING_configurable; + fhq.key_hash = NJS_ATOM_STRING_configurable; setval = (prop->configurable == 1) ? &njs_value_true : &njs_value_false; - pr = njs_object_prop_alloc(vm, setval, 1); - if (njs_slow_path(pr == NULL)) { + ret = njs_flathsh_unique_insert(&desc->hash, &fhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; } - lhq.value = pr; + pr = fhq.value; - ret = njs_flathsh_unique_insert(&desc->hash, &lhq); - if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); - return NJS_ERROR; - } + pr->type = NJS_PROPERTY; + pr->enumerable = 1; + pr->configurable = 1; + pr->writable = 1; + pr->u.value = *setval; njs_set_object(dest, desc); @@ -1007,6 +990,9 @@ njs_prop_type_string(njs_object_prop_type_t type) case NJS_PROPERTY: return "property"; + case NJS_FREE_FLATHSH_ELEMENT: + return "free hash element"; + default: return "unknown"; } @@ -1014,14 +1000,14 @@ njs_prop_type_string(njs_object_prop_type_t type) njs_int_t -njs_object_prop_init(njs_vm_t *vm, const njs_object_init_t* init, +njs_object_props_init(njs_vm_t *vm, const njs_object_init_t* init, njs_object_prop_t *base, uint32_t atom_id, njs_value_t *value, njs_value_t *retval) { njs_int_t ret; njs_object_t *object; njs_object_prop_t *prop; - njs_flathsh_query_t lhq; + njs_flathsh_query_t fhq; object = njs_object_alloc(vm); if (object == NULL) { @@ -1034,31 +1020,26 @@ njs_object_prop_init(njs_vm_t *vm, const njs_object_init_t* init, return NJS_ERROR; } - 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); + fhq.key_hash = atom_id; + fhq.replace = 1; + fhq.pool = vm->mem_pool; + fhq.proto = &njs_object_hash_proto; + + ret = njs_flathsh_unique_insert(njs_object_hash(value), &fhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; } - *prop = *base; + prop = fhq.value; + prop->enumerable = base->enumerable; + prop->configurable = base->configurable; + prop->writable = base->writable; prop->type = NJS_PROPERTY; njs_set_object(njs_prop_value(prop), object); - lhq.value = prop; - lhq.key_hash = atom_id; - lhq.replace = 1; - lhq.pool = vm->mem_pool; - lhq.proto = &njs_object_hash_proto; + njs_value_assign(retval, njs_prop_value(prop)); - ret = njs_flathsh_unique_insert(njs_object_hash(value), &lhq); - if (njs_fast_path(ret == NJS_OK)) { - njs_value_assign(retval, njs_prop_value(prop)); - return NJS_OK; - } - - njs_internal_error(vm, "lvlhsh insert failed"); - - return NJS_ERROR; + return NJS_OK; } |