diff --git a/features.txt b/features.txt index 6290998b2895dfeb6132d4efdc22b8583bd6a534..874e78f58ff9a8a589e8d3aafa1d31d20f47d8f3 100644 --- a/features.txt +++ b/features.txt @@ -72,6 +72,11 @@ String.prototype.trimStart # https://github.com/tc39/proposal-numeric-separator numeric-separator-literal +# String.prototype.matchAll +# https://github.com/tc39/proposal-string-matchall +String.prototype.matchAll +Symbol.matchAll + # Standard language features # # Language features that have been included in a published version of the diff --git a/harness/compareIterator.js b/harness/compareIterator.js new file mode 100644 index 0000000000000000000000000000000000000000..69b9246e1b71685514b89f5542f28ee52f29029c --- /dev/null +++ b/harness/compareIterator.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. +/*--- +description: Compare the values of an iterator with an array of expected values +---*/ + +// Example: +// +// function* numbers() { +// yield 1; +// yield 2; +// yield 3; +// } +// +// compareIterator(numbers(), [ +// v => assert.sameValue(v, 1), +// v => assert.sameValue(v, 2), +// v => assert.sameValue(v, 3), +// ]); +// +assert.compareIterator = function(iter, validators, message) { + message = message || ''; + + var i, result; + for (i = 0; i < validators.length; i++) { + result = iter.next(); + assert(!result.done, 'Expected ' + i + ' values(s). Instead iterator only produced ' + (i - 1) + ' value(s). ' + message); + validators[i](result.value); + } + + result = iter.next(); + assert(result.done, 'Expected only ' + i + ' values(s). Instead iterator produced more. ' + message); + assert.sameValue(result.value, undefined, 'Expected value of `undefined` when iterator completes. ' + message); +} diff --git a/harness/regExpUtils.js b/harness/regExpUtils.js index bdb956427ac5b484487ee5330fe6827172491d42..4dd7ddf13b0c4523cbce947931b1f72d87b0504d 100644 --- a/harness/regExpUtils.js +++ b/harness/regExpUtils.js @@ -37,3 +37,18 @@ function testPropertyEscapes(regex, string, expression) { } } } + +// Returns a function that will validate RegExp match result +// +// Example: +// +// var validate = matchValidator(['b'], 1, 'abc'); +// validate(/b/.exec('abc')); +// +function matchValidator(expectedEntries, expectedIndex, expectedInput) { + return function(match) { + assert.compareArray(match, expectedEntries, 'Match entries'); + assert.sameValue(match.index, expectedIndex, 'Match index'); + assert.sameValue(match.input, expectedInput, 'Match input'); + } +} diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/get-species-constructor-err.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/get-species-constructor-err.js deleted file mode 100644 index 64028836ee8f61689b10a7e82ef6326ac89675cf..0000000000000000000000000000000000000000 --- a/test/built-ins/RegExp/prototype/Symbol.matchAll/get-species-constructor-err.js +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2015 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -description: > - Behavior when error is thrown during retrieval of `Symbol.species` property -info: | - 3. Let C be ? SpeciesConstructor(R, %RegExp%). -features: [Symbol.match, Symbol.matchAll, Symbol.species] ----*/ - -var obj = {}; -Object.defineProperty(obj, Symbol.species, { - get: function () { - throw new Test262Error(); - } -}); -obj[Symbol.match] = true; - -assert.throws(Test262Error, function() { - RegExp.prototype[Symbol.matchAll].call(obj); -}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/internal-regexp-lastindex-not-zero.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/internal-regexp-lastindex-not-zero.js new file mode 100644 index 0000000000000000000000000000000000000000..944ef30989eed624e7497de72e816761a7d2c943 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/internal-regexp-lastindex-not-zero.js @@ -0,0 +1,33 @@ +// 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 internally created RegExp's lastIndex is not 0 +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] + 3. Else, + a. Let matcher be RegExpCreate(R, "g"). + b. If ? IsRegExp(matcher) is not true, throw a TypeError exception. + [...] + 3. If Get(matcher, "lastIndex") is not 0, throw a TypeError exception. +features: [Symbol.match, Symbol.matchAll] +---*/ + +Object.defineProperty(RegExp.prototype, Symbol.match, { + get() { + this.lastIndex = 1; + return true; + } +}); + +assert.throws(TypeError, function() { + RegExp.prototype[Symbol.matchAll].call({}, ''); +}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/isregexp-internal-regexp-is-false.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/isregexp-internal-regexp-is-false.js new file mode 100644 index 0000000000000000000000000000000000000000..214e9b7efd29fe7cf9293e6005a94a4fcda70644 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/isregexp-internal-regexp-is-false.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: Throws TypeError when internally created RegExp's @@match is false +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] + 3. Else, + a. Let matcher be RegExpCreate(R, "g"). + b. If ? IsRegExp(matcher) is not true, throw a TypeError exception. +features: [Symbol.match, Symbol.matchAll] +---*/ + +Object.defineProperty(RegExp.prototype, Symbol.match, { + get() { + return false; + } +}); + +assert.throws(TypeError, function() { + RegExp.prototype[Symbol.matchAll].call({}, ''); +}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/isregexp-internal-regexp-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/isregexp-internal-regexp-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..70b62da39f54a3ab09ca8cc01b1faa5fd62f53b7 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/isregexp-internal-regexp-throws.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: Re-throws errors thrown while accessing @@match property +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] + 3. Else, + a. Let matcher be RegExpCreate(R, "g"). + b. If ? IsRegExp(matcher) is not true, throw a TypeError exception. +features: [Symbol.match, Symbol.matchAll] +---*/ + +Object.defineProperty(RegExp.prototype, Symbol.match, { + get() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + RegExp.prototype[Symbol.matchAll].call({}, ''); +}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/isregexp-this-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/isregexp-this-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..ce31f3392fb8483c113205243a2ccbf52e4b9f5e --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/isregexp-this-throws.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: Re-throws errors thrown while accessing RegExp's @@match property +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] +features: [Symbol.match, Symbol.matchAll] +---*/ + +var obj = { + get [Symbol.match]() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + RegExp.prototype[Symbol.matchAll].call(obj, ''); +}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/length.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/length.js index 241d3d40ce9b7007f6a287b5c6b165aed6c20f16..7aee38c0cb72bd3fb5c9747a4e12b9abab673f41 100644 --- a/test/built-ins/RegExp/prototype/Symbol.matchAll/length.js +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/length.js @@ -1,17 +1,22 @@ // Copyright (C) 2018 Jordan Harband. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- +esid: pending description: RegExp.prototype[Symbol.matchAll] `length` property 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. + 17 ECMAScript Standard Built-in Objects: [...] - Unless otherwise specified, the length property of a built-in Function + 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. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which + are 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] diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/name.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/name.js index a755118e007442a94cd58cda25b832f3738e46d6..b6030216425e225a4c5755d525d3d156bf771ac4 100644 --- a/test/built-ins/RegExp/prototype/Symbol.matchAll/name.js +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/name.js @@ -1,15 +1,20 @@ // Copyright (C) 2018 Jordan Harband. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- +esid: pending description: RegExp.prototype[Symbol.matchAll] `name` property info: | - The value of the name property of this function is "[Symbol.matchAll]". + 17 ECMAScript Standard Built-in Objects: - ES6 Section 17: + [...] + + 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 + 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] diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/prop-desc.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/prop-desc.js index df4f7955db703148f42dc844f78bb4bcd80e8e75..63d27c57b783d89e641cb9a18bcd684bce0ea470 100644 --- a/test/built-ins/RegExp/prototype/Symbol.matchAll/prop-desc.js +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/prop-desc.js @@ -1,10 +1,12 @@ // Copyright (C) 2018 Jordan Harband. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. - /*--- +esid: pending description: RegExp.prototype[Symbol.matchAll] property descriptor info: | - ES6 Section 17 + 17 ECMAScript Standard Built-in Objects: + + [...] Every other data property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, @@ -14,6 +16,7 @@ features: [Symbol.matchAll] ---*/ 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/regexpcreate-this-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/regexpcreate-this-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..d34b563c2827ae2e8c5c1d078c407e9d87743a4a --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/regexpcreate-this-throws.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: Re-throws errors while creating an internal RegExp +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] + 3. Else, + a. Let R be RegExpCreate(R, "g"). +features: [Symbol.matchAll] +---*/ + +var 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/species-constructor-get-constructor-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-get-constructor-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..2c255853ee3b9cab422dc3473cbea92a8b32da90 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-get-constructor-throws.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: | + Re-throws errors thrown while accessing RegExp's constructor property +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + a. Let C be ? SpeciesConstructor(R, RegExp). + + SpeciesConstructor ( O, defaultConstructor ) + [...] + 2. Let C be ? Get(O, "constructor"). +features: [Symbol.matchAll] +---*/ + +var regexp = /./; +Object.defineProperty(regexp, 'constructor', { + get(){ + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + regexp[Symbol.matchAll](''); +}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-get-species-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-get-species-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..3e429a88dc7d29189cafb487baa3be1de05d3060 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-get-species-throws.js @@ -0,0 +1,31 @@ +// 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-throws errors thrown while accessing of @@species property +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + a. Let C be ? SpeciesConstructor(R, RegExp). + + SpeciesConstructor ( O, defaultConstructor ) + [...] + 2. Let C be ? Get(O, "constructor"). +features: [Symbol.matchAll, Symbol.species] +---*/ + +var regexp = /./; +regexp.constructor = { + get [Symbol.species]() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + regexp[Symbol.matchAll](''); +}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-is-not-object-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-is-not-object-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..d26752a94157e21db4136a66191409b1dc6deb15 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-is-not-object-throws.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: Throws TypeError if `constructor` property is not an object +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + a. Let C be ? SpeciesConstructor(R, RegExp). + + SpeciesConstructor ( O, defaultConstructor ) + [...] + 2. Let C be ? Get(O, "constructor"). + 3. If C is undefined, return defaultConstructor. + 4. If Type(C) is not Object, throw a TypeError exception. +features: [Symbol.matchAll] +---*/ + +var regexp = /./; + +function callMatchAll() { regexp[Symbol.matchAll](''); } + +regexp.constructor = null; +assert.throws(TypeError, callMatchAll, "`constructor` value is null"); + +regexp.constructor = true; +assert.throws(TypeError, callMatchAll, "`constructor` value is Boolean"); + +regexp.constructor = ""; +assert.throws(TypeError, callMatchAll, "`constructor` value is String"); + +regexp.constructor = Symbol(); +assert.throws(TypeError, callMatchAll, "`constructor` value is Symbol"); + +regexp.constructor = 1; +assert.throws(TypeError, callMatchAll, "`constructor` value is Number"); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-is-undefined.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-is-undefined.js new file mode 100644 index 0000000000000000000000000000000000000000..792bb1e7f8c35dd810b3fb8417197821497d8da7 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-is-undefined.js @@ -0,0 +1,31 @@ +// 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 if `constructor` property is not an object +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + a. Let C be ? SpeciesConstructor(R, RegExp). + + SpeciesConstructor ( O, defaultConstructor ) + [...] + 2. Let C be ? Get(O, "constructor"). + 3. If C is undefined, return defaultConstructor. +features: [Symbol.matchAll] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +var regexp = /\w/g; +regexp.constructor = undefined; +var str = 'a*b'; + +assert.compareIterator(regexp[Symbol.matchAll](str), [ + matchValidator(['a'], 0, str), + matchValidator(['b'], 2, str) +]); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-species-is-not-constructor.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-species-is-not-constructor.js new file mode 100644 index 0000000000000000000000000000000000000000..b47402d7d69bd26fc2bd5be1fe1f497ee4c1818a --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-species-is-not-constructor.js @@ -0,0 +1,45 @@ +// Copyright (C) 2018 Peter Wong. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: pending +description: TypeError is thrown when species constructor is not a constructor +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 2. Return ? [MatchAllIterator](#matchalliterator)(R, string). + + MatchAllIterator ( R, O ) + [...] + 3. Let C be ? [SpeciesConstructor][species-constructor](R, RegExp). + + SpeciesConstructor ( O, defaultConstructor ) + [...] + 2. Let C be ? Get(O, "constructor"). + 3. If C is undefined, return defaultConstructor. + 4. If Type(C) is not Object, throw a TypeError exception. + 5. Let S be ? Get(C, @@species). + 6. If S is either undefined or null, return defaultConstructor. + 7. If IsConstructor(S) is true, return S. + 8. Throw a TypeError exception. +features: [Symbol.matchAll, Symbol.species] +---*/ + +var regexp = /./; +var speciesConstructor = {}; +regexp.constructor = speciesConstructor; + +var callMatchAll = function() { + regexp[Symbol.matchAll](''); +} + +speciesConstructor[Symbol.species] = true; +assert.throws(TypeError, callMatchAll, "`constructor[Symbol.species]` value is Boolean"); + +speciesConstructor[Symbol.species] = 1; +assert.throws(TypeError, callMatchAll, "`constructor[Symbol.species]` value is Number"); + +speciesConstructor[Symbol.species] = Symbol(); +assert.throws(TypeError, callMatchAll, "`constructor[Symbol.species]` value is Symbol"); + +speciesConstructor[Symbol.species] = true; +assert.throws(TypeError, callMatchAll, "`constructor[Symbol.species]` value is Boolean"); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-species-is-null-or-undefined.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-species-is-null-or-undefined.js new file mode 100644 index 0000000000000000000000000000000000000000..564d8bb58b955a3c48132e76b681cfd85a8898ef --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-species-is-null-or-undefined.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: | + Default constructor is used when species constructor is null or undefined +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 2. Return ? [MatchAllIterator](#matchalliterator)(R, string). + + MatchAllIterator ( R, O ) + [...] + 3. Let C be ? [SpeciesConstructor][species-constructor](R, RegExp). + + SpeciesConstructor ( O, defaultConstructor ) + [...] + 2. Let C be ? Get(O, "constructor"). + 3. If C is undefined, return defaultConstructor. + 4. If Type(C) is not Object, throw a TypeError exception. + 5. Let S be ? Get(C, @@species). + 6. If S is either undefined or null, return defaultConstructor. +features: [Symbol.matchAll, Symbol.species] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +function TestWithConstructor(ctor) { + var regexp = /\w/g; + regexp.constructor = { + [Symbol.species]: ctor + }; + var str = 'a*b'; + + assert.compareIterator(regexp[Symbol.matchAll](str), [ + matchValidator(['a'], 0, str), + matchValidator(['b'], 2, str) + ]); +} + +TestWithConstructor(undefined); +TestWithConstructor(null); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-species-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-species-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..70a6683f4886ce3d68a85e426e79d6ea078a3853 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor-species-throws.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: Re-throws errors when calling constructor's @@species +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + a. Let C be ? SpeciesConstructor(R, RegExp). + b. Let flags be ? ToString(? Get(R, "flags")) + c. Let matcher be ? Construct(C, R, flags). +features: [Symbol.matchAll, Symbol.species] +---*/ + +var regexp = /./; +regexp.constructor = { + [Symbol.species]: function() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + regexp[Symbol.matchAll](''); +}); 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 0000000000000000000000000000000000000000..cb9e9bf03c251719dc0a0e47741de0f633267682 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-constructor.js @@ -0,0 +1,42 @@ +// Copyright (C) 2018 Peter Wong. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: pending +description: Custom species constructor is called when creating internal RegExp +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + a. Let C be ? SpeciesConstructor(R, RegExp). + b. Let flags be ? ToString(? Get(R, "flags")) + c. Let matcher be ? Construct(C, R, flags). +features: [Symbol.matchAll, Symbol.species] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +var callCount = 0; +var callArgs; +var regexp = /\d/u; +regexp.constructor = { + [Symbol.species]: function(){ + callCount++; + callArgs = arguments; + return /\w/g; + } +}; +var str = 'a*b'; +var iter = regexp[Symbol.matchAll](str); + +assert.sameValue(callCount, 1); +assert.sameValue(callArgs.length, 2); +assert.sameValue(callArgs[0], regexp); +assert.sameValue(callArgs[1], 'u'); + +assert.compareIterator(iter, [ + matchValidator(['a'], 0, str), + matchValidator(['b'], 2, str) +]); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/species-regexp-get-global-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-regexp-get-global-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..46304cc84a0178bc9334c0869419b7b343a1f7d7 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-regexp-get-global-throws.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: | + Re-throws errors thrown while accessing species constructed RegExp's + global property +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] + d. Let global be ? ToBoolean(? Get(matcher, "global")). +features: [Symbol.matchAll, Symbol.species] +---*/ + +var regexp = /./; +regexp.constructor = { + [Symbol.species]: function() { + return Object.defineProperty(/./, 'global', { + get() { + throw new Test262Error(); + } + }); + } +}; + +assert.throws(Test262Error, function() { + regexp[Symbol.matchAll](''); +}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/species-regexp-get-unicode-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-regexp-get-unicode-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..931b028995607a4e3c2d6937c858400f6be1aa79 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/species-regexp-get-unicode-throws.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: | + Re-throws errors thrown while accessing species constructed RegExp's + unicode property +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] + e. Let fullUnicode be ? ToBoolean(? Get(matcher, "unicode")). +features: [Symbol.matchAll, Symbol.species] +---*/ + +var regexp = /./; +regexp.constructor = { + [Symbol.species]: function() { + return Object.defineProperty(/./, 'unicode', { + get() { + throw new Test262Error(); + } + }); + } +}; + +assert.throws(Test262Error, function() { + regexp[Symbol.matchAll](''); +}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/coerce-arg.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/string-tostring-throws.js similarity index 59% rename from test/built-ins/RegExp/prototype/Symbol.matchAll/coerce-arg.js rename to test/built-ins/RegExp/prototype/Symbol.matchAll/string-tostring-throws.js index b2557aae99dc29536657493f3ba5c7572056c396..672ba5792c9e74df78de091718de6026614b0d0c 100644 --- a/test/built-ins/RegExp/prototype/Symbol.matchAll/coerce-arg.js +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/string-tostring-throws.js @@ -1,27 +1,27 @@ // Copyright (C) 2018 Jordan Harband. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. - /*--- +esid: pending description: String coercion of string parameter info: | - RegExp.prototype [ @@matchAll ] ( string ) - + RegExp.prototype [ @@matchAll ] ( string ) [...] - 2. Let S be ? ToString(O). - [...] -features: [Symbol.match, Symbol.matchAll] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + 1. Let S be ? ToString(O). +features: [Symbol.matchAll] ---*/ var obj = { - valueOf: function() { + valueOf() { $ERROR('This method should not be invoked.'); }, - toString: function() { + toString() { throw new Test262Error('toString invoked'); } }; -obj[Symbol.match] = true; -assert.throws(Test262Error, function () { +assert.throws(Test262Error, function() { /toString value/[Symbol.matchAll](obj); }); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/string-tostring.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/string-tostring.js new file mode 100644 index 0000000000000000000000000000000000000000..bafeb125b65abebc6df5c921f028d86b0354b1c7 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/string-tostring.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: String coercion of `string` argument +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + 1. Let S be ? ToString(O). +features: [Symbol.matchAll] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +var str = 'a*b'; +var obj = { + toString() { + return str; + } +}; +var regexp = /\w/g; + +assert.compareIterator(regexp[Symbol.matchAll](obj), [ + matchValidator(['a'], 0, str), + matchValidator(['b'], 2, str) +]); + diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/this-get-flags-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-get-flags-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..0f21590b74d72f5fc56c7d8aadc79a3c81c027ac --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-get-flags-throws.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: Re-throws errors thrown while accessing RegExp's flags property +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] + b. Let flags be ? ToString(? Get(R, "flags")) +features: [Symbol.matchAll] +---*/ + +var regexp = /./; +Object.defineProperty(regexp, 'flags', { + get() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + regexp[Symbol.matchAll](''); +}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/this-get-flags.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-get-flags.js new file mode 100644 index 0000000000000000000000000000000000000000..eca4ffa4d4be71e0a23bec3b17fe1b01671be4e3 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-get-flags.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: Regexp's flags +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] + b. Let flags be ? ToString(? Get(R, "flags")) +features: [Symbol.matchAll] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +var regexp = /\w/; +Object.defineProperty(regexp, 'flags', { + value: 'g' +}); +var str = 'a*b'; + +assert.compareIterator(regexp[Symbol.matchAll](str), [ + matchValidator(['a'], 0, str), + matchValidator(['b'], 2, str) +]); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/this-lastindex-cached.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-lastindex-cached.js new file mode 100644 index 0000000000000000000000000000000000000000..ebefdb4e388938956c47b57cb0786003015f6686 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-lastindex-cached.js @@ -0,0 +1,36 @@ +// 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 regexp's lastIndex is cached +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] + f. Let lastIndex be ? ToLength(? Get(R, "lastIndex")). + g. Perform ? Set(matcher, "lastIndex", lastIndex, true). +features: [Symbol.matchAll] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +var regexp = /./g; +regexp.lastIndex = { + valueOf() { + return 2; + } +}; +var str = 'abcd'; +var iter = regexp[Symbol.matchAll](str); + +// Verify lastIndex is cached at the time of calling @@matchAll +regexp.lastIndex = 0; + +assert.compareIterator(iter, [ + matchValidator(['c'], 2, str), + matchValidator(['d'], 3, str) +]); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/this-not-object-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-not-object-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..b8f350d05f67475e0f06b217907326b8a062ec46 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-not-object-throws.js @@ -0,0 +1,31 @@ +// Copyright (C) 2018 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: pending +description: Throws TypeError when `this` is not an Object +info: | + RegExp.prototype [ @@matchAll ] ( string ) + 1. Let R be the this value. + 2. If Type(R) is not Object, throw a TypeError exception. +features: [Symbol.matchAll] +---*/ + +var thisValue; +var callMatchAll = function() { + RegExp.prototype[Symbol.matchAll].call(thisValue, ''); +}; + +thisValue = null; +assert.throws(TypeError, callMatchAll, 'this value is null'); + +thisValue = true; +assert.throws(TypeError, callMatchAll, 'this value is Boolean'); + +thisValue = ''; +assert.throws(TypeError, callMatchAll, 'this value is String'); + +thisValue = Symbol(); +assert.throws(TypeError, callMatchAll, 'this value is Symbol'); + +thisValue = 1; +assert.throws(TypeError, callMatchAll, 'this value is Number'); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/this-tolength-lastindex-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-tolength-lastindex-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..fcaefdaf415f664456739b97862df0653fc91bb8 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-tolength-lastindex-throws.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: Re-throws errors while coercing RegExp's lastIndex +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] + f. Let lastIndex be ? ToLength(? Get(R, "lastIndex")). +features: [Symbol.matchAll] +---*/ + +var regexp = /./; +regexp.lastIndex = { + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + regexp[Symbol.matchAll](''); +}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/this-tostring-flags-throws.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-tostring-flags-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..206cc65d1008d3042742889d1674ad40486052f9 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-tostring-flags-throws.js @@ -0,0 +1,33 @@ +// 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-throws errors while coercing RegExp's flags to a string +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] + b. Let flags be ? ToString(? Get(R, "flags")) +features: [Symbol.matchAll] +---*/ + +var regexp = /\w/; +Object.defineProperty(regexp, 'flags', { + value: { + valueOf() { + ERROR('valueOf Should not be called'); + }, + toString() { + throw new Test262Error(); + } + } +}); + +assert.throws(Test262Error, function() { + regexp[Symbol.matchAll](''); +}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/this-tostring-flags.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-tostring-flags.js new file mode 100644 index 0000000000000000000000000000000000000000..5c7f9cb81593046f7957acf935974dd1f9dcfe29 --- /dev/null +++ b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-tostring-flags.js @@ -0,0 +1,33 @@ +// Copyright (C) 2018 Peter Wong. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: pending +description: Corercing regexp's flags +info: | + RegExp.prototype [ @@matchAll ] ( string ) + [...] + 3. Return ? MatchAllIterator(R, string). + + MatchAllIterator ( R, O ) + [...] + 2. If ? IsRegExp(R) is true, then + [...] + b. Let flags be ? ToString(? Get(R, "flags")) +features: [Symbol.matchAll] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +var regexp = /\w/; +Object.defineProperty(regexp, 'flags', { + value: { + toString() { + return 'g'; + } + } +}); +var str = 'a*b'; + +assert.compareIterator(regexp[Symbol.matchAll](str), [ + matchValidator(['a'], 0, str), + matchValidator(['b'], 2, str) +]); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/this-val-non-obj.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-val-non-obj.js deleted file mode 100644 index b4469f2ac76ae4bcbb8d5c98b861d6092e73e7d8..0000000000000000000000000000000000000000 --- a/test/built-ins/RegExp/prototype/Symbol.matchAll/this-val-non-obj.js +++ /dev/null @@ -1,36 +0,0 @@ -// 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 must be an object -info: | - 1. Let R be the this value. - 2. Return ? MatchAllIterator(R, string). - [...] - 1. If ? IsRegExp(R) is not true, throw a TypeError exception. -features: [Symbol.matchAll] ----*/ - -assert.throws(TypeError, function() { - RegExp.prototype[Symbol.matchAll].call(undefined); -}); - -assert.throws(TypeError, function() { - RegExp.prototype[Symbol.matchAll].call(null); -}); - -assert.throws(TypeError, function() { - RegExp.prototype[Symbol.matchAll].call(true); -}); - -assert.throws(TypeError, function() { - RegExp.prototype[Symbol.matchAll].call('string'); -}); - -assert.throws(TypeError, function() { - RegExp.prototype[Symbol.matchAll].call(Symbol.matchAll); -}); - -assert.throws(TypeError, function() { - RegExp.prototype[Symbol.matchAll].call(86); -}); diff --git a/test/built-ins/RegExp/prototype/Symbol.matchAll/this-val-non-regexp.js b/test/built-ins/RegExp/prototype/Symbol.matchAll/this-val-non-regexp.js deleted file mode 100644 index 76a57831cb1ef840d9504b326dd2ec41fdaa7ca7..0000000000000000000000000000000000000000 --- a/test/built-ins/RegExp/prototype/Symbol.matchAll/this-val-non-regexp.js +++ /dev/null @@ -1,22 +0,0 @@ -// 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 must be a regular expression (has Symbol.match) -info: | - 1. Let R be the this value. - 2. Return ? MatchAllIterator(R, string). - [...] - 1. If ? IsRegExp(R) is not true, throw a TypeError exception. -features: [Symbol.match, Symbol.matchAll] ----*/ - -var regexObj = {}; -regexObj[Symbol.match] = true; -var obj = {}; - -RegExp.prototype[Symbol.matchAll].call(regexObj); - -assert.throws(TypeError, function() { - RegExp.prototype[Symbol.matchAll].call(obj); -}); diff --git a/test/built-ins/RegExpStringIteratorPrototype/Symbol.toStringTag.js b/test/built-ins/RegExpStringIteratorPrototype/Symbol.toStringTag.js new file mode 100644 index 0000000000000000000000000000000000000000..a412432545788b5aa54177ceed2667d51b5249e9 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/Symbol.toStringTag.js @@ -0,0 +1,23 @@ +// Copyright (C) 2018 Peter Wong. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: 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.matchAll, Symbol.toStringTag] +includes: [propertyHelper.js] +---*/ + +var RegExpStringIteratorProto = Object.getPrototypeOf(/./[Symbol.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 0000000000000000000000000000000000000000..f7a6e7b6cbc1d7825a722611b0e0ed97a01e9135 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/ancestry.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: | + The [[Prototype]] internal slot ofthe %RegExpStringIteratorPrototype% is the + %IteratorPrototype% intrinsic object (25.1.2). +features: [Symbol.iterator, Symbol.matchAll] +---*/ + +var RegExpStringIteratorProto = Object.getPrototypeOf(/./[Symbol.matchAll]('a')); +var ArrayIteratorProto = Object.getPrototypeOf( + Object.getPrototypeOf([][Symbol.iterator]()) +); + +assert.sameValue(Object.getPrototypeOf(RegExpStringIteratorProto), ArrayIteratorProto); diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-call-throws.js b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-call-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..74df2c83d10e3ea150c816e18e8e5ee693cef664 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-call-throws.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: Re-throws errors when calling exec +info: | + %RegExpStringIteratorPrototype%.next ( ) + [...] + 9. Let match be ? RegExpExec(R, S). + + Runtime Semantics: RegExpExec ( R, S ) + 1. Assert: Type(R) is Object. + 2. Assert: Type(S) is String. + 3. Let exec be ? Get(R, "exec"). + 4. If IsCallable(exec) is true, then + a. Let result be ? Call(exec, R, « S »). +features: [Symbol.matchAll] +---*/ + +var iter = /./[Symbol.matchAll](''); + +RegExp.prototype.exec = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + iter.next(); +}); diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-get-throws.js b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-get-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..808b142a219b9df447b773836dfbaa2e379aaf51 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-get-throws.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: Re-throws errors thrown while accessing RegExp's exec property +info: | + %RegExpStringIteratorPrototype%.next ( ) + [...] + 9. Let match be ? RegExpExec(R, S). + + Runtime Semantics: RegExpExec ( R, S ) + 1. Assert: Type(R) is Object. + 2. Assert: Type(S) is String. + 3. Let exec be ? Get(R, "exec"). +features: [Symbol.matchAll] +---*/ + +var iter = /./[Symbol.matchAll](''); + +Object.defineProperty(RegExp.prototype, 'exec', { + get() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + iter.next(); +}); diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-match-get-0-throws.js b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-match-get-0-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..7dc986da924940c7bf6ae29f9410b9a5d711709b --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-match-get-0-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-throws errors thrown while accessing the first match +info: | + %RegExpStringIteratorPrototype%.next ( ) + [...] + 9. Let match be ? RegExpExec(R, S). + 10. If match is null, then + [...] + 11. Else, + a. If global is true, + i. Let matchStr be ? ToString(? Get(match, "0")). +features: [Symbol.matchAll] +---*/ + +var iter = /./g[Symbol.matchAll](''); + +RegExp.prototype.exec = function() { + return { + get '0'() { + throw new Test262Error(); + } + }; +}; + +assert.throws(Test262Error, function() { + iter.next(); +}); diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-match-get-0-tostring-throws.js b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-match-get-0-tostring-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..e84b3c4fc03c708dab961a5ba88dac5f65ed03c0 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-match-get-0-tostring-throws.js @@ -0,0 +1,31 @@ +// 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-throws errors thrown from coercing first match to a string +info: | + %RegExpStringIteratorPrototype%.next ( ) + [...] + 9. Let match be ? RegExpExec(R, S). + 10. If match is null, then + [...] + 11. Else, + a. If global is true, + i. Let matchStr be ? ToString(? Get(match, "0")). +features: [Symbol.matchAll] +---*/ + +var iter = /./g[Symbol.matchAll](''); + +RegExp.prototype.exec = function() { + return [{ + toString: function() { + throw new Test262Error(); + } + }]; +}; + +assert.throws(Test262Error, function() { + iter.next(); +}); + diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-match-get-0-tostring.js b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-match-get-0-tostring.js new file mode 100644 index 0000000000000000000000000000000000000000..33ac742ca2d5d9127ae58a261a5c219e952d1034 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-match-get-0-tostring.js @@ -0,0 +1,48 @@ +// 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 first match is coerced to a empty string +info: | + %RegExpStringIteratorPrototype%.next ( ) + [...] + 9. Let match be ? RegExpExec(R, S). + 10. If match is null, then + [...] + 11. Else, + a. If global is true, + i. Let matchStr be ? ToString(? Get(match, "0")). + ii. If matchStr is the empty string, + 1. Let thisIndex be ? ToLength(? Get(R, "lastIndex"). + 2. Let nextIndex be ! AdvanceStringIndex(S, thisIndex, fullUnicode). + 3. Perform ? Set(R, "lastIndex", nextIndex, true). + iii. Return ! CreateIterResultObject(match, false). +features: [Symbol.matchAll] +---*/ + +var iter = /./g[Symbol.matchAll](''); + +var execResult = { + get '0'() { + return { + toString() { return ''; } + }; + } +}; + +var internalRegExp; +RegExp.prototype.exec = function () { + internalRegExp = this; + return execResult; +}; + +var result = iter.next(); +assert.sameValue(internalRegExp.lastIndex, 1); +assert.sameValue(result.value, execResult); +assert(!result.done); + + +result = iter.next(); +assert.sameValue(internalRegExp.lastIndex, 2); +assert.sameValue(result.value, execResult); +assert(!result.done); diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-not-callable.js b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-not-callable.js new file mode 100644 index 0000000000000000000000000000000000000000..d659cd28d44609f01df1cd7a48863f286735d190 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec-not-callable.js @@ -0,0 +1,40 @@ +// 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 with a custom RegExp exec +info: | + %RegExpStringIteratorPrototype%.next ( ) + [...] + 9. Let match be ? RegExpExec(R, S). + + Runtime Semantics: RegExpExec ( R, S ) + 1. Assert: Type(R) is Object. + 2. Assert: Type(S) is String. + 3. Let exec be ? Get(R, "exec"). + 4. If IsCallable(exec) is true, then + [...] + 5. If R does not have a [[RegExpMatcher]] internal slot, throw a + TypeError exception. + 6. Return ? RegExpBuiltinExec(R, S). +features: [Symbol.matchAll] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +function TestWithRegExpExec(exec) { + RegExp.prototype.exec = exec; + + var regexp = /\w/g; + var str = 'a*b'; + + assert.compareIterator(regexp[Symbol.matchAll](str), [ + matchValidator(['a'], 0, str), + matchValidator(['b'], 2, str) + ]); +} + +TestWithRegExpExec(undefined); +TestWithRegExpExec(null); +TestWithRegExpExec(5); +TestWithRegExpExec(true); +TestWithRegExpExec(Symbol()); diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec.js b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec.js new file mode 100644 index 0000000000000000000000000000000000000000..850a7a18c0ec18f754b6b59411b2af01e257c4a0 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/custom-regexpexec.js @@ -0,0 +1,55 @@ +// 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 with a custom RegExp exec +info: | + %RegExpStringIteratorPrototype%.next ( ) + [...] + 9. Let match be ? RegExpExec(R, S). + + Runtime Semantics: RegExpExec ( R, S ) + 1. Assert: Type(R) is Object. + 2. Assert: Type(S) is String. + 3. Let exec be ? Get(R, "exec"). + 4. If IsCallable(exec) is true, then + a. Let result be ? Call(exec, R, « S »). + b. If Type(result) is neither Object or Null, throw a TypeError exception. + c. Return result. +features: [Symbol.matchAll] +---*/ + +var regexp = /./g; +var str = 'abc'; +var iter = regexp[Symbol.matchAll](str); + +var callArgs, callCount; +function callNextWithExecReturnValue(returnValue) { + callArgs = undefined; + callCount = 0; + + RegExp.prototype.exec = function() { + callArgs = arguments; + callCount++; + return returnValue; + } + + return iter.next(); +} + +var firstExecReturnValue = ['ab']; +var result = callNextWithExecReturnValue(firstExecReturnValue); +assert.sameValue(result.value, firstExecReturnValue); +assert(!result.done); + +assert.sameValue(callArgs.length, 1); +assert.sameValue(callArgs[0], str); +assert.sameValue(callCount, 1); + +result = callNextWithExecReturnValue(null); +assert.sameValue(result.value, undefined); +assert(result.done); + +assert.sameValue(callArgs.length, 1); +assert.sameValue(callArgs[0], str); +assert.sameValue(callCount, 1); diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/length.js b/test/built-ins/RegExpStringIteratorPrototype/next/length.js new file mode 100644 index 0000000000000000000000000000000000000000..b9ae0f009984ce3115c9878460920a5a72151638 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/length.js @@ -0,0 +1,33 @@ +// 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` property +info: | + 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. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which + are 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: [Symbol.matchAll] +---*/ + +var RegExpStringIteratorProto = Object.getPrototypeOf(/./[Symbol.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 0000000000000000000000000000000000000000..d9f275fbfeac82223180efb797ec7e6d9b1485ba --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/name.js @@ -0,0 +1,31 @@ +// 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` property +info: | + 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: [Symbol.matchAll] +---*/ + +var RegExpStringIteratorProto = Object.getPrototypeOf(/./[Symbol.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-global.js b/test/built-ins/RegExpStringIteratorPrototype/next/next-iteration-global.js new file mode 100644 index 0000000000000000000000000000000000000000..d1b6726e585087f2676fc63d5a9c37c4b4a40f05 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/next-iteration-global.js @@ -0,0 +1,40 @@ +// Copyright (C) 2018 Peter Wong. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: pending +description: Iterates over each match +info: | + %RegExpStringIteratorPrototype%.next ( ) + [...] + 4. If O.[[Done]] is true, then + a. Return ! reateIterResultObject(undefined, true). + [...] + 9. Let match be ? RegExpExec(R, S). + 10. If match is null, then + a. Set O.[[Done]] to true. + b. Return ! CreateIterResultObject(undefined, true). + 11. Else, + a. If global is true, + i. Let matchStr be ? ToString(? Get(match, "0")). + ii. If matchStr is the empty string, + 1. Let thisIndex be ? ToLength(? Get(R, "lastIndex"). + 2. Let nextIndex be ! AdvanceStringIndex(S, thisIndex, fullUnicode). + 3. Perform ? Set(R, "lastIndex", nextIndex, true). + iii. Return ! CreateIterResultObject(match, false). +features: [Symbol.matchAll] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +var regexp = /\w/g; +var str = 'a*b'; +var iter = regexp[Symbol.matchAll](str); + +assert.compareIterator(iter, [ + matchValidator(['a'], 0, str), + matchValidator(['b'], 2, str) +]); + +// Verifies %RegExpStringIteratorPrototype%.next() step 4 +var result = iter.next(); +assert.sameValue(result.value, undefined); +assert(result.done); 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 0000000000000000000000000000000000000000..a6de2ad8a91a6aa5908adbcfe0c058e1f3aee41f --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/next-iteration.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: Iterates over the first match +info: | + %RegExpStringIteratorPrototype%.next ( ) + [...] + 4. If O.[[Done]] is true, then + a. Return ! reateIterResultObject(undefined, true). + [...] + 9. Let match be ? RegExpExec(R, S). + 10. If match is null, then + a. Set O.[[Done]] to true. + b. Return ! CreateIterResultObject(undefined, true). + 11. Else, + a. If global is true, + [...] + b. Else, + i. Set O.[[Done]] to true. + ii. Return ! CreateIterResultObject(match, false). +features: [Symbol.matchAll] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +var regexp = /\w/; +var str = '*a*b'; +var iter = regexp[Symbol.matchAll](str); + +assert.compareIterator(iter, [ + matchValidator(['a'], 1, str) +]); + +// Verifies %RegExpStringIteratorPrototype%.next() step 4 +var result = iter.next(); +assert.sameValue(result.value, undefined); +assert(result.done); 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 0000000000000000000000000000000000000000..826b2ae3c5d6126a16fb535d3cc8a69ce2ea3f72 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/next-missing-internal-slots.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: Throws TypeError when `this` does not have all internal slots +info: | + %RegExpStringIteratorPrototype%.next ( ) + 1. Let O be the this value. + 2. If Type(O) is not Object, throw a TypeError exception. + 3. If O does not have all of the internal slots of a RegExp String Iterator + Object Instance (see PropertiesOfRegExpStringIteratorInstances), throw a + TypeError. +features: [Symbol.matchAll] +---*/ + +var iterator = /./[Symbol.matchAll](''); +var object = Object.create(iterator); + +assert.throws(TypeError, function() { + object.next(); +}); diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/prop-desc.js b/test/built-ins/RegExpStringIteratorPrototype/next/prop-desc.js new file mode 100644 index 0000000000000000000000000000000000000000..a679e0ae4ccd39d85b68e5cb0f0a08841e018395 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/prop-desc.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: | + %RegExpStringIteratorPrototype%.next property descriptor +info: | + 17 ECMAScript Standard Built-in Objects: + + [...] + + 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. +includes: [propertyHelper.js] +features: [Symbol.matchAll] +---*/ + +var RegExpStringIteratorProto = Object.getPrototypeOf(/./[Symbol.matchAll]('')); + +assert.sameValue(typeof RegExpStringIteratorProto.next, 'function'); + +verifyNotEnumerable(RegExpStringIteratorProto, 'next'); +verifyWritable(RegExpStringIteratorProto, 'next'); +verifyConfigurable(RegExpStringIteratorProto, 'next'); diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/regexp-tolength-lastindex-throws.js b/test/built-ins/RegExpStringIteratorPrototype/next/regexp-tolength-lastindex-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..603393df67dd43a309251dda86309dbc5f0f1e1c --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/regexp-tolength-lastindex-throws.js @@ -0,0 +1,33 @@ +// 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-throws errors thrown coercing RegExp's lastIndex to a length +info: | + %RegExpStringIteratorPrototype%.next ( ) + [...] + 9. Let match be ? RegExpExec(R, S). + 10. If match is null, then + [...] + 11. Else, + a. If global is true, + i. Let matchStr be ? ToString(? Get(match, "0")). + ii. If matchStr is the empty string, + 1. Let thisIndex be ? ToLength(? Get(R, "lastIndex"). +features: [Symbol.matchAll] +---*/ + +var iter = /./g[Symbol.matchAll](''); + +RegExp.prototype.exec = function() { + this.lastIndex = { + valueOf() { + throw new Test262Error(); + } + }; + return ['']; +}; + +assert.throws(Test262Error, function() { + iter.next(); +}); diff --git a/test/built-ins/RegExpStringIteratorPrototype/next/this-is-not-object-throws.js b/test/built-ins/RegExpStringIteratorPrototype/next/this-is-not-object-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..4470ff19e8d9074e568bad53c0c3815e7fc73b42 --- /dev/null +++ b/test/built-ins/RegExpStringIteratorPrototype/next/this-is-not-object-throws.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: Throws TypeError when `this` is not an Object +info: | + %RegExpStringIteratorPrototype%.next ( ) + 1. Let O be the this value. + 2. If Type(O) is not Object, throw a TypeError exception. +features: [Symbol.matchAll] +---*/ + +var RegExpStringIteratorProto = Object.getPrototypeOf(/./[Symbol.matchAll]('')); + +var thisValue; +var callNext = function() { + RegExpStringIteratorProto.next.call(thisValue); +}; + +thisValue = null; +assert.throws(TypeError, callNext, 'this value is null'); + +thisValue = true; +assert.throws(TypeError, callNext, 'this value is Boolean'); + +thisValue = ''; +assert.throws(TypeError, callNext, 'this value is String'); + +thisValue = Symbol(); +assert.throws(TypeError, callNext, 'this value is Symbol'); + +thisValue = 1; +assert.throws(TypeError, callNext, 'this value is Number'); + 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 deleted file mode 100644 index e18431c89d74552930cf68eff30a206906c2cb11..0000000000000000000000000000000000000000 --- a/test/built-ins/String/prototype/matchAll/cstm-matcher-get-err.js +++ /dev/null @@ -1,26 +0,0 @@ -// 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/invoke-builtin-matchall.js b/test/built-ins/String/prototype/matchAll/invoke-builtin-matchall.js deleted file mode 100644 index feeb36bc6e5579b18498c91628672b0a3cf308f0..0000000000000000000000000000000000000000 --- a/test/built-ins/String/prototype/matchAll/invoke-builtin-matchall.js +++ /dev/null @@ -1,43 +0,0 @@ -// 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 index fd5f0104c4f18b7a3c132f1111487dfe75133f85..101d8bbf2ed8b3551adbdb72d1f8388272b73088 100644 --- a/test/built-ins/String/prototype/matchAll/length.js +++ b/test/built-ins/String/prototype/matchAll/length.js @@ -1,20 +1,26 @@ // 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 +esid: pending +description: String.prototype.matchAll `length` property 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. + 17 ECMAScript Standard Built-in Objects: [...] - Unless otherwise specified, the length property of a built-in Function + 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. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which + are 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: [String.prototype.matchAll] ---*/ assert.sameValue(String.prototype.matchAll.length, 1); diff --git a/test/built-ins/String/prototype/matchAll/name.js b/test/built-ins/String/prototype/matchAll/name.js index 84bb3cf647a69fd9d55eaf0f6bdf137cce23e7ec..cef87994c1253c818004c88aa482135aee2c00fa 100644 --- a/test/built-ins/String/prototype/matchAll/name.js +++ b/test/built-ins/String/prototype/matchAll/name.js @@ -1,27 +1,28 @@ // 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 +esid: pending +description: String.prototype.matchAll `name` property info: | - The value of the name property of this function is "matchAll". + 17 ECMAScript Standard Built-in Objects: - 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. + 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 }. + 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: [String.prototype.matchAll] ---*/ -assert.sameValue(String.prototype[Symbol.iterator].name, 'matchAll'); +assert.sameValue(String.prototype.matchAll.name, 'matchAll'); -verifyNotEnumerable(String.prototype[Symbol.iterator], 'name'); -verifyNotWritable(String.prototype[Symbol.iterator], 'name'); -verifyConfigurable(String.prototype[Symbol.iterator], 'name'); +verifyNotEnumerable(String.prototype.matchAll, 'name'); +verifyNotWritable(String.prototype.matchAll, 'name'); +verifyConfigurable(String.prototype.matchAll, 'name'); diff --git a/test/built-ins/String/prototype/matchAll/prop-desc.js b/test/built-ins/String/prototype/matchAll/prop-desc.js index 02b9eaa714042762b441cdc9aaa00062078eefa1..eb1c59a60dcb9f61a98433dd3484df277a22690e 100644 --- a/test/built-ins/String/prototype/matchAll/prop-desc.js +++ b/test/built-ins/String/prototype/matchAll/prop-desc.js @@ -1,18 +1,22 @@ // Copyright (C) 2018 Jordan Harband. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -description: Property descriptor +esid: pending +description: String.prototype.matchAll property descriptor info: | - ES6 Section 17 + 17 ECMAScript Standard Built-in Objects: + + [...] 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] +features: [String.prototype.matchAll] ---*/ 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/regexp-get-matchAll-throws.js b/test/built-ins/String/prototype/matchAll/regexp-get-matchAll-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..8c73480b05b8855e911a2877833af0db55a51eef --- /dev/null +++ b/test/built-ins/String/prototype/matchAll/regexp-get-matchAll-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-throws errors when calling @@matchAll +info: | + String.prototype.matchAll ( regexp ) + [...] + 2. If regexp is neither undefined nor null, then + a. Let matcher be ? GetMethod(regexp, @@matchAll). + b. If matcher is not undefined, then + i. Return ? Call(matcher, regexp, « O »). +features: [Symbol.matchAll, String.prototype.matchAll] +---*/ + +var regexp = /./; +Object.defineProperty(regexp, Symbol.matchAll, { + get() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + ''.matchAll(regexp); +}); diff --git a/test/built-ins/String/prototype/matchAll/regexp-is-null.js b/test/built-ins/String/prototype/matchAll/regexp-is-null.js new file mode 100644 index 0000000000000000000000000000000000000000..9ae102e6b1646645ab61cc1272559f1de3cb50aa --- /dev/null +++ b/test/built-ins/String/prototype/matchAll/regexp-is-null.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: Behavior when regexp is null +info: | + String.prototype.matchAll ( regexp ) + 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"). +features: [String.prototype.matchAll] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +var str = '-null-'; + +assert.compareIterator(str.matchAll(null), [ + matchValidator(['null'], 1, str) +]); diff --git a/test/built-ins/String/prototype/matchAll/regexp-is-undefined.js b/test/built-ins/String/prototype/matchAll/regexp-is-undefined.js new file mode 100644 index 0000000000000000000000000000000000000000..bf9ac09e00437bf9101d836f991cac4593de4396 --- /dev/null +++ b/test/built-ins/String/prototype/matchAll/regexp-is-undefined.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: Behavior when regexp is null +info: | + String.prototype.matchAll ( regexp ) + 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"). +features: [String.prototype.matchAll] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +var str = 'a'; + +assert.compareIterator(str.matchAll(undefined), [ + matchValidator([''], 0, str), + matchValidator([''], 1, str) +]); diff --git a/test/built-ins/String/prototype/matchAll/cstm-matcher-invocation.js b/test/built-ins/String/prototype/matchAll/regexp-matchAll-invocation.js similarity index 67% rename from test/built-ins/String/prototype/matchAll/cstm-matcher-invocation.js rename to test/built-ins/String/prototype/matchAll/regexp-matchAll-invocation.js index 72c09fd5418f849cae51923f642d6afdd5c99276..7afe2c796575deca7fec7811ca54eb0d32183294 100644 --- a/test/built-ins/String/prototype/matchAll/cstm-matcher-invocation.js +++ b/test/built-ins/String/prototype/matchAll/regexp-matchAll-invocation.js @@ -1,14 +1,16 @@ // Copyright (C) 2018 Jordan Harband. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. - /*--- +esid: pending description: Invocation of @@matchAll property of user-supplied RegExp objects info: | + String.prototype.matchAll ( regexp ) [...] - 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] + 2. If regexp is neither undefined nor null, then + a. Let matcher be ? GetMethod(regexp, @@matchAll). + b. If matcher is not undefined, then + i. Return ? Call(matcher, regexp, « O »). +features: [Symbol.matchAll, String.prototype.matchAll] ---*/ var obj = {}; @@ -16,9 +18,8 @@ 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; + callCount++; thisVal = this; args = arguments; return returnVal; diff --git a/test/built-ins/String/prototype/matchAll/regexp-matchAll-throws.js b/test/built-ins/String/prototype/matchAll/regexp-matchAll-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..c94ddd095fe1ec4cdc8f19258621558cdabb888f --- /dev/null +++ b/test/built-ins/String/prototype/matchAll/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: Re-throws errors when calling @@matchAll +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] = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + ''.matchAll(regexp); +}); diff --git a/test/built-ins/String/prototype/matchAll/regexp-prototype-get-matchAll-throws.js b/test/built-ins/String/prototype/matchAll/regexp-prototype-get-matchAll-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..ccafad46a5275d7d4dc42404db54ed6003ff960e --- /dev/null +++ b/test/built-ins/String/prototype/matchAll/regexp-prototype-get-matchAll-throws.js @@ -0,0 +1,22 @@ +// 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-throws errors thrown while accessing RegExp's @@matchAll property +info: | + String.prototype.matchAll ( regexp ) + [...] + 2. If regexp is neither undefined nor null, then + a. Let matcher be ? GetMethod(regexp, @@matchAll). +features: [Symbol.matchAll] +---*/ + +Object.defineProperty(RegExp.prototype, Symbol.matchAll, { + get() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, function() { + ''.matchAll(/./); +}); 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 new file mode 100644 index 0000000000000000000000000000000000000000..0aeb021a9e3ed074e66852419f79940e53433026 --- /dev/null +++ b/test/built-ins/String/prototype/matchAll/regexp-prototype-has-no-matchAll.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: Behavior when @@matchAll is removed from RegExp's prototype +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. Return ? MatchAllIterator(regexp, O). +features: [Symbol.matchAll, String.prototype.matchAll] +includes: [compareArray.js, compareIterator.js, regExpUtils.js] +---*/ + +delete RegExp.prototype[Symbol.matchAll]; +var str = 'a*b'; + +assert.compareIterator(str.matchAll(/\w/g), [ + matchValidator(['a'], 0, str), + matchValidator(['b'], 2, str) +]); diff --git a/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-invocation.js b/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-invocation.js new file mode 100644 index 0000000000000000000000000000000000000000..2aec69141ce0690d0824c651a57ae5fd65f17805 --- /dev/null +++ b/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-invocation.js @@ -0,0 +1,36 @@ +// Copyright (C) 2018 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: pending +description: Behavior when invoking of @@matchAll +info: | + String.prototype.matchAll ( regexp ) + [...] + 2. If regexp is neither undefined nor null, then + a. Let matcher be ? GetMethod(regexp, @@matchAll). + b. If matcher is not undefined, then + i. Return ? Call(matcher, regexp, « O »). +features: [Symbol.matchAll] +---*/ + +var obj = {}; +var returnVal = {}; +var callCount = 0; +var thisVal, args; + +RegExp.prototype[Symbol.matchAll] = function() { + callCount++; + thisVal = this; + args = arguments; + return returnVal; +}; + +var regexp = /./; +var str = ''; + +assert.sameValue(str.matchAll(regexp), returnVal); +assert.sameValue(callCount, 1, 'Invokes the method exactly once'); +assert.sameValue(thisVal, regexp); +assert.notSameValue(args, undefined); +assert.sameValue(args.length, 1); +assert.sameValue(args[0], str); diff --git a/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-throws.js b/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-throws.js new file mode 100644 index 0000000000000000000000000000000000000000..c2be2331a3e0fb6253deb655739b27c3739bb38c --- /dev/null +++ b/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-throws.js @@ -0,0 +1,22 @@ +// 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-throws errors when calling @@matchAll +info: | + String.prototype.matchAll ( regexp ) + [...] + 2. If regexp is neither undefined nor null, then + a. Let matcher be ? GetMethod(regexp, @@matchAll). + b. If matcher is not undefined, then + i. Return ? Call(matcher, regexp, « O »). +features: [Symbol.matchAll] +---*/ + +RegExp.prototype[Symbol.matchAll] = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + ''.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 index 2189df4b65bae28da54e657d894a1da131cf09d6..9cfd7705de6924043380a3ad3dfd51dd5fffe01d 100644 --- 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 @@ -1,12 +1,12 @@ // Copyright (C) 2018 Jordan Harband. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- +esid: pending description: The `this` value cannot be coerced into an object info: | + String.prototype.matchAll ( regexp ) 1. Let O be RequireObjectCoercible(this value). - 2. Let S be ToString(O). - 3. ReturnIfAbrupt(S). -features: [Symbol.iterator] +features: [String.prototype.matchAll] ---*/ var matchAll = String.prototype.matchAll; diff --git a/test/built-ins/Symbol/matchAll/cross-realm.js b/test/built-ins/Symbol/matchAll/cross-realm.js new file mode 100644 index 0000000000000000000000000000000000000000..e6d2f9cebf1a249cd117a1df437c49a4280c067e --- /dev/null +++ b/test/built-ins/Symbol/matchAll/cross-realm.js @@ -0,0 +1,14 @@ +// Copyright (C) 2018 Peter Wong. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: pending +description: Value shared by all realms +info: | + Unless otherwise specified, well-known symbols values are shared by all + realms. +features: [cross-realm, Symbol.matchAll] +---*/ + +var OSymbol = $262.createRealm().global.Symbol; + +assert.sameValue(Symbol.matchAll, OSymbol.matchAll); diff --git a/test/built-ins/Symbol/matchAll/prop-desc.js b/test/built-ins/Symbol/matchAll/prop-desc.js new file mode 100644 index 0000000000000000000000000000000000000000..705adfc519c06b82e38c5742598b724480b66dbb --- /dev/null +++ b/test/built-ins/Symbol/matchAll/prop-desc.js @@ -0,0 +1,17 @@ +// Copyright (C) 2018 Peter Wong. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: pending +description: | + `Symbol.matchAll` property descriptor +info: | + This property has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: false }. +includes: [propertyHelper.js] +features: [Symbol.match] +---*/ + +assert.sameValue(typeof Symbol.matchAll, 'symbol'); +verifyNotEnumerable(Symbol, 'matchAll'); +verifyNotWritable(Symbol, 'matchAll'); +verifyNotConfigurable(Symbol, 'matchAll');