From 2116fe30c971c265dccf51285b49791da9e866d2 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Mon, 25 Nov 2019 17:53:32 +0300 Subject: [PATCH] Fixed njs.dump() for objects with NJS_PROPERTY_HANDLER props. --- src/njs_json.c | 163 +++++++++++++++------------------------ src/njs_value.c | 20 ++++- src/test/njs_unit_test.c | 7 +- 3 files changed, 84 insertions(+), 106 deletions(-) diff --git a/src/njs_json.c b/src/njs_json.c index 95fd8294..4093617a 100644 --- a/src/njs_json.c +++ b/src/njs_json.c @@ -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 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 *); + 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 *stringify, const njs_value_t *value, 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_t *retval, const njs_value_t *value, 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_t *retval, const njs_value_t *value, break; } - key = &state->keys->start[state->index++]; - njs_object_property_key_set(&lhq, key, 0); + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); - if (njs_is_external(&state->value)) { - lhq.proto = &njs_extern_hash_proto; + key = &state->keys->start[state->index++]; - 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; + goto exception; + } - val = &ext_val; + prop = pq.lhq.value; - } else { - object = njs_object(&state->value); - lhq.proto = &njs_object_hash_proto; + if (prop->type == NJS_WHITEOUT || !prop->enumerable) { + break; + } - 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; - } - } + val = &prop->value; - prop = lhq.value; - 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 (prop->type == NJS_WHITEOUT || !prop->enumerable) { - break; + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; } - 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); - } + val = &prop->value; + } + 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_t *retval, const njs_value_t *value, } 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 --git a/src/njs_value.c b/src/njs_value.c index 778e2c93..001c566c 100644 --- a/src/njs_value.c +++ b/src/njs_value.c @@ -815,10 +815,18 @@ njs_external_property_query(njs_vm_t *vm, njs_property_query_t *pq, 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, njs_property_query_t *pq, 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 --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index a503432e..73fba4c4 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -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") }, -- 2.47.3