[njs] Fixed Function.prototype.bind().

Dmitry Volyntsev xeioex at nginx.com
Sat Apr 6 17:51:06 UTC 2019


details:   https://hg.nginx.org/njs/rev/84cb61f23b7e
branches:  
changeset: 873:84cb61f23b7e
user:      hongzhidao <hongzhidao at gmail.com>
date:      Sun Apr 07 00:09:09 2019 +0800
description:
Fixed Function.prototype.bind().

Making a correct copy of a function.

diffstat:

 njs/njs_function.c       |  33 ++++++++++++++++++++++-----------
 njs/test/njs_unit_test.c |  10 ++++++++++
 2 files changed, 32 insertions(+), 11 deletions(-)

diffs (96 lines):

diff -r 7dba758fda64 -r 84cb61f23b7e njs/njs_function.c
--- a/njs/njs_function.c	Fri Apr 05 17:49:22 2019 +0300
+++ b/njs/njs_function.c	Sun Apr 07 00:09:09 2019 +0800
@@ -8,6 +8,8 @@
 #include <string.h>
 
 
+static njs_function_t *njs_function_copy(njs_vm_t *vm,
+    const njs_function_t *function);
 static njs_native_frame_t *njs_function_frame_alloc(njs_vm_t *vm, size_t size);
 static njs_ret_t njs_normalize_args(njs_vm_t *vm, njs_value_t *args,
     uint8_t *args_types, nxt_uint_t nargs);
@@ -71,8 +73,6 @@ fail:
 njs_function_t *
 njs_function_value_copy(njs_vm_t *vm, njs_value_t *value)
 {
-    size_t          size;
-    nxt_uint_t      n, nesting;
     njs_function_t  *function, *copy;
 
     function = value->data.u.function;
@@ -81,6 +81,25 @@ njs_function_value_copy(njs_vm_t *vm, nj
         return function;
     }
 
+    copy = njs_function_copy(vm, function);
+    if (nxt_slow_path(copy == NULL)) {
+        njs_memory_error(vm);
+        return NULL;
+    }
+
+    value->data.u.function = copy;
+
+    return copy;
+}
+
+
+static njs_function_t *
+njs_function_copy(njs_vm_t *vm, const njs_function_t *function)
+{
+    size_t          size;
+    nxt_uint_t      n, nesting;
+    njs_function_t  *copy;
+
     nesting = (function->native) ? 0 : function->u.lambda->nesting;
 
     size = sizeof(njs_function_t) + nesting * sizeof(njs_closure_t *);
@@ -91,8 +110,6 @@ njs_function_value_copy(njs_vm_t *vm, nj
         return NULL;
     }
 
-    value->data.u.function = copy;
-
     *copy = *function;
     copy->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object;
     copy->object.shared = 0;
@@ -1050,18 +1067,12 @@ njs_function_prototype_bind(njs_vm_t *vm
         return NXT_ERROR;
     }
 
-    function = nxt_mp_alloc(vm->mem_pool, sizeof(njs_function_t));
+    function = njs_function_copy(vm, args[0].data.u.function);
     if (nxt_slow_path(function == NULL)) {
         njs_memory_error(vm);
         return NXT_ERROR;
     }
 
-    *function = *args[0].data.u.function;
-
-    function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object;
-    function->object.shared = 0;
-    function->object.extensible = 1;
-
     if (nargs == 1) {
         args = (njs_value_t *) &njs_value_undefined;
 
diff -r 7dba758fda64 -r 84cb61f23b7e njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Fri Apr 05 17:49:22 2019 +0300
+++ b/njs/test/njs_unit_test.c	Sun Apr 07 00:09:09 2019 +0800
@@ -6356,6 +6356,16 @@ static njs_unit_test_t  njs_test[] =
                  "var b = f.bind('1', '2', '3'); b.apply()"),
       nxt_string("123") },
 
+    { nxt_string("function f() { var a; return (function() { a = 1; return a; }).bind()() } f()"),
+      nxt_string("1") },
+
+    { nxt_string("function f() { var a; function baz() { a = 1; return a; } return baz.bind()(); } f()"),
+      nxt_string("1") },
+
+    { nxt_string("function f(a, b) { return a + b }"
+                 "f(3,4) === f.bind()(3,4)"),
+      nxt_string("true") },
+
     { nxt_string("var obj = {prop:'abc'}; "
                  "var func = function(x) { "
                  "    return this === obj && x === 1 && arguments[0] === 1 "


More information about the nginx-devel mailing list