[njs] Refactored working with function calls.

Dmitry Volyntsev xeioex at nginx.com
Fri Jul 19 20:28:16 UTC 2019


details:   https://hg.nginx.org/njs/rev/540f03725df2
branches:  
changeset: 1061:540f03725df2
user:      hongzhidao <hongzhidao at gmail.com>
date:      Tue Jul 16 22:44:16 2019 -0400
description:
Refactored working with function calls.

    1) njs_continuation_t is removed (appropriate functions
       are rewritten).
    2) all function calls are made syncronous.

    This closes #190 issue on Github.

diffstat:

 njs/njs.c                 |    24 +-
 njs/njs_array.c           |  1303 +++++++++++++++-----------------------------
 njs/njs_boolean.c         |     4 +-
 njs/njs_builtin.c         |     2 +-
 njs/njs_crypto.c          |    16 +-
 njs/njs_date.c            |   158 ++--
 njs/njs_error.c           |     7 +-
 njs/njs_fs.c              |    66 +-
 njs/njs_function.c        |   232 ++-----
 njs/njs_function.h        |    75 +-
 njs/njs_json.c            |   173 +++--
 njs/njs_math.c            |   126 ++--
 njs/njs_number.c          |    20 +-
 njs/njs_object.c          |    42 +-
 njs/njs_object.h          |     4 +-
 njs/njs_object_property.c |    18 +-
 njs/njs_regexp.c          |    10 +-
 njs/njs_string.c          |   133 +--
 njs/njs_value.c           |     7 +-
 njs/njs_value.h           |     3 +-
 njs/njs_vm.c              |   136 +---
 njs/njs_vm.h              |    11 +-
 njs/test/njs_unit_test.c  |     9 +-
 23 files changed, 986 insertions(+), 1593 deletions(-)

diffs (truncated from 5002 to 1000 lines):

diff -r 201af81dfa9b -r 540f03725df2 njs/njs.c
--- a/njs/njs.c	Fri Jul 05 21:45:28 2019 +0300
+++ b/njs/njs.c	Tue Jul 16 22:44:16 2019 -0400
@@ -456,7 +456,7 @@ nxt_int_t
 njs_vm_call(njs_vm_t *vm, njs_function_t *function, const njs_value_t *args,
     nxt_uint_t nargs)
 {
-    return njs_vm_invoke(vm, function, args, nargs, NJS_INDEX_GLOBAL_RETVAL);
+    return njs_vm_invoke(vm, function, args, nargs, (njs_index_t) &vm->retval);
 }
 
 
