Add tests for String#replaceAll (#2423)

Fixes #2417
This commit is contained in:
Leo Balter 2019-11-18 10:22:07 -05:00 committed by GitHub
parent 7040938bd0
commit 3682ddd7e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 2308 additions and 0 deletions

View File

@ -158,6 +158,10 @@ Intl.DisplayNames
Promise.any
AggregateError
# String.prototype.replaceAll
# https://github.com/tc39/proposal-string-replaceall
String.prototype.replaceAll
## Standard language features
#
# Language features that have been included in a published version of the

View File

@ -0,0 +1,70 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Replacement Text Symbol Substitutions ($$)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
10. Let position be ! StringIndexOf(string, searchString, 0).
11. Repeat, while position is not -1
a. Append position to the end of matchPositions.
b. Let position be ! StringIndexOf(string, searchString, position + advanceBy).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
StringIndexOf ( string, searchValue, fromIndex )
...
4. Let len be the length of string.
5. If searchValue is the empty string, and fromIndex <= len, return fromIndex.
6. Let searchLen be the length of searchValue.
7. If there exists any integer k such that fromIndex k len - searchLen and for all nonnegative integers j less than searchLen, the code unit at index k + j within string is the same as the code unit at index j within searchValue, let pos be the smallest (closest to -) such integer. Otherwise, let pos be -1.
8. Return pos.
Runtime Semantics: GetSubstitution ( matched, str, position, captures, namedCaptures, replacement )
...
2. Let matchLength be the number of code units in matched.
...
4. Let stringLength be the number of code units in str.
...
9. Let tailPos be position + matchLength.
10. Let m be the number of elements in captures.
11. Let result be the String value derived from replacement by copying code unit elements from replacement to result while performing replacements as specified in Table 53. These $ replacements are done left-to-right, and, once such a replacement is performed, the new replacement text is not subject to further replacements.
12 Return result.
Table 53: Replacement Text Symbol Substitutions
...
features: [String.prototype.replaceAll]
---*/
var str = 'Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar.';
var result;
result = str.replaceAll('ninguém', '$$');
assert.sameValue(result, 'Ninguém é igual a $. Todo o ser humano é um estranho ímpar.');
result = str.replaceAll('é', '$$');
assert.sameValue(result, 'Ningu$m $ igual a ningu$m. Todo o ser humano $ um estranho ímpar.');
result = str.replaceAll('é', '$$ -');
assert.sameValue(result, 'Ningu$ -m $ - igual a ningu$ -m. Todo o ser humano $ - um estranho ímpar.');
result = str.replaceAll('é', '$$&');
assert.sameValue(result, 'Ningu$&m $& igual a ningu$&m. Todo o ser humano $& um estranho ímpar.');
result = str.replaceAll('é', '$$$');
assert.sameValue(result, 'Ningu$$m $$ igual a ningu$$m. Todo o ser humano $$ um estranho ímpar.');
result = str.replaceAll('é', '$$$$');
assert.sameValue(result, 'Ningu$$m $$ igual a ningu$$m. Todo o ser humano $$ um estranho ímpar.');

View File

@ -0,0 +1,64 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Replacement Text Symbol Substitutions ($&)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
10. Let position be ! StringIndexOf(string, searchString, 0).
11. Repeat, while position is not -1
a. Append position to the end of matchPositions.
b. Let position be ! StringIndexOf(string, searchString, position + advanceBy).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
StringIndexOf ( string, searchValue, fromIndex )
...
4. Let len be the length of string.
5. If searchValue is the empty string, and fromIndex <= len, return fromIndex.
6. Let searchLen be the length of searchValue.
7. If there exists any integer k such that fromIndex k len - searchLen and for all nonnegative integers j less than searchLen, the code unit at index k + j within string is the same as the code unit at index j within searchValue, let pos be the smallest (closest to -) such integer. Otherwise, let pos be -1.
8. Return pos.
Runtime Semantics: GetSubstitution ( matched, str, position, captures, namedCaptures, replacement )
...
2. Let matchLength be the number of code units in matched.
...
4. Let stringLength be the number of code units in str.
...
9. Let tailPos be position + matchLength.
10. Let m be the number of elements in captures.
11. Let result be the String value derived from replacement by copying code unit elements from replacement to result while performing replacements as specified in Table 53. These $ replacements are done left-to-right, and, once such a replacement is performed, the new replacement text is not subject to further replacements.
12 Return result.
Table 53: Replacement Text Symbol Substitutions
...
features: [String.prototype.replaceAll]
---*/
var str = 'Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar.';
var result;
result = str.replaceAll('ninguém', '$&');
assert.sameValue(result, 'Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar.');
result = str.replaceAll('ninguém', '($&)');
assert.sameValue(result, 'Ninguém é igual a (ninguém). Todo o ser humano é um estranho ímpar.');
result = str.replaceAll('é', '($&)');
assert.sameValue(result, 'Ningu(é)m (é) igual a ningu(é)m. Todo o ser humano (é) um estranho ímpar.');
result = str.replaceAll('é', '($&) $&');
assert.sameValue(result, 'Ningu(é) ém (é) é igual a ningu(é) ém. Todo o ser humano (é) é um estranho ímpar.');

View File

