]> git.kaiwu.me - njs.git/commitdiff
Fixed String.prototype.repeat() according to the specification.
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 2 Jul 2020 12:59:48 +0000 (12:59 +0000)
committerDmitry Volyntsev <xeioex@nginx.com>
Thu, 2 Jul 2020 12:59:48 +0000 (12:59 +0000)
src/njs_string.c
src/test/njs_unit_test.c

index 5c2997bed98331367db06a4690221a50926c0c3d..371605c7d21d93c09fc5565a63bf93d4f43d67b9 100644 (file)
@@ -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;
index 56c7c5f320c1bde0d5fd3bc780212b26b374f937..2f087b8df2c66fe86bd11985b4cdd205aee3329c 100644 (file)
@@ -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") },