From: Dmitry Volyntsev Date: Fri, 20 Apr 2018 13:42:10 +0000 (+0300) Subject: Making native getters into universal property handlers. X-Git-Url: http://git.kaiwu.me/sitemap.xml?a=commitdiff_plain;h=ffd9624a633d5f9cae4d8f001d22b1c88bd9a464;p=njs.git Making native getters into universal property handlers. --- diff --git a/njs/njs_array.c b/njs/njs_array.c index 800fbb82..c562ffc4 100644 --- a/njs/njs_array.c +++ b/njs/njs_array.c @@ -351,9 +351,9 @@ static const njs_object_prop_t njs_array_constructor_properties[] = /* Array.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, /* Array.isArray(). */ @@ -382,7 +382,7 @@ const njs_object_init_t njs_array_constructor_init = { static njs_ret_t njs_array_prototype_length(njs_vm_t *vm, njs_value_t *array, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { njs_value_number_set(retval, array->data.u.array->length); @@ -2057,9 +2057,9 @@ njs_array_prototype_sort_continuation(njs_vm_t *vm, njs_value_t *args, static const njs_object_prop_t njs_array_prototype_properties[] = { { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("length"), - .value = njs_native_getter(njs_array_prototype_length), + .value = njs_prop_handler(njs_array_prototype_length), }, { diff --git a/njs/njs_boolean.c b/njs/njs_boolean.c index 275d526f..745dd4a3 100644 --- a/njs/njs_boolean.c +++ b/njs/njs_boolean.c @@ -71,9 +71,9 @@ static const njs_object_prop_t njs_boolean_constructor_properties[] = /* Boolean.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, }; @@ -140,9 +140,9 @@ njs_boolean_prototype_to_string(njs_vm_t *vm, njs_value_t *args, static const njs_object_prop_t njs_boolean_prototype_properties[] = { { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("__proto__"), - .value = njs_native_getter(njs_primitive_prototype_get_proto), + .value = njs_prop_handler(njs_primitive_prototype_get_proto), }, { diff --git a/njs/njs_builtin.c b/njs/njs_builtin.c index 1e1b668a..eab304e2 100644 --- a/njs/njs_builtin.c +++ b/njs/njs_builtin.c @@ -246,9 +246,9 @@ njs_builtin_objects_create(njs_vm_t *vm) }; static const njs_object_prop_t function_prototype_property = { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_function_prototype_create), + .value = njs_prop_handler(njs_function_prototype_create), }; ret = njs_object_hash_create(vm, &vm->shared->function_prototype_hash, diff --git a/njs/njs_date.c b/njs/njs_date.c index b8bc0fe7..7977e097 100644 --- a/njs/njs_date.c +++ b/njs/njs_date.c @@ -905,9 +905,9 @@ static const njs_object_prop_t njs_date_constructor_properties[] = /* Date.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, { @@ -1931,9 +1931,9 @@ njs_date_prototype_to_json_continuation(njs_vm_t *vm, njs_value_t *args, static const njs_object_prop_t njs_date_prototype_properties[] = { { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("__proto__"), - .value = njs_native_getter(njs_primitive_prototype_get_proto), + .value = njs_prop_handler(njs_primitive_prototype_get_proto), }, { diff --git a/njs/njs_error.c b/njs/njs_error.c index 441ab3e2..a0f30449 100644 --- a/njs/njs_error.c +++ b/njs/njs_error.c @@ -192,9 +192,9 @@ static const njs_object_prop_t njs_error_constructor_properties[] = /* Error.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, }; @@ -232,9 +232,9 @@ static const njs_object_prop_t njs_eval_error_constructor_properties[] = /* EvalError.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, }; @@ -272,9 +272,9 @@ static const njs_object_prop_t njs_internal_error_constructor_properties[] = /* InternalError.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, }; @@ -312,9 +312,9 @@ static const njs_object_prop_t njs_range_error_constructor_properties[] = /* RangeError.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, }; @@ -352,9 +352,9 @@ static const njs_object_prop_t njs_reference_error_constructor_properties[] = /* ReferenceError.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, }; @@ -392,9 +392,9 @@ static const njs_object_prop_t njs_syntax_error_constructor_properties[] = /* SyntaxError.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, }; @@ -432,9 +432,9 @@ static const njs_object_prop_t njs_type_error_constructor_properties[] = /* TypeError.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, }; @@ -472,9 +472,9 @@ static const njs_object_prop_t njs_uri_error_constructor_properties[] = /* URIError.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, }; @@ -533,7 +533,7 @@ njs_memory_error_constructor(njs_vm_t *vm, njs_value_t *args, static njs_ret_t njs_memory_error_prototype_create(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { int32_t index; njs_value_t *proto; @@ -574,9 +574,9 @@ static const njs_object_prop_t njs_memory_error_constructor_properties[] = /* MemoryError.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_memory_error_prototype_create), + .value = njs_prop_handler(njs_memory_error_prototype_create), }, }; diff --git a/njs/njs_function.c b/njs/njs_function.c index d35c4bca..d3b55794 100644 --- a/njs/njs_function.c +++ b/njs/njs_function.c @@ -419,7 +419,7 @@ njs_function_call(njs_vm_t *vm, njs_index_t retval, size_t advance) njs_ret_t njs_function_prototype_create(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { njs_value_t *proto; @@ -495,9 +495,9 @@ static const njs_object_prop_t njs_function_constructor_properties[] = /* Function.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, }; diff --git a/njs/njs_function.h b/njs/njs_function.h index 13619289..f7e8481c 100644 --- a/njs/njs_function.h +++ b/njs/njs_function.h @@ -147,7 +147,7 @@ njs_function_t *njs_function_alloc(njs_vm_t *vm); njs_function_t *njs_function_value_copy(njs_vm_t *vm, njs_value_t *value); njs_native_frame_t *njs_function_frame_alloc(njs_vm_t *vm, size_t size); njs_ret_t njs_function_prototype_create(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval); + njs_value_t *setval, njs_value_t *retval); njs_value_t *njs_function_property_prototype_create(njs_vm_t *vm, njs_value_t *value); njs_ret_t njs_function_constructor(njs_vm_t *vm, njs_value_t *args, diff --git a/njs/njs_math.c b/njs/njs_math.c index 108ac029..e2e98396 100644 --- a/njs/njs_math.c +++ b/njs/njs_math.c @@ -822,9 +822,9 @@ static const njs_object_prop_t njs_math_object_properties[] = }, { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("__proto__"), - .value = njs_native_getter(njs_object_prototype_get_proto), + .value = njs_prop_handler(njs_object_prototype_get_proto), }, { diff --git a/njs/njs_number.c b/njs/njs_number.c index 99abd2d6..e75967fa 100644 --- a/njs/njs_number.c +++ b/njs/njs_number.c @@ -463,9 +463,9 @@ static const njs_object_prop_t njs_number_constructor_properties[] = /* Number.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, /* ES6. */ @@ -707,9 +707,9 @@ njs_number_to_string_radix(njs_vm_t *vm, njs_value_t *string, static const njs_object_prop_t njs_number_prototype_properties[] = { { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("__proto__"), - .value = njs_native_getter(njs_primitive_prototype_get_proto), + .value = njs_prop_handler(njs_primitive_prototype_get_proto), }, { diff --git a/njs/njs_object.c b/njs/njs_object.c index 013424ee..2ad5d09f 100644 --- a/njs/njs_object.c +++ b/njs/njs_object.c @@ -740,7 +740,7 @@ njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { if (nargs > 1 && njs_is_object(&args[1])) { - njs_object_prototype_get_proto(vm, &args[1], &vm->retval); + njs_object_prototype_get_proto(vm, &args[1], NULL, &vm->retval); return NXT_OK; } @@ -971,7 +971,7 @@ njs_object_is_extensible(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_ret_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { nxt_uint_t index; njs_object_t *proto; @@ -1004,7 +1004,7 @@ njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value, njs_ret_t njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { int32_t index; njs_value_t *proto; @@ -1088,9 +1088,9 @@ static const njs_object_prop_t njs_object_constructor_properties[] = /* Object.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, /* Object.create(). */ @@ -1202,7 +1202,7 @@ const njs_object_init_t njs_object_constructor_init = { njs_ret_t njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { njs_object_t *proto; @@ -1229,7 +1229,7 @@ njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value, static njs_ret_t njs_object_prototype_create_constructor(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { int32_t index; njs_value_t *cons; @@ -1521,15 +1521,15 @@ njs_object_prototype_is_prototype_of(njs_vm_t *vm, njs_value_t *args, static const njs_object_prop_t njs_object_prototype_properties[] = { { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("__proto__"), - .value = njs_native_getter(njs_object_prototype_get_proto), + .value = njs_prop_handler(njs_object_prototype_get_proto), }, { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("constructor"), - .value = njs_native_getter(njs_object_prototype_create_constructor), + .value = njs_prop_handler(njs_object_prototype_create_constructor), }, { diff --git a/njs/njs_object.h b/njs/njs_object.h index a0094a5b..26453eb6 100644 --- a/njs/njs_object.h +++ b/njs/njs_object.h @@ -13,8 +13,7 @@ typedef enum { NJS_GETTER, NJS_SETTER, NJS_METHOD, - NJS_NATIVE_GETTER, - NJS_NATIVE_SETTER, + NJS_PROPERTY_HANDLER, NJS_WHITEOUT, } njs_object_property_type_t; @@ -52,13 +51,13 @@ njs_ret_t njs_object_constructor(njs_vm_t *vm, njs_value_t *args, 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_ret_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval); + njs_value_t *setval, njs_value_t *retval); njs_ret_t njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval); + njs_value_t *setval, njs_value_t *retval); njs_value_t *njs_property_prototype_create(njs_vm_t *vm, nxt_lvlhsh_t *hash, njs_object_t *prototype); njs_ret_t njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval); + njs_value_t *setval, njs_value_t *retval); njs_value_t *njs_property_constructor_create(njs_vm_t *vm, nxt_lvlhsh_t *hash, njs_value_t *constructor); njs_ret_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args, diff --git a/njs/njs_regexp.c b/njs/njs_regexp.c index 2329542e..9b298f18 100644 --- a/njs/njs_regexp.c +++ b/njs/njs_regexp.c @@ -464,7 +464,7 @@ njs_regexp_alloc(njs_vm_t *vm, njs_regexp_pattern_t *pattern) static njs_ret_t njs_regexp_prototype_last_index(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { uint32_t index; njs_regexp_t *regexp; @@ -485,7 +485,7 @@ njs_regexp_prototype_last_index(njs_vm_t *vm, njs_value_t *value, static njs_ret_t njs_regexp_prototype_global(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { njs_regexp_pattern_t *pattern; @@ -499,7 +499,7 @@ njs_regexp_prototype_global(njs_vm_t *vm, njs_value_t *value, static njs_ret_t njs_regexp_prototype_ignore_case(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { njs_regexp_pattern_t *pattern; @@ -513,7 +513,7 @@ njs_regexp_prototype_ignore_case(njs_vm_t *vm, njs_value_t *value, static njs_ret_t njs_regexp_prototype_multiline(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { njs_regexp_pattern_t *pattern; @@ -527,7 +527,7 @@ njs_regexp_prototype_multiline(njs_vm_t *vm, njs_value_t *value, static njs_ret_t njs_regexp_prototype_source(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { u_char *source; int32_t length; @@ -824,9 +824,9 @@ static const njs_object_prop_t njs_regexp_constructor_properties[] = /* RegExp.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, }; @@ -841,33 +841,33 @@ const njs_object_init_t njs_regexp_constructor_init = { static const njs_object_prop_t njs_regexp_prototype_properties[] = { { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("lastIndex"), - .value = njs_native_getter(njs_regexp_prototype_last_index), + .value = njs_prop_handler(njs_regexp_prototype_last_index), }, { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("global"), - .value = njs_native_getter(njs_regexp_prototype_global), + .value = njs_prop_handler(njs_regexp_prototype_global), }, { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("ignoreCase"), - .value = njs_native_getter(njs_regexp_prototype_ignore_case), + .value = njs_prop_handler(njs_regexp_prototype_ignore_case), }, { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("multiline"), - .value = njs_native_getter(njs_regexp_prototype_multiline), + .value = njs_prop_handler(njs_regexp_prototype_multiline), }, { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("source"), - .value = njs_native_getter(njs_regexp_prototype_source), + .value = njs_prop_handler(njs_regexp_prototype_source), }, { diff --git a/njs/njs_string.c b/njs/njs_string.c index 504f47e5..ec8f9ab7 100644 --- a/njs/njs_string.c +++ b/njs/njs_string.c @@ -570,9 +570,9 @@ static const njs_object_prop_t njs_string_constructor_properties[] = /* String.prototype. */ { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("prototype"), - .value = njs_native_getter(njs_object_prototype_create), + .value = njs_prop_handler(njs_object_prototype_create), }, /* String.fromCharCode(). */ @@ -600,7 +600,7 @@ const njs_object_init_t njs_string_constructor_init = { static njs_ret_t njs_string_prototype_length(njs_vm_t *vm, njs_value_t *value, - njs_value_t *retval) + njs_value_t *setval, njs_value_t *retval) { size_t size; uintptr_t length; @@ -3348,15 +3348,15 @@ njs_string_to_c_string(njs_vm_t *vm, njs_value_t *value) static const njs_object_prop_t njs_string_prototype_properties[] = { { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("__proto__"), - .value = njs_native_getter(njs_primitive_prototype_get_proto), + .value = njs_prop_handler(njs_primitive_prototype_get_proto), }, { - .type = NJS_NATIVE_GETTER, + .type = NJS_PROPERTY_HANDLER, .name = njs_string("length"), - .value = njs_native_getter(njs_string_prototype_length), + .value = njs_prop_handler(njs_string_prototype_length), }, { diff --git a/njs/njs_vm.c b/njs/njs_vm.c index 14f0e00f..6f29067b 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -54,7 +54,7 @@ typedef struct { nxt_lvlhsh_query_t lhq; - /* scratch is used to get the value of an NJS_NATIVE_GETTER property. */ + /* scratch is used to get the value of an NJS_PROPERTY_HANDLER property. */ njs_object_prop_t scratch; njs_value_t value; @@ -82,6 +82,8 @@ 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, @@ -695,6 +697,17 @@ njs_vmcode_property_set(njs_vm_t *vm, njs_value_t *object, case NXT_OK: prop = pq.lhq.value; + + if (prop->type == NJS_PROPERTY_HANDLER) { + ret = prop->value.data.u.prop_handler(vm, object, value, + &vm->retval); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + + return sizeof(njs_vmcode_prop_set_t); + } + break; case NXT_DECLINED: @@ -1153,6 +1166,13 @@ njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, 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; @@ -1183,10 +1203,11 @@ njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, if (pq->query == NJS_PROPERTY_QUERY_GET) { prop = pq->lhq.value; - if (prop->type == NJS_NATIVE_GETTER) { + if (prop->type == NJS_PROPERTY_HANDLER) { pq->scratch = *prop; prop = &pq->scratch; - ret = prop->value.data.u.getter(vm, value, &prop->value); + ret = prop->value.data.u.prop_handler(vm, value, NULL, + &prop->value); if (nxt_fast_path(ret == NXT_OK)) { prop->type = NJS_PROPERTY; @@ -1219,6 +1240,33 @@ njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, } +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 --git a/njs/njs_vm.h b/njs/njs_vm.h index c182ddd7..a139f48c 100644 --- a/njs/njs_vm.h +++ b/njs/njs_vm.h @@ -118,8 +118,13 @@ typedef enum { typedef struct njs_parser_s njs_parser_t; -typedef njs_ret_t (*njs_getter_t) (njs_vm_t *vm, njs_value_t *obj, - njs_value_t *retval); +/* + * njs_prop_handler_t operates as a property getter and/or setter. + * The handler receives NULL setval if it is invoked in GET context and + * non-null otherwise. + */ +typedef njs_ret_t (*njs_prop_handler_t) (njs_vm_t *vm, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval); typedef njs_ret_t (*njs_function_native_t) (njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t retval); @@ -177,7 +182,7 @@ union njs_value_s { njs_function_lambda_t *lambda; njs_regexp_t *regexp; njs_date_t *date; - njs_getter_t getter; + njs_prop_handler_t prop_handler; njs_value_t *value; njs_property_next_t *next; void *data; @@ -374,11 +379,11 @@ typedef union { } -#define njs_native_getter(_getter) { \ +#define njs_prop_handler(_handler) { \ .data = { \ .type = NJS_INVALID, \ .truth = 1, \ - .u = { .getter = _getter } \ + .u = { .prop_handler = _handler } \ } \ } diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 6478ea2e..ec84c9d4 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -5792,6 +5792,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("({}).__proto__ === Object.prototype"), nxt_string("true") }, + { nxt_string("({}).__proto__ = 1"), + nxt_string("1") }, + + { nxt_string("var o = {}; o.__proto__ = 1; o.__proto__"), + nxt_string("[object Object]") }, + { nxt_string("({}).__proto__.constructor === Object"), nxt_string("true") },