[njs] A function stored in array could not be called.

Igor Sysoev igor at sysoev.ru
Mon Sep 26 15:42:56 UTC 2016


details:   http://hg.nginx.org/njs/rev/cfa17c3e25da
branches:  
changeset: 184:cfa17c3e25da
user:      Igor Sysoev <igor at sysoev.ru>
date:      Mon Sep 26 18:41:57 2016 +0300
description:
A function stored in array could not be called.

diffstat:

 njs/njs_vm.c             |  116 ++++++++++++++++++++++++++--------------------
 njs/test/njs_unit_test.c |    3 +
 2 files changed, 68 insertions(+), 51 deletions(-)

diffs (167 lines):

diff -r fec0d8dfa38c -r cfa17c3e25da njs/njs_vm.c
--- a/njs/njs_vm.c	Mon Sep 26 14:01:45 2016 +0300
+++ b/njs/njs_vm.c	Mon Sep 26 18:41:57 2016 +0300
@@ -83,6 +83,8 @@ static nxt_noinline njs_ret_t njs_values
 static nxt_noinline njs_ret_t njs_values_compare(njs_value_t *val1,
     njs_value_t *val2);
 static njs_object_t *njs_function_new_object(njs_vm_t *vm, njs_value_t *value);
+static njs_ret_t njs_vmcode_method_call(njs_vm_t *vm, njs_value_t *object,
+    njs_value_t *value);
 static njs_ret_t njs_vmcode_continuation(njs_vm_t *vm, njs_value_t *invld1,
     njs_value_t *invld2);
 static njs_native_frame_t *
@@ -2231,9 +2233,8 @@ njs_ret_t
 njs_vmcode_method_frame(njs_vm_t *vm, njs_value_t *object, njs_value_t *name)
 {
     njs_ret_t                  ret;
-    njs_value_t                this;
+    njs_value_t                this, *value;
     njs_extern_t               *ext;
-    njs_function_t             *function;
     njs_object_prop_t          *prop;
     njs_property_query_t       pq;
     njs_vmcode_method_frame_t  *method;
@@ -2246,13 +2247,35 @@ njs_vmcode_method_frame(njs_vm_t *vm, nj
         prop = pq.lhq.value;
 
         if (njs_is_function(&prop->value)) {
-
+            return njs_vmcode_method_call(vm, object, &prop->value);
+        }
+
+        break;
+
+    case NJS_ARRAY_VALUE:
+        value = pq.lhq.value;
+
+        if (njs_is_function(value)) {
+            return njs_vmcode_method_call(vm, object, value);
+        }
+
+        break;
+
+    case NJS_EXTERNAL_VALUE:
+        ext = object->data.u.external;
+
+        ret = nxt_lvlhsh_find(&ext->hash, &pq.lhq);
+
+        if (ret == NXT_OK) {
             method = (njs_vmcode_method_frame_t *) vm->current;
-            function = prop->value.data.u.function;
-
-            if (!function->native) {
-                ret = njs_function_frame(vm, function, object, NULL,
-                                         method->nargs, method->code.ctor);
+            ext = pq.lhq.value;
+
+            if (ext->type == NJS_EXTERN_METHOD) {
+                this.data.u.data = vm->external[ext->object];
+
+                ret = njs_function_native_frame(vm, ext->function, &this, NULL,
+                                                method->nargs, 0,
+                                                method->code.ctor);
 
                 if (nxt_fast_path(ret == NXT_OK)) {
                     return sizeof(njs_vmcode_method_frame_t);
@@ -2260,54 +2283,45 @@ njs_vmcode_method_frame(njs_vm_t *vm, nj
 
                 return ret;
             }
-
-            ret = njs_function_native_frame(vm, function, object, NULL,
-                                            method->nargs, 0,
-                                            method->code.ctor);
-
-            if (nxt_fast_path(ret == NXT_OK)) {
-                njs_retain(object);
-                return sizeof(njs_vmcode_method_frame_t);
-            }
-
-            return ret;
         }
-
-        break;
-
-    case NJS_EXTERNAL_VALUE:
-        ext = object->data.u.external;
-
-        ret = nxt_lvlhsh_find(&ext->hash, &pq.lhq);
-
-        if (ret == NXT_OK) {
-            method = (njs_vmcode_method_frame_t *) vm->current;
-            ext = pq.lhq.value;
-
-            if (ext->type == NJS_EXTERN_METHOD) {
-                this.data.u.data = vm->external[ext->object];
-
-                ret = njs_function_native_frame(vm, ext->function, &this, NULL,
-                                                method->nargs, 0,
-                                                method->code.ctor);
-
-                if (nxt_fast_path(ret == NXT_OK)) {
-                    return sizeof(njs_vmcode_method_frame_t);
-                }
-
-                return ret;
-            }
+    }
+
+    vm->exception = &njs_exception_type_error;
+
+    return NXT_ERROR;
+}
+
+
+static njs_ret_t
+njs_vmcode_method_call(njs_vm_t *vm, njs_value_t *object, njs_value_t *value)
+{
+    njs_ret_t                  ret;
+    njs_function_t             *function;
+    njs_vmcode_method_frame_t  *method;
+
+    method = (njs_vmcode_method_frame_t *) vm->current;
+    function = value->data.u.function;
+
+    if (!function->native) {
+        ret = njs_function_frame(vm, function, object, NULL, method->nargs,
+                                 method->code.ctor);
+
+        if (nxt_fast_path(ret == NXT_OK)) {
+            return sizeof(njs_vmcode_method_frame_t);
         }
 
-        break;
-
-    default:
-        break;
+        return ret;
     }
 
-    vm->exception = &njs_exception_type_error;
-
-    return NXT_ERROR;
+    ret = njs_function_native_frame(vm, function, object, NULL, method->nargs,
+                                    0, method->code.ctor);
+
+    if (nxt_fast_path(ret == NXT_OK)) {
+        njs_retain(object);
+        return sizeof(njs_vmcode_method_frame_t);
+    }
+
+    return ret;
 }
 
 
diff -r fec0d8dfa38c -r cfa17c3e25da njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Mon Sep 26 14:01:45 2016 +0300
+++ b/njs/test/njs_unit_test.c	Mon Sep 26 18:41:57 2016 +0300
@@ -2092,6 +2092,9 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("a = [1, 2]; delete a[0]; 0 in a"),
       nxt_string("false") },
 
+    { nxt_string("var a = [ function(a) {return a + 1} ]; a[0](5)"),
+      nxt_string("6") },
+
     { nxt_string("var s = '', a = [5,1,2];"
                  "a[null] = null;"
                  "a[undefined] = 'defined';"



More information about the nginx-devel mailing list