[njs] Fixed njs.dump() for objects with NJS_PROPERTY_HANDLER props.
Dmitry Volyntsev
xeioex at nginx.com
Mon Nov 25 14:54:27 UTC 2019
details: https://hg.nginx.org/njs/rev/790caa744e0e
branches:
changeset: 1256:790caa744e0e
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Mon Nov 25 17:53:32 2019 +0300
description:
Fixed njs.dump() for objects with NJS_PROPERTY_HANDLER props.
diffstat:
src/njs_json.c | 177 ++++++++++++++++++----------------------------
src/njs_value.c | 20 ++++-
src/test/njs_unit_test.c | 7 +-
3 files changed, 91 insertions(+), 113 deletions(-)
diffs (307 lines):
diff -r 3eb134dfa896 -r 790caa744e0e src/njs_json.c
--- a/src/njs_json.c Mon Nov 25 17:53:19 2019 +0300
+++ b/src/njs_json.c Mon Nov 25 17:53:32 2019 +0300
@@ -1906,15 +1906,12 @@ static njs_int_t
njs_dump_value(njs_json_stringify_t *stringify, const njs_value_t *value,
njs_uint_t console)
{
- njs_int_t ret;
- njs_str_t str;
- njs_uint_t written;
- njs_value_t str_val;
- const njs_extern_t *ext_proto;
- u_char buf[32], *p;
-
- njs_int_t (*to_string)(njs_vm_t *, njs_value_t *,
- const njs_value_t *);
+ njs_int_t ret;
+ njs_str_t str;
+ njs_value_t str_val;
+ u_char buf[32], *p;
+
+ njs_int_t (*to_string)(njs_vm_t *, njs_value_t *, const njs_value_t *);
switch (value->type) {
case NJS_OBJECT_STRING:
@@ -2032,52 +2029,6 @@ njs_dump_value(njs_json_stringify_t *str
break;
- case NJS_EXTERNAL:
- ext_proto = value->external.proto;
-
- written = 0;
- njs_dump_item("{type:");
-
- switch (ext_proto->type) {
- case NJS_EXTERN_PROPERTY:
- njs_dump("\"property\"");
- break;
- case NJS_EXTERN_METHOD:
- njs_dump("\"method\"");
- break;
- case NJS_EXTERN_OBJECT:
- njs_dump("\"object\"");
- break;
- case NJS_EXTERN_CASELESS_OBJECT:
- njs_dump("\"caseless_object\"");
- break;
- }
-
- njs_dump_item("props:[");
- written = 0;
-
- if (ext_proto->get != NULL) {
- njs_dump_item("\"getter\"");
- }
-
- if (ext_proto->set != NULL) {
- njs_dump_item("\"setter\"");
- }
-
- if (ext_proto->function != NULL) {
- njs_dump_item("\"method\"");
- }
-
- if (ext_proto->find != NULL) {
- njs_dump_item("\"find\"");
- }
-
- if (ext_proto->keys != NULL) {
- njs_dump_item("\"keys\"");
- }
-
- return njs_json_buf_append(stringify, "]}", 2);
-
case NJS_NUMBER:
if (njs_slow_path(njs_number(value) == 0.0
&& signbit(njs_number(value))))
@@ -2135,12 +2086,25 @@ memory_error:
}
-#define njs_dump_is_object(value) \
- (((value)->type == NJS_OBJECT && !njs_object(value)->error_data) \
- || ((value)->type == NJS_ARRAY) \
- || ((value)->type == NJS_OBJECT_VALUE) \
- || ((value)->type == NJS_EXTERNAL \
- && !njs_lvlhsh_is_empty(&(value)->external.proto->hash)))
+njs_inline njs_bool_t
+njs_dump_is_external_object(const njs_value_t *value)
+{
+ if (!njs_is_external(value)) {
+ return 0;
+ }
+
+ return value->external.proto->type == NJS_EXTERN_OBJECT;
+}
+
+
+njs_inline njs_bool_t
+njs_dump_is_object(const njs_value_t *value)
+{
+ return (value->type == NJS_OBJECT && !njs_object(value)->error_data)
+ || (value->type == NJS_ARRAY)
+ || (value->type == NJS_OBJECT_VALUE)
+ || njs_dump_is_external_object(value);
+}
#define njs_dump_append_value(value) \
@@ -2154,6 +2118,11 @@ memory_error:
}
+static const njs_value_t string_get = njs_string("[Getter]");
+static const njs_value_t string_set = njs_string("[Setter]");
+static const njs_value_t string_get_set = njs_long_string("[Getter/Setter]");
+
+
njs_int_t
njs_vm_value_dump(njs_vm_t *vm, njs_str_t *retval, const njs_value_t *value,
njs_uint_t console, njs_uint_t indent)
@@ -2161,18 +2130,13 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_
njs_int_t i;
njs_int_t ret;
njs_str_t str;
- njs_value_t *key, *val, tag, ext_val;
- njs_object_t *object;
+ njs_value_t *key, *val, tag;
njs_json_state_t *state;
njs_string_prop_t string;
njs_object_prop_t *prop;
- njs_lvlhsh_query_t lhq;
+ njs_property_query_t pq;
njs_json_stringify_t *stringify, dump_stringify;
- const njs_value_t string_get = njs_string("[Getter]");
- const njs_value_t string_set = njs_string("[Setter]");
- const njs_value_t string_get_set = njs_long_string("[Getter/Setter]");
-
if (njs_vm_backtrace(vm) != NULL) {
goto exception;
}
@@ -2238,53 +2202,50 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_
break;
}
+ njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0);
+
key = &state->keys->start[state->index++];
- njs_object_property_key_set(&lhq, key, 0);
-
- if (njs_is_external(&state->value)) {
- lhq.proto = &njs_extern_hash_proto;
-
- ret = njs_lvlhsh_find(&state->value.external.proto->hash, &lhq);
- if (njs_slow_path(ret == NJS_DECLINED)) {
+
+ ret = njs_property_query(vm, &pq, &state->value, key);
+ if (njs_slow_path(ret != NJS_OK)) {
+ if (ret == NJS_DECLINED) {
break;
}
- ext_val.type = NJS_EXTERNAL;
- ext_val.data.truth = 1;
- ext_val.external.proto = lhq.value;
-
- val = &ext_val;
-
- } else {
- object = njs_object(&state->value);
- lhq.proto = &njs_object_hash_proto;
-
- ret = njs_lvlhsh_find(&object->hash, &lhq);
- if (ret == NJS_DECLINED) {
- ret = njs_lvlhsh_find(&object->shared_hash, &lhq);
- if (njs_slow_path(ret == NJS_DECLINED)) {
- break;
- }
+ goto exception;
+ }
+
+ prop = pq.lhq.value;
+
+ if (prop->type == NJS_WHITEOUT || !prop->enumerable) {
+ break;
+ }
+
+ val = &prop->value;
+
+ if (prop->type == NJS_PROPERTY_HANDLER) {
+ pq.scratch = *prop;
+ prop = &pq.scratch;
+ ret = prop->value.data.u.prop_handler(vm, prop, &state->value,
+ NULL, &prop->value);
+
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
}
- prop = lhq.value;
val = &prop->value;
-
- if (prop->type == NJS_WHITEOUT || !prop->enumerable) {
- break;
- }
-
- if (njs_is_accessor_descriptor(prop)) {
- if (njs_is_defined(&prop->getter)) {
- if (njs_is_defined(&prop->setter)) {
- val = njs_value_arg(&string_get_set);
- } else {
- val = njs_value_arg(&string_get);
- }
-
+ }
+
+ if (njs_is_accessor_descriptor(prop)) {
+ if (njs_is_defined(&prop->getter)) {
+ if (njs_is_defined(&prop->setter)) {
+ val = njs_value_arg(&string_get_set);
} else {
- val = njs_value_arg(&string_set);
+ val = njs_value_arg(&string_get);
}
+
+ } else {
+ val = njs_value_arg(&string_set);
}
}
@@ -2294,8 +2255,8 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_
}
state->written = 1;
- njs_key_string_get(vm, key, &lhq.key);
- njs_json_stringify_append(lhq.key.start, lhq.key.length);
+ njs_key_string_get(vm, key, &pq.lhq.key);
+ njs_json_stringify_append(pq.lhq.key.start, pq.lhq.key.length);
njs_json_stringify_append(":", 1);
if (stringify->space.length != 0) {
njs_json_stringify_append(" ", 1);
diff -r 3eb134dfa896 -r 790caa744e0e src/njs_value.c
--- a/src/njs_value.c Mon Nov 25 17:53:19 2019 +0300
+++ b/src/njs_value.c Mon Nov 25 17:53:32 2019 +0300
@@ -815,10 +815,18 @@ njs_external_property_query(njs_vm_t *vm
prop = &pq->scratch;
- prop->type = NJS_PROPERTY;
- prop->writable = 0;
+ njs_memzero(prop, sizeof(njs_object_prop_t));
+
+ /*
+ * njs_memzero() does also:
+ * prop->type = NJS_PROPERTY;
+ * prop->writable = 0;
+ * prop->configurable = 0;
+ * njs_set_null(&prop->getter);
+ * njs_set_null(&prop->setter);
+ */
+
prop->enumerable = 1;
- prop->configurable = 0;
ext_proto = object->external.proto;
@@ -840,6 +848,12 @@ njs_external_property_query(njs_vm_t *vm
data = ext_proto->data;
} else {
+
+ if (pq->lhq.key.start == NULL) {
+ /* Symbol.toStringTag is not supported yet. */
+ goto done;
+ }
+
data = (uintptr_t) &pq->lhq.key;
}
diff -r 3eb134dfa896 -r 790caa744e0e src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Mon Nov 25 17:53:19 2019 +0300
+++ b/src/test/njs_unit_test.c Mon Nov 25 17:53:32 2019 +0300
@@ -13842,6 +13842,9 @@ static njs_unit_test_t njs_test[] =
{ njs_str("this.njs = 1; njs"),
njs_str("1") },
+ { njs_str("njs.dump(this) === `global {njs:njs {version:'${njs.version}'},process:process {}}`"),
+ njs_str("true") },
+
{ njs_str("process === process"),
njs_str("true") },
@@ -14594,10 +14597,10 @@ static njs_unit_test_t njs_test[] =
njs_str("{a:'[Setter]'}") },
{ njs_str("njs.dump($r.props)"),
- njs_str("{a:{type:\"property\",props:[\"getter\"]},b:{type:\"property\",props:[\"getter\"]}}") },
+ njs_str("{a:'1',b:42}") },
{ njs_str("njs.dump($r.header)"),
- njs_str("{type:\"object\",props:[\"getter\",\"keys\"]}") },
+ njs_str("{01:'01|АБВ',02:'02|АБВ',03:'03|АБВ'}") },
{ njs_str("njs.dump(njs) == `njs {version:'${njs.version}'}`"),
njs_str("true") },
More information about the nginx-devel
mailing list