[njs] Improved working with arguments in String.prototype.lastIndexOf().

Dmitry Volyntsev xeioex at nginx.com
Tue May 14 16:34:19 UTC 2019


details:   https://hg.nginx.org/njs/rev/1cce73676665
branches:  
changeset: 962:1cce73676665
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Tue May 14 19:00:03 2019 +0300
description:
Improved working with arguments in String.prototype.lastIndexOf().

diffstat:

 njs/njs_string.c         |  128 +++++++++++++++++++++++++---------------------
 njs/test/njs_unit_test.c |   18 ++++++
 2 files changed, 87 insertions(+), 59 deletions(-)

diffs (196 lines):

diff -r 6babef232e87 -r 1cce73676665 njs/njs_string.c
--- a/njs/njs_string.c	Mon May 13 20:28:40 2019 +0300
+++ b/njs/njs_string.c	Tue May 14 19:00:03 2019 +0300
@@ -1796,80 +1796,90 @@ static njs_ret_t
 njs_string_prototype_last_index_of(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused)
 {
+    double             pos;
     ssize_t            index, start, length, search_length;
     const u_char       *p, *end;
+    const njs_value_t  *search_string;
     njs_string_prop_t  string, search;
 
     index = -1;
 
-    if (nargs > 1) {
-        length = njs_string_prop(&string, &args[0]);
-        search_length = njs_string_prop(&search, &args[1]);
-
-        if (length < search_length) {
-            goto done;
-        }
-
+    length = njs_string_prop(&string, njs_arg(args, nargs, 0));
+
+    search_string = njs_arg(args, nargs, 1);
+
+    if (njs_is_undefined(search_string)) {
+        search_string = &njs_string_undefined;
+    }
+
+    search_length = njs_string_prop(&search, search_string);
+
+    if (length < search_length) {
+        goto done;
+    }
+
+    pos = njs_arg(args, nargs, 2)->data.u.number;
+
+    if (isnan(pos)) {
         index = NJS_STRING_MAX_LENGTH;
 
-        if (nargs > 2) {
-            index = args[2].data.u.number;
-
-            if (index < 0) {
-                index = 0;
-            }
+    } else {
+        index = njs_number_to_integer(pos);
+
+        if (index < 0) {
+            index = 0;
         }
-
-        if (index > length) {
-            index = length;
+    }
+
+    if (index > length) {
+        index = length;
+    }
+
+    if (string.size == (size_t) length) {
+        /* Byte or ASCII string. */
+
+        start = length - search.size;
+
+        if (index > start) {
+            index = start;
         }
 
-        if (string.size == (size_t) length) {
-            /* Byte or ASCII string. */
-
-            start = length - search.size;
-
-            if (index > start) {
-                index = start;
+        p = string.start + index;
+
+        do {
+            if (memcmp(p, search.start, search.size) == 0) {
+                goto done;
             }
 
-            p = string.start + index;
-
-            do {
-                if (memcmp(p, search.start, search.size) == 0) {
-                    goto done;
-                }
-
-                index--;
-                p--;
-
-            } while (p >= string.start);
-
-        } else {
-            /* UTF-8 string. */
-
-            end = string.start + string.size;
-            p = njs_string_offset(string.start, end, index);
-            end -= search.size;
-
-            while (p > end) {
-                index--;
-                p = nxt_utf8_prev(p);
+            index--;
+            p--;
+
+        } while (p >= string.start);
+
+    } else {
+        /* UTF-8 string. */
+
+        end = string.start + string.size;
+        p = njs_string_offset(string.start, end, index);
+        end -= search.size;
+
+        while (p > end) {
+            index--;
+            p = nxt_utf8_prev(p);
+        }
+
+        for ( ;; ) {
+            if (memcmp(p, search.start, search.size) == 0) {
+                goto done;
             }
 
-            for ( ;; ) {
-                if (memcmp(p, search.start, search.size) == 0) {
-                    goto done;
-                }
-
-                index--;
-
-                if (p <= string.start) {
-                    break;
-                }
-
-                p = nxt_utf8_prev(p);
+            index--;
+
+            if (p <= string.start) {
+                break;
             }
+
+            p = nxt_utf8_prev(p);
         }
     }
 
@@ -3912,7 +3922,7 @@ static const njs_object_prop_t  njs_stri
         .type = NJS_METHOD,
         .name = njs_string("lastIndexOf"),
         .value = njs_native_function(njs_string_prototype_last_index_of, 0,
-                     NJS_STRING_OBJECT_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG),
+                     NJS_STRING_OBJECT_ARG, NJS_STRING_ARG, NJS_NUMBER_ARG),
         .configurable = 1,
     },
 
diff -r 6babef232e87 -r 1cce73676665 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Mon May 13 20:28:40 2019 +0300
+++ b/njs/test/njs_unit_test.c	Tue May 14 19:00:03 2019 +0300
@@ -5127,6 +5127,18 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("'abc abc абвгд abc'.lastIndexOf('абвгд')"),
       nxt_string("8") },
 
+    { nxt_string("'abc abc абвгд abc'.lastIndexOf('абвгд', undefined)"),
+      nxt_string("8") },
+
+    { nxt_string("'abc abc абвгд abc'.lastIndexOf('абвгд', NaN)"),
+      nxt_string("8") },
+
+    { nxt_string("'abc abc абвгд abc'.lastIndexOf('абвгд', {})"),
+      nxt_string("8") },
+
+    { nxt_string("String.prototype.lastIndexOf.call({toString:()=>'abc abc абвгд abc'}, 'абвгд')"),
+      nxt_string("8") },
+
     { nxt_string("'abc abc абвгдежз'.lastIndexOf('абвгд')"),
       nxt_string("8") },
 
@@ -5154,6 +5166,12 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("''.lastIndexOf('')"),
       nxt_string("0") },
 
+    { nxt_string("''.lastIndexOf()"),
+      nxt_string("-1") },
+
+    { nxt_string("''.lastIndexOf(undefined)"),
+      nxt_string("-1") },
+
     { nxt_string("''.includes('')"),
       nxt_string("true") },
 


More information about the nginx-devel mailing list