From c36bdcfeb37fbcad17ac0ca6cd74d1e4c6afb771 Mon Sep 17 00:00:00 2001
From: Peter Wong <peter.wm.wong@gmail.com>
Date: Mon, 10 Dec 2018 09:53:01 -0600
Subject: [PATCH] Update tests for String.prototype.matchAll (#1990)

- Changes associated with spec changes (tc39/proposal-string-matchall#41)
- Update spec comments
- Added test verifying error thrown when `regexp[Symbol.matchAll]` is not callable
- Added test verifying `ToString` is called on `receiver`
---
 .../prototype/matchAll/regexp-is-null.js      | 11 ++---
 ...p-is-undefined-or-null-invokes-matchAll.js | 30 ++++++++++++++
 .../regexp-matchAll-is-undefined-or-null.js   | 38 +++++++++++++++++
 .../matchAll/regexp-matchAll-not-callable.js  | 34 +++++++++++++++
 .../regexp-prototype-has-no-matchAll.js       | 19 +++------
 .../prototype/matchAll/toString-this-val.js   | 41 +++++++++++++++++++
 6 files changed, 151 insertions(+), 22 deletions(-)
 create mode 100644 test/built-ins/String/prototype/matchAll/regexp-is-undefined-or-null-invokes-matchAll.js
 create mode 100644 test/built-ins/String/prototype/matchAll/regexp-matchAll-is-undefined-or-null.js
 create mode 100644 test/built-ins/String/prototype/matchAll/regexp-matchAll-not-callable.js
 create mode 100644 test/built-ins/String/prototype/matchAll/toString-this-val.js

diff --git a/test/built-ins/String/prototype/matchAll/regexp-is-null.js b/test/built-ins/String/prototype/matchAll/regexp-is-null.js
index 9ae102e6b1..180d7b94ca 100644
--- a/test/built-ins/String/prototype/matchAll/regexp-is-null.js
+++ b/test/built-ins/String/prototype/matchAll/regexp-is-null.js
@@ -8,14 +8,9 @@ info: |
     1. Let O be ? RequireObjectCoercible(this value).
     2. If regexp is neither undefined nor null, then
       [...]
-    3. Return ? MatchAllIterator(regexp, O).
-
-  MatchAllIterator( regexp, O )
-    [...]
-    2. If ? IsRegExp(regexp) is true, then
-      [...]
-    3. Else,
-      a. Let R be RegExpCreate(regexp, "g").
+    3. Let S be ? ToString(O).
+    4. Let rx be ? RegExpCreate(R, "g").
+    5. Return ? Invoke(rx, @@matchAll, « S »).
 features: [String.prototype.matchAll]
 includes: [compareArray.js, compareIterator.js, regExpUtils.js]
 ---*/
diff --git a/test/built-ins/String/prototype/matchAll/regexp-is-undefined-or-null-invokes-matchAll.js b/test/built-ins/String/prototype/matchAll/regexp-is-undefined-or-null-invokes-matchAll.js
new file mode 100644
index 0000000000..adb3705246
--- /dev/null
+++ b/test/built-ins/String/prototype/matchAll/regexp-is-undefined-or-null-invokes-matchAll.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2018 Peter Wong. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: pending
+description: Behavior when regexp is null or undefined
+info: |
+  String.prototype.matchAll ( regexp )
+    1. Let O be ? RequireObjectCoercible(this value).
+    2. If regexp is neither undefined nor null, then
+      [...]
+    3. Let S be ? ToString(O).
+    4. Let rx be ? RegExpCreate(R, "g").
+    5. Return ? Invoke(rx, @@matchAll, « S »).
+features: [String.prototype.matchAll]
+includes: [compareArray.js, compareIterator.js, regExpUtils.js]
+---*/
+
+var callCount = 0;
+var obj = {};
+RegExp.prototype[Symbol.matchAll] = function() {
+  callCount++;
+  return obj;
+};
+
+assert.sameValue('a'.matchAll(null), obj);
+assert.sameValue(callCount, 1);
+
+assert.sameValue(''.matchAll(undefined), obj);
+assert.sameValue(callCount, 2);
+
diff --git a/test/built-ins/String/prototype/matchAll/regexp-matchAll-is-undefined-or-null.js b/test/built-ins/String/prototype/matchAll/regexp-matchAll-is-undefined-or-null.js
new file mode 100644
index 0000000000..d11ff8ad6b
--- /dev/null
+++ b/test/built-ins/String/prototype/matchAll/regexp-matchAll-is-undefined-or-null.js
@@ -0,0 +1,38 @@
+// Copyright (C) 2018 Peter Wong. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: pending
+description: Behavior when regexp[@@matchAll] is undefined or null
+info: |
+  String.prototype.matchAll ( regexp )
+    1. Let O be ? RequireObjectCoercible(this value).
+    2. If regexp is neither undefined nor null, then
+      a. Let matcher be ? GetMethod(regexp, @@matchAll).
+      b. If matcher is not undefined, then
+        [...]
+    3. Let S be ? ToString(O).
+    4. Let rx be ? RegExpCreate(R, "g").
+    5. Return ? Invoke(rx, @@matchAll, « S »).
+features: [Symbol.matchAll, String.prototype.matchAll]
+---*/
+
+var regexp = /./;
+var callCount = 0;
+var arg;
+var obj = {};
+var str = 'abc';
+RegExp.prototype[Symbol.matchAll] = function(string) {
+  arg = string;
+  callCount++;
+  return obj;
+};
+
+regexp[Symbol.matchAll] = undefined;
+assert.sameValue(str.matchAll(regexp), obj);
+assert.sameValue(arg, str);
+assert.sameValue(callCount, 1);
+
+regexp[Symbol.matchAll] = null;
+assert.sameValue(str.matchAll(regexp), obj);
+assert.sameValue(arg, str);
+assert.sameValue(callCount, 2);
diff --git a/test/built-ins/String/prototype/matchAll/regexp-matchAll-not-callable.js b/test/built-ins/String/prototype/matchAll/regexp-matchAll-not-callable.js
new file mode 100644
index 0000000000..de3568c346
--- /dev/null
+++ b/test/built-ins/String/prototype/matchAll/regexp-matchAll-not-callable.js
@@ -0,0 +1,34 @@
+// Copyright (C) 2018 Peter Wong. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: pending
+description: Behavior when regexp[@@matchAll] is not callable
+info: |
+  String.prototype.matchAll ( regexp )
+    [...]
+    2. If regexp is neither undefined nor null, then
+      a. Let matcher be ? GetMethod(regexp, @@matchAll).
+features: [Symbol.matchAll, String.prototype.matchAll]
+---*/
+
+var regexp = /./;
+
+regexp[Symbol.matchAll] = true;
+assert.throws(TypeError, function() {
+  ''.matchAll(regexp);
+});
+
+regexp[Symbol.matchAll] = 5;
+assert.throws(TypeError, function() {
+  ''.matchAll(regexp);
+});
+
+regexp[Symbol.matchAll] = '';
+assert.throws(TypeError, function() {
+  ''.matchAll(regexp);
+});
+
+regexp[Symbol.matchAll] = Symbol();
+assert.throws(TypeError, function() {
+  ''.matchAll(regexp);
+});
diff --git a/test/built-ins/String/prototype/matchAll/regexp-prototype-has-no-matchAll.js b/test/built-ins/String/prototype/matchAll/regexp-prototype-has-no-matchAll.js
index 1c97f88511..ee2b9484ce 100644
--- a/test/built-ins/String/prototype/matchAll/regexp-prototype-has-no-matchAll.js
+++ b/test/built-ins/String/prototype/matchAll/regexp-prototype-has-no-matchAll.js
@@ -11,17 +11,9 @@ info: |
       b. If matcher is not undefined, then
         [...]
     [...]
-    4. Let matcher be ? RegExpCreate(R, "g").
-    [...]
-
-  21.2.3.2.3 Runtime Semantics: RegExpCreate ( P, F )
-    [...]
-    2. Return ? RegExpInitialize(obj, P, F).
+    4. Let rx be ? RegExpCreate(R, "g").
+    5. Return ? Invoke(rx, @@matchAll, « S »).
 
-  21.2.3.2.2 Runtime Semantics: RegExpInitialize ( obj, pattern, flags )
-    1. If pattern is undefined, let P be the empty String.
-    2. Else, let P be ? ToString(pattern).
-    [...]
 features: [Symbol.matchAll, String.prototype.matchAll]
 includes: [compareArray.js, compareIterator.js, regExpUtils.js]
 ---*/
@@ -29,7 +21,6 @@ includes: [compareArray.js, compareIterator.js, regExpUtils.js]
 delete RegExp.prototype[Symbol.matchAll];
 var str = '/a/g*/b/g';
 
-assert.compareIterator(str.matchAll(/\w/g), [
-  matchValidator(['/a/g'], 0, str),
-  matchValidator(['/b/g'], 5, str)
-]);
+assert.throws(TypeError, function() {
+  str.matchAll(/\w/g);
+});
diff --git a/test/built-ins/String/prototype/matchAll/toString-this-val.js b/test/built-ins/String/prototype/matchAll/toString-this-val.js
new file mode 100644
index 0000000000..6b97a54a43
--- /dev/null
+++ b/test/built-ins/String/prototype/matchAll/toString-this-val.js
@@ -0,0 +1,41 @@
+// Copyright (C) 2018 Peter Wong. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: pending
+description: |
+  Verify ToString is called when regexp[@@matchAll] is undefined or null
+info: |
+  String.prototype.matchAll ( regexp )
+    1. Let O be ? RequireObjectCoercible(this value).
+    2. If regexp is neither undefined nor null, then
+      a. Let matcher be ? GetMethod(regexp, @@matchAll).
+      b. If matcher is not undefined, then
+        [...]
+    3. Let S be ? ToString(O).
+    4. Let rx be ? RegExpCreate(R, "g").
+    5. Return ? Invoke(rx, @@matchAll, « S »).
+features: [Symbol.matchAll, String.prototype.matchAll]
+---*/
+
+var regexp = /./;
+var callCount = 0;
+var arg;
+var obj = {};
+var toStringResult = 'abc';
+var receiver = {
+  [Symbol.toPrimitive]: function() {
+    callCount++;
+    return toStringResult;
+  }
+};
+RegExp.prototype[Symbol.matchAll] = function(string) {
+  arg = string;
+};
+
+String.prototype.matchAll.call(receiver, null);
+assert.sameValue(callCount, 1);
+assert.sameValue(arg, toStringResult);
+
+String.prototype.matchAll.call(receiver, undefined);
+assert.sameValue(callCount, 2);
+assert.sameValue(arg, toStringResult);
-- 
GitLab