aboutsummaryrefslogtreecommitdiff
path: root/src/njs_object_prop.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/njs_object_prop.c')
-rw-r--r--src/njs_object_prop.c469
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;
}