@eslint-community/regexpp 4.5.0 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.mjs CHANGED
@@ -2,6 +2,8 @@ var ast = /*#__PURE__*/Object.freeze({
2
2
  __proto__: null
3
3
  });
4
4
 
5
+ const latestEcmaVersion = 2024;
6
+
5
7
  let largeIdStartRanges = undefined;
6
8
  let largeIdContinueRanges = undefined;
7
9
  function isIdStart(cp) {
@@ -68,13 +70,14 @@ function restoreRanges(data) {
68
70
  }
69
71
 
70
72
  class DataSet {
71
- constructor(raw2018, raw2019, raw2020, raw2021, raw2022, raw2023) {
73
+ constructor(raw2018, raw2019, raw2020, raw2021, raw2022, raw2023, raw2024) {
72
74
  this._raw2018 = raw2018;
73
75
  this._raw2019 = raw2019;
74
76
  this._raw2020 = raw2020;
75
77
  this._raw2021 = raw2021;
76
78
  this._raw2022 = raw2022;
77
79
  this._raw2023 = raw2023;
80
+ this._raw2024 = raw2024;
78
81
  }
79
82
  get es2018() {
80
83
  var _a;
@@ -100,12 +103,16 @@ class DataSet {
100
103
  var _a;
101
104
  return ((_a = this._set2023) !== null && _a !== void 0 ? _a : (this._set2023 = new Set(this._raw2023.split(" "))));
102
105
  }
106
+ get es2024() {
107
+ var _a;
108
+ return ((_a = this._set2024) !== null && _a !== void 0 ? _a : (this._set2024 = new Set(this._raw2024.split(" "))));
109
+ }
103
110
  }
104
111
  const gcNameSet = new Set(["General_Category", "gc"]);
105
112
  const scNameSet = new Set(["Script", "Script_Extensions", "sc", "scx"]);
106
- const gcValueSets = new DataSet("C Cased_Letter Cc Cf Close_Punctuation Cn Co Combining_Mark Connector_Punctuation Control Cs Currency_Symbol Dash_Punctuation Decimal_Number Enclosing_Mark Final_Punctuation Format Initial_Punctuation L LC Letter Letter_Number Line_Separator Ll Lm Lo Lowercase_Letter Lt Lu M Mark Math_Symbol Mc Me Mn Modifier_Letter Modifier_Symbol N Nd Nl No Nonspacing_Mark Number Open_Punctuation Other Other_Letter Other_Number Other_Punctuation Other_Symbol P Paragraph_Separator Pc Pd Pe Pf Pi Po Private_Use Ps Punctuation S Sc Separator Sk Sm So Space_Separator Spacing_Mark Surrogate Symbol Titlecase_Letter Unassigned Uppercase_Letter Z Zl Zp Zs cntrl digit punct", "", "", "", "", "");
107
- const scValueSets = new DataSet("Adlam Adlm Aghb Ahom Anatolian_Hieroglyphs Arab Arabic Armenian Armi Armn Avestan Avst Bali Balinese Bamu Bamum Bass Bassa_Vah Batak Batk Beng Bengali Bhaiksuki Bhks Bopo Bopomofo Brah Brahmi Brai Braille Bugi Buginese Buhd Buhid Cakm Canadian_Aboriginal Cans Cari Carian Caucasian_Albanian Chakma Cham Cher Cherokee Common Copt Coptic Cprt Cuneiform Cypriot Cyrillic Cyrl Deseret Deva Devanagari Dsrt Dupl Duployan Egyp Egyptian_Hieroglyphs Elba Elbasan Ethi Ethiopic Geor Georgian Glag Glagolitic Gonm Goth Gothic Gran Grantha Greek Grek Gujarati Gujr Gurmukhi Guru Han Hang Hangul Hani Hano Hanunoo Hatr Hatran Hebr Hebrew Hira Hiragana Hluw Hmng Hung Imperial_Aramaic Inherited Inscriptional_Pahlavi Inscriptional_Parthian Ital Java Javanese Kaithi Kali Kana Kannada Katakana Kayah_Li Khar Kharoshthi Khmer Khmr Khoj Khojki Khudawadi Knda Kthi Lana Lao Laoo Latin Latn Lepc Lepcha Limb Limbu Lina Linb Linear_A Linear_B Lisu Lyci Lycian Lydi Lydian Mahajani Mahj Malayalam Mand Mandaic Mani Manichaean Marc Marchen Masaram_Gondi Meetei_Mayek Mend Mende_Kikakui Merc Mero Meroitic_Cursive Meroitic_Hieroglyphs Miao Mlym Modi Mong Mongolian Mro Mroo Mtei Mult Multani Myanmar Mymr Nabataean Narb Nbat New_Tai_Lue Newa Nko Nkoo Nshu Nushu Ogam Ogham Ol_Chiki Olck Old_Hungarian Old_Italic Old_North_Arabian Old_Permic Old_Persian Old_South_Arabian Old_Turkic Oriya Orkh Orya Osage Osge Osma Osmanya Pahawh_Hmong Palm Palmyrene Pau_Cin_Hau Pauc Perm Phag Phags_Pa Phli Phlp Phnx Phoenician Plrd Prti Psalter_Pahlavi Qaac Qaai Rejang Rjng Runic Runr Samaritan Samr Sarb Saur Saurashtra Sgnw Sharada Shavian Shaw Shrd Sidd Siddham SignWriting Sind Sinh Sinhala Sora Sora_Sompeng Soyo Soyombo Sund Sundanese Sylo Syloti_Nagri Syrc Syriac Tagalog Tagb Tagbanwa Tai_Le Tai_Tham Tai_Viet Takr Takri Tale Talu Tamil Taml Tang Tangut Tavt Telu Telugu Tfng Tglg Thaa Thaana Thai Tibetan Tibt Tifinagh Tirh Tirhuta Ugar Ugaritic Vai Vaii Wara Warang_Citi Xpeo Xsux Yi Yiii Zanabazar_Square Zanb Zinh Zyyy", "Dogr Dogra Gong Gunjala_Gondi Hanifi_Rohingya Maka Makasar Medefaidrin Medf Old_Sogdian Rohg Sogd Sogdian Sogo", "Elym Elymaic Hmnp Nand Nandinagari Nyiakeng_Puachue_Hmong Wancho Wcho", "Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi", "Cpmn Cypro_Minoan Old_Uyghur Ougr Tangsa Tnsa Toto Vith Vithkuqi", "Hrkt Katakana_Or_Hiragana Kawi Nag_Mundari Nagm Unknown Zzzz");
108
- const binPropertySets = new DataSet("AHex ASCII ASCII_Hex_Digit Alpha Alphabetic Any Assigned Bidi_C Bidi_Control Bidi_M Bidi_Mirrored CI CWCF CWCM CWKCF CWL CWT CWU Case_Ignorable Cased Changes_When_Casefolded Changes_When_Casemapped Changes_When_Lowercased Changes_When_NFKC_Casefolded Changes_When_Titlecased Changes_When_Uppercased DI Dash Default_Ignorable_Code_Point Dep Deprecated Dia Diacritic Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Ext Extender Gr_Base Gr_Ext Grapheme_Base Grapheme_Extend Hex Hex_Digit IDC IDS IDSB IDST IDS_Binary_Operator IDS_Trinary_Operator ID_Continue ID_Start Ideo Ideographic Join_C Join_Control LOE Logical_Order_Exception Lower Lowercase Math NChar Noncharacter_Code_Point Pat_Syn Pat_WS Pattern_Syntax Pattern_White_Space QMark Quotation_Mark RI Radical Regional_Indicator SD STerm Sentence_Terminal Soft_Dotted Term Terminal_Punctuation UIdeo Unified_Ideograph Upper Uppercase VS Variation_Selector White_Space XIDC XIDS XID_Continue XID_Start space", "Extended_Pictographic", "", "EBase EComp EMod EPres ExtPict", "", "");
113
+ const gcValueSets = new DataSet("C Cased_Letter Cc Cf Close_Punctuation Cn Co Combining_Mark Connector_Punctuation Control Cs Currency_Symbol Dash_Punctuation Decimal_Number Enclosing_Mark Final_Punctuation Format Initial_Punctuation L LC Letter Letter_Number Line_Separator Ll Lm Lo Lowercase_Letter Lt Lu M Mark Math_Symbol Mc Me Mn Modifier_Letter Modifier_Symbol N Nd Nl No Nonspacing_Mark Number Open_Punctuation Other Other_Letter Other_Number Other_Punctuation Other_Symbol P Paragraph_Separator Pc Pd Pe Pf Pi Po Private_Use Ps Punctuation S Sc Separator Sk Sm So Space_Separator Spacing_Mark Surrogate Symbol Titlecase_Letter Unassigned Uppercase_Letter Z Zl Zp Zs cntrl digit punct", "", "", "", "", "", "");
114
+ const scValueSets = new DataSet("Adlam Adlm Aghb Ahom Anatolian_Hieroglyphs Arab Arabic Armenian Armi Armn Avestan Avst Bali Balinese Bamu Bamum Bass Bassa_Vah Batak Batk Beng Bengali Bhaiksuki Bhks Bopo Bopomofo Brah Brahmi Brai Braille Bugi Buginese Buhd Buhid Cakm Canadian_Aboriginal Cans Cari Carian Caucasian_Albanian Chakma Cham Cher Cherokee Common Copt Coptic Cprt Cuneiform Cypriot Cyrillic Cyrl Deseret Deva Devanagari Dsrt Dupl Duployan Egyp Egyptian_Hieroglyphs Elba Elbasan Ethi Ethiopic Geor Georgian Glag Glagolitic Gonm Goth Gothic Gran Grantha Greek Grek Gujarati Gujr Gurmukhi Guru Han Hang Hangul Hani Hano Hanunoo Hatr Hatran Hebr Hebrew Hira Hiragana Hluw Hmng Hung Imperial_Aramaic Inherited Inscriptional_Pahlavi Inscriptional_Parthian Ital Java Javanese Kaithi Kali Kana Kannada Katakana Kayah_Li Khar Kharoshthi Khmer Khmr Khoj Khojki Khudawadi Knda Kthi Lana Lao Laoo Latin Latn Lepc Lepcha Limb Limbu Lina Linb Linear_A Linear_B Lisu Lyci Lycian Lydi Lydian Mahajani Mahj Malayalam Mand Mandaic Mani Manichaean Marc Marchen Masaram_Gondi Meetei_Mayek Mend Mende_Kikakui Merc Mero Meroitic_Cursive Meroitic_Hieroglyphs Miao Mlym Modi Mong Mongolian Mro Mroo Mtei Mult Multani Myanmar Mymr Nabataean Narb Nbat New_Tai_Lue Newa Nko Nkoo Nshu Nushu Ogam Ogham Ol_Chiki Olck Old_Hungarian Old_Italic Old_North_Arabian Old_Permic Old_Persian Old_South_Arabian Old_Turkic Oriya Orkh Orya Osage Osge Osma Osmanya Pahawh_Hmong Palm Palmyrene Pau_Cin_Hau Pauc Perm Phag Phags_Pa Phli Phlp Phnx Phoenician Plrd Prti Psalter_Pahlavi Qaac Qaai Rejang Rjng Runic Runr Samaritan Samr Sarb Saur Saurashtra Sgnw Sharada Shavian Shaw Shrd Sidd Siddham SignWriting Sind Sinh Sinhala Sora Sora_Sompeng Soyo Soyombo Sund Sundanese Sylo Syloti_Nagri Syrc Syriac Tagalog Tagb Tagbanwa Tai_Le Tai_Tham Tai_Viet Takr Takri Tale Talu Tamil Taml Tang Tangut Tavt Telu Telugu Tfng Tglg Thaa Thaana Thai Tibetan Tibt Tifinagh Tirh Tirhuta Ugar Ugaritic Vai Vaii Wara Warang_Citi Xpeo Xsux Yi Yiii Zanabazar_Square Zanb Zinh Zyyy", "Dogr Dogra Gong Gunjala_Gondi Hanifi_Rohingya Maka Makasar Medefaidrin Medf Old_Sogdian Rohg Sogd Sogdian Sogo", "Elym Elymaic Hmnp Nand Nandinagari Nyiakeng_Puachue_Hmong Wancho Wcho", "Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi", "Cpmn Cypro_Minoan Old_Uyghur Ougr Tangsa Tnsa Toto Vith Vithkuqi", "Hrkt Katakana_Or_Hiragana Kawi Nag_Mundari Nagm Unknown Zzzz", "");
115
+ const binPropertySets = new DataSet("AHex ASCII ASCII_Hex_Digit Alpha Alphabetic Any Assigned Bidi_C Bidi_Control Bidi_M Bidi_Mirrored CI CWCF CWCM CWKCF CWL CWT CWU Case_Ignorable Cased Changes_When_Casefolded Changes_When_Casemapped Changes_When_Lowercased Changes_When_NFKC_Casefolded Changes_When_Titlecased Changes_When_Uppercased DI Dash Default_Ignorable_Code_Point Dep Deprecated Dia Diacritic Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Ext Extender Gr_Base Gr_Ext Grapheme_Base Grapheme_Extend Hex Hex_Digit IDC IDS IDSB IDST IDS_Binary_Operator IDS_Trinary_Operator ID_Continue ID_Start Ideo Ideographic Join_C Join_Control LOE Logical_Order_Exception Lower Lowercase Math NChar Noncharacter_Code_Point Pat_Syn Pat_WS Pattern_Syntax Pattern_White_Space QMark Quotation_Mark RI Radical Regional_Indicator SD STerm Sentence_Terminal Soft_Dotted Term Terminal_Punctuation UIdeo Unified_Ideograph Upper Uppercase VS Variation_Selector White_Space XIDC XIDS XID_Continue XID_Start space", "Extended_Pictographic", "", "EBase EComp EMod EPres ExtPict", "", "", "");
109
116
  function isValidUnicodeProperty(version, name, value) {
110
117
  if (gcNameSet.has(name)) {
111
118
  return version >= 2018 && gcValueSets.es2018.has(value);
@@ -133,7 +140,10 @@ const LINE_TABULATION = 0x0b;
133
140
  const FORM_FEED = 0x0c;
134
141
  const CARRIAGE_RETURN = 0x0d;
135
142
  const EXCLAMATION_MARK = 0x21;
143
+ const NUMBER_SIGN = 0x23;
136
144
  const DOLLAR_SIGN = 0x24;
145
+ const PERCENT_SIGN = 0x25;
146
+ const AMPERSAND = 0x26;
137
147
  const LEFT_PARENTHESIS = 0x28;
138
148
  const RIGHT_PARENTHESIS = 0x29;
139
149
  const ASTERISK = 0x2a;
@@ -147,10 +157,12 @@ const DIGIT_ONE = 0x31;
147
157
  const DIGIT_SEVEN = 0x37;
148
158
  const DIGIT_NINE = 0x39;
149
159
  const COLON = 0x3a;
160
+ const SEMICOLON = 0x3b;
150
161
  const LESS_THAN_SIGN = 0x3c;
151
162
  const EQUALS_SIGN = 0x3d;
152
163
  const GREATER_THAN_SIGN = 0x3e;
153
164
  const QUESTION_MARK = 0x3f;
165
+ const COMMERCIAL_AT = 0x40;
154
166
  const LATIN_CAPITAL_LETTER_A = 0x41;
155
167
  const LATIN_CAPITAL_LETTER_B = 0x42;
156
168
  const LATIN_CAPITAL_LETTER_D = 0x44;
@@ -171,6 +183,7 @@ const LATIN_SMALL_LETTER_K = 0x6b;
171
183
  const LATIN_SMALL_LETTER_M = 0x6d;
172
184
  const LATIN_SMALL_LETTER_N = 0x6e;
173
185
  const LATIN_SMALL_LETTER_P = 0x70;
186
+ const LATIN_SMALL_LETTER_Q = 0x71;
174
187
  const LATIN_SMALL_LETTER_R = 0x72;
175
188
  const LATIN_SMALL_LETTER_S = 0x73;
176
189
  const LATIN_SMALL_LETTER_T = 0x74;
@@ -184,9 +197,11 @@ const LEFT_SQUARE_BRACKET = 0x5b;
184
197
  const REVERSE_SOLIDUS = 0x5c;
185
198
  const RIGHT_SQUARE_BRACKET = 0x5d;
186
199
  const CIRCUMFLEX_ACCENT = 0x5e;
200
+ const GRAVE_ACCENT = 0x60;
187
201
  const LEFT_CURLY_BRACKET = 0x7b;
188
202
  const VERTICAL_LINE = 0x7c;
189
203
  const RIGHT_CURLY_BRACKET = 0x7d;
204
+ const TILDE = 0x7e;
190
205
  const ZERO_WIDTH_NON_JOINER = 0x200c;
191
206
  const ZERO_WIDTH_JOINER = 0x200d;
192
207
  const LINE_SEPARATOR = 0x2028;
@@ -353,29 +368,102 @@ class RegExpSyntaxError extends SyntaxError {
353
368
  }
354
369
  }
355
370
 
371
+ const binPropertyOfStringSets = new Set([
372
+ "Basic_Emoji",
373
+ "Emoji_Keycap_Sequence",
374
+ "RGI_Emoji_Modifier_Sequence",
375
+ "RGI_Emoji_Flag_Sequence",
376
+ "RGI_Emoji_Tag_Sequence",
377
+ "RGI_Emoji_ZWJ_Sequence",
378
+ "RGI_Emoji",
379
+ ]);
380
+ function isValidLoneUnicodePropertyOfString(version, value) {
381
+ return version >= 2024 && binPropertyOfStringSets.has(value);
382
+ }
383
+
384
+ const SYNTAX_CHARACTER = new Set([
385
+ CIRCUMFLEX_ACCENT,
386
+ DOLLAR_SIGN,
387
+ REVERSE_SOLIDUS,
388
+ FULL_STOP,
389
+ ASTERISK,
390
+ PLUS_SIGN,
391
+ QUESTION_MARK,
392
+ LEFT_PARENTHESIS,
393
+ RIGHT_PARENTHESIS,
394
+ LEFT_SQUARE_BRACKET,
395
+ RIGHT_SQUARE_BRACKET,
396
+ LEFT_CURLY_BRACKET,
397
+ RIGHT_CURLY_BRACKET,
398
+ VERTICAL_LINE,
399
+ ]);
400
+ const CLASS_SET_RESERVED_DOUBLE_PUNCTUATOR_CHARACTER = new Set([
401
+ AMPERSAND,
402
+ EXCLAMATION_MARK,
403
+ NUMBER_SIGN,
404
+ DOLLAR_SIGN,
405
+ PERCENT_SIGN,
406
+ ASTERISK,
407
+ PLUS_SIGN,
408
+ COMMA,
409
+ FULL_STOP,
410
+ COLON,
411
+ SEMICOLON,
412
+ LESS_THAN_SIGN,
413
+ EQUALS_SIGN,
414
+ GREATER_THAN_SIGN,
415
+ QUESTION_MARK,
416
+ COMMERCIAL_AT,
417
+ CIRCUMFLEX_ACCENT,
418
+ GRAVE_ACCENT,
419
+ TILDE,
420
+ ]);
421
+ const CLASS_SET_SYNTAX_CHARACTER = new Set([
422
+ LEFT_PARENTHESIS,
423
+ RIGHT_PARENTHESIS,
424
+ LEFT_SQUARE_BRACKET,
425
+ RIGHT_SQUARE_BRACKET,
426
+ LEFT_CURLY_BRACKET,
427
+ RIGHT_CURLY_BRACKET,
428
+ SOLIDUS,
429
+ HYPHEN_MINUS,
430
+ REVERSE_SOLIDUS,
431
+ VERTICAL_LINE,
432
+ ]);
433
+ const CLASS_SET_RESERVED_PUNCTUATOR = new Set([
434
+ AMPERSAND,
435
+ HYPHEN_MINUS,
436
+ EXCLAMATION_MARK,
437
+ NUMBER_SIGN,
438
+ PERCENT_SIGN,
439
+ COMMA,
440
+ COLON,
441
+ SEMICOLON,
442
+ LESS_THAN_SIGN,
443
+ EQUALS_SIGN,
444
+ GREATER_THAN_SIGN,
445
+ COMMERCIAL_AT,
446
+ GRAVE_ACCENT,
447
+ TILDE,
448
+ ]);
356
449
  function isSyntaxCharacter(cp) {
357
- return (cp === CIRCUMFLEX_ACCENT ||
358
- cp === DOLLAR_SIGN ||
359
- cp === REVERSE_SOLIDUS ||
360
- cp === FULL_STOP ||
361
- cp === ASTERISK ||
362
- cp === PLUS_SIGN ||
363
- cp === QUESTION_MARK ||
364
- cp === LEFT_PARENTHESIS ||
365
- cp === RIGHT_PARENTHESIS ||
366
- cp === LEFT_SQUARE_BRACKET ||
367
- cp === RIGHT_SQUARE_BRACKET ||
368
- cp === LEFT_CURLY_BRACKET ||
369
- cp === RIGHT_CURLY_BRACKET ||
370
- cp === VERTICAL_LINE);
450
+ return SYNTAX_CHARACTER.has(cp);
451
+ }
452
+ function isClassSetReservedDoublePunctuatorCharacter(cp) {
453
+ return CLASS_SET_RESERVED_DOUBLE_PUNCTUATOR_CHARACTER.has(cp);
454
+ }
455
+ function isClassSetSyntaxCharacter(cp) {
456
+ return CLASS_SET_SYNTAX_CHARACTER.has(cp);
371
457
  }
372
- function isRegExpIdentifierStart(cp) {
458
+ function isClassSetReservedPunctuator(cp) {
459
+ return CLASS_SET_RESERVED_PUNCTUATOR.has(cp);
460
+ }
461
+ function isIdentifierStartChar(cp) {
373
462
  return isIdStart(cp) || cp === DOLLAR_SIGN || cp === LOW_LINE;
374
463
  }
375
- function isRegExpIdentifierPart(cp) {
464
+ function isIdentifierPartChar(cp) {
376
465
  return (isIdContinue(cp) ||
377
466
  cp === DOLLAR_SIGN ||
378
- cp === LOW_LINE ||
379
467
  cp === ZERO_WIDTH_NON_JOINER ||
380
468
  cp === ZERO_WIDTH_JOINER);
381
469
  }
@@ -388,14 +476,15 @@ function isUnicodePropertyValueCharacter(cp) {
388
476
  class RegExpValidator {
389
477
  constructor(options) {
390
478
  this._reader = new Reader();
391
- this._uFlag = false;
479
+ this._unicodeMode = false;
480
+ this._unicodeSetsMode = false;
392
481
  this._nFlag = false;
393
482
  this._lastIntValue = 0;
394
- this._lastMinValue = 0;
395
- this._lastMaxValue = 0;
483
+ this._lastRange = {
484
+ min: 0,
485
+ max: Number.POSITIVE_INFINITY,
486
+ };
396
487
  this._lastStrValue = "";
397
- this._lastKeyValue = "";
398
- this._lastValValue = "";
399
488
  this._lastAssertionIsQuantifiable = false;
400
489
  this._numCapturingParens = 0;
401
490
  this._groupNames = new Set();
@@ -403,14 +492,18 @@ class RegExpValidator {
403
492
  this._options = options !== null && options !== void 0 ? options : {};
404
493
  }
405
494
  validateLiteral(source, start = 0, end = source.length) {
406
- this._uFlag = this._nFlag = false;
495
+ this._unicodeSetsMode = this._unicodeMode = this._nFlag = false;
407
496
  this.reset(source, start, end);
408
497
  this.onLiteralEnter(start);
409
498
  if (this.eat(SOLIDUS) && this.eatRegExpBody() && this.eat(SOLIDUS)) {
410
499
  const flagStart = this.index;
411
- const uFlag = source.includes("u", flagStart);
500
+ const unicode = source.includes("u", flagStart);
501
+ const unicodeSets = source.includes("v", flagStart);
412
502
  this.validateFlags(source, flagStart, end);
413
- this.validatePattern(source, start + 1, flagStart - 1, uFlag);
503
+ this.validatePattern(source, start + 1, flagStart - 1, {
504
+ unicode,
505
+ unicodeSets,
506
+ });
414
507
  }
415
508
  else if (start >= end) {
416
509
  this.raise("Empty");
@@ -430,6 +523,7 @@ class RegExpValidator {
430
523
  let unicode = false;
431
524
  let dotAll = false;
432
525
  let hasIndices = false;
526
+ let unicodeSets = false;
433
527
  for (let i = start; i < end; ++i) {
434
528
  const flag = source.charCodeAt(i);
435
529
  if (existingFlags.has(flag)) {
@@ -461,6 +555,10 @@ class RegExpValidator {
461
555
  this.ecmaVersion >= 2022) {
462
556
  hasIndices = true;
463
557
  }
558
+ else if (flag === LATIN_SMALL_LETTER_V &&
559
+ this.ecmaVersion >= 2024) {
560
+ unicodeSets = true;
561
+ }
464
562
  else {
465
563
  this.raise(`Invalid flag '${source[i]}'`);
466
564
  }
@@ -473,13 +571,14 @@ class RegExpValidator {
473
571
  sticky,
474
572
  dotAll,
475
573
  hasIndices,
574
+ unicodeSets,
476
575
  });
477
576
  }
478
- validatePattern(source, start = 0, end = source.length, uFlag = false) {
479
- this._uFlag = uFlag && this.ecmaVersion >= 2015;
480
- this._nFlag =
481
- (uFlag && this.ecmaVersion >= 2018) ||
482
- Boolean(this._options.strict && this.ecmaVersion >= 2023);
577
+ validatePattern(source, start = 0, end = source.length, uFlagOrFlags = undefined) {
578
+ const mode = this._parseFlagsOptionToMode(uFlagOrFlags);
579
+ this._unicodeMode = mode.unicodeMode;
580
+ this._nFlag = mode.nFlag;
581
+ this._unicodeSetsMode = mode.unicodeSetsMode;
483
582
  this.reset(source, start, end);
484
583
  this.consumePattern();
485
584
  if (!this._nFlag &&
@@ -490,12 +589,36 @@ class RegExpValidator {
490
589
  this.consumePattern();
491
590
  }
492
591
  }
592
+ _parseFlagsOptionToMode(uFlagOrFlags = undefined) {
593
+ let unicode = false;
594
+ let unicodeSets = false;
595
+ if (uFlagOrFlags && this.ecmaVersion >= 2015) {
596
+ if (typeof uFlagOrFlags === "object") {
597
+ unicode = Boolean(uFlagOrFlags.unicode);
598
+ if (this.ecmaVersion >= 2024) {
599
+ unicodeSets = Boolean(uFlagOrFlags.unicodeSets);
600
+ }
601
+ }
602
+ else {
603
+ unicode = uFlagOrFlags;
604
+ }
605
+ }
606
+ if (unicode && unicodeSets) {
607
+ this.raise("Invalid regular expression flags");
608
+ }
609
+ const unicodeMode = unicode || unicodeSets;
610
+ const nFlag = (unicode && this.ecmaVersion >= 2018) ||
611
+ unicodeSets ||
612
+ Boolean(this._options.strict && this.ecmaVersion >= 2023);
613
+ const unicodeSetsMode = unicodeSets;
614
+ return { unicodeMode, nFlag, unicodeSetsMode };
615
+ }
493
616
  get strict() {
494
- return Boolean(this._options.strict) || this._uFlag;
617
+ return Boolean(this._options.strict) || this._unicodeMode;
495
618
  }
496
619
  get ecmaVersion() {
497
620
  var _a;
498
- return (_a = this._options.ecmaVersion) !== null && _a !== void 0 ? _a : 2023;
621
+ return (_a = this._options.ecmaVersion) !== null && _a !== void 0 ? _a : latestEcmaVersion;
499
622
  }
500
623
  onLiteralEnter(start) {
501
624
  if (this._options.onLiteralEnter) {
@@ -600,9 +723,9 @@ class RegExpValidator {
600
723
  this._options.onEscapeCharacterSet(start, end, kind, negate);
601
724
  }
602
725
  }
603
- onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
726
+ onUnicodePropertyCharacterSet(start, end, kind, key, value, negate, strings) {
604
727
  if (this._options.onUnicodePropertyCharacterSet) {
605
- this._options.onUnicodePropertyCharacterSet(start, end, kind, key, value, negate);
728
+ this._options.onUnicodePropertyCharacterSet(start, end, kind, key, value, negate, strings);
606
729
  }
607
730
  }
608
731
  onCharacter(start, end, value) {
@@ -615,9 +738,9 @@ class RegExpValidator {
615
738
  this._options.onBackreference(start, end, ref);
616
739
  }
617
740
  }
618
- onCharacterClassEnter(start, negate) {
741
+ onCharacterClassEnter(start, negate, unicodeSets) {
619
742
  if (this._options.onCharacterClassEnter) {
620
- this._options.onCharacterClassEnter(start, negate);
743
+ this._options.onCharacterClassEnter(start, negate, unicodeSets);
621
744
  }
622
745
  }
623
746
  onCharacterClassLeave(start, end, negate) {
@@ -630,6 +753,36 @@ class RegExpValidator {
630
753
  this._options.onCharacterClassRange(start, end, min, max);
631
754
  }
632
755
  }
756
+ onClassIntersection(start, end) {
757
+ if (this._options.onClassIntersection) {
758
+ this._options.onClassIntersection(start, end);
759
+ }
760
+ }
761
+ onClassSubtraction(start, end) {
762
+ if (this._options.onClassSubtraction) {
763
+ this._options.onClassSubtraction(start, end);
764
+ }
765
+ }
766
+ onClassStringDisjunctionEnter(start) {
767
+ if (this._options.onClassStringDisjunctionEnter) {
768
+ this._options.onClassStringDisjunctionEnter(start);
769
+ }
770
+ }
771
+ onClassStringDisjunctionLeave(start, end) {
772
+ if (this._options.onClassStringDisjunctionLeave) {
773
+ this._options.onClassStringDisjunctionLeave(start, end);
774
+ }
775
+ }
776
+ onStringAlternativeEnter(start, index) {
777
+ if (this._options.onStringAlternativeEnter) {
778
+ this._options.onStringAlternativeEnter(start, index);
779
+ }
780
+ }
781
+ onStringAlternativeLeave(start, end, index) {
782
+ if (this._options.onStringAlternativeLeave) {
783
+ this._options.onStringAlternativeLeave(start, end, index);
784
+ }
785
+ }
633
786
  get source() {
634
787
  return this._reader.source;
635
788
  }
@@ -649,7 +802,7 @@ class RegExpValidator {
649
802
  return this._reader.nextCodePoint3;
650
803
  }
651
804
  reset(source, start, end) {
652
- this._reader.reset(source, start, end, this._uFlag);
805
+ this._reader.reset(source, start, end, this._unicodeMode);
653
806
  }
654
807
  rewind(index) {
655
808
  this._reader.rewind(index);
@@ -667,7 +820,7 @@ class RegExpValidator {
667
820
  return this._reader.eat3(cp1, cp2, cp3);
668
821
  }
669
822
  raise(message) {
670
- throw new RegExpSyntaxError(this.source, this._uFlag, this.index, message);
823
+ throw new RegExpSyntaxError(this.source, this._unicodeMode, this.index, message);
671
824
  }
672
825
  eatRegExpBody() {
673
826
  const start = this.index;
@@ -782,7 +935,7 @@ class RegExpValidator {
782
935
  this.onAlternativeLeave(start, this.index, i);
783
936
  }
784
937
  consumeTerm() {
785
- if (this._uFlag || this.strict) {
938
+ if (this._unicodeMode || this.strict) {
786
939
  return (this.consumeAssertion() ||
787
940
  (this.consumeAtom() && this.consumeOptionalQuantifier()));
788
941
  }
@@ -851,8 +1004,7 @@ class RegExpValidator {
851
1004
  max = 1;
852
1005
  }
853
1006
  else if (this.eatBracedQuantifier(noConsume)) {
854
- min = this._lastMinValue;
855
- max = this._lastMaxValue;
1007
+ ({ min, max } = this._lastRange);
856
1008
  }
857
1009
  else {
858
1010
  return false;
@@ -866,23 +1018,23 @@ class RegExpValidator {
866
1018
  eatBracedQuantifier(noError) {
867
1019
  const start = this.index;
868
1020
  if (this.eat(LEFT_CURLY_BRACKET)) {
869
- this._lastMinValue = 0;
870
- this._lastMaxValue = Number.POSITIVE_INFINITY;
871
1021
  if (this.eatDecimalDigits()) {
872
- this._lastMinValue = this._lastMaxValue = this._lastIntValue;
1022
+ const min = this._lastIntValue;
1023
+ let max = min;
873
1024
  if (this.eat(COMMA)) {
874
- this._lastMaxValue = this.eatDecimalDigits()
1025
+ max = this.eatDecimalDigits()
875
1026
  ? this._lastIntValue
876
1027
  : Number.POSITIVE_INFINITY;
877
1028
  }
878
1029
  if (this.eat(RIGHT_CURLY_BRACKET)) {
879
- if (!noError && this._lastMaxValue < this._lastMinValue) {
1030
+ if (!noError && max < min) {
880
1031
  this.raise("numbers out of order in {} quantifier");
881
1032
  }
1033
+ this._lastRange = { min, max };
882
1034
  return true;
883
1035
  }
884
1036
  }
885
- if (!noError && (this._uFlag || this.strict)) {
1037
+ if (!noError && (this._unicodeMode || this.strict)) {
886
1038
  this.raise("Incomplete quantifier");
887
1039
  }
888
1040
  this.rewind(start);
@@ -893,7 +1045,7 @@ class RegExpValidator {
893
1045
  return (this.consumePatternCharacter() ||
894
1046
  this.consumeDot() ||
895
1047
  this.consumeReverseSolidusAtomEscape() ||
896
- this.consumeCharacterClass() ||
1048
+ Boolean(this.consumeCharacterClass()) ||
897
1049
  this.consumeUncapturingGroup() ||
898
1050
  this.consumeCapturingGroup());
899
1051
  }
@@ -953,7 +1105,7 @@ class RegExpValidator {
953
1105
  return (this.consumeDot() ||
954
1106
  this.consumeReverseSolidusAtomEscape() ||
955
1107
  this.consumeReverseSolidusFollowedByC() ||
956
- this.consumeCharacterClass() ||
1108
+ Boolean(this.consumeCharacterClass()) ||
957
1109
  this.consumeUncapturingGroup() ||
958
1110
  this.consumeCapturingGroup() ||
959
1111
  this.consumeInvalidBracedQuantifier() ||
@@ -1027,7 +1179,7 @@ class RegExpValidator {
1027
1179
  (this._nFlag && this.consumeKGroupName())) {
1028
1180
  return true;
1029
1181
  }
1030
- if (this.strict || this._uFlag) {
1182
+ if (this.strict || this._unicodeMode) {
1031
1183
  this.raise("Invalid escape");
1032
1184
  }
1033
1185
  return false;
@@ -1040,7 +1192,7 @@ class RegExpValidator {
1040
1192
  this.onBackreference(start - 1, this.index, n);
1041
1193
  return true;
1042
1194
  }
1043
- if (this.strict || this._uFlag) {
1195
+ if (this.strict || this._unicodeMode) {
1044
1196
  this.raise("Invalid escape");
1045
1197
  }
1046
1198
  this.rewind(start);
@@ -1048,52 +1200,57 @@ class RegExpValidator {
1048
1200
  return false;
1049
1201
  }
1050
1202
  consumeCharacterClassEscape() {
1203
+ var _a;
1051
1204
  const start = this.index;
1052
1205
  if (this.eat(LATIN_SMALL_LETTER_D)) {
1053
1206
  this._lastIntValue = -1;
1054
1207
  this.onEscapeCharacterSet(start - 1, this.index, "digit", false);
1055
- return true;
1208
+ return {};
1056
1209
  }
1057
1210
  if (this.eat(LATIN_CAPITAL_LETTER_D)) {
1058
1211
  this._lastIntValue = -1;
1059
1212
  this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
1060
- return true;
1213
+ return {};
1061
1214
  }
1062
1215
  if (this.eat(LATIN_SMALL_LETTER_S)) {
1063
1216
  this._lastIntValue = -1;
1064
1217
  this.onEscapeCharacterSet(start - 1, this.index, "space", false);
1065
- return true;
1218
+ return {};
1066
1219
  }
1067
1220
  if (this.eat(LATIN_CAPITAL_LETTER_S)) {
1068
1221
  this._lastIntValue = -1;
1069
1222
  this.onEscapeCharacterSet(start - 1, this.index, "space", true);
1070
- return true;
1223
+ return {};
1071
1224
  }
1072
1225
  if (this.eat(LATIN_SMALL_LETTER_W)) {
1073
1226
  this._lastIntValue = -1;
1074
1227
  this.onEscapeCharacterSet(start - 1, this.index, "word", false);
1075
- return true;
1228
+ return {};
1076
1229
  }
1077
1230
  if (this.eat(LATIN_CAPITAL_LETTER_W)) {
1078
1231
  this._lastIntValue = -1;
1079
1232
  this.onEscapeCharacterSet(start - 1, this.index, "word", true);
1080
- return true;
1233
+ return {};
1081
1234
  }
1082
1235
  let negate = false;
1083
- if (this._uFlag &&
1236
+ if (this._unicodeMode &&
1084
1237
  this.ecmaVersion >= 2018 &&
1085
1238
  (this.eat(LATIN_SMALL_LETTER_P) ||
1086
1239
  (negate = this.eat(LATIN_CAPITAL_LETTER_P)))) {
1087
1240
  this._lastIntValue = -1;
1241
+ let result = null;
1088
1242
  if (this.eat(LEFT_CURLY_BRACKET) &&
1089
- this.eatUnicodePropertyValueExpression() &&
1243
+ (result = this.eatUnicodePropertyValueExpression()) &&
1090
1244
  this.eat(RIGHT_CURLY_BRACKET)) {
1091
- this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", this._lastKeyValue, this._lastValValue || null, negate);
1092
- return true;
1245
+ if (negate && result.strings) {
1246
+ this.raise("Invalid property name");
1247
+ }
1248
+ this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", result.key, result.value, negate, (_a = result.strings) !== null && _a !== void 0 ? _a : false);
1249
+ return { mayContainStrings: result.strings };
1093
1250
  }
1094
1251
  this.raise("Invalid property name");
1095
1252
  }
1096
- return false;
1253
+ return null;
1097
1254
  }
1098
1255
  consumeCharacterEscape() {
1099
1256
  const start = this.index;
@@ -1103,7 +1260,7 @@ class RegExpValidator {
1103
1260
  this.eatHexEscapeSequence() ||
1104
1261
  this.eatRegExpUnicodeEscapeSequence() ||
1105
1262
  (!this.strict &&
1106
- !this._uFlag &&
1263
+ !this._unicodeMode &&
1107
1264
  this.eatLegacyOctalEscapeSequence()) ||
1108
1265
  this.eatIdentityEscape()) {
1109
1266
  this.onCharacter(start - 1, this.index, this._lastIntValue);
@@ -1128,18 +1285,31 @@ class RegExpValidator {
1128
1285
  const start = this.index;
1129
1286
  if (this.eat(LEFT_SQUARE_BRACKET)) {
1130
1287
  const negate = this.eat(CIRCUMFLEX_ACCENT);
1131
- this.onCharacterClassEnter(start, negate);
1132
- this.consumeClassRanges();
1288
+ this.onCharacterClassEnter(start, negate, this._unicodeSetsMode);
1289
+ const result = this.consumeClassContents();
1133
1290
  if (!this.eat(RIGHT_SQUARE_BRACKET)) {
1134
- this.raise("Unterminated character class");
1291
+ if (this.currentCodePoint === -1) {
1292
+ this.raise("Unterminated character class");
1293
+ }
1294
+ this.raise("Invalid character in character class");
1295
+ }
1296
+ if (negate && result.mayContainStrings) {
1297
+ this.raise("Negated character class may contain strings");
1135
1298
  }
1136
1299
  this.onCharacterClassLeave(start, this.index, negate);
1137
- return true;
1300
+ return result;
1138
1301
  }
1139
- return false;
1302
+ return null;
1140
1303
  }
1141
- consumeClassRanges() {
1142
- const strict = this.strict || this._uFlag;
1304
+ consumeClassContents() {
1305
+ if (this._unicodeSetsMode) {
1306
+ if (this.currentCodePoint === RIGHT_SQUARE_BRACKET) {
1307
+ return {};
1308
+ }
1309
+ const result = this.consumeClassSetExpression();
1310
+ return result;
1311
+ }
1312
+ const strict = this.strict || this._unicodeMode;
1143
1313
  for (;;) {
1144
1314
  const rangeStart = this.index;
1145
1315
  if (!this.consumeClassAtom()) {
@@ -1165,6 +1335,7 @@ class RegExpValidator {
1165
1335
  }
1166
1336
  this.onCharacterClassRange(rangeStart, this.index, min, max);
1167
1337
  }
1338
+ return {};
1168
1339
  }
1169
1340
  consumeClassAtom() {
1170
1341
  const start = this.index;
@@ -1187,7 +1358,7 @@ class RegExpValidator {
1187
1358
  this.onCharacter(start, this.index, this._lastIntValue);
1188
1359
  return true;
1189
1360
  }
1190
- if (this.strict || this._uFlag) {
1361
+ if (this.strict || this._unicodeMode) {
1191
1362
  this.raise("Invalid escape");
1192
1363
  }
1193
1364
  this.rewind(start);
@@ -1201,14 +1372,14 @@ class RegExpValidator {
1201
1372
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1202
1373
  return true;
1203
1374
  }
1204
- if (this._uFlag && this.eat(HYPHEN_MINUS)) {
1375
+ if (this._unicodeMode && this.eat(HYPHEN_MINUS)) {
1205
1376
  this._lastIntValue = HYPHEN_MINUS;
1206
1377
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1207
1378
  return true;
1208
1379
  }
1209
1380
  let cp = 0;
1210
1381
  if (!this.strict &&
1211
- !this._uFlag &&
1382
+ !this._unicodeMode &&
1212
1383
  this.currentCodePoint === LATIN_SMALL_LETTER_C &&
1213
1384
  (isDecimalDigit((cp = this.nextCodePoint)) || cp === LOW_LINE)) {
1214
1385
  this.advance();
@@ -1217,7 +1388,196 @@ class RegExpValidator {
1217
1388
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1218
1389
  return true;
1219
1390
  }
1220
- return (this.consumeCharacterClassEscape() || this.consumeCharacterEscape());
1391
+ return (Boolean(this.consumeCharacterClassEscape()) ||
1392
+ this.consumeCharacterEscape());
1393
+ }
1394
+ consumeClassSetExpression() {
1395
+ const start = this.index;
1396
+ let mayContainStrings = false;
1397
+ let result = null;
1398
+ if (this.consumeClassSetCharacter()) {
1399
+ if (this.consumeClassSetRangeFromOperator(start)) {
1400
+ this.consumeClassUnionRight({});
1401
+ return {};
1402
+ }
1403
+ mayContainStrings = false;
1404
+ }
1405
+ else if ((result = this.consumeClassSetOperand())) {
1406
+ mayContainStrings = result.mayContainStrings;
1407
+ }
1408
+ else {
1409
+ const cp = this.currentCodePoint;
1410
+ if (cp === REVERSE_SOLIDUS) {
1411
+ this.advance();
1412
+ this.raise("Invalid escape");
1413
+ }
1414
+ if (cp === this.nextCodePoint &&
1415
+ isClassSetReservedDoublePunctuatorCharacter(cp)) {
1416
+ this.raise("Invalid set operation in character class");
1417
+ }
1418
+ this.raise("Invalid character in character class");
1419
+ }
1420
+ if (this.eat2(AMPERSAND, AMPERSAND)) {
1421
+ while (this.currentCodePoint !== AMPERSAND &&
1422
+ (result = this.consumeClassSetOperand())) {
1423
+ this.onClassIntersection(start, this.index);
1424
+ if (!result.mayContainStrings) {
1425
+ mayContainStrings = false;
1426
+ }
1427
+ if (this.eat2(AMPERSAND, AMPERSAND)) {
1428
+ continue;
1429
+ }
1430
+ return { mayContainStrings };
1431
+ }
1432
+ this.raise("Invalid character in character class");
1433
+ }
1434
+ if (this.eat2(HYPHEN_MINUS, HYPHEN_MINUS)) {
1435
+ while (this.consumeClassSetOperand()) {
1436
+ this.onClassSubtraction(start, this.index);
1437
+ if (this.eat2(HYPHEN_MINUS, HYPHEN_MINUS)) {
1438
+ continue;
1439
+ }
1440
+ return { mayContainStrings };
1441
+ }
1442
+ this.raise("Invalid character in character class");
1443
+ }
1444
+ return this.consumeClassUnionRight({ mayContainStrings });
1445
+ }
1446
+ consumeClassUnionRight(leftResult) {
1447
+ let mayContainStrings = leftResult.mayContainStrings;
1448
+ for (;;) {
1449
+ const start = this.index;
1450
+ if (this.consumeClassSetCharacter()) {
1451
+ this.consumeClassSetRangeFromOperator(start);
1452
+ continue;
1453
+ }
1454
+ const result = this.consumeClassSetOperand();
1455
+ if (result) {
1456
+ if (result.mayContainStrings) {
1457
+ mayContainStrings = true;
1458
+ }
1459
+ continue;
1460
+ }
1461
+ break;
1462
+ }
1463
+ return { mayContainStrings };
1464
+ }
1465
+ consumeClassSetRangeFromOperator(start) {
1466
+ const currentStart = this.index;
1467
+ const min = this._lastIntValue;
1468
+ if (this.eat(HYPHEN_MINUS)) {
1469
+ if (this.consumeClassSetCharacter()) {
1470
+ const max = this._lastIntValue;
1471
+ if (min === -1 || max === -1) {
1472
+ this.raise("Invalid character class");
1473
+ }
1474
+ if (min > max) {
1475
+ this.raise("Range out of order in character class");
1476
+ }
1477
+ this.onCharacterClassRange(start, this.index, min, max);
1478
+ return true;
1479
+ }
1480
+ this.rewind(currentStart);
1481
+ }
1482
+ return false;
1483
+ }
1484
+ consumeClassSetOperand() {
1485
+ let result = null;
1486
+ if ((result = this.consumeNestedClass())) {
1487
+ return result;
1488
+ }
1489
+ if ((result = this.consumeClassStringDisjunction())) {
1490
+ return result;
1491
+ }
1492
+ if (this.consumeClassSetCharacter()) {
1493
+ return {};
1494
+ }
1495
+ return null;
1496
+ }
1497
+ consumeNestedClass() {
1498
+ const start = this.index;
1499
+ if (this.eat(LEFT_SQUARE_BRACKET)) {
1500
+ const negate = this.eat(CIRCUMFLEX_ACCENT);
1501
+ this.onCharacterClassEnter(start, negate, true);
1502
+ const result = this.consumeClassContents();
1503
+ if (!this.eat(RIGHT_SQUARE_BRACKET)) {
1504
+ this.raise("Unterminated character class");
1505
+ }
1506
+ if (negate && result.mayContainStrings) {
1507
+ this.raise("Negated character class may contain strings");
1508
+ }
1509
+ this.onCharacterClassLeave(start, this.index, negate);
1510
+ return result;
1511
+ }
1512
+ if (this.eat(REVERSE_SOLIDUS)) {
1513
+ const result = this.consumeCharacterClassEscape();
1514
+ if (result) {
1515
+ return result;
1516
+ }
1517
+ this.rewind(start);
1518
+ }
1519
+ return null;
1520
+ }
1521
+ consumeClassStringDisjunction() {
1522
+ const start = this.index;
1523
+ if (this.eat3(REVERSE_SOLIDUS, LATIN_SMALL_LETTER_Q, LEFT_CURLY_BRACKET)) {
1524
+ this.onClassStringDisjunctionEnter(start);
1525
+ let i = 0;
1526
+ let mayContainStrings = false;
1527
+ do {
1528
+ if (this.consumeClassString(i++).mayContainStrings) {
1529
+ mayContainStrings = true;
1530
+ }
1531
+ } while (this.eat(VERTICAL_LINE));
1532
+ if (this.eat(RIGHT_CURLY_BRACKET)) {
1533
+ this.onClassStringDisjunctionLeave(start, this.index);
1534
+ return { mayContainStrings };
1535
+ }
1536
+ this.raise("Unterminated class string disjunction");
1537
+ }
1538
+ return null;
1539
+ }
1540
+ consumeClassString(i) {
1541
+ const start = this.index;
1542
+ let count = 0;
1543
+ this.onStringAlternativeEnter(start, i);
1544
+ while (this.currentCodePoint !== -1 &&
1545
+ this.consumeClassSetCharacter()) {
1546
+ count++;
1547
+ }
1548
+ this.onStringAlternativeLeave(start, this.index, i);
1549
+ return { mayContainStrings: count !== 1 };
1550
+ }
1551
+ consumeClassSetCharacter() {
1552
+ const start = this.index;
1553
+ const cp = this.currentCodePoint;
1554
+ if (cp !== this.nextCodePoint ||
1555
+ !isClassSetReservedDoublePunctuatorCharacter(cp)) {
1556
+ if (cp !== -1 && !isClassSetSyntaxCharacter(cp)) {
1557
+ this._lastIntValue = cp;
1558
+ this.advance();
1559
+ this.onCharacter(start, this.index, this._lastIntValue);
1560
+ return true;
1561
+ }
1562
+ }
1563
+ if (this.eat(REVERSE_SOLIDUS)) {
1564
+ if (this.consumeCharacterEscape()) {
1565
+ return true;
1566
+ }
1567
+ if (isClassSetReservedPunctuator(this.currentCodePoint)) {
1568
+ this._lastIntValue = this.currentCodePoint;
1569
+ this.advance();
1570
+ this.onCharacter(start, this.index, this._lastIntValue);
1571
+ return true;
1572
+ }
1573
+ if (this.eat(LATIN_SMALL_LETTER_B)) {
1574
+ this._lastIntValue = BACKSPACE;
1575
+ this.onCharacter(start, this.index, this._lastIntValue);
1576
+ return true;
1577
+ }
1578
+ this.rewind(start);
1579
+ }
1580
+ return false;
1221
1581
  }
1222
1582
  eatGroupName() {
1223
1583
  if (this.eat(LESS_THAN_SIGN)) {
@@ -1240,7 +1600,7 @@ class RegExpValidator {
1240
1600
  }
1241
1601
  eatRegExpIdentifierStart() {
1242
1602
  const start = this.index;
1243
- const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1603
+ const forceUFlag = !this._unicodeMode && this.ecmaVersion >= 2020;
1244
1604
  let cp = this.currentCodePoint;
1245
1605
  this.advance();
1246
1606
  if (cp === REVERSE_SOLIDUS &&
@@ -1253,7 +1613,7 @@ class RegExpValidator {
1253
1613
  cp = combineSurrogatePair(cp, this.currentCodePoint);
1254
1614
  this.advance();
1255
1615
  }
1256
- if (isRegExpIdentifierStart(cp)) {
1616
+ if (isIdentifierStartChar(cp)) {
1257
1617
  this._lastIntValue = cp;
1258
1618
  return true;
1259
1619
  }
@@ -1264,7 +1624,7 @@ class RegExpValidator {
1264
1624
  }
1265
1625
  eatRegExpIdentifierPart() {
1266
1626
  const start = this.index;
1267
- const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1627
+ const forceUFlag = !this._unicodeMode && this.ecmaVersion >= 2020;
1268
1628
  let cp = this.currentCodePoint;
1269
1629
  this.advance();
1270
1630
  if (cp === REVERSE_SOLIDUS &&
@@ -1277,7 +1637,7 @@ class RegExpValidator {
1277
1637
  cp = combineSurrogatePair(cp, this.currentCodePoint);
1278
1638
  this.advance();
1279
1639
  }
1280
- if (isRegExpIdentifierPart(cp)) {
1640
+ if (isIdentifierPartChar(cp)) {
1281
1641
  this._lastIntValue = cp;
1282
1642
  return true;
1283
1643
  }
@@ -1339,7 +1699,7 @@ class RegExpValidator {
1339
1699
  }
1340
1700
  eatRegExpUnicodeEscapeSequence(forceUFlag = false) {
1341
1701
  const start = this.index;
1342
- const uFlag = forceUFlag || this._uFlag;
1702
+ const uFlag = forceUFlag || this._unicodeMode;
1343
1703
  if (this.eat(LATIN_SMALL_LETTER_U)) {
1344
1704
  if ((uFlag && this.eatRegExpUnicodeSurrogatePairEscape()) ||
1345
1705
  this.eatFixedHexDigits(4) ||
@@ -1395,7 +1755,7 @@ class RegExpValidator {
1395
1755
  if (cp === -1) {
1396
1756
  return false;
1397
1757
  }
1398
- if (this._uFlag) {
1758
+ if (this._unicodeMode) {
1399
1759
  return isSyntaxCharacter(cp) || cp === SOLIDUS;
1400
1760
  }
1401
1761
  if (this.strict) {
@@ -1422,11 +1782,14 @@ class RegExpValidator {
1422
1782
  eatUnicodePropertyValueExpression() {
1423
1783
  const start = this.index;
1424
1784
  if (this.eatUnicodePropertyName() && this.eat(EQUALS_SIGN)) {
1425
- this._lastKeyValue = this._lastStrValue;
1785
+ const key = this._lastStrValue;
1426
1786
  if (this.eatUnicodePropertyValue()) {
1427
- this._lastValValue = this._lastStrValue;
1428
- if (isValidUnicodeProperty(this.ecmaVersion, this._lastKeyValue, this._lastValValue)) {
1429
- return true;
1787
+ const value = this._lastStrValue;
1788
+ if (isValidUnicodeProperty(this.ecmaVersion, key, value)) {
1789
+ return {
1790
+ key,
1791
+ value: value || null,
1792
+ };
1430
1793
  }
1431
1794
  this.raise("Invalid property name");
1432
1795
  }
@@ -1435,18 +1798,28 @@ class RegExpValidator {
1435
1798
  if (this.eatLoneUnicodePropertyNameOrValue()) {
1436
1799
  const nameOrValue = this._lastStrValue;
1437
1800
  if (isValidUnicodeProperty(this.ecmaVersion, "General_Category", nameOrValue)) {
1438
- this._lastKeyValue = "General_Category";
1439
- this._lastValValue = nameOrValue;
1440
- return true;
1801
+ return {
1802
+ key: "General_Category",
1803
+ value: nameOrValue || null,
1804
+ };
1441
1805
  }
1442
1806
  if (isValidLoneUnicodeProperty(this.ecmaVersion, nameOrValue)) {
1443
- this._lastKeyValue = nameOrValue;
1444
- this._lastValValue = "";
1445
- return true;
1807
+ return {
1808
+ key: nameOrValue,
1809
+ value: null,
1810
+ };
1811
+ }
1812
+ if (this._unicodeSetsMode &&
1813
+ isValidLoneUnicodePropertyOfString(this.ecmaVersion, nameOrValue)) {
1814
+ return {
1815
+ key: nameOrValue,
1816
+ value: null,
1817
+ strings: true,
1818
+ };
1446
1819
  }
1447
1820
  this.raise("Invalid property name");
1448
1821
  }
1449
- return false;
1822
+ return null;
1450
1823
  }
1451
1824
  eatUnicodePropertyName() {
1452
1825
  this._lastStrValue = "";
@@ -1473,7 +1846,7 @@ class RegExpValidator {
1473
1846
  if (this.eatFixedHexDigits(2)) {
1474
1847
  return true;
1475
1848
  }
1476
- if (this._uFlag || this.strict) {
1849
+ if (this._unicodeMode || this.strict) {
1477
1850
  this.raise("Invalid escape");
1478
1851
  }
1479
1852
  this.rewind(start);
@@ -1548,16 +1921,24 @@ class RegExpValidator {
1548
1921
  const DUMMY_PATTERN = {};
1549
1922
  const DUMMY_FLAGS = {};
1550
1923
  const DUMMY_CAPTURING_GROUP = {};
1924
+ function isClassSetOperand(node) {
1925
+ return (node.type === "Character" ||
1926
+ node.type === "CharacterSet" ||
1927
+ node.type === "CharacterClass" ||
1928
+ node.type === "ExpressionCharacterClass" ||
1929
+ node.type === "ClassStringDisjunction");
1930
+ }
1551
1931
  class RegExpParserState {
1552
1932
  constructor(options) {
1553
1933
  var _a;
1554
1934
  this._node = DUMMY_PATTERN;
1935
+ this._expressionBuffer = null;
1555
1936
  this._flags = DUMMY_FLAGS;
1556
1937
  this._backreferences = [];
1557
1938
  this._capturingGroups = [];
1558
1939
  this.source = "";
1559
1940
  this.strict = Boolean(options === null || options === void 0 ? void 0 : options.strict);
1560
- this.ecmaVersion = (_a = options === null || options === void 0 ? void 0 : options.ecmaVersion) !== null && _a !== void 0 ? _a : 2023;
1941
+ this.ecmaVersion = (_a = options === null || options === void 0 ? void 0 : options.ecmaVersion) !== null && _a !== void 0 ? _a : latestEcmaVersion;
1561
1942
  }
1562
1943
  get pattern() {
1563
1944
  if (this._node.type !== "Pattern") {
@@ -1571,7 +1952,7 @@ class RegExpParserState {
1571
1952
  }
1572
1953
  return this._flags;
1573
1954
  }
1574
- onRegExpFlags(start, end, { global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices, }) {
1955
+ onRegExpFlags(start, end, { global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices, unicodeSets, }) {
1575
1956
  this._flags = {
1576
1957
  type: "Flags",
1577
1958
  parent: null,
@@ -1585,6 +1966,7 @@ class RegExpParserState {
1585
1966
  sticky,
1586
1967
  dotAll,
1587
1968
  hasIndices,
1969
+ unicodeSets,
1588
1970
  };
1589
1971
  }
1590
1972
  onPatternEnter(start) {
@@ -1799,26 +2181,33 @@ class RegExpParserState {
1799
2181
  negate,
1800
2182
  });
1801
2183
  }
1802
- onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
2184
+ onUnicodePropertyCharacterSet(start, end, kind, key, value, negate, strings) {
1803
2185
  const parent = this._node;
1804
- if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
2186
+ if ((parent.type !== "Alternative" &&
2187
+ parent.type !== "CharacterClass") ||
2188
+ (strings && (negate || value))) {
1805
2189
  throw new Error("UnknownError");
1806
2190
  }
1807
- parent.elements.push({
2191
+ const base = {
1808
2192
  type: "CharacterSet",
1809
2193
  parent,
1810
2194
  start,
1811
2195
  end,
1812
2196
  raw: this.source.slice(start, end),
1813
2197
  kind,
2198
+ strings,
1814
2199
  key,
1815
- value,
1816
- negate,
1817
- });
2200
+ };
2201
+ const node = strings
2202
+ ? Object.assign(Object.assign({}, base), { value: null, negate: false, strings: true }) : Object.assign(Object.assign({}, base), { value,
2203
+ negate, strings: false });
2204
+ parent.elements.push(node);
1818
2205
  }
1819
2206
  onCharacter(start, end, value) {
1820
2207
  const parent = this._node;
1821
- if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
2208
+ if (parent.type !== "Alternative" &&
2209
+ parent.type !== "CharacterClass" &&
2210
+ parent.type !== "StringAlternative") {
1822
2211
  throw new Error("UnknownError");
1823
2212
  }
1824
2213
  parent.elements.push({
@@ -1847,31 +2236,66 @@ class RegExpParserState {
1847
2236
  parent.elements.push(node);
1848
2237
  this._backreferences.push(node);
1849
2238
  }
1850
- onCharacterClassEnter(start, negate) {
2239
+ onCharacterClassEnter(start, negate, unicodeSets) {
1851
2240
  const parent = this._node;
1852
- if (parent.type !== "Alternative") {
1853
- throw new Error("UnknownError");
1854
- }
1855
- this._node = {
2241
+ const base = {
1856
2242
  type: "CharacterClass",
1857
2243
  parent,
1858
2244
  start,
1859
2245
  end: start,
1860
2246
  raw: "",
2247
+ unicodeSets,
1861
2248
  negate,
1862
2249
  elements: [],
1863
2250
  };
1864
- parent.elements.push(this._node);
2251
+ if (parent.type === "Alternative") {
2252
+ const node = Object.assign(Object.assign({}, base), { parent });
2253
+ this._node = node;
2254
+ parent.elements.push(node);
2255
+ }
2256
+ else if (parent.type === "CharacterClass" &&
2257
+ parent.unicodeSets &&
2258
+ unicodeSets) {
2259
+ const node = Object.assign(Object.assign({}, base), { parent,
2260
+ unicodeSets });
2261
+ this._node = node;
2262
+ parent.elements.push(node);
2263
+ }
2264
+ else {
2265
+ throw new Error("UnknownError");
2266
+ }
1865
2267
  }
1866
2268
  onCharacterClassLeave(start, end) {
1867
2269
  const node = this._node;
1868
2270
  if (node.type !== "CharacterClass" ||
1869
- node.parent.type !== "Alternative") {
2271
+ (node.parent.type !== "Alternative" &&
2272
+ node.parent.type !== "CharacterClass") ||
2273
+ (this._expressionBuffer && node.elements.length > 0)) {
1870
2274
  throw new Error("UnknownError");
1871
2275
  }
2276
+ const parent = node.parent;
1872
2277
  node.end = end;
1873
2278
  node.raw = this.source.slice(start, end);
1874
- this._node = node.parent;
2279
+ this._node = parent;
2280
+ const expression = this._expressionBuffer;
2281
+ this._expressionBuffer = null;
2282
+ if (!expression) {
2283
+ return;
2284
+ }
2285
+ const newNode = {
2286
+ type: "ExpressionCharacterClass",
2287
+ parent,
2288
+ start: node.start,
2289
+ end: node.end,
2290
+ raw: node.raw,
2291
+ negate: node.negate,
2292
+ expression,
2293
+ };
2294
+ expression.parent = newNode;
2295
+ if (node !== parent.elements.pop()) {
2296
+ throw new Error("UnknownError");
2297
+ }
2298
+ parent.elements.push(newNode);
1875
2299
  }
1876
2300
  onCharacterClassRange(start, end) {
1877
2301
  const parent = this._node;
@@ -1880,15 +2304,19 @@ class RegExpParserState {
1880
2304
  }
1881
2305
  const elements = parent.elements;
1882
2306
  const max = elements.pop();
1883
- const hyphen = elements.pop();
2307
+ if (!max || max.type !== "Character") {
2308
+ throw new Error("UnknownError");
2309
+ }
2310
+ if (!parent.unicodeSets) {
2311
+ const hyphen = elements.pop();
2312
+ if (!hyphen ||
2313
+ hyphen.type !== "Character" ||
2314
+ hyphen.value !== HYPHEN_MINUS) {
2315
+ throw new Error("UnknownError");
2316
+ }
2317
+ }
1884
2318
  const min = elements.pop();
1885
- if (!min ||
1886
- !max ||
1887
- !hyphen ||
1888
- min.type !== "Character" ||
1889
- max.type !== "Character" ||
1890
- hyphen.type !== "Character" ||
1891
- hyphen.value !== HYPHEN_MINUS) {
2319
+ if (!min || min.type !== "Character") {
1892
2320
  throw new Error("UnknownError");
1893
2321
  }
1894
2322
  const node = {
@@ -1904,6 +2332,111 @@ class RegExpParserState {
1904
2332
  max.parent = node;
1905
2333
  elements.push(node);
1906
2334
  }
2335
+ onClassIntersection(start, end) {
2336
+ var _a;
2337
+ const parent = this._node;
2338
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2339
+ throw new Error("UnknownError");
2340
+ }
2341
+ const right = parent.elements.pop();
2342
+ const left = (_a = this._expressionBuffer) !== null && _a !== void 0 ? _a : parent.elements.pop();
2343
+ if (!left ||
2344
+ !right ||
2345
+ left.type === "ClassSubtraction" ||
2346
+ (left.type !== "ClassIntersection" && !isClassSetOperand(left)) ||
2347
+ !isClassSetOperand(right)) {
2348
+ throw new Error("UnknownError");
2349
+ }
2350
+ const node = {
2351
+ type: "ClassIntersection",
2352
+ parent: parent,
2353
+ start,
2354
+ end,
2355
+ raw: this.source.slice(start, end),
2356
+ left,
2357
+ right,
2358
+ };
2359
+ left.parent = node;
2360
+ right.parent = node;
2361
+ this._expressionBuffer = node;
2362
+ }
2363
+ onClassSubtraction(start, end) {
2364
+ var _a;
2365
+ const parent = this._node;
2366
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2367
+ throw new Error("UnknownError");
2368
+ }
2369
+ const right = parent.elements.pop();
2370
+ const left = (_a = this._expressionBuffer) !== null && _a !== void 0 ? _a : parent.elements.pop();
2371
+ if (!left ||
2372
+ !right ||
2373
+ left.type === "ClassIntersection" ||
2374
+ (left.type !== "ClassSubtraction" && !isClassSetOperand(left)) ||
2375
+ !isClassSetOperand(right)) {
2376
+ throw new Error("UnknownError");
2377
+ }
2378
+ const node = {
2379
+ type: "ClassSubtraction",
2380
+ parent: parent,
2381
+ start,
2382
+ end,
2383
+ raw: this.source.slice(start, end),
2384
+ left,
2385
+ right,
2386
+ };
2387
+ left.parent = node;
2388
+ right.parent = node;
2389
+ this._expressionBuffer = node;
2390
+ }
2391
+ onClassStringDisjunctionEnter(start) {
2392
+ const parent = this._node;
2393
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2394
+ throw new Error("UnknownError");
2395
+ }
2396
+ this._node = {
2397
+ type: "ClassStringDisjunction",
2398
+ parent,
2399
+ start,
2400
+ end: start,
2401
+ raw: "",
2402
+ alternatives: [],
2403
+ };
2404
+ parent.elements.push(this._node);
2405
+ }
2406
+ onClassStringDisjunctionLeave(start, end) {
2407
+ const node = this._node;
2408
+ if (node.type !== "ClassStringDisjunction" ||
2409
+ node.parent.type !== "CharacterClass") {
2410
+ throw new Error("UnknownError");
2411
+ }
2412
+ node.end = end;
2413
+ node.raw = this.source.slice(start, end);
2414
+ this._node = node.parent;
2415
+ }
2416
+ onStringAlternativeEnter(start) {
2417
+ const parent = this._node;
2418
+ if (parent.type !== "ClassStringDisjunction") {
2419
+ throw new Error("UnknownError");
2420
+ }
2421
+ this._node = {
2422
+ type: "StringAlternative",
2423
+ parent,
2424
+ start,
2425
+ end: start,
2426
+ raw: "",
2427
+ elements: [],
2428
+ };
2429
+ parent.alternatives.push(this._node);
2430
+ }
2431
+ onStringAlternativeLeave(start, end) {
2432
+ const node = this._node;
2433
+ if (node.type !== "StringAlternative") {
2434
+ throw new Error("UnknownError");
2435
+ }
2436
+ node.end = end;
2437
+ node.raw = this.source.slice(start, end);
2438
+ this._node = node.parent;
2439
+ }
1907
2440
  }
1908
2441
  class RegExpParser {
1909
2442
  constructor(options) {
@@ -1933,9 +2466,9 @@ class RegExpParser {
1933
2466
  this._validator.validateFlags(source, start, end);
1934
2467
  return this._state.flags;
1935
2468
  }
1936
- parsePattern(source, start = 0, end = source.length, uFlag = false) {
2469
+ parsePattern(source, start = 0, end = source.length, uFlagOrFlags = undefined) {
1937
2470
  this._state.source = source;
1938
- this._validator.validatePattern(source, start, end, uFlag);
2471
+ this._validator.validatePattern(source, start, end, uFlagOrFlags);
1939
2472
  return this._state.pattern;
1940
2473
  }
1941
2474
  }
@@ -1970,6 +2503,18 @@ class RegExpVisitor {
1970
2503
  case "CharacterSet":
1971
2504
  this.visitCharacterSet(node);
1972
2505
  break;
2506
+ case "ClassIntersection":
2507
+ this.visitClassIntersection(node);
2508
+ break;
2509
+ case "ClassStringDisjunction":
2510
+ this.visitClassStringDisjunction(node);
2511
+ break;
2512
+ case "ClassSubtraction":
2513
+ this.visitClassSubtraction(node);
2514
+ break;
2515
+ case "ExpressionCharacterClass":
2516
+ this.visitExpressionCharacterClass(node);
2517
+ break;
1973
2518
  case "Flags":
1974
2519
  this.visitFlags(node);
1975
2520
  break;
@@ -1985,6 +2530,9 @@ class RegExpVisitor {
1985
2530
  case "RegExpLiteral":
1986
2531
  this.visitRegExpLiteral(node);
1987
2532
  break;
2533
+ case "StringAlternative":
2534
+ this.visitStringAlternative(node);
2535
+ break;
1988
2536
  default:
1989
2537
  throw new Error(`Unknown type: ${node.type}`);
1990
2538
  }
@@ -2061,6 +2609,44 @@ class RegExpVisitor {
2061
2609
  this._handlers.onCharacterSetLeave(node);
2062
2610
  }
2063
2611
  }
2612
+ visitClassIntersection(node) {
2613
+ if (this._handlers.onClassIntersectionEnter) {
2614
+ this._handlers.onClassIntersectionEnter(node);
2615
+ }
2616
+ this.visit(node.left);
2617
+ this.visit(node.right);
2618
+ if (this._handlers.onClassIntersectionLeave) {
2619
+ this._handlers.onClassIntersectionLeave(node);
2620
+ }
2621
+ }
2622
+ visitClassStringDisjunction(node) {
2623
+ if (this._handlers.onClassStringDisjunctionEnter) {
2624
+ this._handlers.onClassStringDisjunctionEnter(node);
2625
+ }
2626
+ node.alternatives.forEach(this.visit, this);
2627
+ if (this._handlers.onClassStringDisjunctionLeave) {
2628
+ this._handlers.onClassStringDisjunctionLeave(node);
2629
+ }
2630
+ }
2631
+ visitClassSubtraction(node) {
2632
+ if (this._handlers.onClassSubtractionEnter) {
2633
+ this._handlers.onClassSubtractionEnter(node);
2634
+ }
2635
+ this.visit(node.left);
2636
+ this.visit(node.right);
2637
+ if (this._handlers.onClassSubtractionLeave) {
2638
+ this._handlers.onClassSubtractionLeave(node);
2639
+ }
2640
+ }
2641
+ visitExpressionCharacterClass(node) {
2642
+ if (this._handlers.onExpressionCharacterClassEnter) {
2643
+ this._handlers.onExpressionCharacterClassEnter(node);
2644
+ }
2645
+ this.visit(node.expression);
2646
+ if (this._handlers.onExpressionCharacterClassLeave) {
2647
+ this._handlers.onExpressionCharacterClassLeave(node);
2648
+ }
2649
+ }
2064
2650
  visitFlags(node) {
2065
2651
  if (this._handlers.onFlagsEnter) {
2066
2652
  this._handlers.onFlagsEnter(node);
@@ -2106,6 +2692,15 @@ class RegExpVisitor {
2106
2692
  this._handlers.onRegExpLiteralLeave(node);
2107
2693
  }
2108
2694
  }
2695
+ visitStringAlternative(node) {
2696
+ if (this._handlers.onStringAlternativeEnter) {
2697
+ this._handlers.onStringAlternativeEnter(node);
2698
+ }
2699
+ node.elements.forEach(this.visit, this);
2700
+ if (this._handlers.onStringAlternativeLeave) {
2701
+ this._handlers.onStringAlternativeLeave(node);
2702
+ }
2703
+ }
2109
2704
  }
2110
2705
 
2111
2706
  function parseRegExpLiteral(source, options) {