Created
February 24, 2018 04:15
-
-
Save peterwmwong/3928b67c9e1aee8071c89d93d4f74d66 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/.vscode/tasks.json b/.vscode/tasks.json | |
new file mode 100644 | |
index 000000000..544721e31 | |
--- /dev/null | |
+++ b/.vscode/tasks.json | |
@@ -0,0 +1,15 @@ | |
+{ | |
+ "version": "2.0.0", | |
+ "tasks": [ | |
+ { | |
+ "label": "build", | |
+ "type": "shell", | |
+ "command": | |
+ "clear; cd /p/google/v8 && /p/google/v8/out.gn/x64.optdebug/d8 test/test262/data/harness/sta.js test/test262/data/harness/assert.js test/test262/harness-adapt.js test/test262/data/harness/propertyHelper.js ${file} && echo PASSED", | |
+ "group": { | |
+ "kind": "build", | |
+ "isDefault": true | |
+ } | |
+ } | |
+ ] | |
+} | |
diff --git a/pww-todo.md b/pww-todo.md | |
new file mode 100644 | |
index 000000000..0a13614ab | |
--- /dev/null | |
+++ b/pww-todo.md | |
@@ -0,0 +1,7 @@ | |
+Verify: | |
+- Author is "Peter Wong" | |
+- Copyright is "2018" | |
+- esid is "pending" | |
+ | |
+Replace after everything is working: | |
+- var -> const/let | |
diff --git a/string-prototype-matchall-spec-signoff.md b/string-prototype-matchall-spec-signoff.md | |
new file mode 100644 | |
index 000000000..232da2eee | |
--- /dev/null | |
+++ b/string-prototype-matchall-spec-signoff.md | |
@@ -0,0 +1,185 @@ | |
+# String.prototype.matchAll ( *regexp* )</h1> | |
+ | |
+Performs a regular expression match of the String representing the **this** value against *regexp* and returns an iterator. Each iteration result’s value is an Array object containing the results of the match, or **null** if the String did not match. | |
+ | |
+When the `matchAll` method is called, the following steps are taken: | |
+ 1. Let *O* be ? [RequireObjectCoercible][require-object-coercible](**this** value). | |
+ - SPEC: String/prototype/matchAll/this-is-null-throws.js | |
+ - SPEC: String/prototype/matchAll/this-is-undefined-throws.js | |
+ 1. If ? [IsRegExp][isregexp](*regexp*) is **true**, then | |
+ - SPEC: String/prototype/matchAll/return-abrupt-from-regexp-isregexp.js | |
+ 1. Let *R* be *regexp*. | |
+ 1. Else, | |
+ 1. Let *R* be [RegExpCreate][regexp-create](*regexp*, **undefined**). | |
+ - SPEC: String/prototype/matchAll/tostring-throws.js | |
+ 1. Let *matcher* be ? [GetMethod][getmethod](*R*, @@matchAll). | |
+ - SPEC: String/prototype/matchAll/invoke-regexp-matchAll-throws.js | |
+ - SPEC: String/prototype/matchAll/invoke-internal-regexp-matchAll-throws.js | |
+ 1. If *matcher* is not **undefined**, then | |
+ 1. Return ? [Call](call)(*matcher*, *R*, « *O* »). | |
+ - SPEC: String/prototype/matchAll/invoke-internal-regexp-matchAll.js | |
+ - SPEC: String/prototype/matchAll/invoke-regexp-matchAll.js | |
+ 1. Return ? [MatchAllIterator](#matchalliterator)(*R*, *O*). | |
+ - SPEC: String/prototype/matchAll/invoke-internal-regexp-has-no-matchAll | |
+ - SPEC: String/prototype/matchAll/invoke-regexp-has-no-matchAll | |
+ | |
+Note 1: The `matchAll` function is intentionally generic, it does not require that its *this* value be a String object. Therefore, it can be transferred to other kinds of objects for use as a method. | |
+Note 2: Similarly to `String.prototype.split`, `String.prototype.matchAll` is designed to typically act without mutating its inputs. | |
+ | |
+# RegExp.prototype[ @@matchAll ] ( *string* ) | |
+ | |
+When the `@@matchAll` method is called with argument *string*, the following steps are taken: | |
+ 1. Let *R* be the **this** value. | |
+ 1. Return ? [MatchAllIterator](#matchalliterator)(*R*, *string*). | |
+ | |
+The value of the name property of this function is "[Symbol.matchAll]". | |
+ | |
+# MatchAllIterator ( *R*, *O* ) | |
+ | |
+The abstract operation *MatchAllIterator* performs the following steps: | |
+ 1. If ? [IsRegExp][isregexp](*R*) is not **true**, throw a **TypeError** exception. | |
+ 1. Let *S* be ? [ToString][to-string](*O*). | |
+ 1. Let *C* be ? [SpeciesConstructor][species-constructor](*R*, %RegExp%). | |
+ 1. Let *flags* be ? [ToString][tostring](? [Get][get](*R*, **"flags"**)). | |
+ 1. Let *matcher* be ? [Construct][construct](*C*, « *R*, *flags* »). | |
+ 1. Let *global* be ? [ToBoolean][to-boolean](? [Get][get](*matcher*, **"global"**)). | |
+ 1. Let *fullUnicode* be ? [ToBoolean][to-boolean](? [Get][get](*matcher*, **"unicode"**)). | |
+ 1. Let *lastIndex* be ? [ToLength][tolength](? [Get][get](*R*, **"lastIndex"**)). | |
+ 1. Perform ? [Set][set](*matcher*, **"lastIndex"**, *lastIndex*, **true**). | |
+ 1. Return ! [CreateRegExpStringIterator](#createregexpstringiterator-abstract-operation)(*matcher*, *S*, *global*, *fullUnicode*). | |
+ | |
+## CreateRegExpStringIterator( *R*, *S*, *global*, *fullUnicode* ) | |
+ | |
+The abstract operation *CreateRegExpStringIterator* is used to create such iterator objects. It performs the following steps: | |
+ 1. Assert: [Type][type](*S*) is String. | |
+ 1. Assert: [Type][type](*global*) is Boolean. | |
+ 1. Assert: [Type][type](*unicode*) is Boolean. | |
+ 1. Let *iterator* be ObjectCreate(<emu-xref href="#%RegExpStringIteratorPrototype%">%RegExpStringIteratorPrototype%</emu-xref>, « [[IteratedString]], [[IteratingRegExp]], [[Done]] »). | |
+ 1. Set *iterator*.[[IteratingRegExp]] to *R*. | |
+ 1. Set *iterator*.[[IteratedString]] to *S*. | |
+ 1. Set *iterator*.[[Global]] to *global*. | |
+ 1. Set *iterator*.[[Unicode]] to *fullUnicode*. | |
+ 1. Set *iterator*.[[Done]] to **true**. | |
+ 1. Return *iterator*. | |
+ | |
+### The %RegExpStringIteratorPrototype% Object | |
+ | |
+All RegExp String Iterator Objects inherit properties from the [%RegExpStringIteratorPrototype%](#the-regexpstringiteratorprototype-object) intrinsic object. The %RegExpStringIteratorPrototype% object is an ordinary object and its [[Prototype]] [internal slot][internal-slot] is the [%IteratorPrototype%][iterator-prototype] intrinsic object</a>. In addition, %RegExpStringIteratorPrototype% has the following properties: | |
+ | |
+#### %RegExpStringIteratorPrototype%.next ( ) | |
+ 1. Let O be the **this** value. | |
+ 1. If [Type][type](O) is not Object, throw a **TypeError** exception. | |
+ 1. If O does not have all of the internal slots of a RegExp String Iterator Object Instance (see [here](#PropertiesOfRegExpStringIteratorInstances)), throw a **TypeError** exception. | |
+ 1. If *O*.[[Done]] is **true**, then | |
+ 1. Return ! [CreateIterResultObject][create-iter-result-object](**null**, **true**). | |
+ 1. Let *R* be *O*.[[IteratingRegExp]]. | |
+ 1. Let *S* be *O*.[[IteratedString]]. | |
+ 1. Let *global* be *O*.[[Global]]. | |
+ 1. Let *fullUnicode* be *O*.[[Unicode]]. | |
+ 1. Let *match* be ? [RegExpExec][regexp-exec](*R*, *S*). | |
+ 1. If *match* is **null**, then | |
+ 1. Set *O*.[[Done]] to **true**. | |
+ 1. Return ! [CreateIterResultObject][create-iter-result-object](**null**, **true**). | |
+ 1. Else, | |
+ 1. If *global* is **true**, | |
+ 1. Let *matchStr* be ? [ToString][to-string](? [Get][get](*match*, **"0"**)). | |
+ 1. If *matchStr* is the empty string, | |
+ 1. Let *thisIndex* be ? [ToLength][tolength](? [Get][get](*R*, **"lastIndex"**). | |
+ 1. Let *nextIndex* be ! AdvanceStringIndex(*S*, *thisIndex*, *fullUnicode*). | |
+ 1. Perform ? [Set][set](*R*, **"lastIndex"**, *nextIndex*, **true**). | |
+ 1. Return ! [CreateIterResultObject][create-iter-result-object](*match*, **false**). | |
+ 1. Else, | |
+ 1. Set *O*.[[Done]] to **true**. | |
+ 1. Return ! [CreateIterResultObject][create-iter-result-object](_match_, **false**). | |
+ | |
+#### %RegExpStringIteratorPrototype%[ @@toStringTag ] | |
+ | |
+The initial value of the _@@toStringTag_ property is the String value **"RegExp String Iterator"**.</p> | |
+This property has the attributes { [[Writable]]: **false**, [[Enumerable]]: **false**, [[Configurable]]: **true** }.</p> | |
+ | |
+#### Properties of RegExp String Iterator Instances</h1> | |
+ | |
+RegExp String Iterator instances are ordinary objects that inherit properties from the [%RegExpStringIteratorPrototype%](#%RegExpStringIteratorPrototype%) intrinsic object. RegExp String Iterator instances are initially created with the internal slots listed in <a href="#table-1">Table 1</a>.</p> | |
+ | |
+<figure> | |
+ <figcaption><span id="table-1">Table 1</span> — Internal Slots of RegExp String Iterator Instances</figcaption> | |
+ <table class="real-table"> | |
+ <tbody> | |
+ <tr> | |
+ <th>Internal Slot</th> | |
+ <th>Description</th> | |
+ </tr> | |
+ <tr> | |
+ <td>[[IteratingRegExp]]</td> | |
+ <td>The regular expression used for iteration. [IsRegExp][isregexp]([[IteratingRegExp]]) is always initially true.</td> | |
+ </tr> | |
+ <tr> | |
+ <td>[[IteratedString]]</td> | |
+ <td>The String value being iterated upon.</td> | |
+ </tr> | |
+ <tr> | |
+ <td>[[Global]]</td> | |
+ <td>A Boolean value to indicate whether the [[IteratingRegExp]] is global or not.</td> | |
+ </tr> | |
+ <tr> | |
+ <td>[[Unicode]]</td> | |
+ <td>A Boolean value to indicate whether the [[IteratingRegExp]] is in Unicode mode or not.</td> | |
+ </tr> | |
+ <tr> | |
+ <td>[[Done]]</td> | |
+ <td>A Boolean value to indicate whether the iteration is complete or not.</td> | |
+ </tr> | |
+ </tbody> | |
+ </table> | |
+</figure> | |
+ | |
+# Symbol.matchAll | |
+ | |
+The initial value of *Symbol.matchAll* is the well-known symbol @@matchAll | |
+ | |
+This property has the attributes { [[Writable]]: **false**, [[Enumerable]]: **false**, [[Configurable]]: **false** }. | |
+ | |
+# Well-Known Symbols | |
+ | |
+<figure> | |
+ <figcaption>Table 1: Well-known Symbols</figcaption> | |
+ <table> | |
+ <thead> | |
+ <tr> | |
+ <th>Specification Name</th> | |
+ <th>[[Description]]</th> | |
+ <th>Value and Purpose</th> | |
+ </tr> | |
+ </thead> | |
+ <tbody> | |
+ <tr> | |
+ <td colspan="3">insert after @@match</td> | |
+ </tr> | |
+ <tr> | |
+ <td>@@matchAll</td> | |
+ <td><code>"Symbol.matchAll"</code></td> | |
+ <td>A regular expression method that returns an iterator, that yields matches of the regular expression against a string. Called by the <code>String.prototype.matchAll</code> method.</td> | |
+ </tr> | |
+ <tr> | |
+ <td colspan="3">insert before @@replace</td> | |
+ </tr> | |
+ </tbody> | |
+ </table> | |
+</figure> | |
+ | |
+[to-string]: https://tc39.github.io/ecma262/#sec-tostring | |
+[regexp-create]: https://tc39.github.io/ecma262/#sec-regexpcreate | |
+[regexp-exec]: https://tc39.github.io/ecma262/#sec-regexpexec | |
+[require-object-coercible]: https://tc39.github.io/ecma262/#sec-requireobjectcoercible | |
+[internal-slot]: https://tc39.github.io/ecma262/#sec-object-internal-methods-and-internal-slots | |
+[type]: https://tc39.github.io/ecma262/#sec-ecmascript-data-types-and-values | |
+[iterator-prototype]: https://tc39.github.io/ecma262/#sec-%iteratorprototype%-object | |
+[create-iter-result-object]: https://tc39.github.io/ecma262/#sec-createiterresultobject | |
+[isregexp]: https://tc39.github.io/ecma262/#sec-isregexp | |
+[object-create]: https://tc39.github.io/ecma262/#sec-objectcreate | |
+[call]: https://tc39.github.io/ecma262/#sec-call | |
+[species-constructor]: https://tc39.github.io/ecma262/#sec-speciesconstructor | |
+[construct]: https://tc39.github.io/ecma262/#sec-construct | |
+[tolength]: https://tc39.github.io/ecma262/#sec-tolength | |
+[set]: https://tc39.github.io/ecma262/#sec-set-o-p-v-throw | |
+[to-boolean]: https://tc39.github.io/ecma262/#sec-toboolean | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/length.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/length.js | |
new file mode 100644 | |
index 000000000..ae974ec48 | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/length.js | |
@@ -0,0 +1,26 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: Length of RegExp.prototype[ @@matchAll ] | |
+info: > | |
+ 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 }. | |
+features: [Symbol.matchAll] | |
+includes: [propertyHelper.js] | |
+---*/ | |
+ | |
+assert.sameValue(RegExp.prototype[Symbol.matchAll].length, 1); | |
+ | |
+verifyNotEnumerable(RegExp.prototype[Symbol.matchAll], 'length'); | |
+verifyNotWritable(RegExp.prototype[Symbol.matchAll], 'length'); | |
+verifyConfigurable(RegExp.prototype[Symbol.matchAll], 'length'); | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/name.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/name.js | |
new file mode 100644 | |
index 000000000..1ffd279fd | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/name.js | |
@@ -0,0 +1,27 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: Name of RegExp.prototype[ @@matchAll ] | |
+info: > | |
+ 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 }. | |
+features: [Symbol.matchAll] | |
+includes: [propertyHelper.js] | |
+---*/ | |
+ | |
+assert.sameValue(RegExp.prototype[Symbol.matchAll].name, '[Symbol.matchAll]'); | |
+ | |
+verifyNotEnumerable(RegExp.prototype[Symbol.matchAll], 'name'); | |
+verifyNotWritable(RegExp.prototype[Symbol.matchAll], 'name'); | |
+verifyConfigurable(RegExp.prototype[Symbol.matchAll], 'name'); | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/observable-operations.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/observable-operations.js | |
new file mode 100644 | |
index 000000000..eec1cb4a5 | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/observable-operations.js | |
@@ -0,0 +1,66 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: > | |
+ RegExp.prototype.[@@matchAll] should perform observable operations in the | |
+ correct order | |
+info: > | |
+ pending RegExp.prototype [ @@matchAll ] ( string ) | |
+ [...] | |
+ 2. Return ? [MatchAllIterator](#matchalliterator)(R, string). | |
+ | |
+ pending MatchAllIterator ( R, O ) | |
+ 1. If ? IsRegExp(R) is not true, throw a TypeError exception. | |
+ [...] | |
+ 4. Let flags be ? [ToString][tostring](? [Get][get](R, "flags")). | |
+ 5. Let matcher be ? Construct(C, « R, flags »). | |
+includes: [compareArray.js] | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+const log = []; | |
+ | |
+function observeGetter(obj, prop, propName = prop) { | |
+ const proto = Object.getPrototypeOf(obj); | |
+ const originalGetter = Object.getOwnPropertyDescriptor(proto, prop).get; | |
+ Object.defineProperty(obj, prop, { | |
+ get() { | |
+ log.push(`get ${propName}`); | |
+ return originalGetter.call(obj); | |
+ } | |
+ }); | |
+} | |
+ | |
+function observeValue(obj, prop, propName = prop) { | |
+ const value = obj[prop]; | |
+ Object.defineProperty(obj, prop, { | |
+ get() { | |
+ log.push(`value ${propName}`); | |
+ return value; | |
+ } | |
+ }); | |
+} | |
+ | |
+const receiver = /./; | |
+const string = 'hello'; | |
+ | |
+observeValue(receiver, Symbol.match, 'Symbol.match'); | |
+observeGetter(receiver, 'flags'); | |
+observeGetter(receiver, 'global'); | |
+observeGetter(receiver, 'unicode'); | |
+ | |
+receiver[Symbol.matchAll](string); | |
+ | |
+assert.compareArray(log, [ | |
+ // 1. If ? IsRegExp(R) is not true, throw a TypeError exception. | |
+ 'value Symbol.match', | |
+ | |
+ // 4. Let flags be ? [ToString][tostring](? [Get][get](R, "flags")). | |
+ 'get flags', | |
+ 'get global', | |
+ 'get unicode', | |
+ | |
+ // 5. Let matcher be ? [Construct][construct](C, R, flags). | |
+ 'value Symbol.match' | |
+]); | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/prop-desc.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/prop-desc.js | |
new file mode 100644 | |
index 000000000..bb0b41bdb | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/prop-desc.js | |
@@ -0,0 +1,19 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: Property descriptor of RegExp.prototype[ @@matchAll ] | |
+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.matchAll] | |
+includes: [propertyHelper.js] | |
+---*/ | |
+ | |
+assert.sameValue(typeof RegExp.prototype[Symbol.matchAll], 'function'); | |
+verifyNotEnumerable(RegExp.prototype, Symbol.matchAll); | |
+verifyWritable(RegExp.prototype, Symbol.matchAll); | |
+verifyConfigurable(RegExp.prototype, Symbol.matchAll); | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/regexp-flags-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/regexp-flags-throws.js | |
new file mode 100644 | |
index 000000000..617de2e07 | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/regexp-flags-throws.js | |
@@ -0,0 +1,25 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: > | |
+ Re-throw errors from RegExp's flags getter | |
+info: > | |
+ pending RegExp.prototype [ @@matchAll ] ( string ) | |
+ [...] | |
+ 2. Return ? [MatchAllIterator](#matchalliterator)(R, string). | |
+ | |
+ pending MatchAllIterator ( R, O ) | |
+ [...] | |
+ 4. Let flags be ? [ToString][tostring](? [Get][get](R, "flags")) | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+const regexp = /./; | |
+Object.defineProperty(regexp, 'flags', { | |
+ get() { throw new Test262Error(); } | |
+}); | |
+ | |
+assert.throws(Test262Error, () => { | |
+ RegExp.prototype[Symbol.matchAll].call(regexp, 'a'); | |
+}); | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/returns-iterator-modified-regexp-lastindex.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/returns-iterator-modified-regexp-lastindex.js | |
new file mode 100644 | |
index 000000000..967d8edc0 | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/returns-iterator-modified-regexp-lastindex.js | |
@@ -0,0 +1,64 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: > | |
+ The receiver's lastIndex is cached, changes afterwards do not affect | |
+ iterated results. | |
+info: > | |
+ pending RegExp.prototype [ @@matchAll ] ( string ) | |
+ [...] | |
+ 2. Return ? [MatchAllIterator](#matchalliterator)(R, string). | |
+ | |
+ pending MatchAllIterator ( R, O ) | |
+ [...] | |
+ 8. Let lastIndex be ? [ToLength][tolength](? [Get][get](R, "lastIndex")). | |
+ 9. Perform ? [Set][set](matcher, "lastIndex", lastIndex, true). | |
+ 10. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode). | |
+includes: [compareArray.js] | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+function TestIteration(changeLastIndex) { | |
+ const receiver = /\w/g; | |
+ const string = 'a*b*c'; | |
+ | |
+ receiver.exec(string); | |
+ | |
+ const iter = receiver[Symbol.matchAll](string); | |
+ | |
+ | |
+ if (changeLastIndex) { | |
+ receiver.exec(string); | |
+ assert.sameValue(receiver.lastIndex, 3); | |
+ } | |
+ else { | |
+ assert.sameValue(receiver.lastIndex, 1); | |
+ } | |
+ | |
+ | |
+ let result = iter.next(); | |
+ assert.compareArray(result.value, ['b']); | |
+ assert(!result.done); | |
+ | |
+ | |
+ if (changeLastIndex) { | |
+ receiver.exec(string); | |
+ assert.sameValue(receiver.lastIndex, 5); | |
+ } | |
+ else { | |
+ assert.sameValue(receiver.lastIndex, 1); | |
+ } | |
+ | |
+ | |
+ result = iter.next(); | |
+ assert.compareArray(result.value, ['c']); | |
+ assert(!result.done); | |
+ | |
+ result = iter.next(); | |
+ assert.sameValue(result.value, null); | |
+ assert(result.done); | |
+} | |
+ | |
+TestIteration(false); | |
+TestIteration(true); | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/returns-iterator.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/returns-iterator.js | |
new file mode 100644 | |
index 000000000..c8b983e36 | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/returns-iterator.js | |
@@ -0,0 +1,35 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: > | |
+ RegExp.prototype.[@@matchAll] should perform observable operations in the | |
+ correct order | |
+info: > | |
+ pending RegExp.prototype [ @@matchAll ] ( string ) | |
+ [...] | |
+ 2. Return ? [MatchAllIterator](#matchalliterator)(R, string). | |
+ | |
+ pending MatchAllIterator ( R, O ) | |
+ [...] | |
+ 10. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode). | |
+includes: [compareArray.js] | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+const receiver = /\w/g; | |
+const string = 'a*b'; | |
+const iter = receiver[Symbol.matchAll](string); | |
+ | |
+let result; | |
+result = iter.next(); | |
+assert.compareArray(result.value, ['a']); | |
+assert(!result.done); | |
+ | |
+result = iter.next(); | |
+assert.compareArray(result.value, ['b']); | |
+assert(!result.done); | |
+ | |
+result = iter.next(); | |
+assert.sameValue(result.value, null); | |
+assert(result.done); | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-throws.js | |
new file mode 100644 | |
index 000000000..22664fc13 | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-throws.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: > | |
+ Re-throw errors from RegExp species constructor. | |
+info: > | |
+ pending RegExp.prototype [ @@matchAll ] ( string ) | |
+ [...] | |
+ 2. Return ? [MatchAllIterator](#matchalliterator)(R, string). | |
+ | |
+ pending MatchAllIterator ( R, O ) | |
+ [...] | |
+ 5. Let matcher be ? [Construct][construct](C, R, flags). | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+let should_throw = false; | |
+class FooRegExp extends RegExp { | |
+ constructor(...args) { | |
+ if (should_throw) throw new Test262Error(); | |
+ super(...args); | |
+ } | |
+} | |
+const regexp = new FooRegExp('.', 'gu'); | |
+ | |
+should_throw = true; | |
+assert.throws(Test262Error, () => { | |
+ RegExp.prototype[Symbol.matchAll].call(regexp, 'a'); | |
+}); | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor.js | |
new file mode 100644 | |
index 000000000..ad781f8c5 | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor.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: > | |
+ Verifies species constructor is called when creating internal RegExp | |
+features: [Symbol.matchAll] | |
+info: > | |
+ pending RegExp.prototype [ @@matchAll ] ( string ) | |
+ [...] | |
+ 2. Return ? [MatchAllIterator](#matchalliterator)(R, string). | |
+ | |
+ pending MatchAllIterator ( R, O ) | |
+ [...] | |
+ 5. Let matcher be ? [Construct][construct](C, R, flags). | |
+---*/ | |
+ | |
+let track_calls = false; | |
+let call_count = 0; | |
+let call_args; | |
+class FooRegExp extends RegExp { | |
+ constructor(...args) { | |
+ if (track_calls) { | |
+ call_count++; | |
+ call_args = args; | |
+ } | |
+ return super(...args); | |
+ } | |
+} | |
+const regexp = new FooRegExp('.', 'gu'); | |
+ | |
+track_calls = true; | |
+RegExp.prototype[Symbol.matchAll].call(regexp, 'a'); | |
+ | |
+assert.sameValue(call_count, 1); | |
+assert.sameValue(call_args.length, 2); | |
+assert.sameValue(call_args[0], regexp); | |
+assert.sameValue(call_args[1], 'gu'); | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/species-regexp-global-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-regexp-global-throws.js | |
new file mode 100644 | |
index 000000000..d5398a0bc | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-regexp-global-throws.js | |
@@ -0,0 +1,27 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: > | |
+ Re-throw errors from the species constructed RegExp's | |
+ global getter | |
+info: > | |
+ pending RegExp.prototype [ @@matchAll ] ( string ) | |
+ [...] | |
+ 2. Return ? [MatchAllIterator](#matchalliterator)(R, string). | |
+ | |
+ pending MatchAllIterator ( R, O ) | |
+ [...] | |
+ 6. Let global be ? [ToBoolean][to-boolean](? [Get][get](matcher, "global")). | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+let globalRegexp; | |
+class GlobalThrowsRegExp extends RegExp { | |
+ get global() { if (globalRegexp !== this) throw new Test262Error(); } | |
+} | |
+globalRegexp = new GlobalThrowsRegExp(); | |
+ | |
+assert.throws(Test262Error, () => { | |
+ RegExp.prototype[Symbol.matchAll].call(globalRegexp, 'a'); | |
+}); | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/species-regexp-unicode-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-regexp-unicode-throws.js | |
new file mode 100644 | |
index 000000000..41c561cab | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-regexp-unicode-throws.js | |
@@ -0,0 +1,27 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: > | |
+ Re-throw errors from the species constructed RegExp's | |
+ unicode getter | |
+info: > | |
+ pending RegExp.prototype [ @@matchAll ] ( string ) | |
+ [...] | |
+ 2. Return ? [MatchAllIterator](#matchalliterator)(R, string). | |
+ | |
+ pending MatchAllIterator ( R, O ) | |
+ [...] | |
+ 7. Let fullUnicode be ? [ToBoolean][to-boolean](? [Get][get](matcher, "unicode")). | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+let unicodeRegexp; | |
+class UnicodeThrowsRegExp extends RegExp { | |
+ get unicode() { if (unicodeRegexp !== this) throw new Test262Error(); } | |
+} | |
+unicodeRegexp = new UnicodeThrowsRegExp(); | |
+ | |
+assert.throws(Test262Error, () => { | |
+ RegExp.prototype[Symbol.matchAll].call(unicodeRegexp, 'a'); | |
+}); | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/string-tostring-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/string-tostring-throws.js | |
new file mode 100644 | |
index 000000000..01e72d11b | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/string-tostring-throws.js | |
@@ -0,0 +1,24 @@ | |
+// Copyright (C) 2015 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: > | |
+ Re-throw errors when coercing `string` value to a string | |
+info: > | |
+ pending RegExp.prototype [ @@matchAll ] ( string ) | |
+ [...] | |
+ 2. Return ? [MatchAllIterator](#matchalliterator)(R, string). | |
+ | |
+ pending MatchAllIterator ( R, O ) | |
+ [...] | |
+ 2. Let S be ? [ToString][to-string](O). | |
+features: [Symbol.iterator] | |
+---*/ | |
+ | |
+const obj = { | |
+ toString() { throw new Test262Error(); } | |
+}; | |
+ | |
+assert.throws(Test262Error, function() { | |
+ RegExp.prototype[Symbol.matchAll].call(/./, obj); | |
+}); | |
diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/this-is-not-regexp-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-is-not-regexp-throws.js | |
new file mode 100644 | |
index 000000000..6afffd4e7 | |
--- /dev/null | |
+++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-is-not-regexp-throws.js | |
@@ -0,0 +1,13 @@ | |
+// Copyright (C) 2015 the V8 project authors. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: Error thrown when `this` is not a RegExp | |
+info: > | |
+ 1. If ? [IsRegExp][isregexp](R) is not true, throw a TypeError exception. | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+assert.throws(TypeError, () => { | |
+ RegExp.prototype[Symbol.matchAll].call({}, "a"); | |
+}); | |
diff --git a/test/built-ins/RegExpStringIteratorPrototype/Symbol.toStringTag.js b/test/built-ins/RegExpStringIteratorPrototype/Symbol.toStringTag.js | |
new file mode 100644 | |
index 000000000..fea812fb3 | |
--- /dev/null | |
+++ b/test/built-ins/RegExpStringIteratorPrototype/Symbol.toStringTag.js | |
@@ -0,0 +1,23 @@ | |
+// Copyright (C) 2014 the V8 project authors. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+es6id: pending | |
+description: > | |
+ `Symbol.toStringTag` property descriptor | |
+info: > | |
+ The initial value of the @@toStringTag property is the string value "String | |
+ Iterator". | |
+ | |
+ This property has the attributes { [[Writable]]: false, [[Enumerable]]: | |
+ false, [[Configurable]]: true }. | |
+features: [Symbol.toStringTag] | |
+includes: [propertyHelper.js] | |
+---*/ | |
+ | |
+var RegExpStringIteratorProto = Object.getPrototypeOf('a'.matchAll(/./)); | |
+ | |
+// assert.sameValue(RegExpStringIteratorProto[Symbol.toStringTag], 'RegExp String Iterator'); | |
+ | |
+// verifyNotEnumerable(RegExpStringIteratorProto, Symbol.toStringTag); | |
+// verifyNotWritable(RegExpStringIteratorProto, Symbol.toStringTag); | |
+// verifyConfigurable(RegExpStringIteratorProto, Symbol.toStringTag); | |
diff --git a/test/built-ins/RegExpStringIteratorPrototype/ancestry.js b/test/built-ins/RegExpStringIteratorPrototype/ancestry.js | |
new file mode 100644 | |
index 000000000..e471dca8a | |
--- /dev/null | |
+++ b/test/built-ins/RegExpStringIteratorPrototype/ancestry.js | |
@@ -0,0 +1,20 @@ | |
+// Copyright (C) 2014 the V8 project authors. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: > | |
+ The [[Prototype]] internal slot ofthe %RegExpStringIteratorPrototype% is the | |
+ %IteratorPrototype% intrinsic object (25.1.2). | |
+features: [Symbol.iterator] | |
+---*/ | |
+ | |
+const RegExpStringIteratorProto = Object.getPrototypeOf(''.matchAll(/./)); | |
+const RegExpStringIteratorProto2 = Object.getPrototypeOf(/./[Symbol.matchAll]('')); | |
+ | |
+assert.sameValue(RegExpStringIteratorProto, RegExpStringIteratorProto2); | |
+ | |
+var ArrayIteratorProto = Object.getPrototypeOf( | |
+ Object.getPrototypeOf([][Symbol.iterator]()) | |
+); | |
+ | |
+assert.sameValue(Object.getPrototypeOf(RegExpStringIteratorProto), ArrayIteratorProto); | |
diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/length.js b/test/built-ins/RegExpStringIteratorPrototype/next/length.js | |
new file mode 100644 | |
index 000000000..cde067f53 | |
--- /dev/null | |
+++ b/test/built-ins/RegExpStringIteratorPrototype/next/length.js | |
@@ -0,0 +1,32 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+ | |
+/*--- | |
+esid: pending | |
+description: > | |
+ %RegExpStringIteratorPrototype%.next.length is 0. | |
+info: > | |
+ %RegExpStringIteratorPrototype%.next ( ) | |
+ | |
+ 17 ECMAScript Standard Built-in Objects: | |
+ 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. However, rest parameters shown using the form “...name” | |
+ are not included in the default argument count. | |
+ | |
+ Unless otherwise specified, the length property of a built-in Function | |
+ object has the attributes { [[Writable]]: false, [[Enumerable]]: false, | |
+ [[Configurable]]: true }. | |
+includes: [propertyHelper.js] | |
+features: [] | |
+---*/ | |
+ | |
+var RegExpStringIteratorProto = Object.getPrototypeOf(''.matchAll(/./)); | |
+ | |
+assert.sameValue(RegExpStringIteratorProto.next.length, 0); | |
+ | |
+verifyNotEnumerable(RegExpStringIteratorProto.next, "length"); | |
+verifyNotWritable(RegExpStringIteratorProto.next, "length"); | |
+verifyConfigurable(RegExpStringIteratorProto.next, "length"); | |
diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/name.js b/test/built-ins/RegExpStringIteratorPrototype/next/name.js | |
new file mode 100644 | |
index 000000000..1d03b7ccc | |
--- /dev/null | |
+++ b/test/built-ins/RegExpStringIteratorPrototype/next/name.js | |
@@ -0,0 +1,29 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+ | |
+/*--- | |
+esid: pending | |
+description: > | |
+ %RegExpStringIteratorPrototype%.next.name is "next". | |
+info: > | |
+ %RegExpStringIteratorPrototype%.next ( ) | |
+ | |
+ 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, the name property of a built-in Function | |
+ object, if it exists, has the attributes { [[Writable]]: false, | |
+ [[Enumerable]]: false, [[Configurable]]: true }. | |
+includes: [propertyHelper.js] | |
+features: [] | |
+---*/ | |
+ | |
+var RegExpStringIteratorProto = Object.getPrototypeOf('a'.matchAll(/./)); | |
+ | |
+assert.sameValue(RegExpStringIteratorProto.next.name, "next"); | |
+ | |
+verifyNotEnumerable(RegExpStringIteratorProto.next, "name"); | |
+verifyNotWritable(RegExpStringIteratorProto.next, "name"); | |
+verifyConfigurable(RegExpStringIteratorProto.next, "name"); | |
diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/next-iteration-surrogate-pairs.js b/test/built-ins/RegExpStringIteratorPrototype/next/next-iteration-surrogate-pairs.js | |
new file mode 100644 | |
index 000000000..c57621e13 | |
--- /dev/null | |
+++ b/test/built-ins/RegExpStringIteratorPrototype/next/next-iteration-surrogate-pairs.js | |
@@ -0,0 +1,84 @@ | |
+// Copyright (C) 2014 the V8 project authors. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+es6id: 21.1.5.2.1 | |
+description: > | |
+ Iteration should respect UTF-16-encoded Unicode code points specified via | |
+ surrogate pairs. | |
+features: [Symbol.iterator] | |
+---*/ | |
+ | |
+var lo = '\uD834'; | |
+var hi = '\uDF06'; | |
+var pair = lo + hi; | |
+var string = 'a' + pair + 'b' + lo + pair + hi + lo; | |
+var iterator = string[Symbol.iterator](); | |
+var result; | |
+ | |
+result = iterator.next(); | |
+assert.sameValue(result.value, 'a', 'First normal code point `value`'); | |
+assert.sameValue(result.done, false, 'First normal code point `done` flag'); | |
+ | |
+result = iterator.next(); | |
+assert.sameValue( | |
+ result.value, pair, 'Surrogate pair `value` (between normal code points)' | |
+); | |
+assert.sameValue( | |
+ result.done, false, 'Surrogate pair `done` flag (between normal code points)' | |
+); | |
+ | |
+result = iterator.next(); | |
+assert.sameValue(result.value, 'b', 'Second normal code point `value`'); | |
+assert.sameValue(result.done, false, 'Second normal code point `done` flag'); | |
+ | |
+result = iterator.next(); | |
+assert.sameValue( | |
+ result.value, | |
+ lo, | |
+ 'Lone lower code point `value` (following normal code point)' | |
+); | |
+assert.sameValue( | |
+ result.done, | |
+ false, | |
+ 'Lone lower code point `done` flag (following normal code point)' | |
+); | |
+ | |
+result = iterator.next(); | |
+assert.sameValue( | |
+ result.value, | |
+ pair, | |
+ 'Surrogate pair `value` (between lone lower- and upper- code points)' | |
+); | |
+assert.sameValue( | |
+ result.done, | |
+ false, | |
+ 'Surrogate pair `done` flag (between lone lower- and upper- code points)' | |
+); | |
+ | |
+result = iterator.next(); | |
+assert.sameValue(result.value, hi, 'Lone upper code point `value`'); | |
+assert.sameValue(result.done, false, 'Lone upper code point `done` flag'); | |
+ | |
+result = iterator.next(); | |
+assert.sameValue( | |
+ result.value, | |
+ lo, | |
+ 'Lone lower code point `value` (following lone upper code point)' | |
+); | |
+assert.sameValue( | |
+ result.done, | |
+ false, | |
+ 'Lone lower code point `done` flag (following lone upper code point)' | |
+); | |
+ | |
+result = iterator.next(); | |
+assert.sameValue(result.value, undefined, 'Exhausted result `value`'); | |
+assert.sameValue(result.done, true, 'Exhausted result `done` flag'); | |
+ | |
+result = iterator.next(); | |
+assert.sameValue( | |
+ result.value, undefined, 'Exhausted result `value` (repeated request)' | |
+); | |
+assert.sameValue( | |
+ result.done, true, 'Exhausted result `done` flag (repeated request' | |
+); | |
diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/next-iteration.js b/test/built-ins/RegExpStringIteratorPrototype/next/next-iteration.js | |
new file mode 100644 | |
index 000000000..f43cd3f71 | |
--- /dev/null | |
+++ b/test/built-ins/RegExpStringIteratorPrototype/next/next-iteration.js | |
@@ -0,0 +1,36 @@ | |
+// Copyright (C) 2014 the V8 project authors. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+es6id: 21.1.5.2.1 | |
+description: > | |
+ Iteration should visit each UTF-8 code point exactly once. | |
+features: [Symbol.iterator] | |
+---*/ | |
+ | |
+var string = "abc"; | |
+var iterator = string[Symbol.iterator](); | |
+var result; | |
+ | |
+result = iterator.next(); | |
+assert.sameValue(result.value, 'a', 'First result `value`'); | |
+assert.sameValue(result.done, false, 'First result `done` flag'); | |
+ | |
+result = iterator.next(); | |
+assert.sameValue(result.value, 'b', 'Second result `value`'); | |
+assert.sameValue(result.done, false, 'Second result `done` flag'); | |
+ | |
+result = iterator.next(); | |
+assert.sameValue(result.value, 'c', 'Third result `value`'); | |
+assert.sameValue(result.done, false, 'Third result `done` flag'); | |
+ | |
+result = iterator.next(); | |
+assert.sameValue(result.value, undefined, 'Exhausted result `value`'); | |
+assert.sameValue(result.done, true, 'Exhausted result `done` flag'); | |
+ | |
+result = iterator.next(); | |
+assert.sameValue( | |
+ result.value, undefined, 'Exhausted result `value` (repeated request)' | |
+); | |
+assert.sameValue( | |
+ result.done, true, 'Exhausted result `done` flag (repeated request)' | |
+); | |
diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/next-missing-internal-slots.js b/test/built-ins/RegExpStringIteratorPrototype/next/next-missing-internal-slots.js | |
new file mode 100644 | |
index 000000000..823dea16d | |
--- /dev/null | |
+++ b/test/built-ins/RegExpStringIteratorPrototype/next/next-missing-internal-slots.js | |
@@ -0,0 +1,16 @@ | |
+// Copyright (C) 2014 the V8 project authors. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: > | |
+ If the `this` value does not have all of the internal slots of an String | |
+ Iterator Instance (pending), throw a `TypeError` exception. | |
+features: [] | |
+---*/ | |
+ | |
+var iterator = 'a'.matchAll(/./); | |
+var object = Object.create(iterator); | |
+ | |
+assert.throws(TypeError, function() { | |
+ object.next(); | |
+}); | |
diff --git a/test/built-ins/String/prototype/matchAll/invoke-internal-regexp-has-no-matchAll.js b/test/built-ins/String/prototype/matchAll/invoke-internal-regexp-has-no-matchAll.js | |
new file mode 100644 | |
index 000000000..a15d23f31 | |
--- /dev/null | |
+++ b/test/built-ins/String/prototype/matchAll/invoke-internal-regexp-has-no-matchAll.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: Internally created RegExp has no @@matchAll | |
+info: > | |
+ [...] | |
+ 2. If ? IsRegExp(regexp) is true, then | |
+ 3. Else, | |
+ a. Let R be ? RegExpCreate(regexp, "g"). | |
+ 4. Let matcher be ? [GetMethod][getmethod](R, @@matchAll). | |
+ [...] | |
+ 6. Return ? MatchAllIterator(R, O). | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+const originalMatch = RegExp.prototype[Symbol.matchAll]; | |
+delete RegExp.prototype[Symbol.matchAll]; | |
+try { | |
+ const string = 'a*b'; | |
+ const iter = string.matchAll('\\w'); | |
+ | |
+ let result; | |
+ result = iter.next(); | |
+ assert.compareArray(result.value, ['a']); | |
+ assert(!result.done); | |
+ | |
+ result = iter.next(); | |
+ assert.compareArray(result.value, ['b']); | |
+ assert(!result.done); | |
+ | |
+ result = iter.next(); | |
+ assert.sameValue(result.value, null); | |
+ assert(result.done); | |
+} finally { | |
+ RegExp.prototype[Symbol.matchAll] = originalMatch; | |
+} | |
diff --git a/test/built-ins/String/prototype/matchAll/invoke-internal-regexp-matchAll-throws.js b/test/built-ins/String/prototype/matchAll/invoke-internal-regexp-matchAll-throws.js | |
new file mode 100644 | |
index 000000000..c40abad74 | |
--- /dev/null | |
+++ b/test/built-ins/String/prototype/matchAll/invoke-internal-regexp-matchAll-throws.js | |
@@ -0,0 +1,20 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+ | |
+/*--- | |
+esid: pending | |
+description: > | |
+ Invocation of @@matchAll on internally created RegExp throws | |
+info: > | |
+ [...] | |
+ 4. Let matcher be ? [GetMethod][getmethod](R, @@matchAll). | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+RegExp.prototype[Symbol.matchAll] = function() { | |
+ throw new Test262Error(); | |
+}; | |
+ | |
+assert.throws(Test262Error, function() { | |
+ 'target'.matchAll('.'); | |
+}); | |
diff --git a/test/built-ins/String/prototype/matchAll/invoke-internal-regexp-matchAll.js b/test/built-ins/String/prototype/matchAll/invoke-internal-regexp-matchAll.js | |
new file mode 100644 | |
index 000000000..4ed977d16 | |
--- /dev/null | |
+++ b/test/built-ins/String/prototype/matchAll/invoke-internal-regexp-matchAll.js | |
@@ -0,0 +1,37 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+ | |
+/*--- | |
+esid: pending | |
+description: Invocation of @@matchAll on internally created RegExp | |
+info: > | |
+ [...] | |
+ 4. Let matcher be ? [GetMethod][getmethod](R, @@matchAll). | |
+ 5. If matcher is not undefined, then | |
+ a. Return ? Call(matcher, R, « O »). | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+const originalMatch = RegExp.prototype[Symbol.matchAll]; | |
+const returnVal = {}; | |
+const thisVal, args; | |
+ | |
+RegExp.prototype[Symbol.matchAll] = function() { | |
+ thisVal = this; | |
+ args = arguments; | |
+ return returnVal; | |
+}; | |
+ | |
+try { | |
+ const regexString = '.'; | |
+ const result = 'target'.matchAll(regexString); | |
+ | |
+ assert(thisVal instanceof RegExp); | |
+ assert.sameValue(thisVal.source, regexString); | |
+ assert.sameValue(thisVal.flags, 'g'); | |
+ assert.sameValue(args.length, 1); | |
+ assert.sameValue(args[0], 'target'); | |
+ assert.sameValue(result, returnVal); | |
+} finally { | |
+ RegExp.prototype[Symbol.matchAll] = originalMatch; | |
+} | |
diff --git a/test/built-ins/String/prototype/matchAll/invoke-regexp-has-no-matchAll.js b/test/built-ins/String/prototype/matchAll/invoke-regexp-has-no-matchAll.js | |
new file mode 100644 | |
index 000000000..7dfc77f6d | |
--- /dev/null | |
+++ b/test/built-ins/String/prototype/matchAll/invoke-regexp-has-no-matchAll.js | |
@@ -0,0 +1,35 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+ | |
+/*--- | |
+esid: pending | |
+description: Internally created RegExp has no @@matchAll | |
+info: > | |
+ [...] | |
+ 2. If ? IsRegExp(regexp) is true, then | |
+ 3. Else, | |
+ a. Let R be ? RegExpCreate(regexp, "g"). | |
+ 4. Let matcher be ? [GetMethod][getmethod](R, @@matchAll). | |
+ [...] | |
+ 6. Return ? MatchAllIterator(R, O). | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+const regexp = /\w/g; | |
+delete regexp[Symbol.matchAll]; | |
+const string = 'a*b'; | |
+const iter = string.matchAll(regexp); | |
+ | |
+let result; | |
+result = iter.next(); | |
+assert.compareArray(result.value, ['a']); | |
+assert(!result.done); | |
+ | |
+result = iter.next(); | |
+assert.compareArray(result.value, ['b']); | |
+assert(!result.done); | |
+ | |
+result = iter.next(); | |
+assert.sameValue(result.value, null); | |
+assert(result.done); | |
+ | |
diff --git a/test/built-ins/String/prototype/matchAll/invoke-regexp-matchAll-throws.js b/test/built-ins/String/prototype/matchAll/invoke-regexp-matchAll-throws.js | |
new file mode 100644 | |
index 000000000..f1093fdee | |
--- /dev/null | |
+++ b/test/built-ins/String/prototype/matchAll/invoke-regexp-matchAll-throws.js | |
@@ -0,0 +1,21 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+ | |
+/*--- | |
+esid: pending | |
+description: > | |
+ Invocation of @@matchAll on regexp throws | |
+info: > | |
+ [...] | |
+ 4. Let matcher be ? [GetMethod][getmethod](R, @@matchAll). | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+var regexp = /./; | |
+regexp[Symbol.matchAll] = function() { | |
+ throw new Test262Error(); | |
+}; | |
+ | |
+assert.throws(Test262Error, function() { | |
+ 'target'.matchAll(regexp); | |
+}); | |
diff --git a/test/built-ins/String/prototype/matchAll/invoke-regexp-matchAll.js b/test/built-ins/String/prototype/matchAll/invoke-regexp-matchAll.js | |
new file mode 100644 | |
index 000000000..758de19f8 | |
--- /dev/null | |
+++ b/test/built-ins/String/prototype/matchAll/invoke-regexp-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: Invocation of @@matchAll on regexp | |
+info: > | |
+ [...] | |
+ 4. Let matcher be ? [GetMethod][getmethod](R, @@matchAll). | |
+ 5. If matcher is not undefined, then | |
+ a. Return ? Call(matcher, R, « O »). | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+var regexp = /./; | |
+var returnVal = {}; | |
+var thisVal, args; | |
+regexp[Symbol.matchAll] = function() { | |
+ thisVal = this; | |
+ args = arguments; | |
+ return returnVal; | |
+}; | |
+ | |
+var result = 'target'.matchAll(regexp); | |
+ | |
+assert(thisVal instanceof RegExp); | |
+assert.sameValue(thisVal, regexp); | |
+assert.sameValue(args.length, 1); | |
+assert.sameValue(args[0], 'target'); | |
+assert.sameValue(result, returnVal); | |
diff --git a/test/built-ins/String/prototype/matchAll/return-abrupt-from-regexp-isregexp.js b/test/built-ins/String/prototype/matchAll/return-abrupt-from-regexp-isregexp.js | |
new file mode 100644 | |
index 000000000..cff50bada | |
--- /dev/null | |
+++ b/test/built-ins/String/prototype/matchAll/return-abrupt-from-regexp-isregexp.js | |
@@ -0,0 +1,28 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: > | |
+ Returns abrupt from IsRegExp(O). | |
+info: > | |
+ [...] | |
+ 2. If ? IsRegExp(regexp) is true, then | |
+ | |
+ 7.2.8 IsRegExp ( argument ) | |
+ [...] | |
+ 2. Let matcher be ? Get(argument, @@match). | |
+features: [Symbol.match, String.prototype.matchAll] | |
+---*/ | |
+ | |
+const obj = { | |
+ get [Symbol.match]() { throw new Test262Error(); } | |
+}; | |
+ | |
+assert.throws(Test262Error, () => 'test'.matchAll(obj)); | |
+ | |
+const regexp = /./; | |
+Object.defineProperty(regexp, Symbol.match, { | |
+ get: () => { throw new Test262Error(); } | |
+}); | |
+ | |
+assert.throws(Test262Error, () => 'test'.matchAll(regexp)); | |
diff --git a/test/built-ins/String/prototype/matchAll/this-is-null-throws.js b/test/built-ins/String/prototype/matchAll/this-is-null-throws.js | |
new file mode 100644 | |
index 000000000..84799293e | |
--- /dev/null | |
+++ b/test/built-ins/String/prototype/matchAll/this-is-null-throws.js | |
@@ -0,0 +1,16 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: > | |
+ Throws TypeError when `this` is null | |
+info: > | |
+ pending String.prototype.matchAll ( regexp ) | |
+ | |
+ 1. Let O be RequireObjectCoercible(this value). | |
+features: [String.prototype.matchAll] | |
+---*/ | |
+ | |
+assert.throws(TypeError, function() { | |
+ String.prototype.matchAll.call(null, /./); | |
+}); | |
diff --git a/test/built-ins/String/prototype/matchAll/this-is-undefined-throws.js b/test/built-ins/String/prototype/matchAll/this-is-undefined-throws.js | |
new file mode 100644 | |
index 000000000..796ab7b78 | |
--- /dev/null | |
+++ b/test/built-ins/String/prototype/matchAll/this-is-undefined-throws.js | |
@@ -0,0 +1,16 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+/*--- | |
+esid: pending | |
+description: > | |
+ Throws TypeError when `this` is undefined | |
+info: > | |
+ pending String.prototype.matchAll ( regexp ) | |
+ | |
+ 1. Let O be RequireObjectCoercible(this value). | |
+features: [String.prototype.matchAll] | |
+---*/ | |
+ | |
+assert.throws(TypeError, function() { | |
+ String.prototype.matchAll.call(undefined, /./); | |
+}); | |
diff --git a/test/built-ins/String/prototype/matchAll/tostring-throws.js b/test/built-ins/String/prototype/matchAll/tostring-throws.js | |
new file mode 100644 | |
index 000000000..025f68d05 | |
--- /dev/null | |
+++ b/test/built-ins/String/prototype/matchAll/tostring-throws.js | |
@@ -0,0 +1,24 @@ | |
+// Copyright (C) 2018 Peter Wong. All rights reserved. | |
+// This code is governed by the BSD license found in the LICENSE file. | |
+ | |
+/*--- | |
+esid: pending | |
+description: > | |
+ When regexp is string, create a Regular Expression with global flag set. | |
+info: > | |
+ [...] | |
+ 2. If ? IsRegExp(regexp) is true, then | |
+ [...] | |
+ 3. Else, | |
+ a. Let R be ? RegExpCreate(regexp, "g"). | |
+features: [Symbol.matchAll] | |
+---*/ | |
+ | |
+const obj = { | |
+ toString() { throw new Test262Error(); } | |
+}; | |
+ | |
+assert.throws(Test262Error, function() { | |
+ 'target'.matchAll(obj); | |
+}); | |
+ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment