diff options
Diffstat (limited to 'js/src/tests/test262/built-ins/RegExp/match-indices')
15 files changed, 840 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/browser.js b/js/src/tests/test262/built-ins/RegExp/match-indices/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/browser.js diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-element.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-element.js new file mode 100644 index 0000000000..5b87efcc70 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-element.js @@ -0,0 +1,30 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: A matching element of indices is an Array with exactly two number properties. +esid: sec-getmatchindicesarray +features: [regexp-match-indices] +info: | + GetMatchIndicesArray ( S, match ) + 5. Return CreateArrayFromList(ยซ _match_.[[StartIndex]], _match_.[[EndIndex]] ยป). +---*/ + +let input = "abcd"; +let match = /b(c)/.exec(input); +let indices = match.indices; + +// `indices[0]` is an array +assert.sameValue(Object.getPrototypeOf(indices[0]), Array.prototype); +assert.sameValue(indices[0].length, 2); +assert.sameValue(typeof indices[0][0], "number"); +assert.sameValue(typeof indices[0][1], "number"); + +// `indices[1]` is an array +assert.sameValue(Object.getPrototypeOf(indices[1]), Array.prototype); +assert.sameValue(indices[1].length, 2); +assert.sameValue(typeof indices[1][0], "number"); +assert.sameValue(typeof indices[1][1], "number"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-matched.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-matched.js new file mode 100644 index 0000000000..cef6ead42d --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-matched.js @@ -0,0 +1,41 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: The properties of the "indices" array correspond to the start/end indices of the same values in the match. +includes: [compareArray.js] +esid: sec-makeindicesarray +features: [regexp-match-indices] +info: | + MakeIndicesArray ( S, indices, groupNames ) + 4. Let _n_ be the number of elements in _indices_. + ... + 6. Set _A_ to ! ArrayCreate(_n_). + ... + 11. For each integer _i_ such that _i_ >= 0 and _i_ < _n_, do + a. Let _matchIndices_ be _indices_[_i_]. + b. If _matchIndices_ is not *undefined*, then + i. Let _matchIndicesArray_ be ! GetMatchIndicesArray(_S_, _matchIndices_). + c. Else, + i. Let _matchIndicesArray_ be *undefined*. + d. Perform ! CreateDataProperty(_A_, ! ToString(_n_), _matchIndicesArray_). + ... +---*/ + +let input = "abcd"; +let match = /b(c)/.exec(input); +let indices = match.indices; + +// `indices` has the same length as match +assert.sameValue(indices.length, match.length); + +// The first element of `indices` contains the start/end indices of the match +assert.compareArray(indices[0], [1, 3]); +assert.sameValue(input.slice(indices[0][0], indices[0][1]), match[0]); + +// The second element of `indices` contains the start/end indices of the first capture +assert.compareArray(indices[1], [2, 3]); +assert.sameValue(input.slice(indices[1][0], indices[1][1]), match[1]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-non-unicode-match.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-non-unicode-match.js new file mode 100644 index 0000000000..4884ecee78 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-non-unicode-match.js @@ -0,0 +1,78 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Basic matching cases with non-unicode matches. +includes: [compareArray.js, propertyHelper.js, deepEqual.js] +esid: sec-regexpbuiltinexec +features: [regexp-match-indices] +info: | + Runtime Semantics: RegExpBuiltinExec ( R, S ) + ... + 4. Let _lastIndex_ be ? ToLength(? Get(_R_, `"lastIndex")). + ... + 25. Let _indices_ be a new empty List. + 26. Let _match_ be the Match { [[StartIndex]]: _lastIndex_, [[EndIndex]]: _e_ }. + 27. Add _match_ as the last element of _indices_. + ... + 33. For each integer _i_ such that _i_ > 0 and _i_ <= _n_, in ascending order, do + ... + f. Else, + i. Let _captureStart_ be _captureI_'s _startIndex_. + ii. Let _captureEnd_ be _captureI_'s _endIndex_. + ... + iv. Let _capture_ be the Match { [[StartIndex]]: _captureStart_, [[EndIndex]]: _captureEnd_ }. + v. Append _capture_ to _indices_. + ... + 34. Let _indicesArray_ be MakeIndicesArray( _S_, _indices_, _groupNames_). +---*/ + +assert.deepEqual([[1, 2], [1, 2]], "bab".match(/(a)/).indices); +assert.deepEqual([[0, 3], [1, 2]], "bab".match(/.(a)./).indices); +assert.deepEqual([[0, 3], [1, 2], [2, 3]], "bab".match(/.(a)(.)/).indices); +assert.deepEqual([[0, 3], [1, 3]], "bab".match(/.(\w\w)/).indices); +assert.deepEqual([[0, 3], [0, 3]], "bab".match(/(\w\w\w)/).indices); +assert.deepEqual([[0, 3], [0, 2], [2, 3]], "bab".match(/(\w\w)(\w)/).indices); +assert.deepEqual([[0, 2], [0, 2], undefined], "bab".match(/(\w\w)(\W)?/).indices); + +let groups = /(?<a>.)(?<b>.)(?<c>.)\k<c>\k<b>\k<a>/.exec("abccba").indices.groups; +assert.compareArray([0, 1], groups.a); +assert.compareArray([1, 2], groups.b); +assert.compareArray([2, 3], groups.c); +verifyProperty(groups, "a", { + enumerable: true, + writable: true, + configurable: true +}); +verifyProperty(groups, "b", { + enumerable: true, + writable: true, + configurable: true +}); +verifyProperty(groups, "c", { + enumerable: true, + writable: true, + configurable: true +}); + +// "๐" is U+1d401 MATHEMATICAL BOLD CAPITAL B +// - Also representable as the code point "\u{1d401}" +// - Also representable as the surrogate pair "\uD835\uDC01" + +// Verify assumptions: +assert.sameValue("๐".length, 2, 'The length of "๐" is 2'); +assert.sameValue("\u{1d401}".length, 2, 'The length of "\\u{1d401}" is 2'); +assert.sameValue("\uD835\uDC01".length, 2, 'The length of "\\uD835\\uDC01" is 2'); +assert.sameValue("๐".match(/./)[0].length, 1, 'The length of a single code unit match against "๐" is 1 (without /u flag)'); +assert.sameValue("\u{1d401}".match(/./)[0].length, 1, 'The length of a single code unit match against "\\u{1d401}" is 1 (without /u flag)'); +assert.sameValue("\uD835\uDC01".match(/./)[0].length, 1, 'The length of a single code unit match against "\\ud835\\udc01" is 1 (without /u flag)'); + +assert.compareArray([0, 1], "๐".match(/./).indices[0], 'Indices for non-unicode match against "๐" (without /u flag)'); +assert.compareArray([0, 1], "\u{1d401}".match(/./).indices[0], 'Indices for non-unicode match against "\\u{1d401}" (without /u flag)'); +assert.compareArray([0, 1], "\uD835\uDC01".match(/./).indices[0], 'Indices for non-unicode match against "\\ud835\\udc01" (without /u flag)'); +assert.compareArray([0, 1], "๐".match(/(?<a>.)/).indices.groups.a, 'Indices for non-unicode match against "๐" in groups.a (without /u flag)'); +assert.compareArray([0, 1], "\u{1d401}".match(/(?<a>.)/).indices.groups.a, 'Indices for non-unicode match against "\\u{1d401}" in groups.a (without /u flag)'); +assert.compareArray([0, 1], "\uD835\uDC01".match(/(?<a>.)/).indices.groups.a, 'Indices for non-unicode match against "\\ud835\\udc01" in groups.a (without /u flag)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-properties.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-properties.js new file mode 100644 index 0000000000..e1cc453c34 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-properties.js @@ -0,0 +1,32 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: The properties of the "indices" array are created with CreateDataProperty. +includes: [propertyHelper.js] +esid: sec-makeindicesarray +features: [regexp-match-indices] +info: | + MakeIndicesArray ( S, indices, groupNames ) + 11. For each integer _i_ such that _i_ >= 0 and _i_ < _n_, do + d. Perform ! CreateDataProperty(_A_, ! ToString(_n_), _matchIndicesArray_). +---*/ + +let input = "abcd"; +let match = /b(c)/.exec(input); +let indices = match.indices; + +verifyProperty(indices, '0', { + enumerable: true, + configurable: true, + writable: true +}); + +verifyProperty(indices, '1', { + enumerable: true, + configurable: true, + writable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-match.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-match.js new file mode 100644 index 0000000000..c8460bc580 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-match.js @@ -0,0 +1,87 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Basic matching cases with non-unicode matches. +includes: [compareArray.js, propertyHelper.js, deepEqual.js] +esid: sec-regexpbuiltinexec +features: [regexp-match-indices] +info: | + Runtime Semantics: RegExpBuiltinExec ( R, S ) + ... + 4. Let _lastIndex_ be ? ToLength(? Get(_R_, `"lastIndex")). + ... + 16. If _fullUnicode_ is *true*, set _e_ to ! GetStringIndex(_S_, _Input_, _e_). + ... + 25. Let _indices_ be a new empty List. + 26. Let _match_ be the Match { [[StartIndex]]: _lastIndex_, [[EndIndex]]: _e_ }. + 27. Add _match_ as the last element of _indices_. + ... + 33. For each integer _i_ such that _i_ > 0 and _i_ <= _n_, in ascending order, do + ... + f. Else, + i. Let _captureStart_ be _captureI_'s _startIndex_. + ii. Let _captureEnd_ be _captureI_'s _endIndex_. + iii. If _fullUnicode_ is *true*, then + 1. Set _captureStart_ to ! GetStringIndex(_S_, _Input_, _captureStart_). + 1. Set _captureEnd_ to ! GetStringIndex(_S_, _Input_, _captureEnd_). + iv. Let _capture_ be the Match { [[StartIndex]]: _captureStart_, [[EndIndex]]: _captureEnd_ }. + v. Append _capture_ to _indices_. + ... + 34. Let _indicesArray_ be MakeIndicesArray( _S_, _indices_, _groupNames_). + + GetStringIndex ( S, Input, e ) + ... + 4. Let _eUTF_ be the smallest index into _S_ that corresponds to the character at element _e_ of _Input_. If _e_ is greater than or equal to the number of elements in _Input_, then _eUTF_ is the number of code units in _S_. + 5. Return _eUTF_. +---*/ + +assert.deepEqual([[1, 2], [1, 2]], "bab".match(/(a)/u).indices); +assert.deepEqual([[0, 3], [1, 2]], "bab".match(/.(a)./u).indices); +assert.deepEqual([[0, 3], [1, 2], [2, 3]], "bab".match(/.(a)(.)/u).indices); +assert.deepEqual([[0, 3], [1, 3]], "bab".match(/.(\w\w)/u).indices); +assert.deepEqual([[0, 3], [0, 3]], "bab".match(/(\w\w\w)/u).indices); +assert.deepEqual([[0, 3], [0, 2], [2, 3]], "bab".match(/(\w\w)(\w)/u).indices); +assert.deepEqual([[0, 2], [0, 2], undefined], "bab".match(/(\w\w)(\W)?/u).indices); + +let groups = /(?<a>.)(?<b>.)(?<c>.)\k<c>\k<b>\k<a>/u.exec("abccba").indices.groups; +assert.compareArray([0, 1], groups.a); +assert.compareArray([1, 2], groups.b); +assert.compareArray([2, 3], groups.c); +verifyProperty(groups, "a", { + enumerable: true, + writable: true, + configurable: true +}); +verifyProperty(groups, "b", { + enumerable: true, + writable: true, + configurable: true +}); +verifyProperty(groups, "c", { + enumerable: true, + writable: true, + configurable: true +}); + +// "๐" is U+1d401 MATHEMATICAL BOLD CAPITAL B +// - Also representable as the code point "\u{1d401}" +// - Also representable as the surrogate pair "\uD835\uDC01" + +// Verify assumptions: +assert.sameValue("๐".length, 2, 'The length of "๐" is 2'); +assert.sameValue("\u{1d401}".length, 2, 'The length of "\\u{1d401}" is 2'); +assert.sameValue("\uD835\uDC01".length, 2, 'The length of "\\uD835\\uDC01" is 2'); +assert.sameValue(2, "๐".match(/./u)[0].length, 'The length of a single code point match against "๐" is 2 (with /u flag)'); +assert.sameValue(2, "\u{1d401}".match(/./u)[0].length, 'The length of a single code point match against "\\u{1d401}" is 2 (with /u flag)'); +assert.sameValue(2, "\uD835\uDC01".match(/./u)[0].length, 'The length of a single code point match against "\\ud835\\udc01" is 2 (with /u flag)'); + +assert.compareArray([0, 2], "๐".match(/./u).indices[0], 'Indices for unicode match against "๐" (with /u flag)'); +assert.compareArray([0, 2], "\u{1d401}".match(/./u).indices[0], 'Indices for unicode match against \\u{1d401} (with /u flag)'); +assert.compareArray([0, 2], "\uD835\uDC01".match(/./u).indices[0], 'Indices for unicode match against \\ud835\\udc01 (with /u flag)'); +assert.compareArray([0, 2], "๐".match(/(?<a>.)/u).indices.groups.a, 'Indices for unicode match against ๐ in groups.a (with /u flag)'); +assert.compareArray([0, 2], "\u{1d401}".match(/(?<a>.)/u).indices.groups.a, 'Indices for unicode match against \\u{1d401} in groups.a (with /u flag)'); +assert.compareArray([0, 2], "\uD835\uDC01".match(/(?<a>.)/u).indices.groups.a, 'Indices for unicode match against \\ud835\\udc01 in groups.a (with /u flag)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-property-names.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-property-names.js new file mode 100644 index 0000000000..8bdfb693e2 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unicode-property-names.js @@ -0,0 +1,23 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Basic matching cases with non-unicode matches. +includes: [compareArray.js] +esid: sec-makeindicesarray +features: [regexp-match-indices] +---*/ + +assert.compareArray([1, 2], /(?<ฯ>a)/u.exec("bab").indices.groups.ฯ); +assert.compareArray([1, 2], /(?<\u{03C0}>a)/u.exec("bab").indices.groups.ฯ); +assert.compareArray([1, 2], /(?<ฯ>a)/u.exec("bab").indices.groups.\u03C0); +assert.compareArray([1, 2], /(?<\u{03C0}>a)/u.exec("bab").indices.groups.\u03C0); +assert.compareArray([1, 2], /(?<$>a)/u.exec("bab").indices.groups.$); +assert.compareArray([1, 2], /(?<_>a)/u.exec("bab").indices.groups._); +assert.compareArray([1, 2], /(?<$๐ค>a)/u.exec("bab").indices.groups.$๐ค); +assert.compareArray([1, 2], /(?<_\u200C>a)/u.exec("bab").indices.groups._\u200C); +assert.compareArray([1, 2], /(?<_\u200D>a)/u.exec("bab").indices.groups._\u200D); +assert.compareArray([1, 2], /(?<เฒ _เฒ >a)/u.exec("bab").indices.groups.เฒ _เฒ ); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unmatched.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unmatched.js new file mode 100644 index 0000000000..236c167f5b --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array-unmatched.js @@ -0,0 +1,35 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: An unmatched capture in a match corresponds to an unmatched capture in "indices" +esid: sec-makeindicesarray +features: [regexp-match-indices] +info: | + MakeIndicesArray ( S, indices, groupNames ) + 4. Let _n_ be the number of elements in _indices_. + ... + 6. Set _A_ to ! ArrayCreate(_n_). + ... + 11. For each integer _i_ such that _i_ >= 0 and _i_ < _n_, do + a. Let _matchIndices_ be _indices_[_i_]. + b. If _matchIndices_ is not *undefined*, then + i. Let _matchIndicesArray_ be ! GetMatchIndicesArray(_S_, _matchIndices_). + c. Else, + i. Let _matchIndicesArray_ be *undefined*. + d. Perform ! CreateDataProperty(_A_, ! ToString(_n_), _matchIndicesArray_). + ... +---*/ + +let input = "abd"; +let match = /b(c)?/.exec(input); +let indices = match.indices; + +// `indices` has the same length as match +assert.sameValue(indices.length, match.length); + +// The second element of `indices` should be undefined. +assert.sameValue(indices[1], undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array.js new file mode 100644 index 0000000000..3c7794e77e --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-array.js @@ -0,0 +1,21 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: The "indices" property is an Array. +esid: sec-makeindicesarray +features: [regexp-match-indices] +info: | + MakeIndicesArray ( S, indices, groupNames ) + 6. Set _A_ to ! ArrayCreate(_n_). +---*/ + +let match = /a/.exec("a"); +let indices = match.indices; + +// `indices` is an array +assert.sameValue(Object.getPrototypeOf(indices), Array.prototype); +assert(Array.isArray(indices)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-groups-object-undefined.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-groups-object-undefined.js new file mode 100644 index 0000000000..8db544ef3b --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-groups-object-undefined.js @@ -0,0 +1,29 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: The groups object of indices is created unconditionally. +includes: [propertyHelper.js] +esid: sec-makeindicesarray +features: [regexp-named-groups, regexp-match-indices] +info: | + MakeIndicesArray ( S, indices, groupNames ) + 8. If _groupNames_ is not *undefined*, then + a. Let _groups_ be ! ObjectCreate(*null*). + 9. Else, + a. Let _groups_ be *undefined*. + 10. Perform ! CreateDataProperty(_A_, `"groups"`, _groups_). +---*/ + + +const re = /./; +const indices = re.exec("a").indices; +verifyProperty(indices, 'groups', { + writable: true, + enumerable: true, + configurable: true, + value: undefined +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-groups-object-unmatched.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-groups-object-unmatched.js new file mode 100644 index 0000000000..ee7c18e893 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-groups-object-unmatched.js @@ -0,0 +1,23 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Test the groups object of indices with matched and unmatched named captures. +includes: [compareArray.js] +esid: sec-makeindicesarray +features: [regexp-named-groups, regexp-match-indices] +info: | + MakeIndicesArray ( S, indices, groupNames ) + 11. For each integer _i_ such that _i_ >= 0 and _i_ < _n_, do + e. If _groupNames_ is not *undfined* and _groupNames_[_i_] is not *undefined*, then + i. Perform ! CreateDataProperty(_groups_, _groupNames_[_i_], _matchIndicesArray_). +---*/ + + +const re = /(?<a>a).|(?<x>x)/; +const result = re.exec("ab").indices; +assert.compareArray([0, 1], result.groups.a); +assert.sameValue(undefined, result.groups.x); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-groups-object.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-groups-object.js new file mode 100644 index 0000000000..32eb320def --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-groups-object.js @@ -0,0 +1,42 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: The groups object of indices is created with CreateDataProperty +includes: [propertyHelper.js, compareArray.js] +esid: sec-makeindicesarray +features: [regexp-named-groups, regexp-match-indices] +info: | + MakeIndicesArray ( S, indices, groupNames ) + 8. If _groupNames_ is not *undefined*, then + a. Let _groups_ be ! ObjectCreate(*null*). + 9. Else, + a. Let _groups_ be *undefined*. + 10. Perform ! CreateDataProperty(_A_, `"groups"`, _groups_). +---*/ + +// `groups` is created with Define, not Set. +let counter = 0; +Object.defineProperty(Array.prototype, "groups", { + set() { counter++; } +}); + +let indices = /(?<x>.)/.exec("a").indices; +assert.sameValue(counter, 0); + +// `groups` is writable, enumerable and configurable +// (from CreateDataProperty). +verifyProperty(indices, 'groups', { + writable: true, + enumerable: true, + configurable: true +}); + +// The `__proto__` property on the groups object is not special, +// and does not affect the [[Prototype]] of the resulting groups object. +let {groups} = /(?<__proto__>.)/.exec("a").indices; +assert.compareArray([0, 1], groups.__proto__); +assert.sameValue(null, Object.getPrototypeOf(groups)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-groups-properties.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-groups-properties.js new file mode 100644 index 0000000000..723a726602 --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-groups-properties.js @@ -0,0 +1,38 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Properties of the groups object of indices are created with CreateDataProperty +includes: [compareArray.js, propertyHelper.js] +esid: sec-makeindicesarray +features: [regexp-named-groups, regexp-match-indices] +info: | + MakeIndicesArray ( S, indices, groupNames ) + 11. For each integer _i_ such that _i_ >= 0 and _i_ < _n_, do + e. If _groupNames_ is not *undfined* and _groupNames_[_i_] is not *undefined*, then + i. Perform ! CreateDataProperty(_groups_, _groupNames_[_i_], _matchIndicesArray_). +---*/ + + +// Properties created on result.groups in textual order. +let groupNames = Object.getOwnPropertyNames(/(?<fst>.)|(?<snd>.)/u.exec("abcd").indices.groups); +assert.compareArray(groupNames, ["fst", "snd"]); + +// // Properties are created with Define, not Set +// let counter = 0; +// Object.defineProperty(Object.prototype, 'x', {set() { counter++; }}); + +let indices = /(?<x>.)/.exec('a').indices; +let groups = indices.groups; +// assert.sameValue(counter, 0); + +// Properties are writable, enumerable and configurable +// (from CreateDataProperty) +verifyProperty(groups, 'x', { + writable: true, + enumerable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/indices-property.js b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-property.js new file mode 100644 index 0000000000..3c9f4b444b --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/indices-property.js @@ -0,0 +1,32 @@ +// |reftest| skip -- regexp-match-indices is not supported +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: The "indices" property is created with DefinePropertyOrThrow +includes: [propertyHelper.js] +esid: sec-regexpbuiltinexec +features: [regexp-match-indices] +info: | + Runtime Semantics: RegExpBuiltinExec ( R, S ) + 34. Let _indicesArray_ be MakeIndicesArray(_S_, _indices_, _groupNames_). + 35. Perform ! DefinePropertyOrThrow(_A_, `"indices"`, PropertyDescriptor { [[Value]]: _indicesArray_, [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *true* }). +---*/ + +// `indices` is created with Define, not Set. +let counter = 0; +Object.defineProperty(Array.prototype, "indices", { + set() { counter++; } +}); + +let match = /a/.exec("a"); +assert.sameValue(counter, 0); + +// `indices` is a non-writable, non-enumerable, and configurable data-property. +verifyProperty(match, 'indices', { + writable: true, + enumerable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/RegExp/match-indices/shell.js b/js/src/tests/test262/built-ins/RegExp/match-indices/shell.js new file mode 100644 index 0000000000..276ee734ff --- /dev/null +++ b/js/src/tests/test262/built-ins/RegExp/match-indices/shell.js @@ -0,0 +1,329 @@ +// GENERATED, DO NOT EDIT +// file: deepEqual.js +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Compare two values structurally +defines: [assert.deepEqual] +---*/ + +assert.deepEqual = function(actual, expected, message) { + var format = assert.deepEqual.format; + assert( + assert.deepEqual._compare(actual, expected), + `Expected ${format(actual)} to be structurally equal to ${format(expected)}. ${(message || '')}` + ); +}; + +assert.deepEqual.format = function(value, seen) { + switch (typeof value) { + case 'string': + return typeof JSON !== "undefined" ? JSON.stringify(value) : `"${value}"`; + case 'number': + case 'boolean': + case 'symbol': + case 'bigint': + return value.toString(); + case 'undefined': + return 'undefined'; + case 'function': + return `[Function${value.name ? `: ${value.name}` : ''}]`; + case 'object': + if (value === null) return 'null'; + if (value instanceof Date) return `Date "${value.toISOString()}"`; + if (value instanceof RegExp) return value.toString(); + if (!seen) { + seen = { + counter: 0, + map: new Map() + }; + } + + let usage = seen.map.get(value); + if (usage) { + usage.used = true; + return `[Ref: #${usage.id}]`; + } + + usage = { id: ++seen.counter, used: false }; + seen.map.set(value, usage); + + if (typeof Set !== "undefined" && value instanceof Set) { + return `Set {${Array.from(value).map(value => assert.deepEqual.format(value, seen)).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (typeof Map !== "undefined" && value instanceof Map) { + return `Map {${Array.from(value).map(pair => `${assert.deepEqual.format(pair[0], seen)} => ${assert.deepEqual.format(pair[1], seen)}}`).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (Array.isArray ? Array.isArray(value) : value instanceof Array) { + return `[${value.map(value => assert.deepEqual.format(value, seen)).join(', ')}]${usage.used ? ` as #${usage.id}` : ''}`; + } + let tag = Symbol.toStringTag in value ? value[Symbol.toStringTag] : 'Object'; + if (tag === 'Object' && Object.getPrototypeOf(value) === null) { + tag = '[Object: null prototype]'; + } + return `${tag ? `${tag} ` : ''}{ ${Object.keys(value).map(key => `${key.toString()}: ${assert.deepEqual.format(value[key], seen)}`).join(', ')} }${usage.used ? ` as #${usage.id}` : ''}`; + default: + return typeof value; + } +}; + +assert.deepEqual._compare = (function () { + var EQUAL = 1; + var NOT_EQUAL = -1; + var UNKNOWN = 0; + + function deepEqual(a, b) { + return compareEquality(a, b) === EQUAL; + } + + function compareEquality(a, b, cache) { + return compareIf(a, b, isOptional, compareOptionality) + || compareIf(a, b, isPrimitiveEquatable, comparePrimitiveEquality) + || compareIf(a, b, isObjectEquatable, compareObjectEquality, cache) + || NOT_EQUAL; + } + + function compareIf(a, b, test, compare, cache) { + return !test(a) + ? !test(b) ? UNKNOWN : NOT_EQUAL + : !test(b) ? NOT_EQUAL : cacheComparison(a, b, compare, cache); + } + + function tryCompareStrictEquality(a, b) { + return a === b ? EQUAL : UNKNOWN; + } + + function tryCompareTypeOfEquality(a, b) { + return typeof a !== typeof b ? NOT_EQUAL : UNKNOWN; + } + + function tryCompareToStringTagEquality(a, b) { + var aTag = Symbol.toStringTag in a ? a[Symbol.toStringTag] : undefined; + var bTag = Symbol.toStringTag in b ? b[Symbol.toStringTag] : undefined; + return aTag !== bTag ? NOT_EQUAL : UNKNOWN; + } + + function isOptional(value) { + return value === undefined + || value === null; + } + + function compareOptionality(a, b) { + return tryCompareStrictEquality(a, b) + || NOT_EQUAL; + } + + function isPrimitiveEquatable(value) { + switch (typeof value) { + case 'string': + case 'number': + case 'bigint': + case 'boolean': + case 'symbol': + return true; + default: + return isBoxed(value); + } + } + + function comparePrimitiveEquality(a, b) { + if (isBoxed(a)) a = a.valueOf(); + if (isBoxed(b)) b = b.valueOf(); + return tryCompareStrictEquality(a, b) + || tryCompareTypeOfEquality(a, b) + || compareIf(a, b, isNaNEquatable, compareNaNEquality) + || NOT_EQUAL; + } + + function isNaNEquatable(value) { + return typeof value === 'number'; + } + + function compareNaNEquality(a, b) { + return isNaN(a) && isNaN(b) ? EQUAL : NOT_EQUAL; + } + + function isObjectEquatable(value) { + return typeof value === 'object'; + } + + function compareObjectEquality(a, b, cache) { + if (!cache) cache = new Map(); + return getCache(cache, a, b) + || setCache(cache, a, b, EQUAL) // consider equal for now + || cacheComparison(a, b, tryCompareStrictEquality, cache) + || cacheComparison(a, b, tryCompareToStringTagEquality, cache) + || compareIf(a, b, isValueOfEquatable, compareValueOfEquality) + || compareIf(a, b, isToStringEquatable, compareToStringEquality) + || compareIf(a, b, isArrayLikeEquatable, compareArrayLikeEquality, cache) + || compareIf(a, b, isStructurallyEquatable, compareStructuralEquality, cache) + || compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || cacheComparison(a, b, fail, cache); + } + + function isBoxed(value) { + return value instanceof String + || value instanceof Number + || value instanceof Boolean + || typeof Symbol === 'function' && value instanceof Symbol + || typeof BigInt === 'function' && value instanceof BigInt; + } + + function isValueOfEquatable(value) { + return value instanceof Date; + } + + function compareValueOfEquality(a, b) { + return compareIf(a.valueOf(), b.valueOf(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isToStringEquatable(value) { + return value instanceof RegExp; + } + + function compareToStringEquality(a, b) { + return compareIf(a.toString(), b.toString(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isArrayLikeEquatable(value) { + return (Array.isArray ? Array.isArray(value) : value instanceof Array) + || (typeof Uint8Array === 'function' && value instanceof Uint8Array) + || (typeof Uint8ClampedArray === 'function' && value instanceof Uint8ClampedArray) + || (typeof Uint16Array === 'function' && value instanceof Uint16Array) + || (typeof Uint32Array === 'function' && value instanceof Uint32Array) + || (typeof Int8Array === 'function' && value instanceof Int8Array) + || (typeof Int16Array === 'function' && value instanceof Int16Array) + || (typeof Int32Array === 'function' && value instanceof Int32Array) + || (typeof Float32Array === 'function' && value instanceof Float32Array) + || (typeof Float64Array === 'function' && value instanceof Float64Array) + || (typeof BigUint64Array === 'function' && value instanceof BigUint64Array) + || (typeof BigInt64Array === 'function' && value instanceof BigInt64Array); + } + + function compareArrayLikeEquality(a, b, cache) { + if (a.length !== b.length) return NOT_EQUAL; + for (var i = 0; i < a.length; i++) { + if (compareEquality(a[i], b[i], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + return EQUAL; + } + + function isStructurallyEquatable(value) { + return !(typeof Promise === 'function' && value instanceof Promise // only comparable by reference + || typeof WeakMap === 'function' && value instanceof WeakMap // only comparable by reference + || typeof WeakSet === 'function' && value instanceof WeakSet // only comparable by reference + || typeof Map === 'function' && value instanceof Map // comparable via @@iterator + || typeof Set === 'function' && value instanceof Set); // comparable via @@iterator + } + + function compareStructuralEquality(a, b, cache) { + var aKeys = []; + for (var key in a) aKeys.push(key); + + var bKeys = []; + for (var key in b) bKeys.push(key); + + if (aKeys.length !== bKeys.length) { + return NOT_EQUAL; + } + + aKeys.sort(); + bKeys.sort(); + + for (var i = 0; i < aKeys.length; i++) { + var aKey = aKeys[i]; + var bKey = bKeys[i]; + if (compareEquality(aKey, bKey, cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + if (compareEquality(a[aKey], b[bKey], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + + return compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || EQUAL; + } + + function isIterableEquatable(value) { + return typeof Symbol === 'function' + && typeof value[Symbol.iterator] === 'function'; + } + + function compareIteratorEquality(a, b, cache) { + if (typeof Map === 'function' && a instanceof Map && b instanceof Map || + typeof Set === 'function' && a instanceof Set && b instanceof Set) { + if (a.size !== b.size) return NOT_EQUAL; // exit early if we detect a difference in size + } + + var ar, br; + while (true) { + ar = a.next(); + br = b.next(); + if (ar.done) { + if (br.done) return EQUAL; + if (b.return) b.return(); + return NOT_EQUAL; + } + if (br.done) { + if (a.return) a.return(); + return NOT_EQUAL; + } + if (compareEquality(ar.value, br.value, cache) === NOT_EQUAL) { + if (a.return) a.return(); + if (b.return) b.return(); + return NOT_EQUAL; + } + } + } + + function compareIterableEquality(a, b, cache) { + return compareIteratorEquality(a[Symbol.iterator](), b[Symbol.iterator](), cache); + } + + function cacheComparison(a, b, compare, cache) { + var result = compare(a, b, cache); + if (cache && (result === EQUAL || result === NOT_EQUAL)) { + setCache(cache, a, b, /** @type {EQUAL | NOT_EQUAL} */(result)); + } + return result; + } + + function fail() { + return NOT_EQUAL; + } + + function setCache(cache, left, right, result) { + var otherCache; + + otherCache = cache.get(left); + if (!otherCache) cache.set(left, otherCache = new Map()); + otherCache.set(right, result); + + otherCache = cache.get(right); + if (!otherCache) cache.set(right, otherCache = new Map()); + otherCache.set(left, result); + } + + function getCache(cache, left, right) { + var otherCache; + var result; + + otherCache = cache.get(left); + result = otherCache && otherCache.get(right); + if (result) return result; + + otherCache = cache.get(right); + result = otherCache && otherCache.get(left); + if (result) return result; + + return UNKNOWN; + } + + return deepEqual; +})(); |