]> git.kaiwu.me - njs.git/commitdiff
Making native getters into universal property handlers.
authorDmitry Volyntsev <xeioex@nginx.com>
Fri, 20 Apr 2018 13:42:10 +0000 (16:42 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Fri, 20 Apr 2018 13:42:10 +0000 (16:42 +0300)
16 files changed:
njs/njs_array.c
njs/njs_boolean.c
njs/njs_builtin.c
njs/njs_date.c
njs/njs_error.c
njs/njs_function.c
njs/njs_function.h
njs/njs_math.c
njs/njs_number.c
njs/njs_object.c
njs/njs_object.h
njs/njs_regexp.c
njs/njs_string.c
njs/njs_vm.c
njs/njs_vm.h
njs/test/njs_unit_test.c

index 800fbb82e864d08563b27f9b1b86c66ed00c2944..c562ffc401975ee489746d167c423946928d0ed9 100644 (file)
@@ -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),
     },
 
     {
index 275d526f80bc2ae7cc6d80fc1d5a4896a929715e..745dd4a3da8e24848fc02b02a6487f09e26ab11c 100644 (file)
@@ -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),
     },
 
     {
index 1e1b668a5100fb3a0773aa07b9c1f4902054ae6e..eab304e224b93702b2a52127134127d424d71fb5 100644 (file)
@@ -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,
index b8bc0fe744f56b07c960f0052be58bb2c8c131b5..7977e097c891faf2ca6b5cdbbb463e1ab0eb8567 100644 (file)
@@ -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),
     },
 
     {
index 441ab3e2833a2cc3220380cbf1b06833c9e20597..a0f3044933a0e181a30527387a9b0e32332330b4 100644 (file)
@@ -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),
     },
 };
 
index d35c4bca5a76ba6506917e7d9bd0d72ebcd0178a..d3b55794c5eb1013d5cf8d316c7dd068161d43f2 100644 (file)
@@ -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),
     },
 };
 
index 13619289cf7b91110472be9ffd32405b9df1ff2e..f7e8481c98a1cc691fcf33de87a21bede0fa8d5f 100644 (file)
@@ -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,
index 108ac029dca8019530013ef59402d812cb4c53f8..e2e98396abe481308723cb1b1dc1c2aa14c9f2b6 100644 (file)
@@ -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),
     },
 
     {
index 99abd2d66f35a3380acd874efdb508d47134419e..e75967fa32e03b5635cbdc6360b5a07ea12bcb28 100644 (file)
@@ -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),
     },
 
     {
index 013424ee29f9b67a48e2a49dc009c356f4ef0a52..2ad5d09f0a9746fb51889e499ffd2c10af0162a9 100644 (file)
@@ -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),
     },
 
     {
index a0094a5b499decf84856d37d8ec4b02b28066bb0..26453eb60a62818c28e418110ef12718eb3d2448 100644 (file)
@@ -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,
index 2329542e33f67f390c9b5e5145ff63c0a5d622ae..9b298f18b6b923291017293c9289ca3ba571130a 100644 (file)
@@ -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),
     },
 
     {
index 504f47e500501646310de64b3f6f230f4120e021..ec8f9ab79b5562f1a4bb7e1dd172e9aae2420c64 100644 (file)
@@ -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),
     },
 
     {
index 14f0e00f47995fac8a5d8f506d9d155c36caeffb..6f29067b0db7a513cbf6360fb5e1aeb0ed29f4c2 100644 (file)
@@ -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)
 {
index c182ddd7fe2418f066d3f48c28bb748e202e8063..a139f48c0ac28bf84051f62a5726c8266e4f6033 100644 (file)
@@ -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 }                                     \
     }                                                                         \
 }
 
index 6478ea2ec03719b228d2ea5bdf020128f675a116..ec84c9d4ba5d7e9ec81c75adfc64d0a0e4165626 100644 (file)
@@ -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") },