From 5b3914a37bc1a055a36f6d2e482a270fdfb81d98 Mon Sep 17 00:00:00 2001
From: Jordan Harband <ljharb@gmail.com>
Date: Thu, 25 Jan 2018 00:25:10 -0800
Subject: [PATCH] String.prototype.matchAll: add tests for stage 3

`String.prototype.matchAll`: Add basic tests.
---
 .../matchAll/cstm-matcher-get-err.js          | 26 +++++++++++
 .../matchAll/cstm-matcher-invocation.js       | 34 +++++++++++++++
 .../matchAll/invoke-builtin-matchall.js       | 43 +++++++++++++++++++
 .../String/prototype/matchAll/length.js       | 24 +++++++++++
 .../String/prototype/matchAll/name.js         | 27 ++++++++++++
 .../String/prototype/matchAll/prop-desc.js    | 18 ++++++++
 .../matchAll/this-val-non-obj-coercible.js    | 22 ++++++++++
 7 files changed, 194 insertions(+)
 create mode 100644 test/built-ins/String/prototype/matchAll/cstm-matcher-get-err.js
 create mode 100644 test/built-ins/String/prototype/matchAll/cstm-matcher-invocation.js
 create mode 100644 test/built-ins/String/prototype/matchAll/invoke-builtin-matchall.js
 create mode 100644 test/built-ins/String/prototype/matchAll/length.js
 create mode 100644 test/built-ins/String/prototype/matchAll/name.js
 create mode 100644 test/built-ins/String/prototype/matchAll/prop-desc.js
 create mode 100644 test/built-ins/String/prototype/matchAll/this-val-non-obj-coercible.js

