summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call-fn.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call-fn.js')
-rw-r--r--js/src/tests/test262/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call-fn.js125
1 files changed, 125 insertions, 0 deletions
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);