diff options
Diffstat (limited to 'js/src/tests/test262/built-ins/String/prototype/replaceAll')
43 files changed, 2454 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/browser.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/browser.js diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0024.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0024.js new file mode 100644 index 0000000000..c4e83a5636 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0024.js @@ -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 ($$) +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.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0026.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0026.js new file mode 100644 index 0000000000..17f2031231 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0026.js @@ -0,0 +1,66 @@ +// 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.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0027.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0027.js new file mode 100644 index 0000000000..4bb9f00b60 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0027.js @@ -0,0 +1,66 @@ +// 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.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x003C.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x003C.js new file mode 100644 index 0000000000..a41388960c --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x003C.js @@ -0,0 +1,73 @@ +// 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($<$<)'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0060.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0060.js new file mode 100644 index 0000000000..f82f575bf4 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0060.js @@ -0,0 +1,69 @@ +// 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.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024.js new file mode 100644 index 0000000000..125fcdd7dd --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024.js @@ -0,0 +1,66 @@ +// 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.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024N.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024N.js new file mode 100644 index 0000000000..97e92fead1 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024N.js @@ -0,0 +1,95 @@ +// 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) ---'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024NN.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024NN.js new file mode 100644 index 0000000000..96c3798b35 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/getSubstitution-0x0024NN.js @@ -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: > + 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)'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/length.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/length.js new file mode 100644 index 0000000000..9bd309d638 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/length.js @@ -0,0 +1,23 @@ +// 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, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/name.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/name.js new file mode 100644 index 0000000000..9ca5c78acb --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/name.js @@ -0,0 +1,23 @@ +// 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, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/not-a-constructor.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/not-a-constructor.js new file mode 100644 index 0000000000..b3b9ca6503 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/not-a-constructor.js @@ -0,0 +1,35 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + String.prototype.replaceAll does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, arrow-function] +---*/ + +assert.sameValue( + isConstructor(String.prototype.replaceAll), + false, + 'isConstructor(String.prototype.replaceAll) must return false' +); + +assert.throws(TypeError, () => { + new String.prototype.replaceAll(); +}, '`new String.prototype.replaceAll()` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceAll.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceAll.js new file mode 100644 index 0000000000..d46cba45b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceAll.js @@ -0,0 +1,28 @@ +// 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, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-abrupt.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-abrupt.js new file mode 100644 index 0000000000..24c586519f --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-abrupt.js @@ -0,0 +1,28 @@ +// 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); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-each-match-position.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-each-match-position.js new file mode 100644 index 0000000000..0873c0dd28 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-each-match-position.js @@ -0,0 +1,44 @@ +// 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]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-matching-empty.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-matching-empty.js new file mode 100644 index 0000000000..20bad8d142 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-matching-empty.js @@ -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: > + 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]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-skip-no-match.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-skip-no-match.js new file mode 100644 index 0000000000..d8e75b817b --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-skip-no-match.js @@ -0,0 +1,34 @@ +// 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' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-tostring-abrupt.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-tostring-abrupt.js new file mode 100644 index 0000000000..d4d605a456 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-call-tostring-abrupt.js @@ -0,0 +1,44 @@ +// 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); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-fn-skip-toString.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-fn-skip-toString.js new file mode 100644 index 0000000000..77c34425fd --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-fn-skip-toString.js @@ -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: > + 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'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-tostring-abrupt.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-tostring-abrupt.js new file mode 100644 index 0000000000..c674303092 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-tostring-abrupt.js @@ -0,0 +1,77 @@ +// 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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-value-replaces-string.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-value-replaces-string.js new file mode 100644 index 0000000000..e009730f8d --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-value-replaces-string.js @@ -0,0 +1,38 @@ +// 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'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-value-tostring.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-value-tostring.js new file mode 100644 index 0000000000..aa9d1a5549 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/replaceValue-value-tostring.js @@ -0,0 +1,99 @@ +// 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'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-empty-string-this-empty-string.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-empty-string-this-empty-string.js new file mode 100644 index 0000000000..db3e44c1f9 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-empty-string-this-empty-string.js @@ -0,0 +1,43 @@ +// 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'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-empty-string.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-empty-string.js new file mode 100644 index 0000000000..3ab6dde25a --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-empty-string.js @@ -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: > + 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_'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-flags-no-g-throws.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-flags-no-g-throws.js new file mode 100644 index 0000000000..4bf1ad9aa9 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-flags-no-g-throws.js @@ -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: > + 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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-flags-null-undefined-throws.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-flags-null-undefined-throws.js new file mode 100644 index 0000000000..feb898c2de --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-flags-null-undefined-throws.js @@ -0,0 +1,60 @@ +// 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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-flags-toString-abrupt.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-flags-toString-abrupt.js new file mode 100644 index 0000000000..de261a961c --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-flags-toString-abrupt.js @@ -0,0 +1,60 @@ +// 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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-get-flags-abrupt.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-get-flags-abrupt.js new file mode 100644 index 0000000000..bf9bb3edc4 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-get-flags-abrupt.js @@ -0,0 +1,86 @@ +// 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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-isRegExp-abrupt.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-isRegExp-abrupt.js new file mode 100644 index 0000000000..8933fa13b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-isRegExp-abrupt.js @@ -0,0 +1,49 @@ +// 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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call-fn.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call-fn.js new file mode 100644 index 0000000000..b81dfe90ba --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call-fn.js @@ -0,0 +1,125 @@ +// 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; +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call.js new file mode 100644 index 0000000000..d556547a38 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call.js @@ -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: > + 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; +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-before-tostring.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-before-tostring.js new file mode 100644 index 0000000000..82136a4b42 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-before-tostring.js @@ -0,0 +1,60 @@ +// 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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-call-abrupt.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-call-abrupt.js new file mode 100644 index 0000000000..ed35fa7ed1 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-call-abrupt.js @@ -0,0 +1,50 @@ +// 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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-call.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-call.js new file mode 100644 index 0000000000..2ad07f3c18 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-call.js @@ -0,0 +1,57 @@ +// 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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-is-null.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-is-null.js new file mode 100644 index 0000000000..9614eec319 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-is-null.js @@ -0,0 +1,37 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-string.prototype.replaceall +description: > + If searchValue's Symbol.replace property is null, no error is thrown. +info: | + String.prototype.replaceAll ( searchValue, replaceValue ) + + [...] + 2. If searchValue is neither undefined nor null, then + [...] + c. Let replacer be ? GetMethod(searchValue, @@replace). + d. If replacer is not undefined, then + [...] + [...] + 16. Return result. + + GetMethod ( V, P ) + + [...] + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. +features: [String.prototype.replaceAll, Symbol.replace] +---*/ + +var searchValue = {}; +searchValue[Symbol.replace] = null; +searchValue.toString = function() { return "2"; }; +searchValue.valueOf = function() { throw new Test262Error("should not be called"); }; + +var replacer = function() { return "<foo>"; }; +assert.sameValue("a2b2c".replaceAll(searchValue, replacer), "a<foo>b<foo>c"); +assert.sameValue("a2b2c".replaceAll(searchValue, "<foo>"), "a<foo>b<foo>c"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-method-abrupt.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-method-abrupt.js new file mode 100644 index 0000000000..1556a15ef1 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-method-abrupt.js @@ -0,0 +1,131 @@ +// 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(searchValue.@@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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-tostring-abrupt.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-tostring-abrupt.js new file mode 100644 index 0000000000..fa7926c90a --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-tostring-abrupt.js @@ -0,0 +1,76 @@ +// 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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-tostring-regexp.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-tostring-regexp.js new file mode 100644 index 0000000000..1cdfdbc2e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-tostring-regexp.js @@ -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: > + 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'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/shell.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/shell.js diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/this-is-null-throws.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/this-is-null-throws.js new file mode 100644 index 0000000000..eb84d25c5b --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/this-is-null-throws.js @@ -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: > + 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); +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/this-is-undefined-throws.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/this-is-undefined-throws.js new file mode 100644 index 0000000000..eadce773df --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/this-is-undefined-throws.js @@ -0,0 +1,31 @@ +// 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); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/this-tostring-abrupt.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/this-tostring-abrupt.js new file mode 100644 index 0000000000..fc3376918c --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/this-tostring-abrupt.js @@ -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: > + 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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/String/prototype/replaceAll/this-tostring.js b/js/src/tests/test262/built-ins/String/prototype/replaceAll/this-tostring.js new file mode 100644 index 0000000000..3de2a9919a --- /dev/null +++ b/js/src/tests/test262/built-ins/String/prototype/replaceAll/this-tostring.js @@ -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: > + 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'); + +reportCompare(0, 0); |