@ -0,0 +1,64 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Replacement Text Symbol Substitutions ($')
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
10. Let position be ! StringIndexOf(string, searchString, 0).
11. Repeat, while position is not -1
a. Append position to the end of matchPositions.
b. Let position be ! StringIndexOf(string, searchString, position + advanceBy).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
StringIndexOf ( string, searchValue, fromIndex )
...
4. Let len be the length of string.
5. If searchValue is the empty string, and fromIndex <= len, return fromIndex.
6. Let searchLen be the length of searchValue.
7. If there exists any integer k such that fromIndex k len - searchLen and for all nonnegative integers j less than searchLen, the code unit at index k + j within string is the same as the code unit at index j within searchValue, let pos be the smallest (closest to -) such integer. Otherwise, let pos be -1.
8. Return pos.
Runtime Semantics: GetSubstitution ( matched, str, position, captures, namedCaptures, replacement )
...
2. Let matchLength be the number of code units in matched.
...
4. Let stringLength be the number of code units in str.
...
9. Let tailPos be position + matchLength.
10. Let m be the number of elements in captures.
11. Let result be the String value derived from replacement by copying code unit elements from replacement to result while performing replacements as specified in Table 53. These $ replacements are done left-to-right, and, once such a replacement is performed, the new replacement text is not subject to further replacements.
12 Return result.
Table 53: Replacement Text Symbol Substitutions
...
features: [String.prototype.replaceAll]
---*/
var str = 'Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar.';
var result;
result = str.replaceAll('ninguém', '$\'');
assert.sameValue(result, 'Ninguém é igual a . Todo o ser humano é um estranho ímpar.. Todo o ser humano é um estranho ímpar.');
result = str.replaceAll('.', '--- $\'');
assert.sameValue(result, 'Ninguém é igual a ninguém--- Todo o ser humano é um estranho ímpar. Todo o ser humano é um estranho ímpar--- ');
result = str.replaceAll('é', '($\')');
assert.sameValue(result, 'Ningu(m é igual a ninguém. Todo o ser humano é um estranho ímpar.)m ( igual a ninguém. Todo o ser humano é um estranho ímpar.) igual a ningu(m. Todo o ser humano é um estranho ímpar.)m. Todo o ser humano ( um estranho ímpar.) um estranho ímpar.');
result = str.replaceAll('é', '($\') $\'');
assert.sameValue(result, 'Ningu(m é igual a ninguém. Todo o ser humano é um estranho ímpar.) m é igual a ninguém. Todo o ser humano é um estranho ímpar.m ( igual a ninguém. Todo o ser humano é um estranho ímpar.) igual a ninguém. Todo o ser humano é um estranho ímpar. igual a ningu(m. Todo o ser humano é um estranho ímpar.) m. Todo o ser humano é um estranho ímpar.m. Todo o ser humano ( um estranho ímpar.) um estranho ímpar. um estranho ímpar.');

View File

@ -0,0 +1,71 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Replacement Text Symbol Substitutions ($<)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
10. Let position be ! StringIndexOf(string, searchString, 0).
11. Repeat, while position is not -1
a. Append position to the end of matchPositions.
b. Let position be ! StringIndexOf(string, searchString, position + advanceBy).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
StringIndexOf ( string, searchValue, fromIndex )
...
4. Let len be the length of string.
5. If searchValue is the empty string, and fromIndex <= len, return fromIndex.
6. Let searchLen be the length of searchValue.
7. If there exists any integer k such that fromIndex k len - searchLen and for all nonnegative integers j less than searchLen, the code unit at index k + j within string is the same as the code unit at index j within searchValue, let pos be the smallest (closest to -) such integer. Otherwise, let pos be -1.
8. Return pos.
Runtime Semantics: GetSubstitution ( matched, str, position, captures, namedCaptures, replacement )
...
2. Let matchLength be the number of code units in matched.
...
4. Let stringLength be the number of code units in str.
...
9. Let tailPos be position + matchLength.
10. Let m be the number of elements in captures.
11. Let result be the String value derived from replacement by copying code unit elements from replacement to result while performing replacements as specified in Table 53. These $ replacements are done left-to-right, and, once such a replacement is performed, the new replacement text is not subject to further replacements.
12 Return result.
Table 53: Replacement Text Symbol Substitutions
...
$<
1. If namedCaptures is undefined, the replacement text is the String "$<".
...
features: [String.prototype.replaceAll, Symbol.replace]
---*/
var str = 'aaaaaaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaaaaaa';
var result;
// captures is always an empty list if GetSubstitution is called from the string value of SearchValue
result = str.replaceAll('a', '$<');
assert.sameValue(result, '$<$<$<$<$<$<$<$<$<$<$<$<$<$<$<$< $<$<$<$<$<$<$<$< $<$<$<$<$<$<$<$<$<$<$<$<$<$<$<$<');
var customRE = /./g;
Object.defineProperty(customRE, Symbol.replace, {
value: undefined
});
result = '------------------- /./g -------/./g'.replaceAll(customRE, 'a($<$<)');
assert.sameValue(result, '------------------- a($<$<) -------a($<$<)');

View File

@ -0,0 +1,67 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Replacement Text Symbol Substitutions ($`)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
10. Let position be ! StringIndexOf(string, searchString, 0).
11. Repeat, while position is not -1
a. Append position to the end of matchPositions.
b. Let position be ! StringIndexOf(string, searchString, position + advanceBy).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
StringIndexOf ( string, searchValue, fromIndex )
...
4. Let len be the length of string.
5. If searchValue is the empty string, and fromIndex <= len, return fromIndex.
6. Let searchLen be the length of searchValue.
7. If there exists any integer k such that fromIndex k len - searchLen and for all nonnegative integers j less than searchLen, the code unit at index k + j within string is the same as the code unit at index j within searchValue, let pos be the smallest (closest to -) such integer. Otherwise, let pos be -1.
8. Return pos.
Runtime Semantics: GetSubstitution ( matched, str, position, captures, namedCaptures, replacement )
...
2. Let matchLength be the number of code units in matched.
...
4. Let stringLength be the number of code units in str.
...
9. Let tailPos be position + matchLength.
10. Let m be the number of elements in captures.
11. Let result be the String value derived from replacement by copying code unit elements from replacement to result while performing replacements as specified in Table 53. These $ replacements are done left-to-right, and, once such a replacement is performed, the new replacement text is not subject to further replacements.
12 Return result.
Table 53: Replacement Text Symbol Substitutions
...
features: [String.prototype.replaceAll]
---*/
var str = 'Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar.';
var result;
result = str.replaceAll('ninguém', '$`');
assert.sameValue(result, 'Ninguém é igual a Ninguém é igual a . Todo o ser humano é um estranho ímpar.');
result = str.replaceAll('Ninguém', '$`');
assert.sameValue(result, ' é igual a ninguém. Todo o ser humano é um estranho ímpar.');
result = str.replaceAll('ninguém', '($`)');
assert.sameValue(result, 'Ninguém é igual a (Ninguém é igual a ). Todo o ser humano é um estranho ímpar.');
result = str.replaceAll('é', '($`)');
assert.sameValue(result, 'Ningu(Ningu)m (Ninguém ) igual a ningu(Ninguém é igual a ningu)m. Todo o ser humano (Ninguém é igual a ninguém. Todo o ser humano ) um estranho ímpar.');
result = str.replaceAll('é', '($`) $`');
assert.sameValue(result, 'Ningu(Ningu) Ningum (Ninguém ) Ninguém igual a ningu(Ninguém é igual a ningu) Ninguém é igual a ningum. Todo o ser humano (Ninguém é igual a ninguém. Todo o ser humano ) Ninguém é igual a ninguém. Todo o ser humano um estranho ímpar.');

View File

@ -0,0 +1,64 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Replacement Text Symbol Substitutions ($)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
10. Let position be ! StringIndexOf(string, searchString, 0).
11. Repeat, while position is not -1
a. Append position to the end of matchPositions.
b. Let position be ! StringIndexOf(string, searchString, position + advanceBy).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
StringIndexOf ( string, searchValue, fromIndex )
...
4. Let len be the length of string.
5. If searchValue is the empty string, and fromIndex <= len, return fromIndex.
6. Let searchLen be the length of searchValue.
7. If there exists any integer k such that fromIndex k len - searchLen and for all nonnegative integers j less than searchLen, the code unit at index k + j within string is the same as the code unit at index j within searchValue, let pos be the smallest (closest to -) such integer. Otherwise, let pos be -1.
8. Return pos.
Runtime Semantics: GetSubstitution ( matched, str, position, captures, namedCaptures, replacement )
...
2. Let matchLength be the number of code units in matched.
...
4. Let stringLength be the number of code units in str.
...
9. Let tailPos be position + matchLength.
10. Let m be the number of elements in captures.
11. Let result be the String value derived from replacement by copying code unit elements from replacement to result while performing replacements as specified in Table 53. These $ replacements are done left-to-right, and, once such a replacement is performed, the new replacement text is not subject to further replacements.
12 Return result.
Table 53: Replacement Text Symbol Substitutions
...
features: [String.prototype.replaceAll]
---*/
var str = 'Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar.';
var result;
result = str.replaceAll('ninguém', '$');
assert.sameValue(result, 'Ninguém é igual a $. Todo o ser humano é um estranho ímpar.');
result = str.replaceAll('é', '$');
assert.sameValue(result, 'Ningu$m $ igual a ningu$m. Todo o ser humano $ um estranho ímpar.');
result = str.replaceAll('é', '$ -');
assert.sameValue(result, 'Ningu$ -m $ - igual a ningu$ -m. Todo o ser humano $ - um estranho ímpar.');
result = str.replaceAll('é', '$$$');
assert.sameValue(result, 'Ningu$$m $$ igual a ningu$$m. Todo o ser humano $$ um estranho ímpar.');

View File

@ -0,0 +1,93 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Replacement Text Symbol Substitutions ($N)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
10. Let position be ! StringIndexOf(string, searchString, 0).
11. Repeat, while position is not -1
a. Append position to the end of matchPositions.
b. Let position be ! StringIndexOf(string, searchString, position + advanceBy).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
StringIndexOf ( string, searchValue, fromIndex )
...
4. Let len be the length of string.
5. If searchValue is the empty string, and fromIndex <= len, return fromIndex.
6. Let searchLen be the length of searchValue.
7. If there exists any integer k such that fromIndex k len - searchLen and for all nonnegative integers j less than searchLen, the code unit at index k + j within string is the same as the code unit at index j within searchValue, let pos be the smallest (closest to -) such integer. Otherwise, let pos be -1.
8. Return pos.
Runtime Semantics: GetSubstitution ( matched, str, position, captures, namedCaptures, replacement )
...
2. Let matchLength be the number of code units in matched.
...
4. Let stringLength be the number of code units in str.
...
9. Let tailPos be position + matchLength.
10. Let m be the number of elements in captures.
11. Let result be the String value derived from replacement by copying code unit elements from replacement to result while performing replacements as specified in Table 53. These $ replacements are done left-to-right, and, once such a replacement is performed, the new replacement text is not subject to further replacements.
12 Return result.
Table 53: Replacement Text Symbol Substitutions
...
The nth element of captures, where n is a single digit in the range 1 to 9. If n m and the nth element of captures is undefined, use the empty String instead. If n > m, no replacement is done.
features: [String.prototype.replaceAll, Symbol.replace]
---*/
var str = 'ABC AAA ABC AAA';
var result;
// captures is always an empty list if GetSubstitution is called from the string value of SearchValue
result = str.replaceAll('ABC', '$1');
assert.sameValue(result, '$1 AAA $1 AAA');
result = str.replaceAll('ABC', '$2');
assert.sameValue(result, '$2 AAA $2 AAA');
result = str.replaceAll('ABC', '$3');
assert.sameValue(result, '$3 AAA $3 AAA');
result = str.replaceAll('ABC', '$4');
assert.sameValue(result, '$4 AAA $4 AAA');
result = str.replaceAll('ABC', '$5');
assert.sameValue(result, '$5 AAA $5 AAA');
result = str.replaceAll('ABC', '$6');
assert.sameValue(result, '$6 AAA $6 AAA');
result = str.replaceAll('ABC', '$7');
assert.sameValue(result, '$7 AAA $7 AAA');
result = str.replaceAll('ABC', '$8');
assert.sameValue(result, '$8 AAA $8 AAA');
result = str.replaceAll('ABC', '$9');
assert.sameValue(result, '$9 AAA $9 AAA');
var customRE = /./g;
Object.defineProperty(customRE, Symbol.replace, {
value: undefined
});
result = '--- /./g --- /a/g --- /./g ---'.replaceAll(customRE, 'a($1$1)');
assert.sameValue(result, '--- a($1$1) --- /a/g --- a($1$1) ---');

View File

@ -0,0 +1,72 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Replacement Text Symbol Substitutions ($NN)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
10. Let position be ! StringIndexOf(string, searchString, 0).
11. Repeat, while position is not -1
a. Append position to the end of matchPositions.
b. Let position be ! StringIndexOf(string, searchString, position + advanceBy).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
StringIndexOf ( string, searchValue, fromIndex )
...
4. Let len be the length of string.
5. If searchValue is the empty string, and fromIndex <= len, return fromIndex.
6. Let searchLen be the length of searchValue.
7. If there exists any integer k such that fromIndex k len - searchLen and for all nonnegative integers j less than searchLen, the code unit at index k + j within string is the same as the code unit at index j within searchValue, let pos be the smallest (closest to -) such integer. Otherwise, let pos be -1.
8. Return pos.
Runtime Semantics: GetSubstitution ( matched, str, position, captures, namedCaptures, replacement )
...
2. Let matchLength be the number of code units in matched.
...
4. Let stringLength be the number of code units in str.
...
9. Let tailPos be position + matchLength.
10. Let m be the number of elements in captures.
11. Let result be the String value derived from replacement by copying code unit elements from replacement to result while performing replacements as specified in Table 53. These $ replacements are done left-to-right, and, once such a replacement is performed, the new replacement text is not subject to further replacements.
12 Return result.
Table 53: Replacement Text Symbol Substitutions
...
The nnth element of captures, where nn is a two-digit decimal number in the range 01 to 99. If nn m and the nnth element of captures is undefined, use the empty String instead. If nn is 00 or nn > m, no replacement is done.
features: [String.prototype.replaceAll, Symbol.replace]
---*/
var str = 'aaaaaaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaaaaaa';
var result;
// captures is always an empty list if GetSubstitution is called from the string value of SearchValue
result = str.replaceAll('a', '$11');
assert.sameValue(result, '$11$11$11$11$11$11$11$11$11$11$11$11$11$11$11$11 $11$11$11$11$11$11$11$11 $11$11$11$11$11$11$11$11$11$11$11$11$11$11$11$11');
result = str.replaceAll('a', '$29');
assert.sameValue(result, '$29$29$29$29$29$29$29$29$29$29$29$29$29$29$29$29 $29$29$29$29$29$29$29$29 $29$29$29$29$29$29$29$29$29$29$29$29$29$29$29$29');
var customRE = /./g;
Object.defineProperty(customRE, Symbol.replace, {
value: undefined
});
result = '------------------- /./g -------/./g'.replaceAll(customRE, 'a($12$11)');
assert.sameValue(result, '------------------- a($12$11) -------a($12$11)');

View File

@ -0,0 +1,21 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
String.prototype.replaceAll.length value and descriptor.
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
17 ECMAScript Standard Built-in Objects
includes: [propertyHelper.js]
features: [String.prototype.replaceAll]
---*/
verifyProperty(String.prototype.replaceAll, 'length', {
value: 2,
enumerable: false,
writable: false,
configurable: true,
});

View File

@ -0,0 +1,21 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
String.prototype.replaceAll.name value and descriptor.
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
17 ECMAScript Standard Built-in Objects
includes: [propertyHelper.js]
features: [String.prototype.replaceAll]
---*/
verifyProperty(String.prototype.replaceAll, 'name', {
value: 'replaceAll',
enumerable: false,
writable: false,
configurable: true,
});

View File

@ -0,0 +1,26 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Property type and descriptor.
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
17 ECMAScript Standard Built-in Objects
includes: [propertyHelper.js]
features: [String.prototype.replaceAll]
---*/
assert.sameValue(
typeof String.prototype.replaceAll,
'function',
'`typeof String.prototype.replaceAll` is `function`'
);
verifyProperty(String.prototype, 'replaceAll', {
enumerable: false,
writable: true,
configurable: true,
});

View File

@ -0,0 +1,26 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Return abrupt from Call(replaceValue, ...)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
...
5. Let functionalReplace be IsCallable(replaceValue).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
i. Let replacement be ? ToString(? Call(replaceValue, undefined, « searchString, position, string »).
features: [String.prototype.replaceAll]
---*/
function custom() {
throw new Test262Error();
}
assert.throws(Test262Error, function() {
'a'.replaceAll('a', custom);
});

View File

@ -0,0 +1,42 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
If replaceValue is a function, it's called for each matching position
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
...
5. Let functionalReplace be IsCallable(replaceValue).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
i. Let replacement be ? ToString(? Call(replaceValue, undefined, « searchString, position, string »).
features: [String.prototype.replaceAll]
includes: [compareArray.js]
---*/
var t = (function() { return this; })();
var calls = [];
var replaceValue = function(...args) {
calls.push([this, ...args]);
return 'z';
};
var searchValue = new String('ab c');
var obj = new String('ab c ab cdab cab c');
var result = obj.replaceAll(searchValue, replaceValue);
assert.sameValue(calls.length, 4);
assert.sameValue(result, 'z zdzz');
var str = obj.toString();
assert.compareArray(calls[0], [t, 'ab c', 0, str]);
assert.compareArray(calls[1], [t, 'ab c', 5, str]);
assert.compareArray(calls[2], [t, 'ab c', 10, str]);
assert.compareArray(calls[3], [t, 'ab c', 14, str]);

View File

@ -0,0 +1,39 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
replaceValue can be called for matching position of an empty string
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
...
5. Let functionalReplace be IsCallable(replaceValue).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
i. Let replacement be ? ToString(? Call(replaceValue, undefined, « searchString, position, string »).
features: [String.prototype.replaceAll]
includes: [compareArray.js]
---*/
var t = (function() { return this; })();
var calls = [];
var replaceValue = function(...args) {
calls.push([this, ...args]);
return 'abc';
};
var searchValue = new String('');
var obj = new String('');
var result = obj.replaceAll(searchValue, replaceValue);
assert.sameValue(calls.length, 1);
assert.sameValue(result, 'abc');
var str = obj.toString();
assert.compareArray(calls[0], [t, '', 0, str]);

View File

@ -0,0 +1,32 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
replaceValue is not called if there isn't a match
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
...
5. Let functionalReplace be IsCallable(replaceValue).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
i. Let replacement be ? ToString(? Call(replaceValue, undefined, « searchString, position, string »).
features: [String.prototype.replaceAll]
---*/
function replaceValue() {
throw new Test262Error();
}
assert.sameValue(
'a'.replaceAll('b', replaceValue),
'a'
);
assert.sameValue(
'a'.replaceAll('aa', replaceValue),
'a'
);

View File

@ -0,0 +1,42 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Return abrupt from ToString(Call(replaceValue, ...))
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
...
5. Let functionalReplace be IsCallable(replaceValue).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
i. Let replacement be ? ToString(? Call(replaceValue, undefined, « searchString, position, string »).
features: [String.prototype.replaceAll, Symbol]
---*/
function custom() {
return {
toString() {
throw new Test262Error();
}
}
}
assert.throws(Test262Error, function() {
'a'.replaceAll('a', custom);
});
function symbol() {
return {
toString() {
return Symbol();
}
}
}
assert.throws(TypeError, function() {
'a'.replaceAll('a', symbol);
});

View File

@ -0,0 +1,39 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Skip ToString(replaceValue) if it's a function
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
...
3. Let string be ? ToString(O).
4. Let searchString be ? ToString(searchValue).
5. Let functionalReplace be IsCallable(replaceValue).
6. If functionalReplace is false, then
a. Let replaceValue be ? ToString(replaceValue).
...
features: [String.prototype.replaceAll]
---*/
var called = 0;
var replaceValue = function() {
called += 1;
return 'b';
};
var poisoned = 0;
Object.defineProperty(replaceValue, 'toString', {
value: function() {
poisoned += 1;
throw 'should not call this';
}
});
var result = 'aaa'.replaceAll('a', replaceValue);
assert.sameValue(called, 3);
assert.sameValue(poisoned, 0);
assert.sameValue(result, 'bbb');

View File

@ -0,0 +1,75 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Returns abrupt completions from ToString(replaceValue)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
...
3. Let string be ? ToString(O).
4. Let searchString be ? ToString(searchValue).
5. Let functionalReplace be IsCallable(replaceValue).
6. If functionalReplace is false, then
a. Let replaceValue be ? ToString(replaceValue).
...
features: [String.prototype.replaceAll, Symbol]
---*/
assert.sameValue(
typeof String.prototype.replaceAll,
'function',
'function must exist'
);
var thisValueCalled = 0;
var thisValue = {
toString() {
thisValueCalled += 1;
return '';
}
};
var searchValueCalled = 0;
var searchValue = {
toString() {
searchValueCalled += 1;
return '';
}
};
var called = 0;
var replaceValue = {
toString() {
called += 1;
throw new Test262Error();
}
};
assert.throws(Test262Error, function() {
''.replaceAll.call(thisValue, searchValue, replaceValue);
}, 'custom');
assert.sameValue(called, 1);
assert.sameValue(thisValueCalled, 1);
assert.sameValue(searchValueCalled, 1);
searchValueCalled = 0;
thisValueCalled = 0;
called = 0;
replaceValue = {
toString() {
called += 1;
return Symbol();
}
};
assert.throws(TypeError, function() {
''.replaceAll.call(thisValue, searchValue, replaceValue);
}, 'Symbol');
assert.sameValue(called, 1);
assert.sameValue(thisValueCalled, 1);
assert.sameValue(searchValueCalled, 1);

View File

@ -0,0 +1,36 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
replaceValue is used to replace matching positions in string
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
...
5. Let functionalReplace be IsCallable(replaceValue).
6. If functionalReplace is false, then
a. Let replaceValue be ? ToString(replaceValue).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
features: [String.prototype.replaceAll]
---*/
var result = 'aaab a a aac'.replaceAll('aa', 'z');
assert.sameValue(result, 'zab a a zc');
result = 'aaab a a aac'.replaceAll('aa', 'a');
assert.sameValue(result, 'aab a a ac');
result = 'aaab a a aac'.replaceAll('a', 'a');
assert.sameValue(result, 'aaab a a aac');
result = 'aaab a a aac'.replaceAll('a', 'z');
assert.sameValue(result, 'zzzb z z zzc');

View File

@ -0,0 +1,97 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
ToString(replaceValue)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
...
5. Let functionalReplace be IsCallable(replaceValue).
6. If functionalReplace is false, then
a. Let replaceValue be ? ToString(replaceValue).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
features: [String.prototype.replaceAll, Symbol.toPrimitive]
---*/
var result;
var called;
var replaceValue;
called = 0;
replaceValue = {
[Symbol.toPrimitive](){
called += 1;
return 'z';
},
toString() {
throw 'poison';
},
valueOf() {
throw 'poison';
},
};
result = 'aa'.replaceAll('a', replaceValue);
assert.sameValue(result, 'zz', 'object @@toPrimitive');
assert.sameValue(called, 1, '@@toPrimitive is called only once');
called = 0;
replaceValue = {
[Symbol.toPrimitive]: undefined,
toString() {
called += 1;
return 'z';
},
valueOf() {
throw 'poison';
},
};
result = 'aa'.replaceAll('a', replaceValue);
assert.sameValue(result, 'zz', 'object toString');
assert.sameValue(called, 1, 'toString is called only once');
called = 0;
replaceValue = {
[Symbol.toPrimitive]: undefined,
toString: undefined,
valueOf() {
called += 1;
return 'z';
},
};
result = 'aa'.replaceAll('a', replaceValue);
assert.sameValue(result, 'zz', 'object valueOf');
assert.sameValue(called, 1, 'valueOf is called only once');
replaceValue = 42;
result = 'aa'.replaceAll('a', replaceValue);
assert.sameValue(result, '4242', 'number');
replaceValue = true;
result = 'aa'.replaceAll('a', replaceValue);
assert.sameValue(result, 'truetrue', 'Boolean true');
replaceValue = false;
result = 'aa'.replaceAll('a', replaceValue);
assert.sameValue(result, 'falsefalse', 'Boolean false');
replaceValue = undefined;
result = 'aa'.replaceAll('a', replaceValue);
assert.sameValue(result, 'undefinedundefined', 'undefined');
replaceValue = null;
result = 'aa'.replaceAll('a', replaceValue);
assert.sameValue(result, 'nullnull', 'null');

View File

@ -0,0 +1,41 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Matching empty string for the this value and the searchValue
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
...
5. Let functionalReplace be IsCallable(replaceValue).
6. If functionalReplace is false, then
a. Let replaceValue be ? ToString(replaceValue).
...
10. Let position be ! StringIndexOf(string, searchString, 0).
11. Repeat, while position is not -1
a. Append position to the end of matchPositions.
b. Let position be ! StringIndexOf(string, searchString, position + advanceBy).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
StringIndexOf ( string, searchValue, fromIndex )
...
4. Let len be the length of string.
5. If searchValue is the empty string, and fromIndex <= len, return fromIndex.
6. Let searchLen be the length of searchValue.
7. If there exists any integer k such that fromIndex k len - searchLen and for all nonnegative integers j less than searchLen, the code unit at index k + j within string is the same as the code unit at index j within searchValue, let pos be the smallest (closest to -) such integer. Otherwise, let pos be -1.
8. Return pos.
features: [String.prototype.replaceAll]
---*/
var result = ''.replaceAll('', 'abc');
assert.sameValue(result, 'abc');

View File

@ -0,0 +1,53 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Replacements when the search value is the empty string
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
10. Let position be ! StringIndexOf(string, searchString, 0).
11. Repeat, while position is not -1
a. Append position to the end of matchPositions.
b. Let position be ! StringIndexOf(string, searchString, position + advanceBy).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
StringIndexOf ( string, searchValue, fromIndex )
...
4. Let len be the length of string.
5. If searchValue is the empty string, and fromIndex <= len, return fromIndex.
6. Let searchLen be the length of searchValue.
7. If there exists any integer k such that fromIndex k len - searchLen and for all nonnegative integers j less than searchLen, the code unit at index k + j within string is the same as the code unit at index j within searchValue, let pos be the smallest (closest to -) such integer. Otherwise, let pos be -1.
8. Return pos.
Runtime Semantics: GetSubstitution ( matched, str, position, captures, namedCaptures, replacement )
...
2. Let matchLength be the number of code units in matched.
...
4. Let stringLength be the number of code units in str.
...
9. Let tailPos be position + matchLength.
10. Let m be the number of elements in captures.
11. Let result be the String value derived from replacement by copying code unit elements from replacement to result while performing replacements as specified in Table 53. These $ replacements are done left-to-right, and, once such a replacement is performed, the new replacement text is not subject to further replacements.
12 Return result.
features: [String.prototype.replaceAll]
---*/
var result;
result = 'aab c \nx'.replaceAll('', '_');
assert.sameValue(result, '_a_a_b_ _c_ _ _\n_x_');
result = 'a'.replaceAll('', '_');
assert.sameValue(result, '_a_');

View File

@ -0,0 +1,62 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Throws a TypeError if flags does not contain "g"
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
a. Let isRegExp be ? IsRegExp(searchString).
b. If isRegExp is true, then
i. Let flags be ? Get(searchValue, "flags").
ii. Perform ? RequireObjectCoercible(flags).
iii. If ? ToString(flags) does not contain "g", throw a TypeError exception.
...
features: [String.prototype.replaceAll, Symbol.match, Symbol]
---*/
assert.sameValue(
typeof String.prototype.replaceAll,
'function',
'function must exist'
);
var poisoned = 0;
var poison = {
toString() {
poisoned += 1;
throw 'Should not call toString on this/replaceValue';
},
};
var searchValue = /./;
assert.throws(TypeError, function() {
''.replaceAll.call(poison, searchValue, poison);
}, 'flags is the empty string');
Object.defineProperty(searchValue, 'flags', {
value: 'G',
writable: true,
configurable: true,
});
assert.throws(TypeError, function() {
''.replaceAll.call(poison, searchValue, poison);
}, 'case sensitive G');
Object.defineProperty(searchValue, 'flags', {
value: 'i',
writable: true,
configurable: true,
});
assert.throws(TypeError, function() {
''.replaceAll.call(poison, searchValue, poison);
}, 'i');
assert.sameValue(poisoned, 0);

View File

@ -0,0 +1,58 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Throws a TypeError if flags is not an ObjectCoercible (null or undefined)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
a. Let isRegExp be ? IsRegExp(searchString).
b. If isRegExp is true, then
i. Let flags be ? Get(searchValue, "flags").
ii. Perform ? RequireObjectCoercible(flags).
iii. If ? ToString(flags) does not contain "g", throw a TypeError exception.
...
features: [String.prototype.replaceAll, Symbol.match]
---*/
assert.sameValue(
typeof String.prototype.replaceAll,
'function',
'function must exist'
);
var poisoned = 0;
var poison = {
toString() {
poisoned += 1;
throw 'Should not call toString on this/replaceValue';
},
};
var called = 0;
var value = undefined;
var searchValue = {
[Symbol.match]: true,
get flags() {
called += 1;
return value;
}
};
assert.throws(TypeError, function() {
''.replaceAll.call(poison, searchValue, poison);
}, 'undefined');
assert.sameValue(called, 1);
called = 0;
value = null;
assert.throws(TypeError, function() {
''.replaceAll.call(poison, searchValue, poison);
}, 'null');
assert.sameValue(called, 1);
assert.sameValue(poisoned, 0);

View File

@ -0,0 +1,58 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Returns abrupt completions from ToString(flags)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
a. Let isRegExp be ? IsRegExp(searchString).
b. If isRegExp is true, then
i. Let flags be ? Get(searchValue, "flags").
ii. Perform ? RequireObjectCoercible(flags).
iii. If ? ToString(flags) does not contain "g", throw a TypeError exception.
...
features: [String.prototype.replaceAll, Symbol.match, Symbol]
---*/
assert.sameValue(
typeof String.prototype.replaceAll,
'function',
'function must exist'
);
var poisoned = 0;
var poison = {
toString() {
poisoned += 1;
throw 'Should not call toString on this/replaceValue';
},
};
var searchValue = {
[Symbol.match]: true,
flags: Symbol(),
toString() {
throw 'Should not call toString on searchValue';
}
};
assert.throws(TypeError, function() {
''.replaceAll.call(poison, searchValue, poison);
}, 'Symbol');
searchValue.flags = {
toString() {
throw new Test262Error();
}
};
assert.throws(Test262Error, function() {
''.replaceAll.call(poison, searchValue, poison);
}, 'custom abrupt');
assert.sameValue(poisoned, 0);

View File

@ -0,0 +1,84 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Return Abrupt completion from Get(searchValue, "flags")
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
a. Let isRegExp be ? IsRegExp(searchString).
b. If isRegExp is true, then
i. Let flags be ? Get(searchValue, "flags").
ii. Perform ? RequireObjectCoercible(flags).
iii. If ? ToString(flags) does not contain "g", throw a TypeError exception.
...
features: [String.prototype.replaceAll, Symbol.match]
---*/
var searchValue = {
[Symbol.match]: true,
get flags() {
throw new Test262Error;
}
};
var poisoned = 0;
var poison = {
toString() {
poisoned += 1;
throw 'Should not call toString on this/replaceValue';
},
};
assert.throws(Test262Error, function() {
''.replaceAll.call(poison, searchValue, poison);
}, 'from custom searchValue object');
var re1 = /./;
Object.defineProperty(re1, 'flags', {
get() { throw new Test262Error(); }
});
assert.throws(Test262Error, function() {
''.replaceAll.call(poison, re1, poison);
}, 'from RE instance, using default Symbol.match check');
var called = 0;
var re2 = /./;
Object.defineProperty(re2, Symbol.match, {
get() {
called += 1;
return true;
}
});
Object.defineProperty(re2, 'flags', {
get() { throw new Test262Error(); }
});
assert.throws(Test262Error, function() {
''.replaceAll.call(poison, re2, poison);
}, 'from RE instance, using Symbol.match check (true)');
assert.sameValue(called, 1);
called = 0;
var re3 = /./;
Object.defineProperty(re3, Symbol.match, {
get() {
called += 1;
return 1;
}
});
Object.defineProperty(re3, 'flags', {
get() { throw new Test262Error(); }
});
assert.throws(Test262Error, function() {
''.replaceAll.call(poison, re3, poison);
}, 'from RE instance, using Symbol.match check (1), uses Internal for IsRegExp');
assert.sameValue(called, 1);
assert.sameValue(poisoned, 0);

View File

@ -0,0 +1,47 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Return Abrupt completion from isRegExp
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
a. Let isRegExp be ? IsRegExp(searchString).
...
IsRegExp ( argument )
1. If Type(argument) is not Object, return false.
2. Let matcher be ? Get(argument, @@match).
3. If matcher is not undefined, return ! ToBoolean(matcher).
4. If argument has a [[RegExpMatcher]] internal slot, return true.
5. Return false.
features: [String.prototype.replaceAll, Symbol.match]
---*/
var searchValue = {
get [Symbol.match]() {
throw new Test262Error();
},
toString() {
throw 'Should not call toString on searchValue';
}
};
var poisoned = 0;
var poison = {
toString() {
poisoned += 1;
throw 'Should not call toString on this/replaceValue';
},
};
assert.throws(Test262Error, function() {
''.replaceAll.call(poison, searchValue, poison);
});
assert.sameValue(poisoned, 0);

View File

@ -0,0 +1,129 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Return abrupt completion from GetMethod(searchValeu @@replace)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
a. Let isRegExp be ? IsRegExp(searchString).
b. If isRegExp is true, then
i. Let flags be ? Get(searchValue, "flags").
ii. Perform ? RequireObjectCoercible(flags).
iii. If ? ToString(flags) does not contain "g", throw a TypeError exception.
c. Let replacer be ? GetMethod(searchValue, @@replace).
...
GetMethod ( V, P )
...
2. Let func be ? GetV(V, P).
3. If func is either undefined or null, return undefined.
4. If IsCallable(func) is false, throw a TypeError exception.
5. Return func.
features: [String.prototype.replaceAll, Symbol, Symbol.match, Symbol.replace]
---*/
var poisoned = 0;
var poison = {
toString() {
poisoned += 1;
throw 'Should not call toString on this/replaceValue';
},
};
var searchValue = {
[Symbol.match]: false,
flags: 'g',
get [Symbol.replace]() {
throw new Test262Error();
},
};
assert.throws(Test262Error, function() {
''.replaceAll.call(poison, searchValue, poison);
}, 'custom abrupt');
searchValue = {
[Symbol.match]: false,
flags: 'g',
[Symbol.replace]: {},
toString() {
throw 'Should not call toString on searchValue';
}
};
assert.throws(TypeError, function() {
''.replaceAll.call(poison, searchValue, poison);
}, '@@replace is an object (not callable)');
searchValue = {
[Symbol.match]: false,
flags: 'g',
[Symbol.replace]: '',
toString() {
throw 'Should not call toString on searchValue';
}
};
assert.throws(TypeError, function() {
''.replaceAll.call(poison, searchValue, poison);
}, '@@replace is a string');
searchValue = {
[Symbol.match]: false,
flags: 'g',
[Symbol.replace]: 42,
toString() {
throw 'Should not call toString on searchValue';
}
};
assert.throws(TypeError, function() {
''.replaceAll.call(poison, searchValue, poison);
}, '@@replace is a number');
searchValue = {
[Symbol.match]: false,
flags: 'g',
[Symbol.replace]: Symbol(),
toString() {
throw 'Should not call toString on searchValue';
}
};
assert.throws(TypeError, function() {
''.replaceAll.call(poison, searchValue, poison);
}, '@@replace is a symbol');
searchValue = {
[Symbol.match]: false,
flags: 'g',
[Symbol.replace]: true,
toString() {
throw 'Should not call toString on searchValue';
}
};
assert.throws(TypeError, function() {
''.replaceAll.call(poison, searchValue, poison);
}, '@@replace is true');
searchValue = {
[Symbol.match]: false,
flags: 'g',
[Symbol.replace]: false,
toString() {
throw 'Should not call toString on searchValue';
}
};
assert.throws(TypeError, function() {
''.replaceAll.call(poison, searchValue, poison);
}, '@@replace is false');
assert.sameValue(poisoned, 0);

View File

@ -0,0 +1,123 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
A RegExp searchValue's Symbol.replace can be called instead of the next steps of replaceAll
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
a. Let isRegExp be ? IsRegExp(searchString).
b. If isRegExp is true, then
i. Let flags be ? Get(searchValue, "flags").
ii. Perform ? RequireObjectCoercible(flags).
iii. If ? ToString(flags) does not contain "g", throw a TypeError exception.
c. Let replacer be ? GetMethod(searchValue, @@replace).
d. If replacer is not undefined, then
i. Return ? Call(replacer, searchValue, « O, replaceValue »).
3. Let string be ? ToString(O).
4. Let searchString be ? ToString(searchValue).
...
features: [String.prototype.replaceAll, Symbol.replace, class]
includes: [compareArray.js]
---*/
let called = 0;
class RE extends RegExp {
[Symbol.replace](...args) {
const actual = super[Symbol.replace](...args);
// Ordering is intentional to observe call from super
called += 1;
return actual;
}
toString() {
throw 'Should not call toString on searchValue';
}
}
const t = (function() { return this; })();
let calls;
function getFn(val) {
return function replaceValueFn(...args) {
calls.push([this, ...args]);
return val;
};
}
const samples = [
[ '(a)', 'aaa abc', 'z', 'zzz zbc' ],
[ '(a)', 'aaa abc', '$1', '$1$1$1 $1bc' ],
[ '(a)', 'aaa abc', '$$', '$$$$$$ $$bc' ],
[ '(a)', 'aaa abc', '$&', '$&$&$& $&bc' ],
[ '(a)', 'aaa abc', '$\'', '$\'$\'$\' $\'bc' ],
[ '(a)', 'aaa abc', '$`', '$`$`$` $`bc' ],
];
let count = 0;
for (const [ reStr, thisValue, replaceValue, expected ] of samples) {
const searchValue = new RE(reStr, 'g');
const replaceFn = getFn(replaceValue);
// Observes the toString
const obj = new String(thisValue);
called = 0;
calls = [];
const actual = obj.replaceAll(searchValue, replaceFn);
const message = `sample ${count}: '${thisValue}'.replaceAll(/${reStr}/g, () => '${replaceValue}')`;
assert.sameValue(called, 1, `called -- ${message}`);
assert.sameValue(actual, expected, `actual -- ${message}`);
assert.sameValue(calls.length, 4, `calls.length -- ${message}`);
assert.compareArray(calls[0], [t, 'a', 'a', 0, thisValue]);
assert.compareArray(calls[1], [t, 'a', 'a', 1, thisValue]);
assert.compareArray(calls[2], [t, 'a', 'a', 2, thisValue]);
assert.compareArray(calls[3], [t, 'a', 'a', 4, thisValue]);
count += 1;
}
const samplesSticky = [
[ '(a)', 'aaa abc', 'z', 'zzz abc' ],
[ '(a)', 'aaa abc', '$1', '$1$1$1 abc' ],
[ '(a)', 'aaa abc', '$$', '$$$$$$ abc' ],
[ '(a)', 'aaa abc', '$&', '$&$&$& abc' ],
[ '(a)', 'aaa abc', '$\'', '$\'$\'$\' abc' ],
[ '(a)', 'aaa abc', '$`', '$`$`$` abc' ],
];
count = 0;
for (const [ reStr, thisValue, replaceValue, expected ] of samplesSticky) {
const searchValue = new RE(reStr, 'gy');
const replaceFn = getFn(replaceValue);
// Observes the toString
const obj = new String(thisValue);
called = 0;
calls = [];
const actual = obj.replaceAll(searchValue, replaceFn);
const message = `sample ${count}: '${thisValue}'.replaceAll(/${reStr}/gy, () => '${replaceValue}')`;
assert.sameValue(called, 1, `called -- ${message}`);
assert.sameValue(actual, expected, `actual -- ${message}`);
assert.sameValue(calls.length, 3, `calls.length -- ${message}`);
assert.compareArray(calls[0], [t, 'a', 'a', 0, thisValue]);
assert.compareArray(calls[1], [t, 'a', 'a', 1, thisValue]);
assert.compareArray(calls[2], [t, 'a', 'a', 2, thisValue]);
count += 1;
}

View File

@ -0,0 +1,82 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
A RegExp searchValue's Symbol.replace can be called instead of the next steps of replaceAll
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
a. Let isRegExp be ? IsRegExp(searchString).
b. If isRegExp is true, then
i. Let flags be ? Get(searchValue, "flags").
ii. Perform ? RequireObjectCoercible(flags).
iii. If ? ToString(flags) does not contain "g", throw a TypeError exception.
c. Let replacer be ? GetMethod(searchValue, @@replace).
d. If replacer is not undefined, then
i. Return ? Call(replacer, searchValue, « O, replaceValue »).
3. Let string be ? ToString(O).
4. Let searchString be ? ToString(searchValue).
...
features: [String.prototype.replaceAll, Symbol.replace, class]
---*/
let called = 0;
class RE extends RegExp {
[Symbol.replace](...args) {
const actual = super[Symbol.replace](...args);
// Ordering is intentional to observe call from super
called += 1;
return actual;
}
toString() {
throw 'Should not call toString on searchValue';
}
}
const samples = [
[ ['b', 'g'], 'abc abc abc', 'z', 'azc azc azc' ],
[ ['b', 'gy'], 'abc abc abc', 'z', 'abc abc abc' ],
[ ['b', 'giy'], 'abc abc abc', 'z', 'abc abc abc' ],
[ [ '[A-Z]', 'g' ], 'No Uppercase!', '', 'o ppercase!' ],
[ [ '[A-Z]', 'gy' ], 'No Uppercase?', '', 'o Uppercase?' ],
[ [ '[A-Z]', 'gy' ], 'NO UPPERCASE!', '', ' UPPERCASE!' ],
[ [ 'a(b)(ca)', 'g' ], 'abcabcabcabc', '$2-$1', 'ca-bbcca-bbc' ],
[ [ '(a(.))', 'g' ], 'abcabcabcabc', '$1$2$3', 'abb$3cabb$3cabb$3cabb$3c' ],
[ [ '(((((((((((((a(.).).).).).).).).))))))', 'g' ], 'aabacadaeafagahaiajakalamano a azaya', '($10)-($12)-($1)', '(aabaca)-(aaba)-(aabacadaea)f(agahai)-(agah)-(agahaiajak)(alaman)-(alam)-(alamano a )azaya' ],
[ [ 'b', 'g' ], 'abcba', '$\'', 'acbacaa' ],
[ [ 'b', 'g' ], 'abcba', '$`', 'aacabca' ],
[ [ '(?<named>b)', 'g' ], 'abcba', '($<named>)', 'a(b)c(b)a' ],
[ [ '(?<named>b)', 'g' ], 'abcba', '($<named)', 'a($<named)c($<named)a' ],
[ [ '(?<named>b)', 'g' ], 'abcba', '($<unnamed>)', 'a()c()a' ],
[ [ 'a(b)(ca)', 'g' ], 'abcabcabcabc', '($$)', '($)bc($)bc' ],
[ [ 'a(b)(ca)', 'g' ], 'abcabcabcabc', '($)', '($)bc($)bc' ],
[ [ 'a(b)(ca)', 'g' ], 'abcabcabcabc', '($$$$)', '($$)bc($$)bc' ],
[ [ 'a(b)(ca)', 'g' ], 'abcabcabcabc', '($$$)', '($$)bc($$)bc' ],
[ [ 'a(b)(ca)', 'g' ], 'abcabcabcabc', '($$&)', '($&)bc($&)bc' ],
[ [ 'a(b)(ca)', 'g' ], 'abcabcabcabc', '($$1)', '($1)bc($1)bc' ],
[ [ 'a(b)(ca)', 'g' ], 'abcabcabcabc', '($$`)', '($`)bc($`)bc' ],
[ [ 'a(b)(ca)', 'g' ], 'abcabcabcabc', '($$\')', '($\')bc($\')bc' ],
[ [ 'a(?<z>b)(ca)', 'g' ], 'abcabcabcabc', '($$<z>)', '($<z>)bc($<z>)bc' ],
[ [ 'a(b)(ca)', 'g' ], 'abcabcabcabc', '($&)', '(abca)bc(abca)bc' ],
];
let count = 0;
for (const [ [ reStr, flags ], thisValue, replaceValue, expected ] of samples) {
const searchValue = new RE(reStr, flags);
called = 0;
const actual = thisValue.replaceAll(searchValue, replaceValue);
const message = `sample ${count}: '${thisValue}'.replaceAll(/${reStr}/${flags}, '${replaceValue}')`;
assert.sameValue(called, 1, message);
assert.sameValue(actual, expected, message);
count += 1;
}

View File

@ -0,0 +1,58 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
The searchValue is observed before ToString(this value) and ToString(replaceValue)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
a. Let isRegExp be ? IsRegExp(searchString).
b. If isRegExp is true, then
i. Let flags be ? Get(searchValue, "flags").
ii. Perform ? RequireObjectCoercible(flags).
iii. If ? ToString(flags) does not contain "g", throw a TypeError exception.
c. Let replacer be ? GetMethod(searchValue, @@replace).
d. If replacer is not undefined, then
i. Return ? Call(replacer, searchValue, « O, replaceValue »).
3. Let string be ? ToString(O).
4. Let searchString be ? ToString(searchValue).
...
features: [String.prototype.replaceAll, Symbol.replace]
---*/
var called = 0;
var searchValue = /./g;
Object.defineProperty(searchValue, Symbol.replace, {
value: function(O, replaceValue) {
assert.sameValue(this, searchValue);
assert.sameValue(O, poison, 'first arg is the this value of replaceAll');
assert.sameValue(replaceValue, poison, 'second arg is the replaceValue');
assert.sameValue(arguments.length, 2);
called += 1;
return 'return from searchValue';
}
});
Object.defineProperty(searchValue, 'toString', {
value: function() {
throw 'Should not call toString on searchValue';
}
});
var poisoned = 0;
var poison = {
toString() {
poisoned += 1;
throw 'Should not call toString on this/replaceValue';
},
};
var returned = ''.replaceAll.call(poison, searchValue, poison);
assert.sameValue(returned, 'return from searchValue');
assert.sameValue(called, 1);
assert.sameValue(poisoned, 0);

View File

@ -0,0 +1,48 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Return abrupt completion from Call.call(poison, replacer, poison)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
a. Let isRegExp be ? IsRegExp(searchString).
b. If isRegExp is true, then
i. Let flags be ? Get(searchValue, "flags").
ii. Perform ? RequireObjectCoercible(flags).
iii. If ? ToString(flags) does not contain "g", throw a TypeError exception.
c. Let replacer be ? GetMethod(searchValue, @@replace).
d. If replacer is not undefined, then
i. Return ? Call(replacer, searchValue, « O, replaceValue »).
...
features: [String.prototype.replaceAll, Symbol.match, Symbol.replace]
---*/
var poisoned = 0;
var poison = {
toString() {
poisoned += 1;
throw 'Should not call toString on this/replaceValue';
},
};
var searchValue = {
[Symbol.match]: false,
flags: 'g',
[Symbol.replace]() {
throw new Test262Error();
},
toString() {
throw 'Should not call toString on searchValue';
}
};
assert.throws(Test262Error, function() {
''.replaceAll.call(poison, searchValue, poison);
});
assert.sameValue(poisoned, 0);

View File

@ -0,0 +1,55 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Return value from Call(replacer, ...)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
a. Let isRegExp be ? IsRegExp(searchString).
b. If isRegExp is true, then
i. Let flags be ? Get(searchValue, "flags").
ii. Perform ? RequireObjectCoercible(flags).
iii. If ? ToString(flags) does not contain "g", throw a TypeError exception.
c. Let replacer be ? GetMethod(searchValue, @@replace).
d. If replacer is not undefined, then
i. Return ? Call(replacer, searchValue, « O, replaceValue »).
3. Let string be ? ToString(O).
4. Let searchString be ? ToString(searchValue).
5. Let functionalReplace be IsCallable(replaceValue).
6. If functionalReplace is false, then
a. Let replaceValue be ? ToString(replaceValue).
...
features: [String.prototype.replaceAll, Symbol.replace]
---*/
var called = 0;
var searchValue = /./g;
Object.defineProperty(searchValue, Symbol.replace, {
value: function(O, replaceValue) {
assert.sameValue(this, searchValue);
assert.sameValue(O, str, 'first arg is the this value of replaceAll');
assert.sameValue(replaceValue, obj, 'second arg is the replaceValue');
assert.sameValue(arguments.length, 2);
called += 1;
return 42;
}
});
Object.defineProperty(searchValue, 'toString', {
value: function() {
throw 'Should not call searchValue toString'
}
});
var str = new String('Leo');
var obj = {};
var returned = str.replaceAll(searchValue, obj);
assert.sameValue(returned, 42);
assert.sameValue(called, 1);

View File

@ -0,0 +1,74 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Returns abrupt completions from ToString(searchValue)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
...
3. Let string be ? ToString(O).
4. Let searchString be ? ToString(searchValue).
5. Let functionalReplace be IsCallable(replaceValue).
6. If functionalReplace is false, then
a. Let replaceValue be ? ToString(replaceValue).
...
features: [String.prototype.replaceAll, Symbol]
---*/
assert.sameValue(
typeof String.prototype.replaceAll,
'function',
'function must exist'
);
var poisoned = 0;
var poison = {
toString() {
poisoned += 1;
throw 'Should not call toString on replaceValue';
},
};
var thisValueCalled = 0;
var thisValue = {
toString() {
thisValueCalled += 1;
return '';
}
};
var called = 0;
var searchValue = {
toString() {
called += 1;
throw new Test262Error();
}
};
assert.throws(Test262Error, function() {
''.replaceAll.call(thisValue, searchValue, poison);
}, 'custom');
assert.sameValue(called, 1);
assert.sameValue(thisValueCalled, 1);
thisValueCalled = 0;
called = 0;
searchValue = {
toString() {
called += 1;
return Symbol();
}
};
assert.throws(TypeError, function() {
''.replaceAll.call(thisValue, searchValue, poison);
}, 'Symbol');
assert.sameValue(called, 1);
assert.sameValue(thisValueCalled, 1);
assert.sameValue(poisoned, 0);

View File

@ -0,0 +1,56 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
ToString(searchValue)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
...
4. Let searchString be ? ToString(searchValue).
5. Let functionalReplace be IsCallable(replaceValue).
6. If functionalReplace is false, then
a. Let replaceValue be ? ToString(replaceValue).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
features: [String.prototype.replaceAll, Symbol.replace]
---*/
var result;
var searchValue;
searchValue = /./g;
Object.defineProperty(searchValue, Symbol.replace, { value: undefined });
result = 'aa /./g /./g aa'.replaceAll(searchValue, 'z');
assert.sameValue(result, 'aa z z aa', '/./g');
searchValue = /./gy;
Object.defineProperty(searchValue, Symbol.replace, { value: undefined });
result = 'aa /./gy /./gy aa'.replaceAll(searchValue, 'z');
assert.sameValue(result, 'aa z z aa', '/./gy');
searchValue = /./gi;
Object.defineProperty(searchValue, Symbol.replace, { value: undefined });
result = 'aa /./gi /./gi aa'.replaceAll(searchValue, 'z');
assert.sameValue(result, 'aa z z aa', '/./gi');
searchValue = /./iyg;
Object.defineProperty(searchValue, Symbol.replace, { value: undefined });
result = 'aa /./giy /./iyg /./gyi /./giy aa'.replaceAll(searchValue, 'z');
assert.sameValue(result, 'aa z /./iyg /./gyi z aa', '/./iyg');

View File

@ -0,0 +1,30 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Throws TypeError when `this` is null
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
...
RequireObjectCoercible ( argument )
- Undefined: Throw a TypeError exception.
- Null: Throw a TypeError exception.
features: [String.prototype.replaceAll]
---*/
assert.sameValue(
typeof String.prototype.replaceAll,
'function',
'function must exist'
);
assert.throws(TypeError, function() {
String.prototype.replaceAll.call(null);
});

View File

@ -0,0 +1,29 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Throws TypeError when `this` is undefined
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
...
RequireObjectCoercible ( argument )
- Undefined: Throw a TypeError exception.
- Null: Throw a TypeError exception.
features: [String.prototype.replaceAll]
---*/
assert.sameValue(
typeof String.prototype.replaceAll,
'function',
'function must exist'
);
assert.throws(TypeError, function() {
String.prototype.replaceAll.call(undefined);
});

View File

@ -0,0 +1,65 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
Returns abrupt completions from ToString(this value)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
1. Let O be RequireObjectCoercible(this value).
2. If searchValue is neither undefined nor null, then
...
3. Let string be ? ToString(O).
...
features: [String.prototype.replaceAll, Symbol]
---*/
assert.sameValue(
typeof String.prototype.replaceAll,
'function',
'function must exist'
);
var poisoned = 0;
var poison = {
toString() {
poisoned += 1;
throw 'Should not call toString on replaceValue';
},
};
var called = 0;
var thisValue = {
toString() {
called += 1;
throw new Test262Error();
}
}
var searchValue = {
toString() {
throw 'Should not call toString on searchValue';
}
};
assert.throws(Test262Error, function() {
''.replaceAll.call(thisValue, searchValue, poison);
}, 'custom');
assert.sameValue(called, 1);
called = 0;
thisValue = {
toString() {
called += 1;
return Symbol();
}
};
assert.throws(TypeError, function() {
''.replaceAll.call(thisValue, searchValue, poison);
}, 'Symbol');
assert.sameValue(called, 1);
assert.sameValue(poisoned, 0);

View File

@ -0,0 +1,91 @@
// Copyright (C) 2019 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-string.prototype.replaceall
description: >
ToString(this value)
info: |
String.prototype.replaceAll ( searchValue, replaceValue )
...
3. Let string be ? ToString(O).
4. Let searchString be ? ToString(searchValue).
5. Let functionalReplace be IsCallable(replaceValue).
6. If functionalReplace is false, then
a. Let replaceValue be ? ToString(replaceValue).
...
14. For each position in matchPositions, do
a. If functionalReplace is true, then
...
b. Else,
...
ii. Let captures be a new empty List.
iii. Let replacement be GetSubstitution(searchString, string, position, captures, undefined, replaceValue).
features: [String.prototype.replaceAll, Symbol.toPrimitive]
---*/
var result;
var called;
var thisValue;
called = 0;
thisValue = {
[Symbol.toPrimitive](){
called += 1;
return 'aa';
},
toString() {
throw 'poison';
},
valueOf() {
throw 'poison';
},
};
result = ''.replaceAll.call(thisValue, 'a', 'z');
assert.sameValue(result, 'zz', 'object @@toPrimitive');
assert.sameValue(called, 1, '@@toPrimitive is called only once');
called = 0;
thisValue = {
[Symbol.toPrimitive]: undefined,
toString() {
called += 1;
return 'aa';
},
valueOf() {
throw 'poison';
},
};
result = ''.replaceAll.call(thisValue, 'a', 'z');
assert.sameValue(result, 'zz', 'object toString');
assert.sameValue(called, 1, 'toString is called only once');
called = 0;
thisValue = {
[Symbol.toPrimitive]: undefined,
toString: undefined,
valueOf() {
called += 1;
return 'aa';
},
};
result = ''.replaceAll.call(thisValue, 'a', 'z');
assert.sameValue(result, 'zz', 'object valueOf');
assert.sameValue(called, 1, 'valueOf is called only once');
thisValue = 4244;
result = ''.replaceAll.call(thisValue, '4', 'z');
assert.sameValue(result, 'z2zz', 'number');
thisValue = true;
result = ''.replaceAll.call(thisValue, 'ru', 'o m');
assert.sameValue(result, 'to me', 'Boolean true');
thisValue = false;
result = ''.replaceAll.call(thisValue, 'al', 'on');
assert.sameValue(result, 'fonse', 'Boolean false');