From 7446e885e90e1957294174f8b7d84ebda72f9418 Mon Sep 17 00:00:00 2001 From: Mathias Bynens Date: Mon, 18 Dec 2017 14:21:35 +0100 Subject: [PATCH] [regexp-named-groups] Expand tests for `groups` property The `groups` property must be created unconditionally. https://github.com/tc39/proposal-regexp-named-groups/pull/40 --- .../groups-object-subclass-sans.js | 37 +++++++++++++++++++ .../named-groups/groups-object-subclass.js | 35 ++++++++++++++++++ .../named-groups/groups-object-undefined.js | 33 +++++++++++++++++ .../named-groups/groups-object-unmatched.js | 36 ++++++++++++++++++ .../RegExp/named-groups/groups-object.js | 21 +++++++---- 5 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 test/built-ins/RegExp/named-groups/groups-object-subclass-sans.js create mode 100644 test/built-ins/RegExp/named-groups/groups-object-subclass.js create mode 100644 test/built-ins/RegExp/named-groups/groups-object-undefined.js create mode 100644 test/built-ins/RegExp/named-groups/groups-object-unmatched.js diff --git a/test/built-ins/RegExp/named-groups/groups-object-subclass-sans.js b/test/built-ins/RegExp/named-groups/groups-object-subclass-sans.js new file mode 100644 index 0000000000..8d27ea5052 --- /dev/null +++ b/test/built-ins/RegExp/named-groups/groups-object-subclass-sans.js @@ -0,0 +1,37 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Test the groups object on RegExp subclass results that do not have their own. +includes: [propertyHelper.js] +esid: sec-regexpbuiltinexec +features: [regexp-named-groups] +info: > + Runtime Semantics: RegExpBuiltinExec ( R, S ) + 24. If _R_ contains any |GroupName|, then + a. Let _groups_ be ObjectCreate(*null*). + 25. Else, + a. Let _groups_ be *undefined*. + 26. Perform ! CreateDataProperty(_A_, `"groups"`, _groups_). +---*/ + +class FakeRegExp extends RegExp { + exec(subject) { + const fakeResult = ["ab", "a"]; + fakeResult.index = 0; + // `groups` is not set, triggering prototype lookup. + return fakeResult; + } +}; + +const re = new FakeRegExp(); +const result = re.exec("ab"); +assert.sameValue(result.__proto__, Array.prototype); +assert.sameValue(false, result.hasOwnProperty("groups")); + +Array.prototype.groups = { a: "b" }; +Array.prototype.groups.__proto__.b = "c"; +assert.sameValue("b", "ab".replace(re, "$")); +assert.sameValue("c", "ab".replace(re, "$")); +Array.prototype.groups = undefined; diff --git a/test/built-ins/RegExp/named-groups/groups-object-subclass.js b/test/built-ins/RegExp/named-groups/groups-object-subclass.js new file mode 100644 index 0000000000..a7880586af --- /dev/null +++ b/test/built-ins/RegExp/named-groups/groups-object-subclass.js @@ -0,0 +1,35 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Test the groups object on RegExp subclass results that have their own. +includes: [propertyHelper.js] +esid: sec-regexpbuiltinexec +features: [regexp-named-groups] +info: > + Runtime Semantics: RegExpBuiltinExec ( R, S ) + 24. If _R_ contains any |GroupName|, then + a. Let _groups_ be ObjectCreate(*null*). + 25. Else, + a. Let _groups_ be *undefined*. + 26. Perform ! CreateDataProperty(_A_, `"groups"`, _groups_). +---*/ + +class FakeRegExp extends RegExp { + exec(subject) { + const fakeResult = ["ab", "a"]; + fakeResult.index = 0; + fakeResult.groups = { a: "b" }; + fakeResult.groups.__proto__.b = "c"; + return fakeResult; + } +}; + +const re = new FakeRegExp(); +const result = re.exec("ab"); +assert.sameValue(result.__proto__, Array.prototype); +assert(result.hasOwnProperty("groups")); +assert.sameValue("b", result.groups.a); +assert.sameValue("b", "ab".replace(re, "$")); +assert.sameValue("c", "ab".replace(re, "$")); diff --git a/test/built-ins/RegExp/named-groups/groups-object-undefined.js b/test/built-ins/RegExp/named-groups/groups-object-undefined.js new file mode 100644 index 0000000000..edeeb2a622 --- /dev/null +++ b/test/built-ins/RegExp/named-groups/groups-object-undefined.js @@ -0,0 +1,33 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: The groups object is created unconditionally. +includes: [propertyHelper.js] +esid: sec-regexpbuiltinexec +features: [regexp-named-groups] +info: > + Runtime Semantics: RegExpBuiltinExec ( R, S ) + 24. If _R_ contains any |GroupName|, then + a. Let _groups_ be ObjectCreate(*null*). + 25. Else, + a. Let _groups_ be *undefined*. + 26. Perform ! CreateDataProperty(_A_, `"groups"`, _groups_). +---*/ + +const re = /./; +const result = re.exec("a"); +assert.sameValue(result.__proto__, Array.prototype); +assert(result.hasOwnProperty("groups")); +assert.sameValue("a", result[0]); +assert.sameValue(0, result.index); +assert.sameValue(undefined, result.groups); +verifyProperty(result, "groups", { + writable: true, + enumerable: true, + configurable: true, +}); + +Array.prototype.groups = { a: "b" }; +assert.sameValue("$", "a".replace(re, "$")); +Array.prototype.groups = undefined; diff --git a/test/built-ins/RegExp/named-groups/groups-object-unmatched.js b/test/built-ins/RegExp/named-groups/groups-object-unmatched.js new file mode 100644 index 0000000000..34615d3aeb --- /dev/null +++ b/test/built-ins/RegExp/named-groups/groups-object-unmatched.js @@ -0,0 +1,36 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Test the groups object with matched and unmatched named captures. +includes: [propertyHelper.js] +esid: sec-regexpbuiltinexec +features: [regexp-named-groups] +info: > + Runtime Semantics: RegExpBuiltinExec ( R, S ) + 24. If _R_ contains any |GroupName|, then + a. Let _groups_ be ObjectCreate(*null*). + 25. Else, + a. Let _groups_ be *undefined*. + 26. Perform ! CreateDataProperty(_A_, `"groups"`, _groups_). +---*/ + +const re = /(?a).|(?x)/; +const result = re.exec("ab"); +assert.sameValue(result.__proto__, Array.prototype); +assert(result.hasOwnProperty("groups")); +assert.sameValue("ab", result[0]); +assert.sameValue("a", result[1]); +assert.sameValue(undefined, result[2]); +assert.sameValue(0, result.index); +assert.sameValue("a", result.groups.a); +assert.sameValue(undefined, result.groups.x); + +// `a` is a matched named capture, `b` is an unmatched named capture, and `z` +// is not a named capture. +Array.prototype.groups = { a: "b", x: "y", z: "z" }; +assert.sameValue("a", "ab".replace(re, "$")); +assert.sameValue("", "ab".replace(re, "$")); +assert.sameValue("", "ab".replace(re, "$")); +Array.prototype.groups = undefined; diff --git a/test/built-ins/RegExp/named-groups/groups-object.js b/test/built-ins/RegExp/named-groups/groups-object.js index a7d2b5433c..d511e8b73a 100644 --- a/test/built-ins/RegExp/named-groups/groups-object.js +++ b/test/built-ins/RegExp/named-groups/groups-object.js @@ -8,26 +8,31 @@ esid: sec-regexpbuiltinexec features: [regexp-named-groups] info: > Runtime Semantics: RegExpBuiltinExec ( R, S ) - 24. If R contains any GroupName, - a. Let groups be ObjectCreate(null). - b. Perform ! CreateDataProperty(A, "groups", groups). + 24. If _R_ contains any |GroupName|, then + a. Let _groups_ be ObjectCreate(*null*). + 25. Else, + a. Let _groups_ be *undefined*. + 26. Perform ! CreateDataProperty(_A_, `"groups"`, _groups_). ---*/ -// groups is created with Define, not Set +// `groups` is created with Define, not Set. let counter = 0; -Object.defineProperty(Array.prototype, "groups", {set() { counter++; }}); +Object.defineProperty(Array.prototype, "groups", { + set() { counter++; } +}); + let match = /(?.)/.exec("a"); assert.sameValue(counter, 0); -// groups is writable, enumerable and configurable -// (from CreateDataProperty) +// `groups` is writable, enumerable and configurable +// (from CreateDataProperty). verifyProperty(match, "groups", { writable: true, enumerable: true, configurable: true, }); -// The '__proto__' property on the groups object is not special, +// 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"); assert.sameValue("a", groups.__proto__);