[njs] Making native getters into universal property handlers.

Dmitry Volyntsev xeioex at nginx.com
Fri Apr 20 13:42:37 UTC 2018


details:   http://hg.nginx.org/njs/rev/a65deb4c2e03
branches:  
changeset: 501:a65deb4c2e03
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Fri Apr 20 16:42:10 2018 +0300
description:
Making native getters into universal property handlers.

diffstat:

 njs/njs_array.c          |  10 ++++----
 njs/njs_boolean.c        |   8 +++---
 njs/njs_builtin.c        |   4 +-
 njs/njs_date.c           |   8 +++---
 njs/njs_error.c          |  38 ++++++++++++++++----------------
 njs/njs_function.c       |   6 ++--
 njs/njs_function.h       |   2 +-
 njs/njs_math.c           |   4 +-
 njs/njs_number.c         |   8 +++---
 njs/njs_object.c         |  22 +++++++++---------
 njs/njs_object.h         |   9 +++----
 njs/njs_regexp.c         |  34 +++++++++++++++---------------
 njs/njs_string.c         |  14 ++++++------
 njs/njs_vm.c             |  54 +++++++++++++++++++++++++++++++++++++++++++++--
 njs/njs_vm.h             |  15 ++++++++----
 njs/test/njs_unit_test.c |   6 +++++
 16 files changed, 150 insertions(+), 92 deletions(-)

diffs (720 lines):

diff -r 28d75187de15 -r a65deb4c2e03 njs/njs_array.c
--- a/njs/njs_array.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_array.c	Fri Apr 20 16:42:10 2018 +0300
@@ -351,9 +351,9 @@ static const njs_object_prop_t  njs_arra
 
     /* 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_const
 
 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(nj
 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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_boolean.c
--- a/njs/njs_boolean.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_boolean.c	Fri Apr 20 16:42:10 2018 +0300
@@ -71,9 +71,9 @@ static const njs_object_prop_t  njs_bool
 
     /* 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
 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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_builtin.c
--- a/njs/njs_builtin.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_builtin.c	Fri Apr 20 16:42:10 2018 +0300
@@ -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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_date.c
--- a/njs/njs_date.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_date.c	Fri Apr 20 16:42:10 2018 +0300
@@ -905,9 +905,9 @@ static const njs_object_prop_t  njs_date
 
     /* 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(
 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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_error.c
--- a/njs/njs_error.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_error.c	Fri Apr 20 16:42:10 2018 +0300
@@ -192,9 +192,9 @@ static const njs_object_prop_t  njs_erro
 
     /* 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
 
     /* 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_inte
 
     /* 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_rang
 
     /* 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_refe
 
     /* 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_synt
 
     /* 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
 
     /* 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_
 
     /* 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 *v
 
 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_memo
 
     /* 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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_function.c
--- a/njs/njs_function.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_function.c	Fri Apr 20 16:42:10 2018 +0300
@@ -419,7 +419,7 @@ njs_function_call(njs_vm_t *vm, njs_inde
 
 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_func
 
     /* 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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_function.h
--- a/njs/njs_function.h	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_function.h	Fri Apr 20 16:42:10 2018 +0300
@@ -147,7 +147,7 @@ njs_function_t *njs_function_alloc(njs_v
 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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_math.c
--- a/njs/njs_math.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_math.c	Fri Apr 20 16:42:10 2018 +0300
@@ -822,9 +822,9 @@ static const njs_object_prop_t  njs_math
     },
 
     {
-        .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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_number.c
--- a/njs/njs_number.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_number.c	Fri Apr 20 16:42:10 2018 +0300
@@ -463,9 +463,9 @@ static const njs_object_prop_t  njs_numb
 
     /* 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,
 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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_object.c
--- a/njs/njs_object.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_object.c	Fri Apr 20 16:42:10 2018 +0300
@@ -740,7 +740,7 @@ njs_object_get_prototype_of(njs_vm_t *vm
     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, n
 
 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
 
 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_obje
 
     /* 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_cons
 
 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 
 
 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
 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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_object.h
--- a/njs/njs_object.h	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_object.h	Fri Apr 20 16:42:10 2018 +0300
@@ -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_
 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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_regexp.c
--- a/njs/njs_regexp.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_regexp.c	Fri Apr 20 16:42:10 2018 +0300
@@ -464,7 +464,7 @@ njs_regexp_alloc(njs_vm_t *vm, njs_regex
 
 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
 
 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
 
 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_
 
 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 
 
 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_rege
 
     /* 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_cons
 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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_string.c
--- a/njs/njs_string.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_string.c	Fri Apr 20 16:42:10 2018 +0300
@@ -570,9 +570,9 @@ static const njs_object_prop_t  njs_stri
 
     /* 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_cons
 
 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
 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 -r 28d75187de15 -r a65deb4c2e03 njs/njs_vm.c
--- a/njs/njs_vm.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_vm.c	Fri Apr 20 16:42:10 2018 +0300
@@ -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_quer
     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, nj
 
     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, 
 
     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, 
             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;
@@ -1220,6 +1241,33 @@ njs_object_property_query(njs_vm_t *vm, 
 
 
 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)
 {
     njs_function_t     *function;
diff -r 28d75187de15 -r a65deb4c2e03 njs/njs_vm.h
--- a/njs/njs_vm.h	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/njs_vm.h	Fri Apr 20 16:42:10 2018 +0300
@@ -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 -r 28d75187de15 -r a65deb4c2e03 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Fri Apr 20 16:42:10 2018 +0300
+++ b/njs/test/njs_unit_test.c	Fri Apr 20 16:42:10 2018 +0300
@@ -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") },
 


More information about the nginx-devel mailing list