[njs] Added support for Object.prototype.valueOf() in Buffer.from().

Alexander Borisov alexander.borisov at nginx.com
Tue Oct 20 11:01:15 UTC 2020


details:   https://hg.nginx.org/njs/rev/c262ed3c7df0
branches:  
changeset: 1541:c262ed3c7df0
user:      Alexander Borisov <alexander.borisov at nginx.com>
date:      Tue Oct 20 14:00:40 2020 +0300
description:
Added support for Object.prototype.valueOf() in Buffer.from().

Missed in 27bb9caf186c.

diffstat:

 src/njs_buffer.c         |  17 ++++++++++++++++-
 src/njs_value.c          |  27 +++++++++++++++++++++++++++
 src/njs_value.h          |   1 +
 src/test/njs_unit_test.c |  23 +++++++++++++++++++++++
 4 files changed, 67 insertions(+), 1 deletions(-)

diffs (119 lines):

diff -r 4106bf95d343 -r c262ed3c7df0 src/njs_buffer.c
--- a/src/njs_buffer.c	Mon Oct 19 15:51:37 2020 +0300
+++ b/src/njs_buffer.c	Tue Oct 20 14:00:40 2020 +0300
@@ -228,11 +228,13 @@ njs_buffer_from(njs_vm_t *vm, njs_value_
     njs_index_t unused)
 {
     njs_int_t                    ret;
-    njs_value_t                  *value;
+    njs_value_t                  *value, retval;
     const njs_buffer_encoding_t  *encoding;
 
     value = njs_arg(args, nargs, 1);
 
+next:
+
     switch (value->type) {
     case NJS_TYPED_ARRAY:
         return njs_buffer_from_typed_array(vm, value);
@@ -251,6 +253,19 @@ njs_buffer_from(njs_vm_t *vm, njs_value_
 
     default:
         if (njs_is_object(value)) {
+            ret = njs_value_of(vm, value, &retval);
+            if (njs_slow_path(ret == NJS_ERROR)) {
+                return ret;
+            }
+
+            if (ret == NJS_OK && !njs_is_null(&retval)
+                && !(njs_is_object(&retval)
+                     && njs_object(&retval) == njs_object(value)))
+            {
+                *value = retval;
+                goto next;
+            }
+
             ret = njs_buffer_from_object(vm, value);
             if (njs_slow_path(ret != NJS_DECLINED)) {
                 return ret;
diff -r 4106bf95d343 -r c262ed3c7df0 src/njs_value.c
--- a/src/njs_value.c	Mon Oct 19 15:51:37 2020 +0300
+++ b/src/njs_value.c	Tue Oct 20 14:00:40 2020 +0300
@@ -262,6 +262,33 @@ njs_value_own_enumerate(njs_vm_t *vm, nj
 
 
 njs_int_t
+njs_value_of(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval)
+{
+
+    njs_int_t  ret;
+
+    static const njs_value_t  value_of = njs_string("valueOf");
+
+    if (njs_slow_path(!njs_is_object(value))) {
+        return NJS_DECLINED;
+    }
+
+    ret = njs_value_property(vm, value, njs_value_arg(&value_of),
+                             retval);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return ret;
+    }
+
+    if (!njs_is_function(retval)) {
+        njs_type_error(vm, "object.valueOf is not a function");
+        return NJS_ERROR;
+    }
+
+    return njs_function_apply(vm, njs_function(retval), value, 1, retval);
+}
+
+
+njs_int_t
 njs_value_length(njs_vm_t *vm, njs_value_t *value, int64_t *length)
 {
     njs_string_prop_t  string_prop;
diff -r 4106bf95d343 -r c262ed3c7df0 src/njs_value.h
--- a/src/njs_value.h	Mon Oct 19 15:51:37 2020 +0300
+++ b/src/njs_value.h	Tue Oct 20 14:00:40 2020 +0300
@@ -1053,6 +1053,7 @@ njs_array_t *njs_value_enumerate(njs_vm_
     njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all);
 njs_array_t *njs_value_own_enumerate(njs_vm_t *vm, njs_value_t *value,
     njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all);
+njs_int_t njs_value_of(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval);
 njs_int_t njs_value_length(njs_vm_t *vm, njs_value_t *value, int64_t *dst);
 const char *njs_type_string(njs_value_type_t type);
 
diff -r 4106bf95d343 -r c262ed3c7df0 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Mon Oct 19 15:51:37 2020 +0300
+++ b/src/test/njs_unit_test.c	Tue Oct 20 14:00:40 2020 +0300
@@ -18580,6 +18580,29 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("var buf = Buffer.from('α'); njs.dump(buf)"),
       njs_str("Buffer [206,177]") },
 
+    { njs_str("var arr = new Array(1,2,3); arr.valueOf = () => arr;"
+              "njs.dump(Buffer.from(arr))"),
+      njs_str("Buffer [1,2,3]") },
+
+    { njs_str("var obj = new Object(); obj.valueOf = () => obj;"
+              "Buffer.from(obj)"),
+      njs_str("TypeError: first argument object is not a string or Buffer-like object") },
+
+    { njs_str("var obj = new Object(); obj.valueOf = () => undefined;"
+              "njs.dump(Buffer.from(obj))"),
+      njs_str("TypeError: first argument undefined is not a string or Buffer-like object") },
+
+    { njs_str("var arr = new Array(1,2,3); arr.valueOf = () => null;"
+              "njs.dump(Buffer.from(arr))"),
+      njs_str("Buffer [1,2,3]") },
+
+    { njs_str("var obj = new Object(); obj.valueOf = () => new Array(1,2,3);"
+              "njs.dump(Buffer.from(obj))"),
+      njs_str("Buffer [1,2,3]") },
+
+    { njs_str("njs.dump(Buffer.from(new String('test')))"),
+      njs_str("Buffer [116,101,115,116]") },
+
     { njs_str("["
              " ['6576696c', 'hex'],"
              " ['ZXZpbA==', 'base64'],"


More information about the nginx-devel mailing list