| // Copyright 2019 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // Flags: --harmony-string-replaceall --allow-natives-syntax |
| |
| assertEquals('a-b-c-d', 'a+b+c+d'.replaceAll('+', '-')); |
| assertEquals('aaaa', 'abcd'.replaceAll(/./g, 'a')); |
| assertEquals('', ''.replaceAll('a', 'b')); |
| assertEquals('b', ''.replaceAll('', 'b')); |
| assertEquals('_x_x_x_', 'xxx'.replaceAll('', '_')); |
| assertEquals('yx', 'xxx'.replaceAll('xx', 'y')); |
| assertEquals('xxxx', 'xx'.replaceAll('xx', '$&$&')); |
| assertEquals('ii', '.+*$.+*$'.replaceAll('.+*$', 'i')); |
| |
| { |
| // Non regexp search value with replace method. |
| const nonRegExpSearchValue = { |
| [Symbol.replace]: (string, replacer) => { |
| assertEquals(string, 'barbar'); |
| assertEquals(replacer, 'moo'); |
| return 'foo' |
| }, |
| toString: () => { |
| // Verify toString is not called. |
| unreachable(); |
| } |
| }; |
| assertEquals('foo', 'barbar'.replaceAll(nonRegExpSearchValue, 'moo')); |
| } |
| |
| { |
| // A custom regexp with non coercible flags. |
| class RegExpNonCoercibleFlags extends RegExp { |
| constructor() { |
| super(); |
| } |
| |
| static get [Symbol.species]() { |
| return RegExp; |
| } |
| |
| get flags() { return null; } |
| }; |
| assertThrows( |
| () => { assertEquals( |
| 'foo', |
| 'barbar'.replaceAll(new RegExpNonCoercibleFlags, 'moo')); }, |
| TypeError); |
| } |
| |
| { |
| // Non regexp search value with replace property |
| const nonRegExpSearchValue = { |
| [Symbol.replace]: "doh", |
| toString: () => { |
| // Verify toString is not called. |
| unreachable(); |
| } |
| }; |
| assertThrows( |
| () => { 'barbar'.replaceAll(nonRegExpSearchValue, 'moo'); }, |
| TypeError); |
| } |
| |
| { |
| // Non callable, non string replace value. |
| const nonCallableNonStringReplace = { |
| toString: () => { |
| return 'boo'; |
| }, |
| }; |
| assertEquals('booboo', 'moomoo'.replaceAll('moo', nonCallableNonStringReplace)); |
| } |
| |
| { |
| const positions = []; |
| assertEquals('bcb', 'aca'.replaceAll('a', |
| (searchString, position, string) => { |
| assertEquals('a', searchString); |
| assertEquals('aca', string); |
| positions.push(position); |
| return 'b'; |
| })); |
| assertEquals(positions, [0,2]); |
| } |
| |
| (function NonGlobalRegex() { |
| assertThrows( |
| () => { 'ab'.replaceAll(/./, '.'); }, |
| TypeError); |
| assertThrows( |
| () => { 'ab'.replaceAll(/./y, '.'); }, |
| TypeError); |
| })(); |
| |
| // Tests for stickiness gotcha. |
| assertEquals('o ppercase!', 'No Uppercase!'.replaceAll(/[A-Z]/g, '')); |
| assertEquals('o Uppercase?', 'No Uppercase?'.replaceAll(/[A-Z]/gy, '')); |
| assertEquals(' UPPERCASE!', 'NO UPPERCASE!'.replaceAll(/[A-Z]/gy, '')); |
| |
| // Tests for slow path. |
| assertEquals('a', 'a'.replaceAll(%ConstructConsString('abcdefghijklmn', |
| 'def'), 'b')); |
| assertEquals('b', 'abcdefghijklmndef'.replaceAll( |
| %ConstructConsString('abcdefghijklmn', 'def'), 'b')); |
| |
| assertEquals('aaaaaaaaaaaaaaaaaa', 'aaaaaaaaaaaaaaaaaa'.replaceAll( |
| %ConstructConsString('abcdefghijklmn', 'def'), 'b')); |