]> git.kaiwu.me - njs.git/commitdiff
Initializing closure values of a function.
authorDmitry Volyntsev <xeioex@nginx.com>
Tue, 6 Nov 2018 17:57:53 +0000 (20:57 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Tue, 6 Nov 2018 17:57:53 +0000 (20:57 +0300)
This fixes #55 issue on Github.

njs/njs_function.c
njs/njs_function.h
njs/njs_generator.c
njs/test/njs_unit_test.c

index f98680a98232f5f98fd92a1b2c0f60c0297094fa..b9fcd64bfc9b219ed468b3e55c9193962a0e53bb 100644 (file)
@@ -399,7 +399,7 @@ njs_function_call(njs_vm_t *vm, njs_index_t retval, size_t advance)
     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_index_t retval, size_t advance)
                 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);
         }
index 4c59b73dac72fb1befc6fddd652c842242966768..e6b35e31f9f25450c97db8922d5165ec63af045f 100644 (file)
@@ -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;
index 6094b4870982fe1c400b960d538f6be24efd8832..1ee7072ad1bfb9947c5f73d4a969b52b19dbbcd5 100644 (file)
@@ -2047,11 +2047,13 @@ njs_generate_function_scope(njs_vm_t *vm, njs_function_lambda_t *lambda,
 
         if (closure != NULL) {
             lambda->block_closures = 1;
+            lambda->closure_scope = closure->start;
             size = (1 + closure->items) * sizeof(njs_value_t);
         }
 
-        lambda->nesting = node->scope->nesting;
         lambda->closure_size = size;
+
+        lambda->nesting = node->scope->nesting;
         lambda->arguments_object = parser->arguments_object;
 
         lambda->local_size = parser->scope_size;
index d2269083aedd2715264aba0f89b298c09c6d5018..d605a67b2be2070b6779f709cf8f5d69cf7fb5b5 100644 (file)
@@ -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) {"