Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # HG changeset patch
- # User hongzhidao <hongzhidao@gmail.com>
- # Date 1565146453 14400
- # Tue Aug 06 22:54:13 2019 -0400
- # Node ID fd41406b655c03551d8681ab07b0ac5154513ea1
- # Parent 05fb6e4fdb36b83c35ea66fb0355f46a38231312
- Added property getter support for njs_object_property().
- diff --git a/src/njs_array.c b/src/njs_array.c
- --- a/src/njs_array.c
- +++ b/src/njs_array.c
- @@ -825,18 +825,22 @@ static njs_int_t
- njs_array_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t unused)
- {
- - njs_object_prop_t *prop;
- + njs_int_t ret;
- + njs_value_t value;
- njs_lvlhsh_query_t lhq;
- if (njs_is_object(&args[0])) {
- - lhq.key_hash = NJS_JOIN_HASH;
- - lhq.key = njs_str_value("join");
- -
- - prop = njs_object_property(vm, njs_object(&args[0]), &lhq);
- -
- - if (njs_fast_path(prop != NULL && njs_is_function(&prop->value))) {
- - return njs_function_apply(vm, njs_function(&prop->value), args,
- - nargs, &vm->retval);
- + njs_object_property_init(&lhq, "join", NJS_JOIN_HASH);
- +
- + ret = njs_object_property(vm, &args[0], &lhq, &value);
- +
- + if (njs_slow_path(ret == NJS_ERROR)) {
- + return ret;
- + }
- +
- + if (njs_is_function(&value)) {
- + return njs_function_apply(vm, njs_function(&value), args, nargs,
- + &vm->retval);
- }
- }
- diff --git a/src/njs_date.c b/src/njs_date.c
- --- a/src/njs_date.c
- +++ b/src/njs_date.c
- @@ -1896,18 +1896,22 @@ static njs_int_t
- njs_date_prototype_to_json(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t retval)
- {
- - njs_object_prop_t *prop;
- + njs_int_t ret;
- + njs_value_t value;
- njs_lvlhsh_query_t lhq;
- if (njs_is_object(&args[0])) {
- - lhq.key_hash = NJS_TO_ISO_STRING_HASH;
- - lhq.key = njs_str_value("toISOString");
- -
- - prop = njs_object_property(vm, njs_object(&args[0]), &lhq);
- -
- - if (njs_fast_path(prop != NULL && njs_is_function(&prop->value))) {
- - return njs_function_apply(vm, njs_function(&prop->value), args,
- - nargs, &vm->retval);
- + njs_object_property_init(&lhq, "toISOString", NJS_TO_ISO_STRING_HASH);
- +
- + ret = njs_object_property(vm, &args[0], &lhq, &value);
- +
- + if (njs_slow_path(ret == NJS_ERROR)) {
- + return ret;
- + }
- +
- + if (njs_is_function(&value)) {
- + return njs_function_apply(vm, njs_function(&value), args, nargs,
- + &vm->retval);
- }
- }
- diff --git a/src/njs_error.c b/src/njs_error.c
- --- a/src/njs_error.c
- +++ b/src/njs_error.c
- @@ -619,24 +619,29 @@ njs_error_to_string(njs_vm_t *vm, njs_va
- {
- size_t size;
- u_char *p;
- + njs_int_t ret;
- njs_str_t name, message;
- + njs_value_t value1, value2;
- const njs_value_t *name_value, *message_value;
- - njs_object_prop_t *prop;
- njs_lvlhsh_query_t lhq;
- static const njs_value_t default_name = njs_string("Error");
- - lhq.key_hash = NJS_NAME_HASH;
- - lhq.key = njs_str_value("name");
- - lhq.proto = &njs_object_hash_proto;
- + njs_object_property_init(&lhq, "name", NJS_NAME_HASH);
- - prop = njs_object_property(vm, njs_object(error), &lhq);
- + ret = njs_object_property(vm, error, &lhq, &value1);
- - if (prop != NULL) {
- - name_value = &prop->value;
- + switch (ret) {
- + case NJS_OK:
- + name_value = &value1;
- + break;
- - } else {
- + case NJS_DECLINED:
- name_value = &default_name;
- + break;
- +
- + default:
- + return ret;
- }
- njs_string_get(name_value, &name);
- @@ -644,13 +649,19 @@ njs_error_to_string(njs_vm_t *vm, njs_va
- lhq.key_hash = NJS_MESSAGE_HASH;
- lhq.key = njs_str_value("message");
- - prop = njs_object_property(vm, njs_object(error), &lhq);
- + ret = njs_object_property(vm, error, &lhq, &value2);
- - if (prop != NULL) {
- - message_value = &prop->value;
- + switch (ret) {
- + case NJS_OK:
- + message_value = &value2;
- + break;
- - } else {
- + case NJS_DECLINED:
- message_value = &njs_string_empty;
- + break;
- +
- + default:
- + return ret;
- }
- njs_string_get(message_value, &message);
- diff --git a/src/njs_json.c b/src/njs_json.c
- --- a/src/njs_json.c
- +++ b/src/njs_json.c
- @@ -1497,19 +1497,19 @@ memory_error:
- static njs_function_t *
- njs_object_to_json_function(njs_vm_t *vm, njs_value_t *value)
- {
- - njs_object_prop_t *prop;
- + njs_int_t ret;
- + njs_value_t retval;
- njs_lvlhsh_query_t lhq;
- - lhq.key_hash = NJS_TO_JSON_HASH;
- - lhq.key = njs_str_value("toJSON");
- -
- - prop = njs_object_property(vm, njs_object(value), &lhq);
- -
- - if (prop != NULL && njs_is_function(&prop->value)) {
- - return njs_function(&prop->value);
- + njs_object_property_init(&lhq, "toJSON", NJS_TO_JSON_HASH);
- +
- + ret = njs_object_property(vm, value, &lhq, &retval);
- +
- + if (njs_slow_path(ret == NJS_ERROR)) {
- + return NULL;
- }
- - return NULL;
- + return njs_is_function(&retval) ? njs_function(&retval) : NULL;
- }
- diff --git a/src/njs_object.h b/src/njs_object.h
- --- a/src/njs_object.h
- +++ b/src/njs_object.h
- @@ -20,6 +20,14 @@
- (!njs_is_data_descriptor(prop) && !njs_is_accessor_descriptor(prop))
- +#define njs_object_property_init(lhq, _key, hash) \
- + do { \
- + (lhq)->proto = &njs_object_hash_proto; \
- + (lhq)->key_hash = hash; \
- + (lhq)->key = njs_str_value(_key); \
- + } while (0)
- +
- +
- struct njs_object_init_s {
- njs_str_t name;
- const njs_object_prop_t *properties;
- @@ -56,8 +64,8 @@ njs_int_t njs_object_prototype_to_string
- njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name,
- const njs_value_t *value, uint8_t attributes);
- -njs_object_prop_t *njs_object_property(njs_vm_t *vm, const njs_object_t *obj,
- - njs_lvlhsh_query_t *lhq);
- +njs_int_t njs_object_property(njs_vm_t *vm, const njs_value_t *value,
- + njs_lvlhsh_query_t *lhq, njs_value_t *retval);
- njs_int_t njs_object_prop_define(njs_vm_t *vm, njs_value_t *object,
- njs_value_t *name, njs_value_t *value);
- njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest,
- diff --git a/src/njs_object_prop.c b/src/njs_object_prop.c
- --- a/src/njs_object_prop.c
- +++ b/src/njs_object_prop.c
- @@ -9,7 +9,7 @@
- static njs_object_prop_t *njs_descriptor_prop(njs_vm_t *vm,
- - const njs_value_t *name, const njs_object_t *descriptor);
- + const njs_value_t *name, const njs_value_t *desc);
- njs_object_prop_t *
- @@ -45,32 +45,53 @@ njs_object_prop_alloc(njs_vm_t *vm, cons
- }
- -njs_object_prop_t *
- -njs_object_property(njs_vm_t *vm, const njs_object_t *object,
- - njs_lvlhsh_query_t *lhq)
- +njs_int_t
- +njs_object_property(njs_vm_t *vm, const njs_value_t *value,
- + njs_lvlhsh_query_t *lhq, njs_value_t *retval)
- {
- - njs_int_t ret;
- + njs_int_t ret;
- + njs_object_t *object;
- + njs_object_prop_t *prop;
- - lhq->proto = &njs_object_hash_proto;
- + object = njs_object(value);
- do {
- ret = njs_lvlhsh_find(&object->hash, lhq);
- if (njs_fast_path(ret == NJS_OK)) {
- - return lhq->value;
- + goto found;
- }
- ret = njs_lvlhsh_find(&object->shared_hash, lhq);
- if (njs_fast_path(ret == NJS_OK)) {
- - return lhq->value;
- + goto found;
- }
- object = object->__proto__;
- } while (object != NULL);
- - return NULL;
- + *retval = njs_value_undefined;
- +
- + return NJS_DECLINED;
- +
- +found:
- +
- + prop = lhq->value;
- +
- + if (njs_is_data_descriptor(prop)) {
- + *retval = prop->value;
- + return NJS_OK;
- + }
- +
- + if (njs_is_undefined(&prop->getter)) {
- + *retval = njs_value_undefined;
- + return NJS_OK;
- + }
- +
- + return njs_function_apply(vm, njs_function(&prop->getter), value,
- + 1, retval);
- }
- @@ -95,7 +116,7 @@ njs_object_prop_define(njs_vm_t *vm, njs
- return ret;
- }
- - prop = njs_descriptor_prop(vm, name, njs_object(value));
- + prop = njs_descriptor_prop(vm, name, value);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
- @@ -313,12 +334,13 @@ exception:
- static njs_object_prop_t *
- njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *name,
- - const njs_object_t *desc)
- + const njs_value_t *desc)
- {
- + njs_int_t ret;
- njs_bool_t data, accessor;
- - njs_object_prop_t *prop, *pr;
- - const njs_value_t *setter, *getter;
- - njs_lvlhsh_query_t pq;
- + njs_value_t value;
- + njs_object_prop_t *prop;
- + njs_lvlhsh_query_t lhq;
- data = 0;
- accessor = 0;
- @@ -329,72 +351,103 @@ njs_descriptor_prop(njs_vm_t *vm, const
- return NULL;
- }
- - getter = &njs_value_invalid;
- - pq.key = njs_str_value("get");
- - pq.key_hash = NJS_GET_HASH;
- + njs_object_property_init(&lhq, "get", NJS_GET_HASH);
- - pr = njs_object_property(vm, desc, &pq);
- - if (pr != NULL) {
- - if (njs_is_defined(&pr->value) && !njs_is_function(&pr->value)) {
- + ret = njs_object_property(vm, desc, &lhq, &value);
- +
- + if (njs_slow_path(ret == NJS_ERROR)) {
- + return NULL;
- + }
- +
- + if (ret == NJS_OK) {
- + if (njs_is_defined(&value) && !njs_is_function(&value)) {
- njs_type_error(vm, "Getter must be a function");
- return NULL;
- }
- accessor = 1;
- - getter = &pr->value;
- + prop->getter = value;
- +
- + } else {
- + /* NJS_DECLINED */
- + prop->getter = njs_value_invalid;
- }
- - prop->getter = *getter;
- + lhq.key = njs_str_value("set");
- + lhq.key_hash = NJS_SET_HASH;
- - setter = &njs_value_invalid;
- - pq.key = njs_str_value("set");
- - pq.key_hash = NJS_SET_HASH;
- + ret = njs_object_property(vm, desc, &lhq, &value);
- - pr = njs_object_property(vm, desc, &pq);
- - if (pr != NULL) {
- - if (njs_is_defined(&pr->value) && !njs_is_function(&pr->value)) {
- + if (njs_slow_path(ret == NJS_ERROR)) {
- + return NULL;
- + }
- +
- + if (ret == NJS_OK) {
- + if (njs_is_defined(&value) && !njs_is_function(&value)) {
- njs_type_error(vm, "Setter must be a function");
- return NULL;
- }
- accessor = 1;
- - setter = &pr->value;
- + prop->setter = value;
- +
- + } else {
- + /* NJS_DECLINED */
- + prop->setter = njs_value_invalid;
- }
- - prop->setter = *setter;
- + lhq.key = njs_str_value("value");
- + lhq.key_hash = NJS_VALUE_HASH;
- - pq.key = njs_str_value("value");
- - pq.key_hash = NJS_VALUE_HASH;
- + ret = njs_object_property(vm, desc, &lhq, &value);
- - pr = njs_object_property(vm, desc, &pq);
- - if (pr != NULL) {
- - data = 1;
- - prop->value = pr->value;
- + if (njs_slow_path(ret == NJS_ERROR)) {
- + return NULL;
- }
- - pq.key = njs_str_value("writable");
- - pq.key_hash = NJS_WRITABABLE_HASH;
- -
- - pr = njs_object_property(vm, desc, &pq);
- - if (pr != NULL) {
- + if (ret == NJS_OK) {
- data = 1;
- - prop->writable = njs_is_true(&pr->value);
- + prop->value = value;
- }
- - pq.key = njs_str_value("enumerable");
- - pq.key_hash = NJS_ENUMERABLE_HASH;
- + lhq.key = njs_str_value("writable");
- + lhq.key_hash = NJS_WRITABABLE_HASH;
- - pr = njs_object_property(vm, desc, &pq);
- - if (pr != NULL) {
- - prop->enumerable = njs_is_true(&pr->value);
- + ret = njs_object_property(vm, desc, &lhq, &value);
- +
- + if (njs_slow_path(ret == NJS_ERROR)) {
- + return NULL;
- }
- - pq.key = njs_str_value("configurable");
- - pq.key_hash = NJS_CONFIGURABLE_HASH;
- + if (ret == NJS_OK) {
- + data = 1;
- + prop->writable = njs_is_true(&value);
- + }
- - pr = njs_object_property(vm, desc, &pq);
- - if (pr != NULL) {
- - prop->configurable = njs_is_true(&pr->value);
- + lhq.key = njs_str_value("enumerable");
- + lhq.key_hash = NJS_ENUMERABLE_HASH;
- +
- + ret = njs_object_property(vm, desc, &lhq, &value);
- +
- + if (njs_slow_path(ret == NJS_ERROR)) {
- + return NULL;
- + }
- +
- + if (ret == NJS_OK) {
- + prop->enumerable = njs_is_true(&value);
- + }
- +
- + lhq.key = njs_str_value("configurable");
- + lhq.key_hash = NJS_CONFIGURABLE_HASH;
- +
- + ret = njs_object_property(vm, desc, &lhq, &value);
- +
- + if (njs_slow_path(ret == NJS_ERROR)) {
- + return NULL;
- + }
- +
- + if (ret == NJS_OK) {
- + prop->configurable = njs_is_true(&value);
- }
- if (accessor && data) {
- @@ -435,6 +488,29 @@ njs_object_prop_descriptor(njs_vm_t *vm,
- switch (ret) {
- case NJS_OK:
- + prop = pq.lhq.value;
- +
- + switch (prop->type) {
- + case NJS_PROPERTY:
- + break;
- +
- + case NJS_PROPERTY_HANDLER:
- + pq.scratch = *prop;
- + prop = &pq.scratch;
- + ret = prop->value.data.u.prop_handler(vm, value, NULL,
- + &prop->value);
- + if (njs_slow_path(ret != NJS_OK)) {
- + return ret;
- + }
- +
- + break;
- +
- + default:
- + njs_type_error(vm, "unexpected property type: %s",
- + njs_prop_type_string(prop->type));
- + return NJS_ERROR;
- + }
- +
- break;
- case NJS_DECLINED:
- @@ -446,28 +522,6 @@ njs_object_prop_descriptor(njs_vm_t *vm,
- return ret;
- }
- - prop = pq.lhq.value;
- -
- - switch (prop->type) {
- - case NJS_PROPERTY:
- - break;
- -
- - case NJS_PROPERTY_HANDLER:
- - pq.scratch = *prop;
- - prop = &pq.scratch;
- - ret = prop->value.data.u.prop_handler(vm, value, NULL, &prop->value);
- - if (njs_slow_path(ret != NJS_OK)) {
- - return ret;
- - }
- -
- - break;
- -
- - default:
- - njs_type_error(vm, "unexpected property type: %s",
- - njs_prop_type_string(prop->type));
- - return NJS_ERROR;
- - }
- -
- desc = njs_object_alloc(vm);
- if (njs_slow_path(desc == NULL)) {
- return NJS_ERROR;
- diff --git a/src/njs_value.c b/src/njs_value.c
- --- a/src/njs_value.c
- +++ b/src/njs_value.c
- @@ -122,8 +122,7 @@ njs_value_to_primitive(njs_vm_t *vm, njs
- {
- njs_int_t ret;
- njs_uint_t tries;
- - njs_value_t retval;
- - njs_object_prop_t *prop;
- + njs_value_t method, retval;
- njs_lvlhsh_query_t lhq;
- static const uint32_t hashes[] = {
- @@ -144,6 +143,7 @@ njs_value_to_primitive(njs_vm_t *vm, njs
- }
- tries = 0;
- + lhq.proto = &njs_object_hash_proto;
- for ( ;; ) {
- ret = NJS_ERROR;
- @@ -154,28 +154,27 @@ njs_value_to_primitive(njs_vm_t *vm, njs
- lhq.key_hash = hashes[hint];
- lhq.key = names[hint];
- - prop = njs_object_property(vm, njs_object(value), &lhq);
- + ret = njs_object_property(vm, value, &lhq, &method);
- - if (prop == NULL || !njs_is_function(&prop->value)) {
- - /* Try the second method. */
- - continue;
- + if (njs_slow_path(ret == NJS_ERROR)) {
- + return ret;
- }
- - ret = njs_function_apply(vm, njs_function(&prop->value), value, 1,
- - &retval);
- + if (njs_is_function(&method)) {
- + ret = njs_function_apply(vm, njs_function(&method), value, 1,
- + &retval);
- - if (njs_fast_path(ret == NJS_OK)) {
- + if (njs_slow_path(ret != NJS_OK)) {
- + return ret;
- + }
- +
- if (njs_is_primitive(&retval)) {
- break;
- - }
- + }
- + }
- - /* Try the second method. */
- - continue;
- - }
- -
- - /* NJS_ERROR */
- -
- - return ret;
- + /* Try the second method. */
- + continue;
- }
- njs_type_error(vm, "Cannot convert object to primitive value");
- diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c
- --- a/src/test/njs_unit_test.c
- +++ b/src/test/njs_unit_test.c
- @@ -9811,6 +9811,43 @@ static njs_unit_test_t njs_test[] =
- { njs_str("var arr = [0, 1]; Object.defineProperty(arr, 'length', {value:3}); arr.length"),
- njs_str("3") },
- + { njs_str("Object.defineProperty(Array.prototype, 'toString', { get: function() {return () => 1}});"
- + "'a' + []"),
- + njs_str("a1") },
- +
- + { njs_str("Object.defineProperty(Array.prototype, 'toJSON', { get: function() {return () => 1}});"
- + "JSON.stringify([])"),
- + njs_str("1") },
- +
- + { njs_str("Object.defineProperty(Array.prototype, 'join', { get: function() {return () => 1}});"
- + "([]).toString()"),
- + njs_str("1") },
- +
- + { njs_str("var o = {}, desc = {};"
- + "Object.defineProperty(desc, 'get', { get() { return () => 1 } });"
- + "Object.defineProperty(o, 'a', desc); o.a"),
- + njs_str("1") },
- +
- + { njs_str("Object.defineProperty(Error.prototype, 'message', { get() {return 'm'}});"
- + "Object.defineProperty(Error.prototype, 'name', { get() {return 'n'}});"
- + "Error()"),
- + njs_str("n: m") },
- +
- + { njs_str("var o = {}, desc = {};"
- + "Object.defineProperty(desc, 'value', { get() { return 'x'}});"
- + "Object.defineProperty(o, 'a', desc); o.a"),
- + njs_str("x") },
- +
- + { njs_str("var o = {}, desc = {};"
- + "Object.defineProperty(desc, 'value', { get() { return 'x'}});"
- + "Object.defineProperty(desc, 'enumerable', { get() { return !NaN}});"
- + "Object.defineProperty(desc, 'writable', { get() { return 'x'}});"
- + "Object.defineProperty(desc, 'configurable', { get() { return 1}});"
- + "Object.defineProperty(o, 'a', desc);"
- + "var d = Object.getOwnPropertyDescriptor(o, 'a');"
- + "d.enumerable && d.writable && d.configurable"),
- + njs_str("true") },
- +
- { njs_str("Object.defineProperties()"),
- njs_str("TypeError: cannot convert undefined argument to object") },
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement