@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.js CHANGED
@@ -6,6 +6,8 @@ var ast = /*#__PURE__*/Object.freeze({
6
6
  __proto__: null
7
7
  });
8
8
 
9
+ const latestEcmaVersion = 2024;
10
+
9
11
  let largeIdStartRanges = undefined;
10
12
  let largeIdContinueRanges = undefined;
11
13
  function isIdStart(cp) {
@@ -72,13 +74,14 @@ function restoreRanges(data) {
72
74
  }
73
75
 
74
76
  class DataSet {
75
- constructor(raw2018, raw2019, raw2020, raw2021, raw2022, raw2023) {
77
+ constructor(raw2018, raw2019, raw2020, raw2021, raw2022, raw2023, raw2024) {
76
78
  this._raw2018 = raw2018;
77
79
  this._raw2019 = raw2019;
78
80
  this._raw2020 = raw2020;
79
81
  this._raw2021 = raw2021;
80
82
  this._raw2022 = raw2022;
81
83
  this._raw2023 = raw2023;
84
+ this._raw2024 = raw2024;
82
85
  }
83
86
  get es2018() {
84
87
  var _a;
@@ -104,12 +107,16 @@ class DataSet {
104
107
  var _a;
105
108
  return ((_a = this._set2023) !== null && _a !== void 0 ? _a : (this._set2023 = new Set(this._raw2023.split(" "))));
106
109
  }
110
+ get es2024() {
111
+ var _a;
112
+ return ((_a = this._set2024) !== null && _a !== void 0 ? _a : (this._set2024 = new Set(this._raw2024.split(" "))));
113
+ }
107
114
  }
108
115
  const gcNameSet = new Set(["General_Category", "gc"]);
109
116
  const scNameSet = new Set(["Script", "Script_Extensions", "sc", "scx"]);
110
- 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", "", "", "", "", "");
111
- 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");
112
- 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", "", "");
117
+ 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", "", "", "", "", "", "");
118
+ 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", "");
119
+ 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
120
  function isValidUnicodeProperty(version, name, value) {
114
121
  if (gcNameSet.has(name)) {
115
122
  return version >= 2018 && gcValueSets.es2018.has(value);
@@ -137,7 +144,10 @@ const LINE_TABULATION = 0x0b;
137
144
  const FORM_FEED = 0x0c;
138
145
  const CARRIAGE_RETURN = 0x0d;
139
146
  const EXCLAMATION_MARK = 0x21;
147
+ const NUMBER_SIGN = 0x23;
140
148
  const DOLLAR_SIGN = 0x24;
149
+ const PERCENT_SIGN = 0x25;
150
+ const AMPERSAND = 0x26;
141
151
  const LEFT_PARENTHESIS = 0x28;
142
152
  const RIGHT_PARENTHESIS = 0x29;
143
153
  const ASTERISK = 0x2a;
@@ -151,10 +161,12 @@ const DIGIT_ONE = 0x31;
151
161
  const DIGIT_SEVEN = 0x37;
152
162
  const DIGIT_NINE = 0x39;
153
163
  const COLON = 0x3a;
164
+ const SEMICOLON = 0x3b;
154
165
  const LESS_THAN_SIGN = 0x3c;
155
166
  const EQUALS_SIGN = 0x3d;
156
167
  const GREATER_THAN_SIGN = 0x3e;
157
168
  const QUESTION_MARK = 0x3f;
169
+ const COMMERCIAL_AT = 0x40;
158
170
  const LATIN_CAPITAL_LETTER_A = 0x41;
159
171
  const LATIN_CAPITAL_LETTER_B = 0x42;
160
172
  const LATIN_CAPITAL_LETTER_D = 0x44;
@@ -175,6 +187,7 @@ const LATIN_SMALL_LETTER_K = 0x6b;
175
187
  const LATIN_SMALL_LETTER_M = 0x6d;
176
188
  const LATIN_SMALL_LETTER_N = 0x6e;
177
189
  const LATIN_SMALL_LETTER_P = 0x70;
190
+ const LATIN_SMALL_LETTER_Q = 0x71;
178
191
  const LATIN_SMALL_LETTER_R = 0x72;
179
192
  const LATIN_SMALL_LETTER_S = 0x73;
180
193
  const LATIN_SMALL_LETTER_T = 0x74;
@@ -188,9 +201,11 @@ const LEFT_SQUARE_BRACKET = 0x5b;
188
201
  const REVERSE_SOLIDUS = 0x5c;
189
202
  const RIGHT_SQUARE_BRACKET = 0x5d;
190
203
  const CIRCUMFLEX_ACCENT = 0x5e;
204
+ const GRAVE_ACCENT = 0x60;
191
205
  const LEFT_CURLY_BRACKET = 0x7b;
192
206
  const VERTICAL_LINE = 0x7c;
193
207
  const RIGHT_CURLY_BRACKET = 0x7d;
208
+ const TILDE = 0x7e;
194
209
  const ZERO_WIDTH_NON_JOINER = 0x200c;
195
210
  const ZERO_WIDTH_JOINER = 0x200d;
196
211
  const LINE_SEPARATOR = 0x2028;
@@ -357,29 +372,102 @@ class RegExpSyntaxError extends SyntaxError {
357
372
  }
358
373
  }
359
374
 
375
+ const binPropertyOfStringSets = new Set([
376
+ "Basic_Emoji",
377
+ "Emoji_Keycap_Sequence",
378
+ "RGI_Emoji_Modifier_Sequence",
379
+ "RGI_Emoji_Flag_Sequence",
380
+ "RGI_Emoji_Tag_Sequence",
381
+ "RGI_Emoji_ZWJ_Sequence",
382
+ "RGI_Emoji",
383
+ ]);
384
+ function isValidLoneUnicodePropertyOfString(version, value) {
385
+ return version >= 2024 && binPropertyOfStringSets.has(value);
386
+ }
387
+
388
+ const SYNTAX_CHARACTER = new Set([
389
+ CIRCUMFLEX_ACCENT,
390
+ DOLLAR_SIGN,
391
+ REVERSE_SOLIDUS,
392
+ FULL_STOP,
393
+ ASTERISK,
394
+ PLUS_SIGN,
395
+ QUESTION_MARK,
396
+ LEFT_PARENTHESIS,
397
+ RIGHT_PARENTHESIS,
398
+ LEFT_SQUARE_BRACKET,
399
+ RIGHT_SQUARE_BRACKET,
400
+ LEFT_CURLY_BRACKET,
401
+ RIGHT_CURLY_BRACKET,
402
+ VERTICAL_LINE,
403
+ ]);
404
+ const CLASS_SET_RESERVED_DOUBLE_PUNCTUATOR_CHARACTER = new Set([
405
+ AMPERSAND,
406
+ EXCLAMATION_MARK,
407
+ NUMBER_SIGN,
408
+ DOLLAR_SIGN,
409
+ PERCENT_SIGN,
410
+ ASTERISK,
411
+ PLUS_SIGN,
412
+ COMMA,
413
+ FULL_STOP,
414
+ COLON,
415
+ SEMICOLON,
416
+ LESS_THAN_SIGN,
417
+ EQUALS_SIGN,
418
+ GREATER_THAN_SIGN,
419
+ QUESTION_MARK,
420
+ COMMERCIAL_AT,
421
+ CIRCUMFLEX_ACCENT,
422
+ GRAVE_ACCENT,
423
+ TILDE,
424
+ ]);
425
+ const CLASS_SET_SYNTAX_CHARACTER = new Set([
426
+ LEFT_PARENTHESIS,
427
+ RIGHT_PARENTHESIS,
428
+ LEFT_SQUARE_BRACKET,
429
+ RIGHT_SQUARE_BRACKET,
430
+ LEFT_CURLY_BRACKET,
431
+ RIGHT_CURLY_BRACKET,
432
+ SOLIDUS,
433
+ HYPHEN_MINUS,
434
+ REVERSE_SOLIDUS,
435
+ VERTICAL_LINE,
436
+ ]);
437
+ const CLASS_SET_RESERVED_PUNCTUATOR = new Set([
438
+ AMPERSAND,
439
+ HYPHEN_MINUS,
440
+ EXCLAMATION_MARK,
441
+ NUMBER_SIGN,
442
+ PERCENT_SIGN,
443
+ COMMA,
444
+ COLON,
445
+ SEMICOLON,
446
+ LESS_THAN_SIGN,
447
+ EQUALS_SIGN,
448
+ GREATER_THAN_SIGN,
449
+ COMMERCIAL_AT,
450
+ GRAVE_ACCENT,
451
+ TILDE,
452
+ ]);
360
453
  function isSyntaxCharacter(cp) {
361
- return (cp === CIRCUMFLEX_ACCENT ||
362
- cp === DOLLAR_SIGN ||
363
- cp === REVERSE_SOLIDUS ||
364
- cp === FULL_STOP ||
365
- cp === ASTERISK ||
366
- cp === PLUS_SIGN ||
367
- cp === QUESTION_MARK ||
368
- cp === LEFT_PARENTHESIS ||
369
- cp === RIGHT_PARENTHESIS ||
370
- cp === LEFT_SQUARE_BRACKET ||
371
- cp === RIGHT_SQUARE_BRACKET ||
372
- cp === LEFT_CURLY_BRACKET ||
373
- cp === RIGHT_CURLY_BRACKET ||
374
- cp === VERTICAL_LINE);
454
+ return SYNTAX_CHARACTER.has(cp);
455
+ }
456
+ function isClassSetReservedDoublePunctuatorCharacter(cp) {
457
+ return CLASS_SET_RESERVED_DOUBLE_PUNCTUATOR_CHARACTER.has(cp);
458
+ }
459
+ function isClassSetSyntaxCharacter(cp) {
460
+ return CLASS_SET_SYNTAX_CHARACTER.has(cp);
375
461
  }
376
- function isRegExpIdentifierStart(cp) {
462
+ function isClassSetReservedPunctuator(cp) {
463
+ return CLASS_SET_RESERVED_PUNCTUATOR.has(cp);
464
+ }
465
+ function isIdentifierStartChar(cp) {
377
466
  return isIdStart(cp) || cp === DOLLAR_SIGN || cp === LOW_LINE;
378
467
  }
379
- function isRegExpIdentifierPart(cp) {
468
+ function isIdentifierPartChar(cp) {
380
469
  return (isIdContinue(cp) ||
381
470
  cp === DOLLAR_SIGN ||
382
- cp === LOW_LINE ||
383
471
  cp === ZERO_WIDTH_NON_JOINER ||
384
472
  cp === ZERO_WIDTH_JOINER);
385
473
  }
@@ -392,14 +480,15 @@ function isUnicodePropertyValueCharacter(cp) {
392
480
  class RegExpValidator {
393
481
  constructor(options) {
394
482
  this._reader = new Reader();
395
- this._uFlag = false;
483
+ this._unicodeMode = false;
484
+ this._unicodeSetsMode = false;
396
485
  this._nFlag = false;
397
486
  this._lastIntValue = 0;
398
- this._lastMinValue = 0;
399
- this._lastMaxValue = 0;
487
+ this._lastRange = {
488
+ min: 0,
489
+ max: Number.POSITIVE_INFINITY,
490
+ };
400
491
  this._lastStrValue = "";
401
- this._lastKeyValue = "";
402
- this._lastValValue = "";
403
492
  this._lastAssertionIsQuantifiable = false;
404
493
  this._numCapturingParens = 0;
405
494
  this._groupNames = new Set();
@@ -407,14 +496,18 @@ class RegExpValidator {
407
496
  this._options = options !== null && options !== void 0 ? options : {};
408
497
  }
409
498
  validateLiteral(source, start = 0, end = source.length) {
410
- this._uFlag = this._nFlag = false;
499
+ this._unicodeSetsMode = this._unicodeMode = this._nFlag = false;
411
500
  this.reset(source, start, end);
412
501
  this.onLiteralEnter(start);
413
502
  if (this.eat(SOLIDUS) && this.eatRegExpBody() && this.eat(SOLIDUS)) {
414
503
  const flagStart = this.index;
415
- const uFlag = source.includes("u", flagStart);
504
+ const unicode = source.includes("u", flagStart);
505
+ const unicodeSets = source.includes("v", flagStart);
416
506
  this.validateFlags(source, flagStart, end);
417
- this.validatePattern(source, start + 1, flagStart - 1, uFlag);
507
+ this.validatePattern(source, start + 1, flagStart - 1, {
508
+ unicode,
509
+ unicodeSets,
510
+ });
418
511
  }
419
512
  else if (start >= end) {
420
513
  this.raise("Empty");
@@ -434,6 +527,7 @@ class RegExpValidator {
434
527
  let unicode = false;
435
528
  let dotAll = false;
436
529
  let hasIndices = false;
530
+ let unicodeSets = false;
437
531
  for (let i = start; i < end; ++i) {
438
532
  const flag = source.charCodeAt(i);
439
533
  if (existingFlags.has(flag)) {
@@ -465,6 +559,10 @@ class RegExpValidator {
465
559
  this.ecmaVersion >= 2022) {
466
560
  hasIndices = true;
467
561
  }
562
+ else if (flag === LATIN_SMALL_LETTER_V &&
563
+ this.ecmaVersion >= 2024) {
564
+ unicodeSets = true;
565
+ }
468
566
  else {
469
567
  this.raise(`Invalid flag '${source[i]}'`);
470
568
  }
@@ -477,13 +575,14 @@ class RegExpValidator {
477
575
  sticky,
478
576
  dotAll,
479
577
  hasIndices,
578
+ unicodeSets,
480
579
  });
481
580
  }
482
- validatePattern(source, start = 0, end = source.length, uFlag = false) {
483
- this._uFlag = uFlag && this.ecmaVersion >= 2015;
484
- this._nFlag =
485
- (uFlag && this.ecmaVersion >= 2018) ||
486
- Boolean(this._options.strict && this.ecmaVersion >= 2023);
581
+ validatePattern(source, start = 0, end = source.length, uFlagOrFlags = undefined) {
582
+ const mode = this._parseFlagsOptionToMode(uFlagOrFlags);
583
+ this._unicodeMode = mode.unicodeMode;
584
+ this._nFlag = mode.nFlag;
585
+ this._unicodeSetsMode = mode.unicodeSetsMode;
487
586
  this.reset(source, start, end);
488
587
  this.consumePattern();
489
588
  if (!this._nFlag &&
@@ -494,12 +593,36 @@ class RegExpValidator {
494
593
  this.consumePattern();
495
594
  }
496
595
  }
596
+ _parseFlagsOptionToMode(uFlagOrFlags = undefined) {
597
+ let unicode = false;
598
+ let unicodeSets = false;
599
+ if (uFlagOrFlags && this.ecmaVersion >= 2015) {
600
+ if (typeof uFlagOrFlags === "object") {
601
+ unicode = Boolean(uFlagOrFlags.unicode);
602
+ if (this.ecmaVersion >= 2024) {
603
+ unicodeSets = Boolean(uFlagOrFlags.unicodeSets);
604
+ }
605
+ }
606
+ else {
607
+ unicode = uFlagOrFlags;
608
+ }
609
+ }
610
+ if (unicode && unicodeSets) {
611
+ this.raise("Invalid regular expression flags");
612
+ }
613
+ const unicodeMode = unicode || unicodeSets;
614
+ const nFlag = (unicode && this.ecmaVersion >= 2018) ||
615
+ unicodeSets ||
616
+ Boolean(this._options.strict && this.ecmaVersion >= 2023);
617
+ const unicodeSetsMode = unicodeSets;
618
+ return { unicodeMode, nFlag, unicodeSetsMode };
619
+ }
497
620
  get strict() {
498
- return Boolean(this._options.strict) || this._uFlag;
621
+ return Boolean(this._options.strict) || this._unicodeMode;
499
622
  }
500
623
  get ecmaVersion() {
501
624
  var _a;
502
- return (_a = this._options.ecmaVersion) !== null && _a !== void 0 ? _a : 2023;
625
+ return (_a = this._options.ecmaVersion) !== null && _a !== void 0 ? _a : latestEcmaVersion;
503
626
  }
504
627
  onLiteralEnter(start) {
505
628
  if (this._options.onLiteralEnter) {
@@ -604,9 +727,9 @@ class RegExpValidator {
604
727
  this._options.onEscapeCharacterSet(start, end, kind, negate);
605
728
  }
606
729
  }
607
- onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
730
+ onUnicodePropertyCharacterSet(start, end, kind, key, value, negate, strings) {
608
731
  if (this._options.onUnicodePropertyCharacterSet) {
609
- this._options.onUnicodePropertyCharacterSet(start, end, kind, key, value, negate);
732
+ this._options.onUnicodePropertyCharacterSet(start, end, kind, key, value, negate, strings);
610
733
  }
611
734
  }
612
735
  onCharacter(start, end, value) {
@@ -619,9 +742,9 @@ class RegExpValidator {
619
742
  this._options.onBackreference(start, end, ref);
620
743
  }
621
744
  }
622
- onCharacterClassEnter(start, negate) {
745
+ onCharacterClassEnter(start, negate, unicodeSets) {
623
746
  if (this._options.onCharacterClassEnter) {
624
- this._options.onCharacterClassEnter(start, negate);
747
+ this._options.onCharacterClassEnter(start, negate, unicodeSets);
625
748
  }
626
749
  }
627
750
  onCharacterClassLeave(start, end, negate) {
@@ -634,6 +757,36 @@ class RegExpValidator {
634
757
  this._options.onCharacterClassRange(start, end, min, max);
635
758
  }
636
759
  }
760
+ onClassIntersection(start, end) {
761
+ if (this._options.onClassIntersection) {
762
+ this._options.onClassIntersection(start, end);
763
+ }
764
+ }
765
+ onClassSubtraction(start, end) {
766
+ if (this._options.onClassSubtraction) {
767
+ this._options.onClassSubtraction(start, end);
768
+ }
769
+ }
770
+ onClassStringDisjunctionEnter(start) {
771
+ if (this._options.onClassStringDisjunctionEnter) {
772
+ this._options.onClassStringDisjunctionEnter(start);
773
+ }
774
+ }
775
+ onClassStringDisjunctionLeave(start, end) {
776
+ if (this._options.onClassStringDisjunctionLeave) {
777
+ this._options.onClassStringDisjunctionLeave(start, end);
778
+ }
779
+ }
780
+ onStringAlternativeEnter(start, index) {
781
+ if (this._options.onStringAlternativeEnter) {
782
+ this._options.onStringAlternativeEnter(start, index);
783
+ }
784
+ }
785
+ onStringAlternativeLeave(start, end, index) {
786
+ if (this._options.onStringAlternativeLeave) {
787
+ this._options.onStringAlternativeLeave(start, end, index);
788
+ }
789
+ }
637
790
  get source() {
638
791
  return this._reader.source;
639
792
  }
@@ -653,7 +806,7 @@ class RegExpValidator {
653
806
  return this._reader.nextCodePoint3;
654
807
  }
655
808
  reset(source, start, end) {
656
- this._reader.reset(source, start, end, this._uFlag);
809
+ this._reader.reset(source, start, end, this._unicodeMode);
657
810
  }
658
811
  rewind(index) {
659
812
  this._reader.rewind(index);
@@ -671,7 +824,7 @@ class RegExpValidator {
671
824
  return this._reader.eat3(cp1, cp2, cp3);
672
825
  }
673
826
  raise(message) {
674
- throw new RegExpSyntaxError(this.source, this._uFlag, this.index, message);
827
+ throw new RegExpSyntaxError(this.source, this._unicodeMode, this.index, message);
675
828
  }
676
829
  eatRegExpBody() {
677
830
  const start = this.index;
@@ -786,7 +939,7 @@ class RegExpValidator {
786
939
  this.onAlternativeLeave(start, this.index, i);
787
940
  }
788
941
  consumeTerm() {
789
- if (this._uFlag || this.strict) {
942
+ if (this._unicodeMode || this.strict) {
790
943
  return (this.consumeAssertion() ||
791
944
  (this.consumeAtom() && this.consumeOptionalQuantifier()));
792
945
  }
@@ -855,8 +1008,7 @@ class RegExpValidator {
855
1008
  max = 1;
856
1009
  }
857
1010
  else if (this.eatBracedQuantifier(noConsume)) {
858
- min = this._lastMinValue;
859
- max = this._lastMaxValue;
1011
+ ({ min, max } = this._lastRange);
860
1012
  }
861
1013
  else {
862
1014
  return false;
@@ -870,23 +1022,23 @@ class RegExpValidator {
870
1022
  eatBracedQuantifier(noError) {
871
1023
  const start = this.index;
872
1024
  if (this.eat(LEFT_CURLY_BRACKET)) {
873
- this._lastMinValue = 0;
874
- this._lastMaxValue = Number.POSITIVE_INFINITY;
875
1025
  if (this.eatDecimalDigits()) {
876
- this._lastMinValue = this._lastMaxValue = this._lastIntValue;
1026
+ const min = this._lastIntValue;
1027
+ let max = min;
877
1028
  if (this.eat(COMMA)) {
878
- this._lastMaxValue = this.eatDecimalDigits()
1029
+ max = this.eatDecimalDigits()
879
1030
  ? this._lastIntValue
880
1031
  : Number.POSITIVE_INFINITY;
881
1032
  }
882
1033
  if (this.eat(RIGHT_CURLY_BRACKET)) {
883
- if (!noError && this._lastMaxValue < this._lastMinValue) {
1034
+ if (!noError && max < min) {
884
1035
  this.raise("numbers out of order in {} quantifier");
885
1036
  }
1037
+ this._lastRange = { min, max };
886
1038
  return true;
887
1039
  }
888
1040
  }
889
- if (!noError && (this._uFlag || this.strict)) {
1041
+ if (!noError && (this._unicodeMode || this.strict)) {
890
1042
  this.raise("Incomplete quantifier");
891
1043
  }
892
1044
  this.rewind(start);
@@ -897,7 +1049,7 @@ class RegExpValidator {
897
1049
  return (this.consumePatternCharacter() ||
898
1050
  this.consumeDot() ||
899
1051
  this.consumeReverseSolidusAtomEscape() ||
900
- this.consumeCharacterClass() ||
1052
+ Boolean(this.consumeCharacterClass()) ||
901
1053
  this.consumeUncapturingGroup() ||
902
1054
  this.consumeCapturingGroup());
903
1055
  }
@@ -957,7 +1109,7 @@ class RegExpValidator {
957
1109
  return (this.consumeDot() ||
958
1110
  this.consumeReverseSolidusAtomEscape() ||
959
1111
  this.consumeReverseSolidusFollowedByC() ||
960
- this.consumeCharacterClass() ||
1112
+ Boolean(this.consumeCharacterClass()) ||
961
1113
  this.consumeUncapturingGroup() ||
962
1114
  this.consumeCapturingGroup() ||
963
1115
  this.consumeInvalidBracedQuantifier() ||
@@ -1031,7 +1183,7 @@ class RegExpValidator {
1031
1183
  (this._nFlag && this.consumeKGroupName())) {
1032
1184
  return true;
1033
1185
  }
1034
- if (this.strict || this._uFlag) {
1186
+ if (this.strict || this._unicodeMode) {
1035
1187
  this.raise("Invalid escape");
1036
1188
  }
1037
1189
  return false;
@@ -1044,7 +1196,7 @@ class RegExpValidator {
1044
1196
  this.onBackreference(start - 1, this.index, n);
1045
1197
  return true;
1046
1198
  }
1047
- if (this.strict || this._uFlag) {
1199
+ if (this.strict || this._unicodeMode) {
1048
1200
  this.raise("Invalid escape");
1049
1201
  }
1050
1202
  this.rewind(start);
@@ -1052,52 +1204,57 @@ class RegExpValidator {
1052
1204
  return false;
1053
1205
  }
1054
1206
  consumeCharacterClassEscape() {
1207
+ var _a;
1055
1208
  const start = this.index;
1056
1209
  if (this.eat(LATIN_SMALL_LETTER_D)) {
1057
1210
  this._lastIntValue = -1;
1058
1211
  this.onEscapeCharacterSet(start - 1, this.index, "digit", false);
1059
- return true;
1212
+ return {};
1060
1213
  }
1061
1214
  if (this.eat(LATIN_CAPITAL_LETTER_D)) {
1062
1215
  this._lastIntValue = -1;
1063
1216
  this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
1064
- return true;
1217
+ return {};
1065
1218
  }
1066
1219
  if (this.eat(LATIN_SMALL_LETTER_S)) {
1067
1220
  this._lastIntValue = -1;
1068
1221
  this.onEscapeCharacterSet(start - 1, this.index, "space", false);
1069
- return true;
1222
+ return {};
1070
1223
  }
1071
1224
  if (this.eat(LATIN_CAPITAL_LETTER_S)) {
1072
1225
  this._lastIntValue = -1;
1073
1226
  this.onEscapeCharacterSet(start - 1, this.index, "space", true);
1074
- return true;
1227
+ return {};
1075
1228
  }
1076
1229
  if (this.eat(LATIN_SMALL_LETTER_W)) {
1077
1230
  this._lastIntValue = -1;
1078
1231
  this.onEscapeCharacterSet(start - 1, this.index, "word", false);
1079
- return true;
1232
+ return {};
1080
1233
  }
1081
1234
  if (this.eat(LATIN_CAPITAL_LETTER_W)) {
1082
1235
  this._lastIntValue = -1;
1083
1236
  this.onEscapeCharacterSet(start - 1, this.index, "word", true);
1084
- return true;
1237
+ return {};
1085
1238
  }
1086
1239
  let negate = false;
1087
- if (this._uFlag &&
1240
+ if (this._unicodeMode &&
1088
1241
  this.ecmaVersion >= 2018 &&
1089
1242
  (this.eat(LATIN_SMALL_LETTER_P) ||
1090
1243
  (negate = this.eat(LATIN_CAPITAL_LETTER_P)))) {
1091
1244
  this._lastIntValue = -1;
1245
+ let result = null;
1092
1246
  if (this.eat(LEFT_CURLY_BRACKET) &&
1093
- this.eatUnicodePropertyValueExpression() &&
1247
+ (result = this.eatUnicodePropertyValueExpression()) &&
1094
1248
  this.eat(RIGHT_CURLY_BRACKET)) {
1095
- this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", this._lastKeyValue, this._lastValValue || null, negate);
1096
- return true;
1249
+ if (negate && result.strings) {
1250
+ this.raise("Invalid property name");
1251
+ }
1252
+ this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", result.key, result.value, negate, (_a = result.strings) !== null && _a !== void 0 ? _a : false);
1253
+ return { mayContainStrings: result.strings };
1097
1254
  }
1098
1255
  this.raise("Invalid property name");
1099
1256
  }
1100
- return false;
1257
+ return null;
1101
1258
  }
1102
1259
  consumeCharacterEscape() {
1103
1260
  const start = this.index;
@@ -1107,7 +1264,7 @@ class RegExpValidator {
1107
1264
  this.eatHexEscapeSequence() ||
1108
1265
  this.eatRegExpUnicodeEscapeSequence() ||
1109
1266
  (!this.strict &&
1110
- !this._uFlag &&
1267
+ !this._unicodeMode &&
1111
1268
  this.eatLegacyOctalEscapeSequence()) ||
1112
1269
  this.eatIdentityEscape()) {
1113
1270
  this.onCharacter(start - 1, this.index, this._lastIntValue);
@@ -1132,18 +1289,31 @@ class RegExpValidator {
1132
1289
  const start = this.index;
1133
1290
  if (this.eat(LEFT_SQUARE_BRACKET)) {
1134
1291
  const negate = this.eat(CIRCUMFLEX_ACCENT);
1135
- this.onCharacterClassEnter(start, negate);
1136
- this.consumeClassRanges();
1292
+ this.onCharacterClassEnter(start, negate, this._unicodeSetsMode);
1293
+ const result = this.consumeClassContents();
1137
1294
  if (!this.eat(RIGHT_SQUARE_BRACKET)) {
1138
- this.raise("Unterminated character class");
1295
+ if (this.currentCodePoint === -1) {
1296
+ this.raise("Unterminated character class");
1297
+ }
1298
+ this.raise("Invalid character in character class");
1299
+ }
1300
+ if (negate && result.mayContainStrings) {
1301
+ this.raise("Negated character class may contain strings");
1139
1302
  }
1140
1303
  this.onCharacterClassLeave(start, this.index, negate);
1141
- return true;
1304
+ return result;
1142
1305
  }
1143
- return false;
1306
+ return null;
1144
1307
  }
1145
- consumeClassRanges() {
1146
- const strict = this.strict || this._uFlag;
1308
+ consumeClassContents() {
1309
+ if (this._unicodeSetsMode) {
1310
+ if (this.currentCodePoint === RIGHT_SQUARE_BRACKET) {
1311
+ return {};
1312
+ }
1313
+ const result = this.consumeClassSetExpression();
1314
+ return result;
1315
+ }
1316
+ const strict = this.strict || this._unicodeMode;
1147
1317
  for (;;) {
1148
1318
  const rangeStart = this.index;
1149
1319
  if (!this.consumeClassAtom()) {
@@ -1169,6 +1339,7 @@ class RegExpValidator {
1169
1339
  }
1170
1340
  this.onCharacterClassRange(rangeStart, this.index, min, max);
1171
1341
  }
1342
+ return {};
1172
1343
  }
1173
1344
  consumeClassAtom() {
1174
1345
  const start = this.index;
@@ -1191,7 +1362,7 @@ class RegExpValidator {
1191
1362
  this.onCharacter(start, this.index, this._lastIntValue);
1192
1363
  return true;
1193
1364
  }
1194
- if (this.strict || this._uFlag) {
1365
+ if (this.strict || this._unicodeMode) {
1195
1366
  this.raise("Invalid escape");
1196
1367
  }
1197
1368
  this.rewind(start);
@@ -1205,14 +1376,14 @@ class RegExpValidator {
1205
1376
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1206
1377
  return true;
1207
1378
  }
1208
- if (this._uFlag && this.eat(HYPHEN_MINUS)) {
1379
+ if (this._unicodeMode && this.eat(HYPHEN_MINUS)) {
1209
1380
  this._lastIntValue = HYPHEN_MINUS;
1210
1381
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1211
1382
  return true;
1212
1383
  }
1213
1384
  let cp = 0;
1214
1385
  if (!this.strict &&
1215
- !this._uFlag &&
1386
+ !this._unicodeMode &&
1216
1387
  this.currentCodePoint === LATIN_SMALL_LETTER_C &&
1217
1388
  (isDecimalDigit((cp = this.nextCodePoint)) || cp === LOW_LINE)) {
1218
1389
  this.advance();
@@ -1221,7 +1392,196 @@ class RegExpValidator {
1221
1392
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1222
1393
  return true;
1223
1394
  }
1224
- return (this.consumeCharacterClassEscape() || this.consumeCharacterEscape());
1395
+ return (Boolean(this.consumeCharacterClassEscape()) ||
1396
+ this.consumeCharacterEscape());
1397
+ }
1398
+ consumeClassSetExpression() {
1399
+ const start = this.index;
1400
+ let mayContainStrings = false;
1401
+ let result = null;
1402
+ if (this.consumeClassSetCharacter()) {
1403
+ if (this.consumeClassSetRangeFromOperator(start)) {
1404
+ this.consumeClassUnionRight({});
1405
+ return {};
1406
+ }
1407
+ mayContainStrings = false;
1408
+ }
1409
+ else if ((result = this.consumeClassSetOperand())) {
1410
+ mayContainStrings = result.mayContainStrings;
1411
+ }
1412
+ else {
1413
+ const cp = this.currentCodePoint;
1414
+ if (cp === REVERSE_SOLIDUS) {
1415
+ this.advance();
1416
+ this.raise("Invalid escape");
1417
+ }
1418
+ if (cp === this.nextCodePoint &&
1419
+ isClassSetReservedDoublePunctuatorCharacter(cp)) {
1420
+ this.raise("Invalid set operation in character class");
1421
+ }
1422
+ this.raise("Invalid character in character class");
1423
+ }
1424
+ if (this.eat2(AMPERSAND, AMPERSAND)) {
1425
+ while (this.currentCodePoint !== AMPERSAND &&
1426
+ (result = this.consumeClassSetOperand())) {
1427
+ this.onClassIntersection(start, this.index);
1428
+ if (!result.mayContainStrings) {
1429
+ mayContainStrings = false;
1430
+ }
1431
+ if (this.eat2(AMPERSAND, AMPERSAND)) {
1432
+ continue;
1433
+ }
1434
+ return { mayContainStrings };
1435
+ }
1436
+ this.raise("Invalid character in character class");
1437
+ }
1438
+ if (this.eat2(HYPHEN_MINUS, HYPHEN_MINUS)) {
1439
+ while (this.consumeClassSetOperand()) {
1440
+ this.onClassSubtraction(start, this.index);
1441
+ if (this.eat2(HYPHEN_MINUS, HYPHEN_MINUS)) {
1442
+ continue;
1443
+ }
1444
+ return { mayContainStrings };
1445
+ }
1446
+ this.raise("Invalid character in character class");
1447
+ }
1448
+ return this.consumeClassUnionRight({ mayContainStrings });
1449
+ }
1450
+ consumeClassUnionRight(leftResult) {
1451
+ let mayContainStrings = leftResult.mayContainStrings;
1452
+ for (;;) {
1453
+ const start = this.index;
1454
+ if (this.consumeClassSetCharacter()) {
1455
+ this.consumeClassSetRangeFromOperator(start);
1456
+ continue;
1457
+ }
1458
+ const result = this.consumeClassSetOperand();
1459
+ if (result) {
1460
+ if (result.mayContainStrings) {
1461
+ mayContainStrings = true;
1462
+ }
1463
+ continue;
1464
+ }
1465
+ break;
1466
+ }
1467
+ return { mayContainStrings };
1468
+ }
1469
+ consumeClassSetRangeFromOperator(start) {
1470
+ const currentStart = this.index;
1471
+ const min = this._lastIntValue;
1472
+ if (this.eat(HYPHEN_MINUS)) {
1473
+ if (this.consumeClassSetCharacter()) {
1474
+ const max = this._lastIntValue;
1475
+ if (min === -1 || max === -1) {
1476
+ this.raise("Invalid character class");
1477
+ }
1478
+ if (min > max) {
1479
+ this.raise("Range out of order in character class");
1480
+ }
1481
+ this.onCharacterClassRange(start, this.index, min, max);
1482
+ return true;
1483
+ }
1484
+ this.rewind(currentStart);
1485
+ }
1486
+ return false;
1487
+ }
1488
+ consumeClassSetOperand() {
1489
+ let result = null;
1490
+ if ((result = this.consumeNestedClass())) {
1491
+ return result;
1492
+ }
1493
+ if ((result = this.consumeClassStringDisjunction())) {
1494
+ return result;
1495
+ }
1496
+ if (this.consumeClassSetCharacter()) {
1497
+ return {};
1498
+ }
1499
+ return null;
1500
+ }
1501
+ consumeNestedClass() {
1502
+ const start = this.index;
1503
+ if (this.eat(LEFT_SQUARE_BRACKET)) {
1504
+ const negate = this.eat(CIRCUMFLEX_ACCENT);
1505
+ this.onCharacterClassEnter(start, negate, true);
1506
+ const result = this.consumeClassContents();
1507
+ if (!this.eat(RIGHT_SQUARE_BRACKET)) {
1508
+ this.raise("Unterminated character class");
1509
+ }
1510
+ if (negate && result.mayContainStrings) {
1511
+ this.raise("Negated character class may contain strings");
1512
+ }
1513
+ this.onCharacterClassLeave(start, this.index, negate);
1514
+ return result;
1515
+ }
1516
+ if (this.eat(REVERSE_SOLIDUS)) {
1517
+ const result = this.consumeCharacterClassEscape();
1518
+ if (result) {
1519
+ return result;
1520
+ }
1521
+ this.rewind(start);
1522
+ }
1523
+ return null;
1524
+ }
1525
+ consumeClassStringDisjunction() {
1526
+ const start = this.index;
1527
+ if (this.eat3(REVERSE_SOLIDUS, LATIN_SMALL_LETTER_Q, LEFT_CURLY_BRACKET)) {
1528
+ this.onClassStringDisjunctionEnter(start);
1529
+ let i = 0;
1530
+ let mayContainStrings = false;
1531
+ do {
1532
+ if (this.consumeClassString(i++).mayContainStrings) {
1533
+ mayContainStrings = true;
1534
+ }
1535
+ } while (this.eat(VERTICAL_LINE));
1536
+ if (this.eat(RIGHT_CURLY_BRACKET)) {
1537
+ this.onClassStringDisjunctionLeave(start, this.index);
1538
+ return { mayContainStrings };
1539
+ }
1540
+ this.raise("Unterminated class string disjunction");
1541
+ }
1542
+ return null;
1543
+ }
1544
+ consumeClassString(i) {
1545
+ const start = this.index;
1546
+ let count = 0;
1547
+ this.onStringAlternativeEnter(start, i);
1548
+ while (this.currentCodePoint !== -1 &&
1549
+ this.consumeClassSetCharacter()) {
1550
+ count++;
1551
+ }
1552
+ this.onStringAlternativeLeave(start, this.index, i);
1553
+ return { mayContainStrings: count !== 1 };
1554
+ }
1555
+ consumeClassSetCharacter() {
1556
+ const start = this.index;
1557
+ const cp = this.currentCodePoint;
1558
+ if (cp !== this.nextCodePoint ||
1559
+ !isClassSetReservedDoublePunctuatorCharacter(cp)) {
1560
+ if (cp !== -1 && !isClassSetSyntaxCharacter(cp)) {
1561
+ this._lastIntValue = cp;
1562
+ this.advance();
1563
+ this.onCharacter(start, this.index, this._lastIntValue);
1564
+ return true;
1565
+ }
1566
+ }
1567
+ if (this.eat(REVERSE_SOLIDUS)) {
1568
+ if (this.consumeCharacterEscape()) {
1569
+ return true;
1570
+ }
1571
+ if (isClassSetReservedPunctuator(this.currentCodePoint)) {
1572
+ this._lastIntValue = this.currentCodePoint;
1573
+ this.advance();
1574
+ this.onCharacter(start, this.index, this._lastIntValue);
1575
+ return true;
1576
+ }
1577
+ if (this.eat(LATIN_SMALL_LETTER_B)) {
1578
+ this._lastIntValue = BACKSPACE;
1579
+ this.onCharacter(start, this.index, this._lastIntValue);
1580
+ return true;
1581
+ }
1582
+ this.rewind(start);
1583
+ }
1584
+ return false;
1225
1585
  }
1226
1586
  eatGroupName() {
1227
1587
  if (this.eat(LESS_THAN_SIGN)) {
@@ -1244,7 +1604,7 @@ class RegExpValidator {
1244
1604
  }
1245
1605
  eatRegExpIdentifierStart() {
1246
1606
  const start = this.index;
1247
- const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1607
+ const forceUFlag = !this._unicodeMode && this.ecmaVersion >= 2020;
1248
1608
  let cp = this.currentCodePoint;
1249
1609
  this.advance();
1250
1610
  if (cp === REVERSE_SOLIDUS &&
@@ -1257,7 +1617,7 @@ class RegExpValidator {
1257
1617
  cp = combineSurrogatePair(cp, this.currentCodePoint);
1258
1618
  this.advance();
1259
1619
  }
1260
- if (isRegExpIdentifierStart(cp)) {
1620
+ if (isIdentifierStartChar(cp)) {
1261
1621
  this._lastIntValue = cp;
1262
1622
  return true;
1263
1623
  }
@@ -1268,7 +1628,7 @@ class RegExpValidator {
1268
1628
  }
1269
1629
  eatRegExpIdentifierPart() {
1270
1630
  const start = this.index;
1271
- const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1631
+ const forceUFlag = !this._unicodeMode && this.ecmaVersion >= 2020;
1272
1632
  let cp = this.currentCodePoint;
1273
1633
  this.advance();
1274
1634
  if (cp === REVERSE_SOLIDUS &&
@@ -1281,7 +1641,7 @@ class RegExpValidator {
1281
1641
  cp = combineSurrogatePair(cp, this.currentCodePoint);
1282
1642
  this.advance();
1283
1643
  }
1284
- if (isRegExpIdentifierPart(cp)) {
1644
+ if (isIdentifierPartChar(cp)) {
1285
1645
  this._lastIntValue = cp;
1286
1646
  return true;
1287
1647
  }
@@ -1343,7 +1703,7 @@ class RegExpValidator {
1343
1703
  }
1344
1704
  eatRegExpUnicodeEscapeSequence(forceUFlag = false) {
1345
1705
  const start = this.index;
1346
- const uFlag = forceUFlag || this._uFlag;
1706
+ const uFlag = forceUFlag || this._unicodeMode;
1347
1707
  if (this.eat(LATIN_SMALL_LETTER_U)) {
1348
1708
  if ((uFlag && this.eatRegExpUnicodeSurrogatePairEscape()) ||
1349
1709
  this.eatFixedHexDigits(4) ||
@@ -1399,7 +1759,7 @@ class RegExpValidator {
1399
1759
  if (cp === -1) {
1400
1760
  return false;
1401
1761
  }
1402
- if (this._uFlag) {
1762
+ if (this._unicodeMode) {
1403
1763
  return isSyntaxCharacter(cp) || cp === SOLIDUS;
1404
1764
  }
1405
1765
  if (this.strict) {
@@ -1426,11 +1786,14 @@ class RegExpValidator {
1426
1786
  eatUnicodePropertyValueExpression() {
1427
1787
  const start = this.index;
1428
1788
  if (this.eatUnicodePropertyName() && this.eat(EQUALS_SIGN)) {
1429
- this._lastKeyValue = this._lastStrValue;
1789
+ const key = this._lastStrValue;
1430
1790
  if (this.eatUnicodePropertyValue()) {
1431
- this._lastValValue = this._lastStrValue;
1432
- if (isValidUnicodeProperty(this.ecmaVersion, this._lastKeyValue, this._lastValValue)) {
1433
- return true;
1791
+ const value = this._lastStrValue;
1792
+ if (isValidUnicodeProperty(this.ecmaVersion, key, value)) {
1793
+ return {
1794
+ key,
1795
+ value: value || null,
1796
+ };
1434
1797
  }
1435
1798
  this.raise("Invalid property name");
1436
1799
  }
@@ -1439,18 +1802,28 @@ class RegExpValidator {
1439
1802
  if (this.eatLoneUnicodePropertyNameOrValue()) {
1440
1803
  const nameOrValue = this._lastStrValue;
1441
1804
  if (isValidUnicodeProperty(this.ecmaVersion, "General_Category", nameOrValue)) {
1442
- this._lastKeyValue = "General_Category";
1443
- this._lastValValue = nameOrValue;
1444
- return true;
1805
+ return {
1806
+ key: "General_Category",
1807
+ value: nameOrValue || null,
1808
+ };
1445
1809
  }
1446
1810
  if (isValidLoneUnicodeProperty(this.ecmaVersion, nameOrValue)) {
1447
- this._lastKeyValue = nameOrValue;
1448
- this._lastValValue = "";
1449
- return true;
1811
+ return {
1812
+ key: nameOrValue,
1813
+ value: null,
1814
+ };
1815
+ }
1816
+ if (this._unicodeSetsMode &&
1817
+ isValidLoneUnicodePropertyOfString(this.ecmaVersion, nameOrValue)) {
1818
+ return {
1819
+ key: nameOrValue,
1820
+ value: null,
1821
+ strings: true,
1822
+ };
1450
1823
  }
1451
1824
  this.raise("Invalid property name");
1452
1825
  }
1453
- return false;
1826
+ return null;
1454
1827
  }
1455
1828
  eatUnicodePropertyName() {
1456
1829
  this._lastStrValue = "";
@@ -1477,7 +1850,7 @@ class RegExpValidator {
1477
1850
  if (this.eatFixedHexDigits(2)) {
1478
1851
  return true;
1479
1852
  }
1480
- if (this._uFlag || this.strict) {
1853
+ if (this._unicodeMode || this.strict) {
1481
1854
  this.raise("Invalid escape");
1482
1855
  }
1483
1856
  this.rewind(start);
@@ -1552,16 +1925,24 @@ class RegExpValidator {
1552
1925
  const DUMMY_PATTERN = {};
1553
1926
  const DUMMY_FLAGS = {};
1554
1927
  const DUMMY_CAPTURING_GROUP = {};
1928
+ function isClassSetOperand(node) {
1929
+ return (node.type === "Character" ||
1930
+ node.type === "CharacterSet" ||
1931
+ node.type === "CharacterClass" ||
1932
+ node.type === "ExpressionCharacterClass" ||
1933
+ node.type === "ClassStringDisjunction");
1934
+ }
1555
1935
  class RegExpParserState {
1556
1936
  constructor(options) {
1557
1937
  var _a;
1558
1938
  this._node = DUMMY_PATTERN;
1939
+ this._expressionBuffer = null;
1559
1940
  this._flags = DUMMY_FLAGS;
1560
1941
  this._backreferences = [];
1561
1942
  this._capturingGroups = [];
1562
1943
  this.source = "";
1563
1944
  this.strict = Boolean(options === null || options === void 0 ? void 0 : options.strict);
1564
- this.ecmaVersion = (_a = options === null || options === void 0 ? void 0 : options.ecmaVersion) !== null && _a !== void 0 ? _a : 2023;
1945
+ this.ecmaVersion = (_a = options === null || options === void 0 ? void 0 : options.ecmaVersion) !== null && _a !== void 0 ? _a : latestEcmaVersion;
1565
1946
  }
1566
1947
  get pattern() {
1567
1948
  if (this._node.type !== "Pattern") {
@@ -1575,7 +1956,7 @@ class RegExpParserState {
1575
1956
  }
1576
1957
  return this._flags;
1577
1958
  }
1578
- onRegExpFlags(start, end, { global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices, }) {
1959
+ onRegExpFlags(start, end, { global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices, unicodeSets, }) {
1579
1960
  this._flags = {
1580
1961
  type: "Flags",
1581
1962
  parent: null,
@@ -1589,6 +1970,7 @@ class RegExpParserState {
1589
1970
  sticky,
1590
1971
  dotAll,
1591
1972
  hasIndices,
1973
+ unicodeSets,
1592
1974
  };
1593
1975
  }
1594
1976
  onPatternEnter(start) {
@@ -1803,26 +2185,33 @@ class RegExpParserState {
1803
2185
  negate,
1804
2186
  });
1805
2187
  }
1806
- onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
2188
+ onUnicodePropertyCharacterSet(start, end, kind, key, value, negate, strings) {
1807
2189
  const parent = this._node;
1808
- if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
2190
+ if ((parent.type !== "Alternative" &&
2191
+ parent.type !== "CharacterClass") ||
2192
+ (strings && (negate || value))) {
1809
2193
  throw new Error("UnknownError");
1810
2194
  }
1811
- parent.elements.push({
2195
+ const base = {
1812
2196
  type: "CharacterSet",
1813
2197
  parent,
1814
2198
  start,
1815
2199
  end,
1816
2200
  raw: this.source.slice(start, end),
1817
2201
  kind,
2202
+ strings,
1818
2203
  key,
1819
- value,
1820
- negate,
1821
- });
2204
+ };
2205
+ const node = strings
2206
+ ? Object.assign(Object.assign({}, base), { value: null, negate: false, strings: true }) : Object.assign(Object.assign({}, base), { value,
2207
+ negate, strings: false });
2208
+ parent.elements.push(node);
1822
2209
  }
1823
2210
  onCharacter(start, end, value) {
1824
2211
  const parent = this._node;
1825
- if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
2212
+ if (parent.type !== "Alternative" &&
2213
+ parent.type !== "CharacterClass" &&
2214
+ parent.type !== "StringAlternative") {
1826
2215
  throw new Error("UnknownError");
1827
2216
  }
1828
2217
  parent.elements.push({
@@ -1851,31 +2240,66 @@ class RegExpParserState {
1851
2240
  parent.elements.push(node);
1852
2241
  this._backreferences.push(node);
1853
2242
  }
1854
- onCharacterClassEnter(start, negate) {
2243
+ onCharacterClassEnter(start, negate, unicodeSets) {
1855
2244
  const parent = this._node;
1856
- if (parent.type !== "Alternative") {
1857
- throw new Error("UnknownError");
1858
- }
1859
- this._node = {
2245
+ const base = {
1860
2246
  type: "CharacterClass",
1861
2247
  parent,
1862
2248
  start,
1863
2249
  end: start,
1864
2250
  raw: "",
2251
+ unicodeSets,
1865
2252
  negate,
1866
2253
  elements: [],
1867
2254
  };
1868
- parent.elements.push(this._node);
2255
+ if (parent.type === "Alternative") {
2256
+ const node = Object.assign(Object.assign({}, base), { parent });
2257
+ this._node = node;
2258
+ parent.elements.push(node);
2259
+ }
2260
+ else if (parent.type === "CharacterClass" &&
2261
+ parent.unicodeSets &&
2262
+ unicodeSets) {
2263
+ const node = Object.assign(Object.assign({}, base), { parent,
2264
+ unicodeSets });
2265
+ this._node = node;
2266
+ parent.elements.push(node);
2267
+ }
2268
+ else {
2269
+ throw new Error("UnknownError");
2270
+ }
1869
2271
  }
1870
2272
  onCharacterClassLeave(start, end) {
1871
2273
  const node = this._node;
1872
2274
  if (node.type !== "CharacterClass" ||
1873
- node.parent.type !== "Alternative") {
2275
+ (node.parent.type !== "Alternative" &&
2276
+ node.parent.type !== "CharacterClass") ||
2277
+ (this._expressionBuffer && node.elements.length > 0)) {
1874
2278
  throw new Error("UnknownError");
1875
2279
  }
2280
+ const parent = node.parent;
1876
2281
  node.end = end;
1877
2282
  node.raw = this.source.slice(start, end);
1878
- this._node = node.parent;
2283
+ this._node = parent;
2284
+ const expression = this._expressionBuffer;
2285
+ this._expressionBuffer = null;
2286
+ if (!expression) {
2287
+ return;
2288
+ }
2289
+ const newNode = {
2290
+ type: "ExpressionCharacterClass",
2291
+ parent,
2292
+ start: node.start,
2293
+ end: node.end,
2294
+ raw: node.raw,
2295
+ negate: node.negate,
2296
+ expression,
2297
+ };
2298
+ expression.parent = newNode;
2299
+ if (node !== parent.elements.pop()) {
2300
+ throw new Error("UnknownError");
2301
+ }
2302
+ parent.elements.push(newNode);
1879
2303
  }
1880
2304
  onCharacterClassRange(start, end) {
1881
2305
  const parent = this._node;
@@ -1884,15 +2308,19 @@ class RegExpParserState {
1884
2308
  }
1885
2309
  const elements = parent.elements;
1886
2310
  const max = elements.pop();
1887
- const hyphen = elements.pop();
2311
+ if (!max || max.type !== "Character") {
2312
+ throw new Error("UnknownError");
2313
+ }
2314
+ if (!parent.unicodeSets) {
2315
+ const hyphen = elements.pop();
2316
+ if (!hyphen ||
2317
+ hyphen.type !== "Character" ||
2318
+ hyphen.value !== HYPHEN_MINUS) {
2319
+ throw new Error("UnknownError");
2320
+ }
2321
+ }
1888
2322
  const min = elements.pop();
1889
- if (!min ||
1890
- !max ||
1891
- !hyphen ||
1892
- min.type !== "Character" ||
1893
- max.type !== "Character" ||
1894
- hyphen.type !== "Character" ||
1895
- hyphen.value !== HYPHEN_MINUS) {
2323
+ if (!min || min.type !== "Character") {
1896
2324
  throw new Error("UnknownError");
1897
2325
  }
1898
2326
  const node = {
@@ -1908,6 +2336,111 @@ class RegExpParserState {
1908
2336
  max.parent = node;
1909
2337
  elements.push(node);
1910
2338
  }
2339
+ onClassIntersection(start, end) {
2340
+ var _a;
2341
+ const parent = this._node;
2342
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2343
+ throw new Error("UnknownError");
2344
+ }
2345
+ const right = parent.elements.pop();
2346
+ const left = (_a = this._expressionBuffer) !== null && _a !== void 0 ? _a : parent.elements.pop();
2347
+ if (!left ||
2348
+ !right ||
2349
+ left.type === "ClassSubtraction" ||
2350
+ (left.type !== "ClassIntersection" && !isClassSetOperand(left)) ||
2351
+ !isClassSetOperand(right)) {
2352
+ throw new Error("UnknownError");
2353
+ }
2354
+ const node = {
2355
+ type: "ClassIntersection",
2356
+ parent: parent,
2357
+ start,
2358
+ end,
2359
+ raw: this.source.slice(start, end),
2360
+ left,
2361
+ right,
2362
+ };
2363
+ left.parent = node;
2364
+ right.parent = node;
2365
+ this._expressionBuffer = node;
2366
+ }
2367
+ onClassSubtraction(start, end) {
2368
+ var _a;
2369
+ const parent = this._node;
2370
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2371
+ throw new Error("UnknownError");
2372
+ }
2373
+ const right = parent.elements.pop();
2374
+ const left = (_a = this._expressionBuffer) !== null && _a !== void 0 ? _a : parent.elements.pop();
2375
+ if (!left ||
2376
+ !right ||
2377
+ left.type === "ClassIntersection" ||
2378
+ (left.type !== "ClassSubtraction" && !isClassSetOperand(left)) ||
2379
+ !isClassSetOperand(right)) {
2380
+ throw new Error("UnknownError");
2381
+ }
2382
+ const node = {
2383
+ type: "ClassSubtraction",
2384
+ parent: parent,
2385
+ start,
2386
+ end,
2387
+ raw: this.source.slice(start, end),
2388
+ left,
2389
+ right,
2390
+ };
2391
+ left.parent = node;
2392
+ right.parent = node;
2393
+ this._expressionBuffer = node;
2394
+ }
2395
+ onClassStringDisjunctionEnter(start) {
2396
+ const parent = this._node;
2397
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2398
+ throw new Error("UnknownError");
2399
+ }
2400
+ this._node = {
2401
+ type: "ClassStringDisjunction",
2402
+ parent,
2403
+ start,
2404
+ end: start,
2405
+ raw: "",
2406
+ alternatives: [],
2407
+ };
2408
+ parent.elements.push(this._node);
2409
+ }
2410
+ onClassStringDisjunctionLeave(start, end) {
2411
+ const node = this._node;
2412
+ if (node.type !== "ClassStringDisjunction" ||
2413
+ node.parent.type !== "CharacterClass") {
2414
+ throw new Error("UnknownError");
2415
+ }
2416
+ node.end = end;
2417
+ node.raw = this.source.slice(start, end);
2418
+ this._node = node.parent;
2419
+ }
2420
+ onStringAlternativeEnter(start) {
2421
+ const parent = this._node;
2422
+ if (parent.type !== "ClassStringDisjunction") {
2423
+ throw new Error("UnknownError");
2424
+ }
2425
+ this._node = {
2426
+ type: "StringAlternative",
2427
+ parent,
2428
+ start,
2429
+ end: start,
2430
+ raw: "",
2431
+ elements: [],
2432
+ };
2433
+ parent.alternatives.push(this._node);
2434
+ }
2435
+ onStringAlternativeLeave(start, end) {
2436
+ const node = this._node;
2437
+ if (node.type !== "StringAlternative") {
2438
+ throw new Error("UnknownError");
2439
+ }
2440
+ node.end = end;
2441
+ node.raw = this.source.slice(start, end);
2442
+ this._node = node.parent;
2443
+ }
1911
2444
  }
1912
2445
  class RegExpParser {
1913
2446
  constructor(options) {
@@ -1937,9 +2470,9 @@ class RegExpParser {
1937
2470
  this._validator.validateFlags(source, start, end);
1938
2471
  return this._state.flags;
1939
2472
  }
1940
- parsePattern(source, start = 0, end = source.length, uFlag = false) {
2473
+ parsePattern(source, start = 0, end = source.length, uFlagOrFlags = undefined) {
1941
2474
  this._state.source = source;
1942
- this._validator.validatePattern(source, start, end, uFlag);
2475
+ this._validator.validatePattern(source, start, end, uFlagOrFlags);
1943
2476
  return this._state.pattern;
1944
2477
  }
1945
2478
  }
@@ -1974,6 +2507,18 @@ class RegExpVisitor {
1974
2507
  case "CharacterSet":
1975
2508
  this.visitCharacterSet(node);
1976
2509
  break;
2510
+ case "ClassIntersection":
2511
+ this.visitClassIntersection(node);
2512
+ break;
2513
+ case "ClassStringDisjunction":
2514
+ this.visitClassStringDisjunction(node);
2515
+ break;
2516
+ case "ClassSubtraction":
2517
+ this.visitClassSubtraction(node);
2518
+ break;
2519
+ case "ExpressionCharacterClass":
2520
+ this.visitExpressionCharacterClass(node);
2521
+ break;
1977
2522
  case "Flags":
1978
2523
  this.visitFlags(node);
1979
2524
  break;
@@ -1989,6 +2534,9 @@ class RegExpVisitor {
1989
2534
  case "RegExpLiteral":
1990
2535
  this.visitRegExpLiteral(node);
1991
2536
  break;
2537
+ case "StringAlternative":
2538
+ this.visitStringAlternative(node);
2539
+ break;
1992
2540
  default:
1993
2541
  throw new Error(`Unknown type: ${node.type}`);
1994
2542
  }
@@ -2065,6 +2613,44 @@ class RegExpVisitor {
2065
2613
  this._handlers.onCharacterSetLeave(node);
2066
2614
  }
2067
2615
  }
2616
+ visitClassIntersection(node) {
2617
+ if (this._handlers.onClassIntersectionEnter) {
2618
+ this._handlers.onClassIntersectionEnter(node);
2619
+ }
2620
+ this.visit(node.left);
2621
+ this.visit(node.right);
2622
+ if (this._handlers.onClassIntersectionLeave) {
2623
+ this._handlers.onClassIntersectionLeave(node);
2624
+ }
2625
+ }
2626
+ visitClassStringDisjunction(node) {
2627
+ if (this._handlers.onClassStringDisjunctionEnter) {
2628
+ this._handlers.onClassStringDisjunctionEnter(node);
2629
+ }
2630
+ node.alternatives.forEach(this.visit, this);
2631
+ if (this._handlers.onClassStringDisjunctionLeave) {
2632
+ this._handlers.onClassStringDisjunctionLeave(node);
2633
+ }
2634
+ }
2635
+ visitClassSubtraction(node) {
2636
+ if (this._handlers.onClassSubtractionEnter) {
2637
+ this._handlers.onClassSubtractionEnter(node);
2638
+ }
2639
+ this.visit(node.left);
2640
+ this.visit(node.right);
2641
+ if (this._handlers.onClassSubtractionLeave) {
2642
+ this._handlers.onClassSubtractionLeave(node);
2643
+ }
2644
+ }
2645
+ visitExpressionCharacterClass(node) {
2646
+ if (this._handlers.onExpressionCharacterClassEnter) {
2647
+ this._handlers.onExpressionCharacterClassEnter(node);
2648
+ }
2649
+ this.visit(node.expression);
2650
+ if (this._handlers.onExpressionCharacterClassLeave) {
2651
+ this._handlers.onExpressionCharacterClassLeave(node);
2652
+ }
2653
+ }
2068
2654
  visitFlags(node) {
2069
2655
  if (this._handlers.onFlagsEnter) {
2070
2656
  this._handlers.onFlagsEnter(node);
@@ -2110,6 +2696,15 @@ class RegExpVisitor {
2110
2696
  this._handlers.onRegExpLiteralLeave(node);
2111
2697
  }
2112
2698
  }
2699
+ visitStringAlternative(node) {
2700
+ if (this._handlers.onStringAlternativeEnter) {
2701
+ this._handlers.onStringAlternativeEnter(node);
2702
+ }
2703
+ node.elements.forEach(this.visit, this);
2704
+ if (this._handlers.onStringAlternativeLeave) {
2705
+ this._handlers.onStringAlternativeLeave(node);
2706
+ }
2707
+ }
2113
2708
  }
2114
2709
 
2115
2710
  function parseRegExpLiteral(source, options) {