[njs] Fixed handling of props in Object.getOwnPropertyDescriptor().
Dmitry Volyntsev
xeioex at nginx.com
Thu Apr 26 17:36:53 UTC 2018
details: http://hg.nginx.org/njs/rev/cba7742a0a65
branches:
changeset: 508:cba7742a0a65
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Thu Apr 26 19:53:16 2018 +0300
description:
Fixed handling of props in Object.getOwnPropertyDescriptor().
njs_property_query() is moved to njs_object.c without changes.
diffstat:
njs/njs_object.c | 338 +++++++++++++++++++++++++++++++++++++++++++++-
njs/njs_object.h | 16 ++
njs/njs_vm.c | 333 ----------------------------------------------
njs/njs_vm.h | 18 ++
njs/test/njs_unit_test.c | 9 +
5 files changed, 368 insertions(+), 346 deletions(-)
diffs (843 lines):
diff -r ee72fc2329bf -r cba7742a0a65 njs/njs_object.c
--- a/njs/njs_object.c Thu Apr 26 19:24:55 2018 +0300
+++ b/njs/njs_object.c Thu Apr 26 19:53:16 2018 +0300
@@ -19,7 +19,9 @@
#include <njs_string.h>
#include <njs_object.h>
#include <njs_object_hash.h>
+#include <njs_number.h>
#include <njs_array.h>
+#include <njs_extern.h>
#include <njs_function.h>
#include <njs_error.h>
#include <stdio.h>
@@ -27,6 +29,12 @@
static nxt_int_t njs_object_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
+static njs_ret_t njs_object_property_query(njs_vm_t *vm,
+ njs_property_query_t *pq, njs_value_t *value, njs_object_t *object);
+static njs_ret_t njs_array_property_query(njs_vm_t *vm,
+ njs_property_query_t *pq, njs_value_t *object, uint32_t index);
+static njs_ret_t njs_object_query_prop_handler(njs_property_query_t *pq,
+ njs_object_t *object);
static njs_ret_t njs_define_property(njs_vm_t *vm, njs_object_t *object,
const njs_value_t *name, const njs_object_t *descriptor);
@@ -229,6 +237,301 @@ njs_object_property(njs_vm_t *vm, const
}
+/*
+ * The njs_property_query() returns values
+ * NXT_OK property has been found in object,
+ * NXT_DECLINED property was not found in object,
+ * NJS_PRIMITIVE_VALUE property operation was applied to a numeric
+ * or boolean value,
+ * NJS_STRING_VALUE property operation was applied to a string,
+ * NJS_ARRAY_VALUE object is array,
+ * NJS_EXTERNAL_VALUE object is external entity,
+ * NJS_TRAP_PROPERTY the property trap must be called,
+ * NXT_ERROR exception has been thrown.
+ */
+
+njs_ret_t
+njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object,
+ njs_value_t *property)
+{
+ uint32_t index;
+ uint32_t (*hash)(const void *, size_t);
+ njs_ret_t ret;
+ njs_object_t *obj;
+ njs_function_t *function;
+ const njs_extern_t *ext_proto;
+
+ hash = nxt_djb_hash;
+
+ switch (object->type) {
+
+ case NJS_BOOLEAN:
+ case NJS_NUMBER:
+ if (pq->query != NJS_PROPERTY_QUERY_GET) {
+ return NJS_PRIMITIVE_VALUE;
+ }
+
+ index = njs_primitive_prototype_index(object->type);
+ obj = &vm->prototypes[index].object;
+ break;
+
+ case NJS_STRING:
+ if (pq->query == NJS_PROPERTY_QUERY_DELETE) {
+ return NXT_DECLINED;
+ }
+
+ obj = &vm->prototypes[NJS_PROTOTYPE_STRING].object;
+ break;
+
+ case NJS_ARRAY:
+ if (nxt_fast_path(!njs_is_null_or_void_or_boolean(property))) {
+
+ if (nxt_fast_path(njs_is_primitive(property))) {
+ index = njs_value_to_index(property);
+
+ if (nxt_fast_path(index < NJS_ARRAY_MAX_LENGTH)) {
+ return njs_array_property_query(vm, pq, object, index);
+ }
+
+ } else {
+ return NJS_TRAP_PROPERTY;
+ }
+ }
+
+ /* Fall through. */
+
+ case NJS_OBJECT:
+ case NJS_OBJECT_BOOLEAN:
+ case NJS_OBJECT_NUMBER:
+ case NJS_OBJECT_STRING:
+ case NJS_REGEXP:
+ case NJS_DATE:
+ case NJS_OBJECT_ERROR:
+ case NJS_OBJECT_EVAL_ERROR:
+ case NJS_OBJECT_INTERNAL_ERROR:
+ case NJS_OBJECT_RANGE_ERROR:
+ case NJS_OBJECT_REF_ERROR:
+ case NJS_OBJECT_SYNTAX_ERROR:
+ case NJS_OBJECT_TYPE_ERROR:
+ case NJS_OBJECT_URI_ERROR:
+ case NJS_OBJECT_VALUE:
+ obj = object->data.u.object;
+ break;
+
+ case NJS_FUNCTION:
+ function = njs_function_value_copy(vm, object);
+ if (nxt_slow_path(function == NULL)) {
+ return NXT_ERROR;
+ }
+
+ obj = &function->object;
+ break;
+
+ case NJS_EXTERNAL:
+ ext_proto = object->external.proto;
+
+ if (ext_proto->type == NJS_EXTERN_CASELESS_OBJECT) {
+ hash = nxt_djb_hash_lowcase;
+ }
+
+ obj = NULL;
+ break;
+
+ case NJS_VOID:
+ case NJS_NULL:
+ default:
+ if (nxt_fast_path(njs_is_primitive(property))) {
+
+ ret = njs_primitive_value_to_string(vm, &pq->value, property);
+
+ if (nxt_fast_path(ret == NXT_OK)) {
+ njs_string_get(&pq->value, &pq->lhq.key);
+ njs_type_error(vm, "cannot get property '%.*s' of undefined",
+ (int) pq->lhq.key.length, pq->lhq.key.start);
+ return NXT_ERROR;
+ }
+ }
+
+ njs_type_error(vm, "cannot get property 'unknown' of undefined", NULL);
+
+ return NXT_ERROR;
+ }
+
+ if (nxt_fast_path(njs_is_primitive(property))) {
+
+ ret = njs_primitive_value_to_string(vm, &pq->value, property);
+
+ if (nxt_fast_path(ret == NXT_OK)) {
+
+ njs_string_get(&pq->value, &pq->lhq.key);
+ pq->lhq.key_hash = hash(pq->lhq.key.start, pq->lhq.key.length);
+
+ if (obj == NULL) {
+ pq->lhq.proto = &njs_extern_hash_proto;
+
+ return NJS_EXTERNAL_VALUE;
+ }
+
+ return njs_object_property_query(vm, pq, object, obj);
+ }
+
+ return ret;
+ }
+
+ return NJS_TRAP_PROPERTY;
+}
+
+
+njs_ret_t
+njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq,
+ njs_value_t *value, njs_object_t *object)
+{
+ njs_ret_t ret;
+ njs_object_prop_t *prop;
+
+ pq->lhq.proto = &njs_object_hash_proto;
+
+ if (pq->query == NJS_PROPERTY_QUERY_SET) {
+ ret = njs_object_query_prop_handler(pq, object);
+ if (ret == NXT_OK) {
+ return ret;
+ }
+ }
+
+ do {
+ pq->prototype = object;
+
+ ret = nxt_lvlhsh_find(&object->hash, &pq->lhq);
+
+ if (ret == NXT_OK) {
+ prop = pq->lhq.value;
+
+ if (prop->type != NJS_WHITEOUT) {
+ pq->shared = 0;
+
+ return ret;
+ }
+
+ goto next;
+ }
+
+ if (pq->query > NJS_PROPERTY_QUERY_IN) {
+ /* NXT_DECLINED */
+ return ret;
+ }
+
+ ret = nxt_lvlhsh_find(&object->shared_hash, &pq->lhq);
+
+ if (ret == NXT_OK) {
+ pq->shared = 1;
+
+ if (pq->query == NJS_PROPERTY_QUERY_GET) {
+ prop = pq->lhq.value;
+
+ if (prop->type == NJS_PROPERTY_HANDLER) {
+ pq->scratch = *prop;
+ prop = &pq->scratch;
+ ret = prop->value.data.u.prop_handler(vm, value, NULL,
+ &prop->value);
+
+ if (nxt_fast_path(ret == NXT_OK)) {
+ prop->type = NJS_PROPERTY;
+ pq->lhq.value = prop;
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ if (pq->query > NJS_PROPERTY_QUERY_IN) {
+ /* NXT_DECLINED */
+ return ret;
+ }
+
+ next:
+
+ object = object->__proto__;
+
+ } while (object != NULL);
+
+ if (njs_is_string(value)) {
+ return NJS_STRING_VALUE;
+ }
+
+ /* NXT_DECLINED */
+
+ return ret;
+}
+
+
+static njs_ret_t
+njs_array_property_query(njs_vm_t *vm, njs_property_query_t *pq,
+ njs_value_t *object, uint32_t index)
+{
+ uint32_t size;
+ njs_ret_t ret;
+ njs_value_t *value;
+ njs_array_t *array;
+
+ array = object->data.u.array;
+
+ if (index >= array->length) {
+ if (pq->query != NJS_PROPERTY_QUERY_SET) {
+ return NXT_DECLINED;
+ }
+
+ size = index - array->length;
+
+ ret = njs_array_expand(vm, array, 0, size + 1);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return ret;
+ }
+
+ value = &array->start[array->length];
+
+ while (size != 0) {
+ njs_set_invalid(value);
+ value++;
+ size--;
+ }
+
+ array->length = index + 1;
+ }
+
+ pq->lhq.value = &array->start[index];
+
+ return NJS_ARRAY_VALUE;
+}
+
+
+static njs_ret_t
+njs_object_query_prop_handler(njs_property_query_t *pq, njs_object_t *object)
+{
+ njs_ret_t ret;
+ njs_object_prop_t *prop;
+
+ do {
+ pq->prototype = object;
+
+ ret = nxt_lvlhsh_find(&object->shared_hash, &pq->lhq);
+
+ if (ret == NXT_OK) {
+ prop = pq->lhq.value;
+
+ if (prop->type == NJS_PROPERTY_HANDLER) {
+ return NXT_OK;
+ }
+ }
+
+ object = object->__proto__;
+
+ } while (object != NULL);
+
+ return NXT_DECLINED;
+}
+
+
njs_ret_t
njs_object_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
@@ -618,13 +921,15 @@ static njs_ret_t
njs_object_get_own_property_descriptor(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused)
{
- uint32_t index;
- nxt_int_t ret;
- njs_array_t *array;
- njs_object_t *descriptor;
- njs_object_prop_t *pr, *prop, array_prop;
- const njs_value_t *value, *property, *setval;
- nxt_lvlhsh_query_t lhq;
+ double num;
+ uint32_t index;
+ nxt_int_t ret;
+ njs_array_t *array;
+ njs_object_t *descriptor;
+ njs_object_prop_t *pr, *prop, array_prop;
+ const njs_value_t *value, *property, *setval;
+ nxt_lvlhsh_query_t lhq;
+ njs_property_query_t pq;
value = njs_arg(args, nargs, 1);
@@ -644,9 +949,13 @@ njs_object_get_own_property_descriptor(n
if (njs_is_array(value)) {
array = value->data.u.array;
- index = njs_string_to_index(property);
+ num = njs_string_to_index(property);
+ index = num;
- if (index < array->length && njs_is_valid(&array->start[index])) {
+ if ((double) index == num
+ && index < array->length
+ && njs_is_valid(&array->start[index]))
+ {
prop = &array_prop;
array_prop.name = *property;
@@ -661,17 +970,19 @@ njs_object_get_own_property_descriptor(n
lhq.proto = &njs_object_hash_proto;
if (prop == NULL) {
- njs_string_get(property, &lhq.key);
- lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length);
+ pq.query = NJS_PROPERTY_QUERY_GET;
+ pq.lhq.key.length = 0;
+ pq.lhq.key.start = NULL;
- ret = nxt_lvlhsh_find(&value->data.u.object->hash, &lhq);
+ ret = njs_property_query(vm, &pq, (njs_value_t *) value,
+ (njs_value_t *) property);
if (ret != NXT_OK) {
vm->retval = njs_value_void;
return NXT_OK;
}
- prop = lhq.value;
+ prop = pq.lhq.value;
}
descriptor = njs_object_alloc(vm);
@@ -681,6 +992,7 @@ njs_object_get_own_property_descriptor(n
lhq.replace = 0;
lhq.pool = vm->mem_cache_pool;
+ lhq.proto = &njs_object_hash_proto;
lhq.key = nxt_string_value("value");
lhq.key_hash = NJS_VALUE_HASH;
diff -r ee72fc2329bf -r cba7742a0a65 njs/njs_object.h
--- a/njs/njs_object.h Thu Apr 26 19:24:55 2018 +0300
+++ b/njs/njs_object.h Thu Apr 26 19:53:16 2018 +0300
@@ -30,6 +30,20 @@ typedef struct {
} njs_object_prop_t;
+typedef struct {
+ nxt_lvlhsh_query_t lhq;
+
+ /* scratch is used to get the value of an NJS_PROPERTY_HANDLER property. */
+ njs_object_prop_t scratch;
+
+ njs_value_t value;
+ njs_object_t *prototype;
+ uint8_t query;
+ uint8_t shared;
+} njs_property_query_t;
+
+
+
struct njs_object_init_s {
nxt_str_t name;
const njs_object_prop_t *properties;
@@ -44,6 +58,8 @@ njs_object_t *njs_object_value_alloc(njs
njs_array_t *njs_object_keys_array(njs_vm_t *vm, const njs_value_t *object);
njs_object_prop_t *njs_object_property(njs_vm_t *vm, const njs_object_t *obj,
nxt_lvlhsh_query_t *lhq);
+njs_ret_t njs_property_query(njs_vm_t *vm, njs_property_query_t *pq,
+ njs_value_t *object, njs_value_t *property);
nxt_int_t njs_object_hash_create(njs_vm_t *vm, nxt_lvlhsh_t *hash,
const njs_object_prop_t *prop, nxt_uint_t n);
njs_ret_t njs_object_constructor(njs_vm_t *vm, njs_value_t *args,
diff -r ee72fc2329bf -r cba7742a0a65 njs/njs_vm.c
--- a/njs/njs_vm.c Thu Apr 26 19:24:55 2018 +0300
+++ b/njs/njs_vm.c Thu Apr 26 19:53:16 2018 +0300
@@ -33,36 +33,6 @@
#include <stdio.h>
-/* The values must be greater than NXT_OK. */
-#define NJS_PRIMITIVE_VALUE 1
-#define NJS_STRING_VALUE 2
-#define NJS_ARRAY_VALUE 3
-#define NJS_EXTERNAL_VALUE 4
-
-
-/*
- * NJS_PROPERTY_QUERY_GET must be less or equal to NJS_PROPERTY_QUERY_IN,
- * NJS_PROPERTY_QUERY_SET and NJS_PROPERTY_QUERY_DELETE must be greater
- * than NJS_PROPERTY_QUERY_IN.
- */
-#define NJS_PROPERTY_QUERY_GET 0
-#define NJS_PROPERTY_QUERY_IN 1
-#define NJS_PROPERTY_QUERY_SET 2
-#define NJS_PROPERTY_QUERY_DELETE 3
-
-
-typedef struct {
- nxt_lvlhsh_query_t lhq;
-
- /* scratch is used to get the value of an NJS_PROPERTY_HANDLER property. */
- njs_object_prop_t scratch;
-
- njs_value_t value;
- njs_object_t *prototype;
- uint8_t query;
- uint8_t shared;
-} njs_property_query_t;
-
struct njs_property_next_s {
int32_t index;
@@ -76,14 +46,6 @@ struct njs_property_next_s {
* and should fit in CPU L1 instruction cache.
*/
-static nxt_noinline njs_ret_t njs_property_query(njs_vm_t *vm,
- njs_property_query_t *pq, njs_value_t *object, njs_value_t *property);
-static njs_ret_t njs_array_property_query(njs_vm_t *vm,
- njs_property_query_t *pq, njs_value_t *object, uint32_t index);
-static njs_ret_t njs_object_property_query(njs_vm_t *vm,
- njs_property_query_t *pq, njs_value_t *value, njs_object_t *object);
-static njs_ret_t njs_object_query_prop_handler(njs_property_query_t *pq,
- njs_object_t *object);
static njs_ret_t njs_method_private_copy(njs_vm_t *vm,
njs_property_query_t *pq);
static nxt_noinline njs_ret_t njs_values_equal(const njs_value_t *val1,
@@ -972,301 +934,6 @@ njs_vmcode_property_delete(njs_vm_t *vm,
}
-/*
- * The njs_property_query() returns values
- * NXT_OK property has been found in object,
- * NXT_DECLINED property was not found in object,
- * NJS_PRIMITIVE_VALUE property operation was applied to a numeric
- * or boolean value,
- * NJS_STRING_VALUE property operation was applied to a string,
- * NJS_ARRAY_VALUE object is array,
- * NJS_EXTERNAL_VALUE object is external entity,
- * NJS_TRAP_PROPERTY the property trap must be called,
- * NXT_ERROR exception has been thrown.
- */
-
-static nxt_noinline njs_ret_t
-njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object,
- njs_value_t *property)
-{
- uint32_t index;
- uint32_t (*hash)(const void *, size_t);
- njs_ret_t ret;
- njs_object_t *obj;
- njs_function_t *function;
- const njs_extern_t *ext_proto;
-
- hash = nxt_djb_hash;
-
- switch (object->type) {
-
- case NJS_BOOLEAN:
- case NJS_NUMBER:
- if (pq->query != NJS_PROPERTY_QUERY_GET) {
- return NJS_PRIMITIVE_VALUE;
- }
-
- index = njs_primitive_prototype_index(object->type);
- obj = &vm->prototypes[index].object;
- break;
-
- case NJS_STRING:
- if (pq->query == NJS_PROPERTY_QUERY_DELETE) {
- return NXT_DECLINED;
- }
-
- obj = &vm->prototypes[NJS_PROTOTYPE_STRING].object;
- break;
-
- case NJS_ARRAY:
- if (nxt_fast_path(!njs_is_null_or_void_or_boolean(property))) {
-
- if (nxt_fast_path(njs_is_primitive(property))) {
- index = njs_value_to_index(property);
-
- if (nxt_fast_path(index < NJS_ARRAY_MAX_LENGTH)) {
- return njs_array_property_query(vm, pq, object, index);
- }
-
- } else {
- return NJS_TRAP_PROPERTY;
- }
- }
-
- /* Fall through. */
-
- case NJS_OBJECT:
- case NJS_OBJECT_BOOLEAN:
- case NJS_OBJECT_NUMBER:
- case NJS_OBJECT_STRING:
- case NJS_REGEXP:
- case NJS_DATE:
- case NJS_OBJECT_ERROR:
- case NJS_OBJECT_EVAL_ERROR:
- case NJS_OBJECT_INTERNAL_ERROR:
- case NJS_OBJECT_RANGE_ERROR:
- case NJS_OBJECT_REF_ERROR:
- case NJS_OBJECT_SYNTAX_ERROR:
- case NJS_OBJECT_TYPE_ERROR:
- case NJS_OBJECT_URI_ERROR:
- case NJS_OBJECT_VALUE:
- obj = object->data.u.object;
- break;
-
- case NJS_FUNCTION:
- function = njs_function_value_copy(vm, object);
- if (nxt_slow_path(function == NULL)) {
- return NXT_ERROR;
- }
-
- obj = &function->object;
- break;
-
- case NJS_EXTERNAL:
- ext_proto = object->external.proto;
-
- if (ext_proto->type == NJS_EXTERN_CASELESS_OBJECT) {
- hash = nxt_djb_hash_lowcase;
- }
-
- obj = NULL;
- break;
-
- case NJS_VOID:
- case NJS_NULL:
- default:
- if (nxt_fast_path(njs_is_primitive(property))) {
-
- ret = njs_primitive_value_to_string(vm, &pq->value, property);
-
- if (nxt_fast_path(ret == NXT_OK)) {
- njs_string_get(&pq->value, &pq->lhq.key);
- njs_type_error(vm, "cannot get property '%.*s' of undefined",
- (int) pq->lhq.key.length, pq->lhq.key.start);
- return NXT_ERROR;
- }
- }
-
- njs_type_error(vm, "cannot get property 'unknown' of undefined", NULL);
-
- return NXT_ERROR;
- }
-
- if (nxt_fast_path(njs_is_primitive(property))) {
-
- ret = njs_primitive_value_to_string(vm, &pq->value, property);
-
- if (nxt_fast_path(ret == NXT_OK)) {
-
- njs_string_get(&pq->value, &pq->lhq.key);
- pq->lhq.key_hash = hash(pq->lhq.key.start, pq->lhq.key.length);
-
- if (obj == NULL) {
- pq->lhq.proto = &njs_extern_hash_proto;
-
- return NJS_EXTERNAL_VALUE;
- }
-
- return njs_object_property_query(vm, pq, object, obj);
- }
-
- return ret;
- }
-
- return NJS_TRAP_PROPERTY;
-}
-
-
-static njs_ret_t
-njs_array_property_query(njs_vm_t *vm, njs_property_query_t *pq,
- njs_value_t *object, uint32_t index)
-{
- uint32_t size;
- njs_ret_t ret;
- njs_value_t *value;
- njs_array_t *array;
-
- array = object->data.u.array;
-
- if (index >= array->length) {
- if (pq->query != NJS_PROPERTY_QUERY_SET) {
- return NXT_DECLINED;
- }
-
- size = index - array->length;
-
- ret = njs_array_expand(vm, array, 0, size + 1);
- if (nxt_slow_path(ret != NXT_OK)) {
- return ret;
- }
-
- value = &array->start[array->length];
-
- while (size != 0) {
- njs_set_invalid(value);
- value++;
- size--;
- }
-
- array->length = index + 1;
- }
-
- pq->lhq.value = &array->start[index];
-
- return NJS_ARRAY_VALUE;
-}
-
-
-static njs_ret_t
-njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq,
- njs_value_t *value, njs_object_t *object)
-{
- njs_ret_t ret;
- njs_object_prop_t *prop;
-
- pq->lhq.proto = &njs_object_hash_proto;
-
- if (pq->query == NJS_PROPERTY_QUERY_SET) {
- ret = njs_object_query_prop_handler(pq, object);
- if (ret == NXT_OK) {
- return ret;
- }
- }
-
- do {
- pq->prototype = object;
-
- ret = nxt_lvlhsh_find(&object->hash, &pq->lhq);
-
- if (ret == NXT_OK) {
- prop = pq->lhq.value;
-
- if (prop->type != NJS_WHITEOUT) {
- pq->shared = 0;
-
- return ret;
- }
-
- goto next;
- }
-
- if (pq->query > NJS_PROPERTY_QUERY_IN) {
- /* NXT_DECLINED */
- return ret;
- }
-
- ret = nxt_lvlhsh_find(&object->shared_hash, &pq->lhq);
-
- if (ret == NXT_OK) {
- pq->shared = 1;
-
- if (pq->query == NJS_PROPERTY_QUERY_GET) {
- prop = pq->lhq.value;
-
- if (prop->type == NJS_PROPERTY_HANDLER) {
- pq->scratch = *prop;
- prop = &pq->scratch;
- ret = prop->value.data.u.prop_handler(vm, value, NULL,
- &prop->value);
-
- if (nxt_fast_path(ret == NXT_OK)) {
- prop->type = NJS_PROPERTY;
- pq->lhq.value = prop;
- }
- }
- }
-
- return ret;
- }
-
- if (pq->query > NJS_PROPERTY_QUERY_IN) {
- /* NXT_DECLINED */
- return ret;
- }
-
- next:
-
- object = object->__proto__;
-
- } while (object != NULL);
-
- if (njs_is_string(value)) {
- return NJS_STRING_VALUE;
- }
-
- /* NXT_DECLINED */
-
- return ret;
-}
-
-
-static njs_ret_t
-njs_object_query_prop_handler(njs_property_query_t *pq, njs_object_t *object)
-{
- njs_ret_t ret;
- njs_object_prop_t *prop;
-
- do {
- pq->prototype = object;
-
- ret = nxt_lvlhsh_find(&object->shared_hash, &pq->lhq);
-
- if (ret == NXT_OK) {
- prop = pq->lhq.value;
-
- if (prop->type == NJS_PROPERTY_HANDLER) {
- return NXT_OK;
- }
- }
-
- object = object->__proto__;
-
- } while (object != NULL);
-
- return NXT_DECLINED;
-}
-
-
static njs_ret_t
njs_method_private_copy(njs_vm_t *vm, njs_property_query_t *pq)
{
diff -r ee72fc2329bf -r cba7742a0a65 njs/njs_vm.h
--- a/njs/njs_vm.h Thu Apr 26 19:24:55 2018 +0300
+++ b/njs/njs_vm.h Thu Apr 26 19:53:16 2018 +0300
@@ -49,6 +49,24 @@
#define NJS_APPLIED NXT_DONE
+/* The values must be greater than NXT_OK. */
+#define NJS_PRIMITIVE_VALUE 1
+#define NJS_STRING_VALUE 2
+#define NJS_ARRAY_VALUE 3
+#define NJS_EXTERNAL_VALUE 4
+
+
+/*
+ * NJS_PROPERTY_QUERY_GET must be less or equal to NJS_PROPERTY_QUERY_IN,
+ * NJS_PROPERTY_QUERY_SET and NJS_PROPERTY_QUERY_DELETE must be greater
+ * than NJS_PROPERTY_QUERY_IN.
+ */
+#define NJS_PROPERTY_QUERY_GET 0
+#define NJS_PROPERTY_QUERY_IN 1
+#define NJS_PROPERTY_QUERY_SET 2
+#define NJS_PROPERTY_QUERY_DELETE 3
+
+
/*
* The order of the enum is used in njs_vmcode_typeof()
* and njs_object_prototype_to_string().
diff -r ee72fc2329bf -r cba7742a0a65 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Thu Apr 26 19:24:55 2018 +0300
+++ b/njs/test/njs_unit_test.c Thu Apr 26 19:53:16 2018 +0300
@@ -6596,6 +6596,9 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("Object.getOwnPropertyDescriptor([3,4], 1).value"),
nxt_string("4") },
+ { nxt_string("Object.getOwnPropertyDescriptor([], 'length').value"),
+ nxt_string("0") },
+
{ nxt_string("Object.getOwnPropertyDescriptor([3,4], '3')"),
nxt_string("undefined") },
@@ -6611,6 +6614,12 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("Object.getOwnPropertyDescriptor(undefined)"),
nxt_string("TypeError: cannot convert void argument to object") },
+ { nxt_string("var o = {}; o[void 0] = 'a'; Object.getOwnPropertyDescriptor(o).value"),
+ nxt_string("a") },
+
+ { nxt_string("var o = {}; o[void 0] = 'a'; Object.getOwnPropertyDescriptor(o, undefined).value"),
+ nxt_string("a") },
+
{ nxt_string("Object.defineProperty(Object.freeze({}), 'b', {})"),
nxt_string("TypeError: object is not extensible") },
More information about the nginx-devel
mailing list