[njs] Initializing closure values of a function.

Dmitry Volyntsev xeioex at nginx.com
Tue Nov 6 17:58:14 UTC 2018


details:   http://hg.nginx.org/njs/rev/0372810c0d98
branches:  
changeset: 639:0372810c0d98
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Tue Nov 06 20:57:53 2018 +0300
description:
Initializing closure values of a function.

This fixes #55 issue on Github.

diffstat:

 njs/njs_function.c       |  10 +++++-----
 njs/njs_function.h       |   1 +
 njs/njs_generator.c      |   4 +++-
 njs/test/njs_unit_test.c |  40 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 49 insertions(+), 6 deletions(-)

diffs (110 lines):

diff -r 5766e459c203 -r 0372810c0d98 njs/njs_function.c
--- a/njs/njs_function.c	Tue Nov 06 20:57:52 2018 +0300
+++ b/njs/njs_function.c	Tue Nov 06 20:57:53 2018 +0300
@@ -399,7 +399,7 @@ njs_function_call(njs_vm_t *vm, njs_inde
     njs_ret_t              ret;
     nxt_uint_t             n, nesting;
     njs_frame_t            *frame;
-    njs_value_t            *value;
+    njs_value_t            *dst, *src;
     njs_closure_t          *closure, **closures;
     njs_function_t         *function;
     njs_function_lambda_t  *lambda;
@@ -459,14 +459,14 @@ njs_function_call(njs_vm_t *vm, njs_inde
                 return NXT_ERROR;
             }
 
-            /* TODO: copy initialzed values. */
-
             size -= sizeof(njs_value_t);
             closure->u.count = 0;
-            value = closure->values;
+            dst = closure->values;
+
+            src = lambda->closure_scope;
 
             do {
-                *value++ = njs_value_void;
+                *dst++ = *src++;
                 size -= sizeof(njs_value_t);
             } while (size != 0);
         }
diff -r 5766e459c203 -r 0372810c0d98 njs/njs_function.h
--- a/njs/njs_function.h	Tue Nov 06 20:57:52 2018 +0300
+++ b/njs/njs_function.h	Tue Nov 06 20:57:53 2018 +0300
@@ -34,6 +34,7 @@ struct njs_function_lambda_s {
 
     /* Initial values of local scope. */
     njs_value_t                    *local_scope;
+    njs_value_t                    *closure_scope;
 
     union {
         u_char                     *start;
diff -r 5766e459c203 -r 0372810c0d98 njs/njs_generator.c
--- a/njs/njs_generator.c	Tue Nov 06 20:57:52 2018 +0300
+++ b/njs/njs_generator.c	Tue Nov 06 20:57:53 2018 +0300
@@ -2047,11 +2047,13 @@ njs_generate_function_scope(njs_vm_t *vm
 
         if (closure != NULL) {
             lambda->block_closures = 1;
+            lambda->closure_scope = closure->start;
             size = (1 + closure->items) * sizeof(njs_value_t);
         }
 
+        lambda->closure_size = size;
+
         lambda->nesting = node->scope->nesting;
-        lambda->closure_size = size;
         lambda->arguments_object = parser->arguments_object;
 
         lambda->local_size = parser->scope_size;
diff -r 5766e459c203 -r 0372810c0d98 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Tue Nov 06 20:57:52 2018 +0300
+++ b/njs/test/njs_unit_test.c	Tue Nov 06 20:57:53 2018 +0300
@@ -5287,6 +5287,46 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("function f() { var a = f2(); }"),
       nxt_string("ReferenceError: \"f2\" is not defined in 1") },
 
+    { nxt_string("(function(){ function f() {return f}; return f()})()"),
+      nxt_string("[object Function]") },
+
+    { nxt_string("var a = ''; "
+                 "function f(list) {"
+                 "    function add(v) {a+=v};"
+                 "    list.forEach(function(v) {add(v)});"
+                 "};"
+                 "f(['a', 'b', 'c']); a"),
+      nxt_string("abc") },
+
+    { nxt_string("var l = [];"
+                 "var f = function() { "
+                 "    function f2() { l.push(f); l.push(f2); }; "
+                 "    l.push(f); l.push(f2); "
+                 "    f2(); "
+                 "}; "
+                 "f(); "
+                 "l.every(function(v) {return typeof v == 'function'})"),
+      nxt_string("true") },
+
+    { nxt_string("var l = [];"
+                 "function baz() {"
+                 "  function foo(v) {"
+                 "     function bar() { foo(0); }"
+                 "     l.push(v);"
+                 "     if (v === 1) { bar(); }"
+                 "  }"
+                 "  foo(1);"
+                 "}; baz(); l"),
+      nxt_string("1,0") },
+
+    { nxt_string("var gen = (function(){  "
+                 "           var s = 0; "
+                 "           return { inc: function() {s++}, "
+                 "                    s: function() {return s} };});"
+                 "var o1 = gen(); var o2 = gen();"
+                 "[o1.s(),o2.s(),o1.inc(),o1.s(),o2.s(),o2.inc(),o1.s(),o2.s()]"),
+      nxt_string("0,0,,1,0,,1,1") },
+
     /* Recursive fibonacci. */
 
     { nxt_string("function fibo(n) {"


More information about the nginx-devel mailing list