[njs] Fixed special getters for objects created using Object.create().

Dmitry Volyntsev xeioex at nginx.com
Thu Apr 25 12:19:45 UTC 2019


details:   https://hg.nginx.org/njs/rev/f5bdddca3252
branches:  
changeset: 926:f5bdddca3252
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Apr 25 15:19:37 2019 +0300
description:
Fixed special getters for objects created using Object.create().

This closes #124 issue on Github.

diffstat:

 njs/njs_array.c          |  15 +++++++++++++--
 njs/njs_function.c       |  13 ++++++++++++-
 njs/njs_object.c         |   1 -
 njs/njs_string.c         |  23 +++++++++++++++++++----
 njs/test/njs_unit_test.c |  12 ++++++++++++
 5 files changed, 56 insertions(+), 8 deletions(-)

diffs (124 lines):

diff -r e104c8c583c2 -r f5bdddca3252 njs/njs_array.c
--- a/njs/njs_array.c	Thu Apr 25 15:19:36 2019 +0300
+++ b/njs/njs_array.c	Thu Apr 25 15:19:37 2019 +0300
@@ -420,8 +420,19 @@ njs_array_length(njs_vm_t *vm, njs_value
     njs_ret_t    ret;
     njs_value_t  *val;
     njs_array_t  *array;
-
-    array = value->data.u.array;
+    njs_object_t *proto;
+
+    proto = value->data.u.object;
+
+    do {
+        if (nxt_fast_path(proto->type == NJS_ARRAY)) {
+            break;
+        }
+
+        proto = proto->__proto__;
+    } while (proto != NULL);
+
+    array = (njs_array_t *) proto;
 
     if (setval != NULL) {
         if (!njs_is_number(setval)) {
diff -r e104c8c583c2 -r f5bdddca3252 njs/njs_function.c
--- a/njs/njs_function.c	Thu Apr 25 15:19:36 2019 +0300
+++ b/njs/njs_function.c	Thu Apr 25 15:19:37 2019 +0300
@@ -894,10 +894,21 @@ njs_function_instance_length(njs_vm_t *v
     njs_value_t *setval, njs_value_t *retval)
 {
     nxt_uint_t             n;
+    njs_object_t           *proto;
     njs_function_t         *function;
     njs_function_lambda_t  *lambda;
 
-    function = value->data.u.function;
+    proto = value->data.u.object;
+
+    do {
+        if (nxt_fast_path(proto->type == NJS_FUNCTION)) {
+            break;
+        }
+
+        proto = proto->__proto__;
+    } while (proto != NULL);
+
+    function = (njs_function_t *) proto;
 
     if (function->native) {
         for (n = function->args_offset; n < NJS_ARGS_TYPES_MAX; n++) {
diff -r e104c8c583c2 -r f5bdddca3252 njs/njs_object.c
--- a/njs/njs_object.c	Thu Apr 25 15:19:36 2019 +0300
+++ b/njs/njs_object.c	Thu Apr 25 15:19:37 2019 +0300
@@ -283,7 +283,6 @@ njs_object_property(njs_vm_t *vm, const 
  *   NXT_ERROR            exception has been thrown.
  *
  *   TODO:
- *     Object.create([1,2]).length
  *     Object.defineProperty([1,2], '1', {configurable:false})
  */
 
diff -r e104c8c583c2 -r f5bdddca3252 njs/njs_string.c
--- a/njs/njs_string.c	Thu Apr 25 15:19:36 2019 +0300
+++ b/njs/njs_string.c	Thu Apr 25 15:19:37 2019 +0300
@@ -626,8 +626,10 @@ static njs_ret_t
 njs_string_instance_length(njs_vm_t *vm, njs_value_t *value,
     njs_value_t *setval, njs_value_t *retval)
 {
-    size_t     size;
-    uintptr_t  length;
+    size_t              size;
+    uintptr_t           length;
+    njs_object_t        *proto;
+    njs_object_value_t  *ov;
 
     /*
      * This getter can be called for string primitive, String object,
@@ -635,8 +637,21 @@ njs_string_instance_length(njs_vm_t *vm,
      */
     length = 0;
 
-    if (value->type == NJS_OBJECT_STRING) {
-        value = &value->data.u.object_value->value;
+    if (nxt_slow_path(njs_is_object(value))) {
+        proto = value->data.u.object;
+
+        do {
+            if (nxt_fast_path(proto->type == NJS_OBJECT_STRING)) {
+                break;
+            }
+
+            proto = proto->__proto__;
+        } while (proto != NULL);
+
+        if (proto != NULL) {
+            ov = (njs_object_value_t *) proto;
+            value = &ov->value;
+        }
     }
 
     if (njs_is_string(value)) {
diff -r e104c8c583c2 -r f5bdddca3252 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Thu Apr 25 15:19:36 2019 +0300
+++ b/njs/test/njs_unit_test.c	Thu Apr 25 15:19:37 2019 +0300
@@ -9110,6 +9110,18 @@ static njs_unit_test_t  njs_test[] =
                  "1..isPrototypeOf(p)"),
       nxt_string("false") },
 
+    { nxt_string("Object.create(new String('asdf')).length"),
+      nxt_string("4") },
+
+    { nxt_string("Object.create(Object('123')).length"),
+      nxt_string("3") },
+
+    { nxt_string("Object.create([1,2]).length"),
+      nxt_string("2") },
+
+    { nxt_string("Object.create(function(a,b,c){}).length"),
+      nxt_string("3") },
+
     { nxt_string("Object.getOwnPropertyDescriptor({a:1}, 'a').value"),
       nxt_string("1") },
 


More information about the nginx-devel mailing list