[njs] Array.prototype.lastIndexOf() and Array.prototype.indexOf(...

Andrey Zelenkov zelenkov at nginx.com
Tue Oct 25 14:33:39 UTC 2016


details:   http://hg.nginx.org/njs/rev/76e57071e411
branches:  
changeset: 220:76e57071e411
user:      Andrey Zelenkov <zelenkov at nginx.com>
date:      Mon Oct 24 19:02:31 2016 +0300
description:
Array.prototype.lastIndexOf() and Array.prototype.indexOf() fixes.

The fromIndex parameter processing in lastIndexOf() has been fixed.
The lastIndexOf() search algorithm has been optimized.
The njs_array_index_of() function has been removed.

In collaboration with Valentin Bartenev.

diffstat:

 njs/njs_array.c          |  125 +++++++++++++++++++++++++++++++++-------------
 njs/test/njs_unit_test.c |   25 ++++++++-
 2 files changed, 112 insertions(+), 38 deletions(-)

diffs (215 lines):

diff -r 12a38e4e030b -r 76e57071e411 njs/njs_array.c
--- a/njs/njs_array.c	Mon Oct 24 18:27:31 2016 +0300
+++ b/njs/njs_array.c	Mon Oct 24 19:02:31 2016 +0300
@@ -84,8 +84,6 @@ static njs_ret_t njs_array_prototype_to_
 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_index_of(njs_vm_t *vm, njs_value_t *args,
-    nxt_uint_t nargs, nxt_bool_t first);
 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,
@@ -974,7 +972,59 @@ static njs_ret_t
 njs_array_prototype_index_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
-    return njs_array_index_of(vm, args, nargs, 1);
+    nxt_int_t    i, index, length;
+    njs_value_t  *value, *start;
+    njs_array_t  *array;
+
+    index = -1;
+
+    if (nargs < 2 || !njs_is_array(&args[0])) {
+        goto done;
+    }
+
+    array = args[0].data.u.array;
+    length = array->length;
+
+    if (length == 0) {
+        goto done;
+    }
+
+    i = 0;
+
+    if (nargs > 2) {
+        i = args[2].data.u.number;
+
+        if (i >= length) {
+            goto done;
+        }
+
+        if (i < 0) {
+            i += length;
+
+            if (i < 0) {
+                i = 0;
+            }
+        }
+    }
+
+    value = &args[1];
+    start = array->start;
+
+    do {
+        if (njs_values_strict_equal(value, &start[i])) {
+            index = i;
+            break;
+        }
+
+        i++;
+
+    } while (i < length);
+
+done:
+
+    njs_number_set(&vm->retval, index);
+
+    return NXT_OK;
 }
 
 
@@ -982,51 +1032,54 @@ static njs_ret_t
 njs_array_prototype_last_index_of(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused)
 {
-    return njs_array_index_of(vm, args, nargs, 0);
-}
-
-
-static njs_ret_t
-njs_array_index_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
-    nxt_bool_t first)
-{
-    nxt_int_t    i, index, length;
-    njs_value_t  *value;
+    nxt_int_t    i, n, index, length;
+    njs_value_t  *value, *start;
     njs_array_t  *array;
 
     index = -1;
 
-    if (nargs > 1 && njs_is_array(&args[0])) {
-        i = 0;
-        array = args[0].data.u.array;
-        length = array->length;
+    if (nargs < 2 || !njs_is_array(&args[0])) {
+        goto done;
+    }
 
-        if (nargs > 2) {
-            i = args[2].data.u.number;
+    array = args[0].data.u.array;
+    length = array->length;
+
+    if (length == 0) {
+        goto done;
+    }
+
+    i = length - 1;
+
+    if (nargs > 2) {
+        n = args[2].data.u.number;
+
+        if (n < 0) {
+            i = n + length;
 
             if (i < 0) {
-                i += length;
+                goto done;
+            }
 
-                if (i < 0) {
-                    i = 0;
-                }
-            }
+        } else if (n < length) {
+            i = n;
+        }
+    }
+
+    value = &args[1];
+    start = array->start;
+
+    do {
+        if (njs_values_strict_equal(value, &start[i])) {
+            index = i;
+            break;
         }
 
-        value = &args[1];
-
-        while (i < length) {
-            if (njs_values_strict_equal(value, &array->start[i])) {
-                index = i;
+        i--;
 
-                if (first) {
-                    break;
-                }
-            }
+    } while (i >= 0);
 
-            i++;
-        }
-    }
+done:
 
     njs_number_set(&vm->retval, index);
 
diff -r 12a38e4e030b -r 76e57071e411 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Mon Oct 24 18:27:31 2016 +0300
+++ b/njs/test/njs_unit_test.c	Mon Oct 24 19:02:31 2016 +0300
@@ -2362,6 +2362,12 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("var a = [1,2,3,4]; a.indexOf(5)"),
       nxt_string("-1") },
 
+    { nxt_string("var a = [1,2,3,4]; a.indexOf(4, 3)"),
+      nxt_string("3") },
+
+    { nxt_string("var a = [1,2,3,4]; a.indexOf(4, 4)"),
+      nxt_string("-1") },
+
     { nxt_string("var a = [1,2,3,4,3,4]; a.indexOf(3, '2')"),
       nxt_string("2") },
 
@@ -2374,20 +2380,35 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("[].indexOf.bind(0)(0, 0)"),
       nxt_string("-1") },
 
+    { nxt_string("[].lastIndexOf(1, -1)"),
+      nxt_string("-1") },
+
     { nxt_string("var a = [1,2,3,4]; a.lastIndexOf()"),
       nxt_string("-1") },
 
     { nxt_string("var a = [1,2,3,4]; a.lastIndexOf(5)"),
       nxt_string("-1") },
 
+    { nxt_string("var a = [1,2,3,4,3,4]; a.lastIndexOf(1, 0)"),
+      nxt_string("0") },
+
     { nxt_string("var a = [1,2,3,4,3,4]; a.lastIndexOf(3, '2')"),
-      nxt_string("4") },
+      nxt_string("2") },
+
+    { nxt_string("var a = [1,2,3,4,3,4]; a.lastIndexOf(1, 6)"),
+      nxt_string("0") },
+
+    { nxt_string("var a = [1,2,3,4,3,4]; a.lastIndexOf(2, 6)"),
+      nxt_string("1") },
 
     { nxt_string("var a = [1,2,3,4,3,4]; a.lastIndexOf(4, -1)"),
       nxt_string("5") },
 
+    { nxt_string("var a = [1,2,3,4,3,4]; a.lastIndexOf(4, -6)"),
+      nxt_string("-1") },
+
     { nxt_string("var a = [1,2,3,4,3,4]; a.lastIndexOf(3, -10)"),
-      nxt_string("4") },
+      nxt_string("-1") },
 
     { nxt_string("var a = []; var s = { sum: 0 };"
                  "a.forEach(function(v, i, a) { this.sum += v }, s); s.sum"),



More information about the nginx-devel mailing list