diff --git a/test/built-ins/String/prototype/matchAll/cstm-matcher-get-err.js b/test/built-ins/String/prototype/matchAll/cstm-matcher-get-err.js
new file mode 100644
index 0000000000..e18431c89d
--- /dev/null
+++ b/test/built-ins/String/prototype/matchAll/cstm-matcher-get-err.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2018 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Behavior when error is thrown accessing @@matchAll property
+info: |
+    [...]
+    4. Let matcher be ? GetMethod(R, @@matchAll).
+    5. If matcher is not undefined, then
+      a. Return ? Call(matcher, R, « O »).
+features: [Symbol.match, Symbol.matchAll]
+---*/
+
+var obj = {};
+Object.defineProperty(obj, Symbol.match, {
+  value: true // to make IsRegExp pass
+});
+Object.defineProperty(obj, Symbol.matchAll, {
+  get: function() {
+    throw new Test262Error();
+  }
+});
+
+assert.throws(Test262Error, function() {
+  ''.matchAll(obj);
+});
diff --git a/test/built-ins/String/prototype/matchAll/cstm-matcher-invocation.js b/test/built-ins/String/prototype/matchAll/cstm-matcher-invocation.js
new file mode 100644
index 0000000000..72c09fd541
--- /dev/null
+++ b/test/built-ins/String/prototype/matchAll/cstm-matcher-invocation.js
@@ -0,0 +1,34 @@
+// Copyright (C) 2018 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Invocation of @@matchAll property of user-supplied RegExp objects
+info: |
+    [...]
+    4. Let matcher be ? GetMethod(R, @@matchAll).
+    5. If matcher is not undefined, then
+      a. Return ? Call(matcher, R, « O »).
+features: [Symbol.match, Symbol.matchAll]
+---*/
+
+var obj = {};
+var returnVal = {};
+var callCount = 0;
+var thisVal, args;
+
+obj[Symbol.match] = true; // https://tc39.github.io/ecma262/#sec-isregexp steps 1-3
+obj[Symbol.matchAll] = function () {
+  callCount += 1;
+  thisVal = this;
+  args = arguments;
+  return returnVal;
+};
+
+var str = '';
+
+assert.sameValue(str.matchAll(obj), returnVal);
+assert.sameValue(callCount, 1, 'Invokes the method exactly once');
+assert.sameValue(thisVal, obj);
+assert.notSameValue(args, undefined);
+assert.sameValue(args.length, 1);
+assert.sameValue(args[0], str);
diff --git a/test/built-ins/String/prototype/matchAll/invoke-builtin-matchall.js b/test/built-ins/String/prototype/matchAll/invoke-builtin-matchall.js
new file mode 100644
index 0000000000..feeb36bc6e
--- /dev/null
+++ b/test/built-ins/String/prototype/matchAll/invoke-builtin-matchall.js
@@ -0,0 +1,43 @@
+// Copyright (C) 2018 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Invocation of @@matchAll property of internally-created RegExps
+info: |
+    [...]
+    3. Else,
+      a. Let R be ? RegExpCreate(regexp, "g").
+    4. Let matcher be ? GetMethod(R, @@matchAll).
+    5. If matcher is not undefined, then
+      a. Return ? Call(matcher, R, « O »).
+    6. Return ? MatchAllIterator(R, O).
+features: [Symbol.match, Symbol.matchAll]
+---*/
+
+var originalMatchAll = RegExp.prototype[Symbol.matchAll];
+var returnVal = {};
+var result, thisVal, args;
+
+RegExp.prototype[Symbol.matchAll] = function() {
+  thisVal = this;
+  args = arguments;
+  return returnVal;
+};
+
+var str = 'target';
+var stringToMatch = 'string source';
+
+try {
+  result = str.matchAll(stringToMatch);
+
+  assert(thisVal instanceof RegExp);
+  assert.sameValue(!!thisVal[Symbol.match], true);
+  assert.sameValue(thisVal.source, stringToMatch);
+  assert.sameValue(thisVal.flags, 'g');
+  assert.sameValue(thisVal.lastIndex, 0);
+  assert.sameValue(args.length, 1);
+  assert.sameValue(args[0], str);
+  assert.sameValue(result, returnVal);
+} finally {
+  RegExp.prototype[Symbol.matchAll] = originalMatchAll;
+}
diff --git a/test/built-ins/String/prototype/matchAll/length.js b/test/built-ins/String/prototype/matchAll/length.js
new file mode 100644
index 0000000000..fd5f0104c4
--- /dev/null
+++ b/test/built-ins/String/prototype/matchAll/length.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2018 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Length of String.prototype.matchAll
+info: |
+    ES6 Section 17:
+    Every built-in Function object, including constructors, has a length
+    property whose value is an integer. Unless otherwise specified, this value
+    is equal to the largest number of named arguments shown in the subclause
+    headings for the function description, including optional parameters.
+
+    [...]
+
+    Unless otherwise specified, the length property of a built-in Function
+    object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+    [[Configurable]]: true }.
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(String.prototype.matchAll.length, 1);
+
+verifyNotEnumerable(String.prototype.matchAll, 'length');
+verifyNotWritable(String.prototype.matchAll, 'length');
+verifyConfigurable(String.prototype.matchAll, 'length');
diff --git a/test/built-ins/String/prototype/matchAll/name.js b/test/built-ins/String/prototype/matchAll/name.js
new file mode 100644
index 0000000000..84bb3cf647
--- /dev/null
+++ b/test/built-ins/String/prototype/matchAll/name.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2018 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Descriptor for `name` property
+info: |
+  The value of the name property of this function is "matchAll".
+
+  ES6 Section 17: ECMAScript Standard Built-in Objects
+
+  Every built-in Function object, including constructors, that is not
+  identified as an anonymous function has a name property whose value is a
+  String. Unless otherwise specified, this value is the name that is given to
+  the function in this specification.
+
+  [...]
+
+  Unless otherwise specified, the name property of a built-in Function
+  object, if it exists, has the attributes { [[Writable]]: false,
+  [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(String.prototype[Symbol.iterator].name, 'matchAll');
+
+verifyNotEnumerable(String.prototype[Symbol.iterator], 'name');
+verifyNotWritable(String.prototype[Symbol.iterator], 'name');
+verifyConfigurable(String.prototype[Symbol.iterator], 'name');
diff --git a/test/built-ins/String/prototype/matchAll/prop-desc.js b/test/built-ins/String/prototype/matchAll/prop-desc.js
new file mode 100644
index 0000000000..02b9eaa714
--- /dev/null
+++ b/test/built-ins/String/prototype/matchAll/prop-desc.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2018 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Property descriptor
+info: |
+    ES6 Section 17
+
+    Every other data property described in clauses 18 through 26 and in Annex
+    B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+    [[Configurable]]: true } unless otherwise specified.
+features: [Symbol.iterator]
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(typeof String.prototype.matchAll, 'function');
+verifyNotEnumerable(String.prototype, 'matchAll');
+verifyWritable(String.prototype, 'matchAll');
+verifyConfigurable(String.prototype, 'matchAll');
diff --git a/test/built-ins/String/prototype/matchAll/this-val-non-obj-coercible.js b/test/built-ins/String/prototype/matchAll/this-val-non-obj-coercible.js
new file mode 100644
index 0000000000..2189df4b65
--- /dev/null
+++ b/test/built-ins/String/prototype/matchAll/this-val-non-obj-coercible.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2018 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: The `this` value cannot be coerced into an object
+info: |
+    1. Let O be RequireObjectCoercible(this value).
+    2. Let S be ToString(O).
+    3. ReturnIfAbrupt(S).
+features: [Symbol.iterator]
+---*/
+
+var matchAll = String.prototype.matchAll;
+
+assert.sameValue(typeof matchAll, 'function');
+
+assert.throws(TypeError, function() {
+  matchAll.call(undefined);
+}, 'undefined');
+
+assert.throws(TypeError, function() {
+  matchAll.call(null);
+}, 'null');
-- 
GitLab