]> git.kaiwu.me - njs.git/commitdiff
Array.prototype.lastIndexOf() and Array.prototype.indexOf() fixes.
authorAndrey Zelenkov <zelenkov@nginx.com>
Mon, 24 Oct 2016 16:02:31 +0000 (19:02 +0300)
committerAndrey Zelenkov <zelenkov@nginx.com>
Mon, 24 Oct 2016 16:02:31 +0000 (19:02 +0300)
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.

njs/njs_array.c
njs/test/njs_unit_test.c

index 7e402fc9264b8fb160ae96e91bb8153e86aba851..06313f7794ce68c6103b522dc8af3138174035cb 100644 (file)
@@ -84,8 +84,6 @@ static njs_ret_t njs_array_prototype_to_string_continuation(njs_vm_t *vm,
 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,60 +972,115 @@ 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;
 
-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);
+    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;
 }
 
 
 static njs_ret_t
-njs_array_index_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
-    nxt_bool_t first)
+njs_array_prototype_last_index_of(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
 {
-    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 (i < 0) {
-                i += length;
+    if (length == 0) {
+        goto done;
+    }
 
-                if (i < 0) {
-                    i = 0;
-                }
-            }
-        }
+    i = length - 1;
 
-        value = &args[1];
+    if (nargs > 2) {
+        n = args[2].data.u.number;
 
-        while (i < length) {
-            if (njs_values_strict_equal(value, &array->start[i])) {
-                index = i;
+        if (n < 0) {
+            i = n + length;
 
-                if (first) {
-                    break;
-                }
+            if (i < 0) {
+                goto done;
             }
 
-            i++;
+        } else if (n < length) {
+            i = n;
         }
     }
 
+    value = &args[1];
+    start = array->start;
+
+    do {
+        if (njs_values_strict_equal(value, &start[i])) {
+            index = i;
+            break;
+        }
+
+        i--;
+
+    } while (i >= 0);
+
+done:
+
     njs_number_set(&vm->retval, index);
 
     return NXT_OK;
index cd7a141563ce0af30ed0b5b98af251e544265200..7dad6c689c57152c9ac2d433bf4c3bbdc7b75c43 100644 (file)
@@ -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"),