Skip to content

Commit

Permalink
Duplicate named capture groups: .groups and .indices.groups objects
Browse files Browse the repository at this point in the history
These tests should cover the full functionality of the .groups object (and
the .indices.groups object, in the case of the /d flag) for RegExp.p.exec
and String.p.match:

- Matched DNCG has a result
- Unmatched DNCG is present and undefined
- DNCG matched in previous iteration but not in current iteration is
  treated as unmatched
- Iteration order of properties corresponds with source order

See: #3704
  • Loading branch information
ptomato authored and Ms2ger committed Nov 2, 2022
1 parent fabb1fd commit 27063ae
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
description: Properties on groups object with duplicate named capture groups
esid: prod-GroupSpecifier
features: [regexp-duplicate-named-groups]
includes: [compareArray.js]
---*/

const matcher = /(?:(?<x>a)|(?<y>a)(?<x>b))(?:(?<z>c)|(?<z>d))/;

const threeMatchResult = matcher.exec("abc");
assert.sameValue(threeMatchResult.groups.x, "b", "group x matches b");
assert.sameValue(threeMatchResult.groups.y, "a", "group y matches a");
assert.sameValue(threeMatchResult.groups.z, "c", "group z matches c");
assert.compareArray(
Object.keys(threeMatchResult.groups),
["x", "y", "z"],
"Properties of groups are ordered in RegExp source order despite y matching before x in this alternative"
);

const twoMatchResult = matcher.exec("ad");
assert.sameValue(twoMatchResult.groups.x, "a", "group x matches a");
assert.sameValue(twoMatchResult.groups.y, undefined, "group y does not match");
assert.sameValue(twoMatchResult.groups.z, "d", "group z matches d");
assert.compareArray(
Object.keys(twoMatchResult.groups),
["x", "y", "z"],
"y is still present on groups object, in the right order, despite not matching"
);

const iteratedMatcher = /(?:(?:(?<x>a)|(?<x>b)|c)\k<x>){2}/;

const matchedInPrevIterationResult = iteratedMatcher.exec("aac");
assert.sameValue(matchedInPrevIterationResult.groups.x, undefined, "group x does not match in the last iteration");
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
description: Properties on indices.groups object with duplicate named capture groups
esid: prod-GroupSpecifier
features: [regexp-duplicate-named-groups, regexp-match-indices]
includes: [compareArray.js]
---*/

const matcher = /(?:(?<x>a)|(?<y>a)(?<x>b))(?:(?<z>c)|(?<z>d))/d;

const threeMatchResult = matcher.exec("abc");
assert.compareArray(threeMatchResult.indices.groups.x, [1, 2], "group x matches b");
assert.compareArray(threeMatchResult.indices.groups.y, [0, 1], "group y matches a");
assert.compareArray(threeMatchResult.indices.groups.z, [2, 3], "group z matches c");
assert.compareArray(
Object.keys(threeMatchResult.indices.groups),
["x", "y", "z"],
"Properties of groups are ordered in RegExp source order despite y matching before x in this alternative"
);

const twoMatchResult = matcher.exec("ad");
assert.compareArray(twoMatchResult.indices.groups.x, [0, 1], "group x matches a");
assert.sameValue(twoMatchResult.indices.groups.y, undefined, "group y does not match");
assert.compareArray(twoMatchResult.indices.groups.z, [1, 2], "group z matches d");
assert.compareArray(
Object.keys(twoMatchResult.indices.groups),
["x", "y", "z"],
"y is still present on groups object, in the right order, despite not matching"
);

const iteratedMatcher = /(?:(?:(?<x>a)|(?<x>b)|c)\k<x>){2}/d;

const matchedInPrevIterationResult = iteratedMatcher.exec("aac");
assert.sameValue(matchedInPrevIterationResult.indices.groups.x, undefined, "group x does not match in the last iteration");
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
description: Properties on groups object with duplicate named capture groups
esid: prod-GroupSpecifier
features: [regexp-duplicate-named-groups]
includes: [compareArray.js]
---*/

const matcher = /(?:(?<x>a)|(?<y>a)(?<x>b))(?:(?<z>c)|(?<z>d))/;

const threeMatchResult = "abc".match(matcher);
assert.sameValue(threeMatchResult.groups.x, "b", "group x matches b");
assert.sameValue(threeMatchResult.groups.y, "a", "group y matches a");
assert.sameValue(threeMatchResult.groups.z, "c", "group z matches c");
assert.compareArray(
Object.keys(threeMatchResult.groups),
["x", "y", "z"],
"Properties of groups are ordered in RegExp source order despite y matching before x in this alternative"
);

const twoMatchResult = "ad".match(matcher);
assert.sameValue(twoMatchResult.groups.x, "a", "group x matches a");
assert.sameValue(twoMatchResult.groups.y, undefined, "group y does not match");
assert.sameValue(twoMatchResult.groups.z, "d", "group z matches d");
assert.compareArray(
Object.keys(twoMatchResult.groups),
["x", "y", "z"],
"y is still present on groups object, in the right order, despite not matching"
);

const iteratedMatcher = /(?:(?:(?<x>a)|(?<x>b)|c)\k<x>){2}/;

const matchedInPrevIterationResult = "aac".match(iteratedMatcher);
assert.sameValue(matchedInPrevIterationResult.groups.x, undefined, "group x does not match in the last iteration");
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
description: Properties on indices.groups object with duplicate named capture groups
esid: prod-GroupSpecifier
features: [regexp-duplicate-named-groups, regexp-match-indices]
includes: [compareArray.js]
---*/

const matcher = /(?:(?<x>a)|(?<y>a)(?<x>b))(?:(?<z>c)|(?<z>d))/d;

const threeMatchResult = "abc".match(matcher);
assert.compareArray(threeMatchResult.indices.groups.x, [1, 2], "group x matches b");
assert.compareArray(threeMatchResult.indices.groups.y, [0, 1], "group y matches a");
assert.compareArray(threeMatchResult.indices.groups.z, [2, 3], "group z matches c");
assert.compareArray(
Object.keys(threeMatchResult.indices.groups),
["x", "y", "z"],
"Properties of groups are ordered in RegExp source order despite y matching before x in this alternative"
);

const twoMatchResult = "ad".match(matcher);
assert.compareArray(twoMatchResult.indices.groups.x, [0, 1], "group x matches a");
assert.sameValue(twoMatchResult.indices.groups.y, undefined, "group y does not match");
assert.compareArray(twoMatchResult.indices.groups.z, [1, 2], "group z matches d");
assert.compareArray(
Object.keys(twoMatchResult.indices.groups),
["x", "y", "z"],
"y is still present on groups object, in the right order, despite not matching"
);

const iteratedMatcher = /(?:(?:(?<x>a)|(?<x>b)|c)\k<x>){2}/d;

const matchedInPrevIterationResult = "aac".match(iteratedMatcher);
assert.sameValue(matchedInPrevIterationResult.indices.groups.x, undefined, "group x does not match in the last iteration");

0 comments on commit 27063ae

Please sign in to comment.