[njs] Fixed String.prototype.repeat() according to the specification.

Dmitry Volyntsev xeioex at nginx.com
Thu Jul 2 14:01:37 UTC 2020


details:   https://hg.nginx.org/njs/rev/27b88bd86e61
branches:  
changeset: 1445:27b88bd86e61
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Jul 02 12:59:48 2020 +0000
description:
Fixed String.prototype.repeat() according to the specification.

diffstat:

 src/njs_string.c         |  42 ++++++++++++++++++++++++++++--------------
 src/test/njs_unit_test.c |   8 +++++---
 2 files changed, 33 insertions(+), 17 deletions(-)

diffs (107 lines):

diff -r 6345c07f1c52 -r 27b88bd86e61 src/njs_string.c
--- a/src/njs_string.c	Thu Jul 02 12:58:50 2020 +0000
+++ b/src/njs_string.c	Thu Jul 02 12:59:48 2020 +0000
@@ -2772,47 +2772,61 @@ static njs_int_t
 njs_string_prototype_repeat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     njs_index_t unused)
 {
-    u_char             *p, *start;
+    u_char             *p;
+    double             count;
     int64_t            n, max;
     uint64_t           size, length;
     njs_int_t          ret;
+    njs_value_t        *this;
     njs_string_prop_t  string;
 
-    ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0));
+    this = njs_argument(args, 0);
+
+    if (njs_slow_path(njs_is_null_or_undefined(this))) {
+        njs_type_error(vm, "cannot convert \"%s\"to object",
+                       njs_type_string(this->type));
+        return NJS_ERROR;
+    }
+
+    ret = njs_value_to_string(vm, this, this);
     if (njs_slow_path(ret != NJS_OK)) {
         return ret;
     }
 
-    ret = njs_value_to_integer(vm, njs_arg(args, nargs, 1), &n);
+    ret = njs_value_to_number(vm, njs_arg(args, nargs, 1), &count);
     if (njs_slow_path(ret != NJS_OK)) {
         return ret;
     }
 
-    (void) njs_string_prop(&string, njs_argument(args, 0));
-
-    max = (string.size > 1) ? NJS_STRING_MAX_LENGTH / string.size
-                            : NJS_STRING_MAX_LENGTH;
-
-    if (njs_slow_path(n < 0 || n >= max)) {
+    if (njs_slow_path(!isnan(count) && (count < 0 || isinf(count)))) {
         njs_range_error(vm, NULL);
         return NJS_ERROR;
     }
 
-    if (string.size == 0) {
+     n = njs_number_to_integer(count);
+
+    (void) njs_string_prop(&string, this);
+
+    if (njs_slow_path(n == 0 || string.size == 0)) {
         vm->retval = njs_string_empty;
         return NJS_OK;
     }
 
+    max = NJS_STRING_MAX_LENGTH / string.size;
+
+    if (njs_slow_path(n >= max)) {
+        njs_range_error(vm, NULL);
+        return NJS_ERROR;
+    }
+
     size = string.size * n;
     length = string.length * n;
 
-    start = njs_string_alloc(vm, &vm->retval, size, length);
-    if (njs_slow_path(start == NULL)) {
+    p = njs_string_alloc(vm, &vm->retval, size, length);
+    if (njs_slow_path(p == NULL)) {
         return NJS_ERROR;
     }
 
-    p = start;
-
     while (n != 0) {
         p = memcpy(p, string.start, string.size);
         p += string.size;
diff -r 6345c07f1c52 -r 27b88bd86e61 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Thu Jul 02 12:58:50 2020 +0000
+++ b/src/test/njs_unit_test.c	Thu Jul 02 12:59:48 2020 +0000
@@ -7892,12 +7892,11 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("''.repeat(2147483646)"),
       njs_str("") },
 
-    /* ES6: "". */
     { njs_str("''.repeat(2147483647)"),
-      njs_str("RangeError") },
+      njs_str("") },
 
     { njs_str("''.repeat(2147483648)"),
-      njs_str("RangeError") },
+      njs_str("") },
 
     { njs_str("''.repeat(Infinity)"),
       njs_str("RangeError") },
@@ -7905,6 +7904,9 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("''.repeat(NaN)"),
       njs_str("") },
 
+    { njs_str("String.prototype.repeat.call({},2)"),
+      njs_str("[object Object][object Object]") },
+
     { njs_str("'abc'.padStart(7)"),
       njs_str("    abc") },
 


More information about the nginx-devel mailing list