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