11import type { EcmaVersion } from "./ecma-versions"
22import { latestEcmaVersion } from "./ecma-versions"
3+ import type { GroupSpecifiers } from "./group-specifiers"
4+ import {
5+ GroupSpecifiersAsES2018 ,
6+ GroupSpecifiersAsES2025 ,
7+ } from "./group-specifiers"
38import { Reader } from "./reader"
49import { newRegExpSyntaxError } from "./regexp-syntax-error"
510import {
@@ -231,14 +236,15 @@ export namespace RegExpValidator {
231236 strict ?: boolean
232237
233238 /**
234- * ECMAScript version. Default is `2024 `.
239+ * ECMAScript version. Default is `2025 `.
235240 * - `2015` added `u` and `y` flags.
236241 * - `2018` added `s` flag, Named Capturing Group, Lookbehind Assertion,
237242 * and Unicode Property Escape.
238243 * - `2019`, `2020`, and `2021` added more valid Unicode Property Escapes.
239244 * - `2022` added `d` flag.
240245 * - `2023` added more valid Unicode Property Escapes.
241246 * - `2024` added `v` flag.
247+ * - `2025` added duplicate named capturing groups.
242248 */
243249 ecmaVersion ?: EcmaVersion
244250
@@ -631,7 +637,7 @@ export class RegExpValidator {
631637
632638 private _numCapturingParens = 0
633639
634- private _groupNames = new Set < string > ( )
640+ private _groupSpecifiers : GroupSpecifiers
635641
636642 private _backreferenceNames = new Set < string > ( )
637643
@@ -643,6 +649,10 @@ export class RegExpValidator {
643649 */
644650 public constructor ( options ?: RegExpValidator . Options ) {
645651 this . _options = options ?? { }
652+ this . _groupSpecifiers =
653+ this . ecmaVersion >= 2025
654+ ? new GroupSpecifiersAsES2025 ( )
655+ : new GroupSpecifiersAsES2018 ( )
646656 }
647657
648658 /**
@@ -763,7 +773,7 @@ export class RegExpValidator {
763773 if (
764774 ! this . _nFlag &&
765775 this . ecmaVersion >= 2018 &&
766- this . _groupNames . size > 0
776+ ! this . _groupSpecifiers . isEmpty ( )
767777 ) {
768778 this . _nFlag = true
769779 this . rewind ( start )
@@ -1301,7 +1311,7 @@ export class RegExpValidator {
13011311 private consumePattern ( ) : void {
13021312 const start = this . index
13031313 this . _numCapturingParens = this . countCapturingParens ( )
1304- this . _groupNames . clear ( )
1314+ this . _groupSpecifiers . clear ( )
13051315 this . _backreferenceNames . clear ( )
13061316
13071317 this . onPatternEnter ( start )
@@ -1322,7 +1332,7 @@ export class RegExpValidator {
13221332 this . raise ( `Unexpected character '${ c } '` )
13231333 }
13241334 for ( const name of this . _backreferenceNames ) {
1325- if ( ! this . _groupNames . has ( name ) ) {
1335+ if ( ! this . _groupSpecifiers . hasInPattern ( name ) ) {
13261336 this . raise ( "Invalid named capture referenced" )
13271337 }
13281338 }
@@ -1378,6 +1388,7 @@ export class RegExpValidator {
13781388 const start = this . index
13791389 let i = 0
13801390
1391+ this . _groupSpecifiers . enterDisjunction ( )
13811392 this . onDisjunctionEnter ( start )
13821393 do {
13831394 this . consumeAlternative ( i ++ )
@@ -1390,6 +1401,7 @@ export class RegExpValidator {
13901401 this . raise ( "Lone quantifier brackets" )
13911402 }
13921403 this . onDisjunctionLeave ( start , this . index )
1404+ this . _groupSpecifiers . leaveDisjunction ( )
13931405 }
13941406
13951407 /**
@@ -1403,6 +1415,7 @@ export class RegExpValidator {
14031415 private consumeAlternative ( i : number ) : void {
14041416 const start = this . index
14051417
1418+ this . _groupSpecifiers . enterAlternative ( i )
14061419 this . onAlternativeEnter ( start , i )
14071420 while ( this . currentCodePoint !== - 1 && this . consumeTerm ( ) ) {
14081421 // do nothing.
@@ -1846,8 +1859,8 @@ export class RegExpValidator {
18461859 private consumeGroupSpecifier ( ) : boolean {
18471860 if ( this . eat ( QUESTION_MARK ) ) {
18481861 if ( this . eatGroupName ( ) ) {
1849- if ( ! this . _groupNames . has ( this . _lastStrValue ) ) {
1850- this . _groupNames . add ( this . _lastStrValue )
1862+ if ( ! this . _groupSpecifiers . hasInScope ( this . _lastStrValue ) ) {
1863+ this . _groupSpecifiers . addToScope ( this . _lastStrValue )
18511864 return true
18521865 }
18531866 this . raise ( "Duplicate capture group name" )
0 commit comments