]> git.kaiwu.me - njs.git/commitdiff
Array.reduceRight() function.
authorIgor Sysoev <igor@sysoev.ru>
Tue, 9 Aug 2016 11:10:33 +0000 (14:10 +0300)
committerIgor Sysoev <igor@sysoev.ru>
Tue, 9 Aug 2016 11:10:33 +0000 (14:10 +0300)
njs/njs_array.c
njs/test/njs_unit_test.c

index 1790c7b43a55dccd4d508d5e0fa1b925d75361d0..5cc72d37bb548d6068dcec86048086fd509a2005 100644 (file)
@@ -70,12 +70,15 @@ static njs_ret_t njs_array_prototype_map_cont(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused);
 static njs_ret_t njs_array_prototype_reduce_cont(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_cont(njs_vm_t *vm,
+    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
 static nxt_noinline njs_ret_t njs_array_iterator_args(njs_vm_t *vm,
     njs_value_t *args, nxt_uint_t nargs);
 static nxt_noinline uint32_t njs_array_iterator_next(njs_array_t *array,
     uint32_t n, uint32_t length);
 static nxt_noinline 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 uint32_t njs_array_reduce_right_next(njs_array_t *array, int32_t n);
 
 
 nxt_noinline njs_array_t *
@@ -1206,6 +1209,101 @@ njs_array_iterator_apply(njs_vm_t *vm, njs_array_iter_t *iter,
 }
 
 
+static njs_ret_t
+njs_array_prototype_reduce_right(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    int32_t           n;
+    njs_array_t       *array;
+    njs_array_iter_t  *iter;
+
+    if (nargs > 1 && njs_is_array(&args[0]) && njs_is_function(&args[1])) {
+        array = args[0].data.u.array;
+        iter = njs_continuation(vm->frame);
+        iter->next_index = njs_array_reduce_right_next(array, array->length);
+
+    } else {
+        vm->exception = &njs_exception_type_error;
+        return NXT_ERROR;
+    }
+
+    iter = njs_continuation(vm->frame);
+    iter->u.cont.function = njs_array_prototype_reduce_right_cont;
+
+    if (nargs > 2) {
+        iter->retval = args[2];
+
+    } else {
+        array = args[0].data.u.array;
+        n = iter->next_index;
+
+        if (n < 0) {
+            vm->exception = &njs_exception_type_error;
+            return NXT_ERROR;
+        }
+
+        iter->retval = array->start[n];
+
+        iter->next_index = njs_array_reduce_right_next(array, n);
+    }
+
+    return njs_array_prototype_reduce_right_cont(vm, args, nargs, unused);
+}
+
+
+static njs_ret_t
+njs_array_prototype_reduce_right_cont(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    nxt_int_t         n;
+    njs_array_t       *array;
+    njs_value_t       arguments[5];
+    njs_array_iter_t  *iter;
+
+    iter = njs_continuation(vm->frame);
+
+    if ((int32_t) iter->next_index < 0) {
+        vm->retval = iter->retval;
+        return NXT_OK;
+    }
+
+    arguments[0] = njs_value_void;
+
+    /* GC: array elt, array */
+    arguments[1] = iter->retval;
+
+    array = args[0].data.u.array;
+    n = iter->next_index;
+    arguments[2] = array->start[n];
+
+    njs_number_set(&arguments[3], n);
+
+    arguments[4] = args[0];
+
+    iter->next_index = njs_array_reduce_right_next(array, n);
+
+    return njs_function_apply(vm, args[1].data.u.function, arguments, 5,
+                              (njs_index_t) &iter->retval);
+}
+
+
+static nxt_noinline uint32_t
+njs_array_reduce_right_next(njs_array_t *array, int32_t n)
+{
+    n = nxt_min(n, (int32_t) array->length) - 1;
+
+    while (n >= 0) {
+        if (njs_is_valid(&array->start[n])) {
+            return n;
+        }
+
+        n--;
+    }
+
+    return n;
+}
+
+
 static const njs_object_prop_t  njs_array_prototype_properties[] =
 {
     {
@@ -1314,6 +1412,13 @@ static const njs_object_prop_t  njs_array_prototype_properties[] =
         .value = njs_native_function(njs_array_prototype_reduce,
                      njs_continuation_size(njs_array_iter_t), 0),
     },
+
+    {
+        .type = NJS_METHOD,
+        .name = njs_string("reduceRight"),
+        .value = njs_native_function(njs_array_prototype_reduce_right,
+                     njs_continuation_size(njs_array_iter_t), 0),
+    },
 };
 
 
index 7c30c26d925b496263e29cadc6a347195185d826..114f128f39b2a32bf85557926e30b72e3124dc21 100644 (file)
@@ -2421,6 +2421,48 @@ static njs_unit_test_t  njs_test[] =
                  "                         { return a.concat(b) }, [])"),
       nxt_string("0,1,2,3,4,5") },
 
+    { nxt_string("var a = [];"
+                 "a.reduceRight(function(p, v, i, a) { return p + v })"),
+      nxt_string("TypeError") },
+
+    { nxt_string("var a = [];"
+                 "a.reduceRight(function(p, v, i, a) { return p + v }, 10)"),
+      nxt_string("10") },
+
+    { nxt_string("var a = [,,];"
+                 "a.reduceRight(function(p, v, i, a) { return p + v })"),
+      nxt_string("TypeError") },
+
+    { nxt_string("var a = [,,];"
+                 "a.reduceRight(function(p, v, i, a) { return p + v }, 10)"),
+      nxt_string("10") },
+
+    { nxt_string("var a = [1];"
+                 "a.reduceRight(function(p, v, i, a) { return p + v })"),
+      nxt_string("1") },
+
+    { nxt_string("var a = [1];"
+                 "a.reduceRight(function(p, v, i, a) { return p + v }, 10)"),
+      nxt_string("11") },
+
+    { nxt_string("var a = [1,2,3];"
+                 "a.reduceRight(function(p, v, i, a) { return p + v })"),
+      nxt_string("6") },
+
+    { nxt_string("var a = [1,2,3];"
+                 "a.reduceRight(function(p, v, i, a) { return p + v }, 10)"),
+      nxt_string("16") },
+
+    { nxt_string("var a = [1,2,3];"
+                 "a.reduceRight(function(p, v, i, a)"
+                 "              { a.shift(); return p + v })"),
+      nxt_string("7") },
+
+    { nxt_string("var a = [1,2,3];"
+                 "a.reduceRight(function(p, v, i, a)"
+                 "              { a.shift(); return p + v }, 10)"),
+      nxt_string("19") },
+
     /* Strings. */
 
     { nxt_string("var a = '0123456789' + '012345'"