@@ -464,30 +464,18 @@ nxt_int_t
 njs_vm_invoke(njs_vm_t *vm, njs_function_t *function, const njs_value_t *args,
     nxt_uint_t nargs, njs_index_t retval)
 {
-    u_char       *current;
     njs_ret_t    ret;
     njs_value_t  *this;
 
     this = (njs_value_t *) &njs_value_undefined;
 
-    current = vm->current;
-
-    vm->current = (u_char *) njs_continuation_nexus;
-
-    ret = njs_function_activate(vm, function, this, args, nargs, retval,
-                                sizeof(njs_vmcode_generic_t));
-
-    if (nxt_fast_path(ret == NJS_APPLIED)) {
-        ret = njs_vmcode_interpreter(vm);
-
-        if (ret == NJS_STOP) {
-            ret = NXT_OK;
-        }
+    ret = njs_function_frame(vm, function, this, (njs_value_t *) args, nargs,
+                             0);
+    if (nxt_slow_path(ret != NXT_OK)) {
+        return ret;
     }
 
-    vm->current = current;
-
-    return ret;
+    return njs_function_frame_invoke(vm, retval);
 }
 
 
diff -r 201af81dfa9b -r 540f03725df2 njs/njs_array.c
--- a/njs/njs_array.c	Fri Jul 05 21:45:28 2019 +0300
+++ b/njs/njs_array.c	Tue Jul 16 22:44:16 2019 -0400
@@ -9,133 +9,9 @@
 #include <stdint.h>
 
 
-typedef struct {
-    union {
-        njs_continuation_t  cont;
-        u_char              padding[NJS_CONTINUATION_SIZE];
-    } u;
-    /*
-     * This retval value must be aligned so the continuation is padded
-     * to aligned size.
-     */
-    njs_value_t             length;
-} njs_array_slice_t;
-
-
-typedef struct {
-    union {
-        njs_continuation_t  cont;
-        u_char              padding[NJS_CONTINUATION_SIZE];
-    } u;
-
-    njs_value_t             length;
-    nxt_int_t               start;
-    nxt_int_t               end;
-} njs_array_fill_t;
-
-
-typedef struct {
-    njs_continuation_t      cont;
-    njs_value_t             *values;
-    uint32_t                max;
-} njs_array_join_t;
-
-
-typedef struct {
-    union {
-        njs_continuation_t  cont;
-        u_char              padding[NJS_CONTINUATION_SIZE];
-    } u;
-    /*
-     * This retval value must be aligned so the continuation is padded
-     * to aligned size.
-     */
-    njs_value_t             retval;
-
-    uint32_t                index;
-    uint32_t                length;
-} njs_array_iter_t;
-
-
-typedef struct {
-    njs_array_iter_t        iter;
-    njs_value_t             value;
-    njs_array_t             *array;
-} njs_array_filter_t;
-
-
-typedef struct {
-    njs_array_iter_t        iter;
-    njs_value_t             value;
-} njs_array_find_t;
-
-
-typedef struct {
-    njs_array_iter_t        iter;
-    njs_array_t             *array;
-} njs_array_map_t;
-
-
-typedef struct {
-    union {
-        njs_continuation_t  cont;
-        u_char              padding[NJS_CONTINUATION_SIZE];
-    } u;
-    /*
-     * This retval value must be aligned so the continuation is padded
-     * to aligned size.
-     */
-    njs_value_t             retval;
-
-    njs_function_t          *function;
-    uint32_t                index;
-    uint32_t                current;
-} njs_array_sort_t;
-
-
-static njs_ret_t njs_array_prototype_slice_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
 static njs_ret_t njs_array_prototype_slice_copy(njs_vm_t *vm,
     njs_value_t *this, int64_t start, int64_t length);
-static njs_ret_t njs_array_prototype_join_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
 static njs_value_t *njs_array_copy(njs_value_t *dst, njs_value_t *src);
-static njs_ret_t njs_array_prototype_fill_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
-static njs_ret_t njs_array_prototype_fill_object_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
-static njs_ret_t njs_array_prototype_for_each_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
-static njs_ret_t njs_array_prototype_some_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
-static njs_ret_t njs_array_prototype_every_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
-static njs_ret_t njs_array_prototype_filter_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
-static njs_ret_t njs_array_prototype_find_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
-static njs_ret_t njs_array_prototype_find_index_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
-static njs_ret_t njs_array_prototype_map_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
-static uint32_t njs_array_prototype_map_index(njs_array_t *array,
-    njs_array_map_t *map);
-static njs_ret_t njs_array_iterator_args(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs);
-static uint32_t njs_array_iterator_index(njs_array_t *array,
-    njs_array_iter_t *iter);
-static njs_ret_t njs_array_iterator_apply(njs_vm_t *vm,
-    njs_array_iter_t *iter, njs_value_t *args, nxt_uint_t nargs);
-static njs_ret_t njs_array_prototype_find_apply(njs_vm_t *vm,
-    njs_array_iter_t *iter, njs_value_t *args, nxt_uint_t nargs);
-static njs_ret_t njs_array_prototype_reduce_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
-static njs_ret_t njs_array_prototype_reduce_right_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
-static uint32_t njs_array_reduce_right_index(njs_array_t *array,
-    njs_array_iter_t *iter);
-static njs_ret_t njs_array_prototype_sort_continuation(njs_vm_t *vm,
-    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
 
 
 njs_array_t *
@@ -407,7 +283,7 @@ static const njs_object_prop_t  njs_arra
     {
         .type = NJS_METHOD,
         .name = njs_string("isArray"),
-        .value = njs_native_function(njs_array_is_array, 0, 0),
+        .value = njs_native_function(njs_array_is_array, 0),
         .writable = 1,
         .configurable = 1,
     },
@@ -417,7 +293,7 @@ static const njs_object_prop_t  njs_arra
     {
         .type = NJS_METHOD,
         .name = njs_string("of"),
-        .value = njs_native_function(njs_array_of, 0, 0),
+        .value = njs_native_function(njs_array_of, 0),
         .writable = 1,
         .configurable = 1,
     },
@@ -517,44 +393,26 @@ static njs_ret_t
 njs_array_prototype_slice(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
-    njs_ret_t          ret;
-    njs_array_slice_t  *slice;
-
-    static const njs_value_t  njs_string_length = njs_string("length");
-
-    slice = njs_vm_continuation(vm);
-    slice->u.cont.function = njs_array_prototype_slice_continuation;
-
-    ret = njs_value_property(vm, &args[0], &njs_string_length, &slice->length,
-                             0);
-
-    if (nxt_slow_path(ret == NXT_ERROR || ret == NJS_APPLIED)) {
+    int64_t      start, end, length;
+    njs_ret_t    ret;
+    njs_value_t  prop_length;
+
+    static const njs_value_t  string_length = njs_string("length");
+
+    ret = njs_value_property(vm, &args[0], &string_length, &prop_length);
+    if (nxt_slow_path(ret == NXT_ERROR)) {
         return ret;
     }
 
-    return njs_array_prototype_slice_continuation(vm, args, nargs, unused);
-}
-
-
-static njs_ret_t
-njs_array_prototype_slice_continuation(njs_vm_t *vm, njs_value_t *args,
-    nxt_uint_t nargs, njs_index_t unused)
-{
-    int64_t            start, end, length;
-    njs_ret_t          ret;
-    njs_array_slice_t  *slice;
-
-    slice = njs_vm_continuation(vm);
-
-    if (nxt_slow_path(!njs_is_primitive(&slice->length))) {
-        ret = njs_value_to_numeric(vm, &slice->length, &slice->length);
+    if (nxt_slow_path(!njs_is_primitive(&prop_length))) {
+        ret = njs_value_to_numeric(vm, &prop_length, &prop_length);
         if (ret != NXT_OK) {
             return ret;
         }
     }
 
     start = njs_primitive_value_to_integer(njs_arg(args, nargs, 1));
-    length = njs_primitive_value_to_length(&slice->length);
+    length = njs_primitive_value_to_length(&prop_length);
 
     if (start < 0) {
         start += length;
@@ -675,7 +533,7 @@ njs_array_prototype_slice_copy(njs_vm_t 
                 njs_uint32_to_string(&name, start++);
 
                 value = &array->start[n++];
-                ret = njs_value_property(vm, this, &name, value, 0);
+                ret = njs_value_property(vm, this, &name, value);
 
                 if (ret != NXT_OK) {
                     *value = njs_value_invalid;
@@ -970,8 +828,8 @@ njs_array_prototype_to_string(njs_vm_t *
         prop = njs_object_property(vm, njs_object(&args[0]), &lhq);
 
         if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) {
-            return njs_function_call(vm, njs_function(&prop->value), args,
-                                     nargs, (njs_index_t) &vm->retval);
+            return njs_function_apply(vm, njs_function(&prop->value), args,
+                                      nargs, &vm->retval);
         }
     }
 
@@ -983,26 +841,24 @@ static njs_ret_t
 njs_array_prototype_join(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
-    uint32_t          max;
-    nxt_uint_t        i, n;
-    njs_array_t       *array;
-    njs_value_t       *value, *values;
-    njs_array_join_t  *join;
-
-    if (!njs_is_array(&args[0])) {
-        goto empty;
+    u_char             *p;
+    uint32_t           max;
+    size_t             size, length, mask;
+    njs_ret_t          ret;
+    nxt_uint_t         i, n;
+    njs_array_t        *array;
+    njs_value_t        *value, *values;
+    njs_string_prop_t  separator, string;
+
+    if (!njs_is_array(&args[0]) || njs_array_len(&args[0]) == 0) {
+        vm->retval = njs_string_empty;
+        return NXT_OK;
     }
 
     array = njs_array(&args[0]);
 
-    if (array->length == 0) {
-        goto empty;
-    }
-
-    join = njs_vm_continuation(vm);
-    join->values = NULL;
-    join->max = 0;
     max = 0;
+    values = NULL;
 
     for (i = 0; i < array->length; i++) {
         value = &array->start[i];
@@ -1023,11 +879,6 @@ njs_array_prototype_join(njs_vm_t *vm, n
             return NXT_ERROR;
         }
 
-        join = njs_vm_continuation(vm);
-        join->cont.function = njs_array_prototype_join_continuation;
-        join->values = values;
-        join->max = max;
-
         n = 0;
 
         for (i = 0; i < array->length; i++) {
@@ -1046,34 +897,6 @@ njs_array_prototype_join(njs_vm_t *vm, n
         }
     }
 
-    return njs_array_prototype_join_continuation(vm, args, nargs, unused);
-
-empty:
-
-    vm->retval = njs_string_empty;
-
-    return NXT_OK;
-}
-
-
-static njs_ret_t
-njs_array_prototype_join_continuation(njs_vm_t *vm, njs_value_t *args,
-    nxt_uint_t nargs, njs_index_t unused)
-{
-    u_char             *p;
-    size_t             size, length, mask;
-    uint32_t           max;
-    njs_ret_t          ret;
-    nxt_uint_t         i, n;
-    njs_array_t        *array;
-    njs_value_t        *value, *values;
-    njs_array_join_t   *join;
-    njs_string_prop_t  separator, string;
-
-    join = njs_vm_continuation(vm);
-    values = join->values;
-    max = join->max;
-
     size = 0;
     length = 0;
     n = 0;
@@ -1422,11 +1245,14 @@ static njs_ret_t
 njs_array_prototype_fill(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
-    njs_ret_t         ret;
-    njs_value_t       *this;
-    njs_array_fill_t  *fill;
-
-    static const njs_value_t  njs_string_length = njs_string("length");
+    njs_ret_t          ret;
+    nxt_int_t          i, start, end, length;
+    njs_array_t        *array;
+    njs_value_t        name, prop_length;
+    njs_object_t       *object;
+    const njs_value_t  *this, *value;
+
+    static const njs_value_t  string_length = njs_string("length");
 
     this = (njs_value_t *) njs_arg(args, nargs, 0);
 
@@ -1437,38 +1263,6 @@ njs_array_prototype_fill(njs_vm_t *vm, n
             return NJS_ERROR;
         }
 
-    } else if (!njs_is_array(this)) {
-        fill = njs_vm_continuation(vm);
-        fill->u.cont.function = njs_array_prototype_fill_continuation;
-
-        ret = njs_value_property(vm, this, &njs_string_length, &fill->length,
-                                 0);
-
-        if (nxt_slow_path(ret == NXT_ERROR || ret == NJS_APPLIED)) {
-            return ret;
-        }
-    }
-
-    return njs_array_prototype_fill_continuation(vm, args, nargs, unused);
-}
-
-
-static njs_ret_t
-njs_array_prototype_fill_continuation(njs_vm_t *vm, njs_value_t *args,
-    nxt_uint_t nargs, njs_index_t unused)
-{
-    nxt_int_t          i, start, end, length;
-    njs_ret_t          ret;
-    njs_array_t        *array;
-    njs_object_t       *object;
-    njs_array_fill_t   *fill;
-    const njs_value_t  *this, *value;
-
-    array = NULL;
-
-    this = njs_arg(args, nargs, 0);
-
-    if (njs_is_primitive(this)) {
         object = njs_object_value_alloc(vm, this, this->type);
         if (nxt_slow_path(object == NULL)) {
             return NXT_ERROR;
@@ -1479,22 +1273,26 @@ njs_array_prototype_fill_continuation(nj
         return NXT_OK;
     }
 
-    fill = njs_vm_continuation(vm);
+    array = NULL;
 
     if (njs_is_array(this)) {
         array = njs_array(this);
         length = array->length;
 
     } else {
-
-        if (nxt_slow_path(!njs_is_primitive(&fill->length))) {
-            ret = njs_value_to_numeric(vm, &fill->length, &fill->length);
+        ret = njs_value_property(vm, this, &string_length, &prop_length);
+        if (nxt_slow_path(ret == NXT_ERROR)) {
+            return ret;
+        }
+
+        if (nxt_slow_path(!njs_is_primitive(&prop_length))) {
+            ret = njs_value_to_numeric(vm, &prop_length, &prop_length);
             if (ret != NXT_OK) {
                 return ret;
             }
         }
 
-        length = njs_primitive_value_to_length(&fill->length);
+        length = njs_primitive_value_to_length(&prop_length);
     }
 
     start = njs_primitive_value_to_integer(njs_arg(args, nargs, 2));
@@ -1521,81 +1319,79 @@ njs_array_prototype_fill_continuation(nj
         return NXT_OK;
     }
 
-    fill->u.cont.function = njs_array_prototype_fill_object_continuation;
-    fill->start = start;
-    fill->end = end;
-
-    return njs_array_prototype_fill_object_continuation(vm, args, nargs,
-                                                        unused);
-}
-
-
-static njs_ret_t
-njs_array_prototype_fill_object_continuation(njs_vm_t *vm, njs_value_t *args,
-    nxt_uint_t nargs, njs_index_t unused)
-{
-    njs_ret_t          ret;
-    nxt_int_t          end;
-    njs_value_t        name;
-    njs_array_fill_t   *fill;
-    const njs_value_t  *value;
-
-    fill = njs_vm_continuation(vm);
-    end = fill->end;
-
-    vm->retval = *njs_arg(args, nargs, 0);
     value = njs_arg(args, nargs, 1);
 
-    while (fill->start < end) {
-        njs_uint32_to_string(&name, fill->start++);
-
-        ret = njs_value_property_set(vm, &vm->retval, &name,
-                                     (njs_value_t *) value, 0);
-        if (nxt_slow_path(ret == NXT_ERROR || ret == NJS_APPLIED)) {
+    while (start < end) {
+        njs_uint32_to_string(&name, start++);
+
+        ret = njs_value_property_set(vm, (njs_value_t *) this, &name,
+                                     (njs_value_t *) value);
+        if (nxt_slow_path(ret == NXT_ERROR)) {
             return ret;
         }
     }
 
+    vm->retval = *this;
+
     return NXT_OK;
 }
 
 
+nxt_inline njs_ret_t
+njs_array_iterator_call(njs_vm_t *vm, njs_function_t *function,
+    const njs_value_t *this_arg, njs_value_t *value, uint32_t n,
+    njs_value_t *array)
+{
+    njs_value_t  arguments[3];
+
+    /* GC: array elt, array */
+
+    arguments[0] = *value;
+    njs_set_number(&arguments[1], n);
+    arguments[2] = *array;
+
+    return njs_function_call(vm, function, (njs_value_t *) this_arg,
+                             arguments, 3, &vm->retval);
+}
+
+
 static njs_ret_t
 njs_array_prototype_for_each(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
-    nxt_int_t         ret;
-    njs_array_iter_t  *iter;
-
-    ret = njs_array_iterator_args(vm, args, nargs);
-    if (nxt_slow_path(ret != NXT_OK)) {
-        return ret;
+    uint32_t           i, length;
+    nxt_int_t          ret;
+    njs_value_t        *array, *value;
+    njs_function_t     *function;
+    const njs_value_t  *this_arg;
+
+    if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) {
+        njs_type_error(vm, "unexpected iterator arguments");
+        return NXT_ERROR;
     }
 
-    iter = njs_vm_continuation(vm);
-    iter->u.cont.function = njs_array_prototype_for_each_continuation;
-
-    return njs_array_prototype_for_each_continuation(vm, args, nargs, unused);
-}
-
-
-static njs_ret_t
-njs_array_prototype_for_each_continuation(njs_vm_t *vm, njs_value_t *args,
-    nxt_uint_t nargs, njs_index_t unused)
-{
-    uint32_t          index;
-    njs_array_iter_t  *iter;
-
-    iter = njs_vm_continuation(vm);
-
-    index = njs_array_iterator_index(njs_array(&args[0]), iter);
-
-    if (index == NJS_ARRAY_INVALID_INDEX) {
-        vm->retval = njs_value_undefined;
-        return NXT_OK;
+    array = &args[0];
+    length = njs_array_len(array);
+    function =  njs_function(&args[1]);
+    this_arg = njs_arg(args, nargs, 2);
+
+    for (i = 0; i < length; i++) {
+        value = &njs_array_start(array)[i];
+
+        if (njs_is_valid(value)) {
+            ret = njs_array_iterator_call(vm, function, this_arg, value, i,
+                                          array);
+            if (nxt_slow_path(ret != NXT_OK)) {
+                return ret;
+            }
+        }
+
+        length = nxt_min(length, njs_array_len(array));
     }
 
-    return njs_array_iterator_apply(vm, iter, args, nargs);
+    vm->retval = njs_value_undefined;
+
+    return NXT_OK;
 }
 
 
@@ -1603,43 +1399,41 @@ static njs_ret_t
 njs_array_prototype_some(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
-    nxt_int_t         ret;
-    njs_array_iter_t  *iter;
-
-    ret = njs_array_iterator_args(vm, args, nargs);
-    if (nxt_slow_path(ret != NXT_OK)) {
-        return ret;
+    uint32_t           i, length;
+    nxt_int_t          ret;
+    njs_value_t        *array, *value;
+    njs_function_t     *function;
+    const njs_value_t  *this_arg, *retval;
+
+    if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) {
+        njs_type_error(vm, "unexpected iterator arguments");
+        return NXT_ERROR;
     }
 
-    iter = njs_vm_continuation(vm);
-    iter->u.cont.function = njs_array_prototype_some_continuation;
-
-    return njs_array_prototype_some_continuation(vm, args, nargs, unused);
-}
-
-
-static njs_ret_t
-njs_array_prototype_some_continuation(njs_vm_t *vm, njs_value_t *args,
-    nxt_uint_t nargs, njs_index_t unused)
-{
-    uint32_t           index;
-    njs_array_iter_t   *iter;
-    const njs_value_t  *retval;
-
-    iter = njs_vm_continuation(vm);
-
-    if (njs_is_true(&iter->retval)) {
-        retval = &njs_value_true;
-
-    } else {
-        index = njs_array_iterator_index(njs_array(&args[0]), iter);
-
-        if (index == NJS_ARRAY_INVALID_INDEX) {
-            retval = &njs_value_false;
-
-        } else {
-            return njs_array_iterator_apply(vm, iter, args, nargs);
+    array = &args[0];
+    length = njs_array_len(array);
+    function =  njs_function(&args[1]);
+    this_arg = njs_arg(args, nargs, 2);
+
+    retval = &njs_value_false;
+
+    for (i = 0; i < length; i++) {
+        value = &njs_array_start(array)[i];
+
+        if (njs_is_valid(value)) {
+            ret = njs_array_iterator_call(vm, function, this_arg, value, i,
+                                          array);
+            if (nxt_slow_path(ret != NXT_OK)) {
+                return ret;
+            }
+
+            if (njs_is_true(&vm->retval)) {
+                retval = &njs_value_true;
+                break;
+            }
         }
+
+        length = nxt_min(length, njs_array_len(array));
     }
 
     vm->retval = *retval;
@@ -1652,44 +1446,41 @@ static njs_ret_t
 njs_array_prototype_every(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
-    nxt_int_t         ret;
-    njs_array_iter_t  *iter;
-
-    ret = njs_array_iterator_args(vm, args, nargs);
-    if (nxt_slow_path(ret != NXT_OK)) {
-        return ret;
+    uint32_t           i, length;
+    nxt_int_t          ret;
+    njs_value_t        *array, *value;
+    njs_function_t     *function;
+    const njs_value_t  *this_arg, *retval;
+
+    if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) {
+        njs_type_error(vm, "unexpected iterator arguments");
+        return NXT_ERROR;
     }
 
-    iter = njs_vm_continuation(vm);
-    iter->u.cont.function = njs_array_prototype_every_continuation;
-    iter->retval.data.truth = 1;
-
-    return njs_array_prototype_every_continuation(vm, args, nargs, unused);
-}
-
-
-static njs_ret_t
-njs_array_prototype_every_continuation(njs_vm_t *vm, njs_value_t *args,
-    nxt_uint_t nargs, njs_index_t unused)
-{
-    uint32_t           index;
-    njs_array_iter_t   *iter;
-    const njs_value_t  *retval;
-
-    iter = njs_vm_continuation(vm);
-
-    if (!njs_is_true(&iter->retval)) {
-        retval = &njs_value_false;
-
-    } else {
-        index = njs_array_iterator_index(njs_array(&args[0]), iter);
-
-        if (index == NJS_ARRAY_INVALID_INDEX) {
-            retval = &njs_value_true;
-
-        } else {
-            return njs_array_iterator_apply(vm, iter, args, nargs);
+    array = &args[0];
+    length = njs_array_len(array);
+    function =  njs_function(&args[1]);
+    this_arg = njs_arg(args, nargs, 2);
+
+    retval = &njs_value_true;
+
+    for (i = 0; i < length; i++) {
+        value = &njs_array_start(array)[i];
+
+        if (njs_is_valid(value)) {
+            ret = njs_array_iterator_call(vm, function, this_arg, value, i,
+                                          array);
+            if (nxt_slow_path(ret != NXT_OK)) {
+                return ret;
+            }
+
+            if (!njs_is_true(&vm->retval)) {
+                retval = &njs_value_false;
+                break;
+            }
         }
+
+        length = nxt_min(length, njs_array_len(array));
     }
 
     vm->retval = *retval;
@@ -1702,57 +1493,52 @@ static njs_ret_t
 njs_array_prototype_filter(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
-    nxt_int_t           ret;
-    njs_array_filter_t  *filter;
-
-    ret = njs_array_iterator_args(vm, args, nargs);
-    if (nxt_slow_path(ret != NXT_OK)) {
-        return ret;
+    uint32_t           i, length;
+    nxt_int_t          ret;
+    njs_array_t        *retval;
+    njs_value_t        *array, value;
+    njs_function_t     *function;
+    const njs_value_t  *this_arg;
+
+    if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) {
+        njs_type_error(vm, "unexpected iterator arguments");
+        return NXT_ERROR;
     }
 
-    filter = njs_vm_continuation(vm);
-    filter->iter.u.cont.function = njs_array_prototype_filter_continuation;
-
-    filter->array = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
-    if (nxt_slow_path(filter->array == NULL)) {
+    array = &args[0];
+    length = njs_array_len(array);
+    function =  njs_function(&args[1]);
+    this_arg = njs_arg(args, nargs, 2);
+
+    retval = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
+    if (nxt_slow_path(retval == NULL)) {
         return NXT_ERROR;
     }
 
-    return njs_array_prototype_filter_continuation(vm, args, nargs, unused);
-}
-
-
-static njs_ret_t
-njs_array_prototype_filter_continuation(njs_vm_t *vm, njs_value_t *args,
-    nxt_uint_t nargs, njs_index_t unused)
-{
-    uint32_t            index;
-    nxt_int_t           ret;
-    njs_array_t         *array;
-    njs_array_filter_t  *filter;
-
-    filter = njs_vm_continuation(vm);
-
-    if (njs_is_true(&filter->iter.retval)) {
-        ret = njs_array_add(vm, filter->array, &filter->value);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return ret;
+    for (i = 0; i < length; i++) {
+        value = njs_array_start(array)[i];
+
+        if (njs_is_valid(&value)) {
+            ret = njs_array_iterator_call(vm, function, this_arg, &value, i,
+                                          array);
+            if (nxt_slow_path(ret != NXT_OK)) {
+                return ret;
+            }
+
+            if (njs_is_true(&vm->retval)) {
+                ret = njs_array_add(vm, retval, &value);
+                if (nxt_slow_path(ret != NXT_OK)) {
+                    return ret;
+                }
+            }
         }
+
+        length = nxt_min(length, njs_array_len(array));
     }
 
-    array = njs_array(&args[0]);
-    index = njs_array_iterator_index(array, &filter->iter);
-
-    if (index == NJS_ARRAY_INVALID_INDEX) {
-        njs_set_array(&vm->retval, filter->array);
-
-        return NXT_OK;
-    }
-
-    /* GC: filter->value */
-    filter->value = array->start[index];
-
-    return njs_array_iterator_apply(vm, &filter->iter, args, nargs);
+    njs_set_array(&vm->retval, retval);
+
+    return NXT_OK;
 }
 
 
@@ -1760,50 +1546,42 @@ static njs_ret_t
 njs_array_prototype_find(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
-    nxt_int_t         ret;
-    njs_array_find_t  *find;
-
-    ret = njs_array_iterator_args(vm, args, nargs);
-    if (nxt_slow_path(ret != NXT_OK)) {
-        return ret;
+    uint32_t           i, length;
+    nxt_int_t          ret;
+    njs_value_t        *array, value;
+    njs_function_t     *function;
+    const njs_value_t  *this_arg, *retval;
+
+    if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) {
+        njs_type_error(vm, "unexpected iterator arguments");
+        return NXT_ERROR;
     }
 
-    find = njs_vm_continuation(vm);
-    find->iter.u.cont.function = njs_array_prototype_find_continuation;
-
-    return njs_array_prototype_find_continuation(vm, args, nargs, unused);
-}
-
-
-static njs_ret_t
-njs_array_prototype_find_continuation(njs_vm_t *vm, njs_value_t *args,
-    nxt_uint_t nargs, njs_index_t unused)
-{
-    njs_array_t        *array;
-    njs_array_iter_t   *iter;
-    njs_array_find_t   *find;
-    const njs_value_t  *retval;
+    array = &args[0];
+    length = njs_array_len(array);
+    function =  njs_function(&args[1]);
+    this_arg = njs_arg(args, nargs, 2);
 
     retval = &njs_value_undefined;
 
-    find = njs_vm_continuation(vm);
-    iter = &find->iter;
-
-    if (!njs_is_true(&iter->retval)) {
-        array = njs_array(&args[0]);
-        iter->index++;
-
-        if (iter->index < iter->length && iter->index < array->length) {
-            /* GC: find->value */
-            find->value = array->start[iter->index];
-
-            return njs_array_prototype_find_apply(vm, iter, args, nargs);
+    for (i = 0; i < length; i++) {
+        value = njs_array_start(array)[i];
+
+        if (!njs_is_valid(&value)) {
+            value = njs_value_undefined;
         }
 
-    } else {
-        if (njs_is_valid(&find->value)) {
-            retval = &find->value;
+        ret = njs_array_iterator_call(vm, function, this_arg, &value, i, array);
+        if (nxt_slow_path(ret != NXT_OK)) {
+            return ret;
         }
+
+        if (njs_is_true(&vm->retval)) {
+            retval = &value;
+            break;
+        }
+
+        length = nxt_min(length, njs_array_len(array));
     }
 
     vm->retval = *retval;
@@ -1816,41 +1594,43 @@ static njs_ret_t
 njs_array_prototype_find_index(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused)
 {
-    nxt_int_t         ret;
-    njs_array_iter_t  *iter;
-
-    ret = njs_array_iterator_args(vm, args, nargs);
-    if (nxt_slow_path(ret != NXT_OK)) {
-        return ret;
+    double             index;
+    uint32_t           i, length;
+    nxt_int_t          ret;
+    njs_value_t        *array, value;
+    njs_function_t     *function;
+    const njs_value_t  *this_arg;
+
+    if (nargs < 2 || !njs_is_array(&args[0]) || !njs_is_function(&args[1])) {
+        njs_type_error(vm, "unexpected iterator arguments");
+        return NXT_ERROR;
     }
 
-    iter = njs_vm_continuation(vm);
-    iter->u.cont.function = njs_array_prototype_find_index_continuation;
-
-    return njs_array_prototype_find_index_continuation(vm, args, nargs, unused);
-}
-
-
-static njs_ret_t
-njs_array_prototype_find_index_continuation(njs_vm_t *vm, njs_value_t *args,
-    nxt_uint_t nargs, njs_index_t unused)
-{
-    double             index;
-    njs_array_iter_t   *iter;
-
-    iter = njs_vm_continuation(vm);
-    index = iter->index;
-
-    if (!njs_is_true(&iter->retval)) {
-        iter->index++;
-
-        if (iter->index < iter->length
-            && iter->index < njs_array_len(&args[0]))
-        {
-            return njs_array_prototype_find_apply(vm, iter, args, nargs);
+    array = &args[0];
+    length = njs_array_len(array);
+    function =  njs_function(&args[1]);
+    this_arg = njs_arg(args, nargs, 2);
+
+    index = -1;
+
+    for (i = 0; i < length; i++) {
+        value = njs_array_start(array)[i];
+
+        if (!njs_is_valid(&value)) {
+            value = njs_value_undefined;
         }
 
-        index = -1;
+        ret = njs_array_iterator_call(vm, function, this_arg, &value, i, array);
+        if (nxt_slow_path(ret != NXT_OK)) {
+            return ret;
+        }
+
+        if (njs_is_true(&vm->retval)) {
+            index = i;
+            break;
+        }
+
+        length = nxt_min(length, njs_array_len(array));
     }
 
     njs_set_number(&vm->retval, index);
@@ -1860,109 +1640,79 @@ njs_array_prototype_find_index_continuat
 
 


More information about the nginx-devel mailing list