blob: 644f7406f04cd061050d0bcb0acd5a131463b6e1 [file] [log] [blame]
// 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'));