From: Dmitry Volyntsev Date: Tue, 6 Nov 2018 17:57:53 +0000 (+0300) Subject: Initializing closure values of a function. X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=fce8389ae1d35a11b54f82fdba3c53a0fd0edba9;p=njs.git Initializing closure values of a function. This fixes #55 issue on Github. --- diff --git a/njs/njs_function.c b/njs/njs_function.c index f98680a9..b9fcd64b 100644 --- a/njs/njs_function.c +++ b/njs/njs_function.c @@ -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); } diff --git a/njs/njs_function.h b/njs/njs_function.h index 4c59b73d..e6b35e31 100644 --- a/njs/njs_function.h +++ b/njs/njs_function.h @@ -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 --git a/njs/njs_generator.c b/njs/njs_generator.c index 6094b487..1ee7072a 100644 --- a/njs/njs_generator.c +++ b/njs/njs_generator.c @@ -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; diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index d2269083..d605a67b 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -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) {"