@eslint-community/regexpp 4.5.1 → 4.6.1

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) {
@@ -142,7 +144,10 @@ const LINE_TABULATION = 0x0b;
142
144
  const FORM_FEED = 0x0c;
143
145
  const CARRIAGE_RETURN = 0x0d;
144
146
  const EXCLAMATION_MARK = 0x21;
147
+ const NUMBER_SIGN = 0x23;
145
148
  const DOLLAR_SIGN = 0x24;
149
+ const PERCENT_SIGN = 0x25;
150
+ const AMPERSAND = 0x26;
146
151
  const LEFT_PARENTHESIS = 0x28;
147
152
  const RIGHT_PARENTHESIS = 0x29;
148
153
  const ASTERISK = 0x2a;
@@ -156,10 +161,12 @@ const DIGIT_ONE = 0x31;
156
161
  const DIGIT_SEVEN = 0x37;
157
162
  const DIGIT_NINE = 0x39;
158
163
  const COLON = 0x3a;
164
+ const SEMICOLON = 0x3b;
159
165
  const LESS_THAN_SIGN = 0x3c;
160
166
  const EQUALS_SIGN = 0x3d;
161
167
  const GREATER_THAN_SIGN = 0x3e;
162
168
  const QUESTION_MARK = 0x3f;
169
+ const COMMERCIAL_AT = 0x40;
163
170
  const LATIN_CAPITAL_LETTER_A = 0x41;
164
171
  const LATIN_CAPITAL_LETTER_B = 0x42;
165
172
  const LATIN_CAPITAL_LETTER_D = 0x44;
@@ -180,6 +187,7 @@ const LATIN_SMALL_LETTER_K = 0x6b;
180
187
  const LATIN_SMALL_LETTER_M = 0x6d;
181
188
  const LATIN_SMALL_LETTER_N = 0x6e;
182
189
  const LATIN_SMALL_LETTER_P = 0x70;
190
+ const LATIN_SMALL_LETTER_Q = 0x71;
183
191
  const LATIN_SMALL_LETTER_R = 0x72;
184
192
  const LATIN_SMALL_LETTER_S = 0x73;
185
193
  const LATIN_SMALL_LETTER_T = 0x74;
@@ -193,9 +201,11 @@ const LEFT_SQUARE_BRACKET = 0x5b;
193
201
  const REVERSE_SOLIDUS = 0x5c;
194
202
  const RIGHT_SQUARE_BRACKET = 0x5d;
195
203
  const CIRCUMFLEX_ACCENT = 0x5e;
204
+ const GRAVE_ACCENT = 0x60;
196
205
  const LEFT_CURLY_BRACKET = 0x7b;
197
206
  const VERTICAL_LINE = 0x7c;
198
207
  const RIGHT_CURLY_BRACKET = 0x7d;
208
+ const TILDE = 0x7e;
199
209
  const ZERO_WIDTH_NON_JOINER = 0x200c;
200
210
  const ZERO_WIDTH_JOINER = 0x200d;
201
211
  const LINE_SEPARATOR = 0x2028;
@@ -350,10 +360,10 @@ class Reader {
350
360
  }
351
361
 
352
362
  class RegExpSyntaxError extends SyntaxError {
353
- constructor(source, uFlag, index, message) {
363
+ constructor(source, flags, index, message) {
354
364
  if (source) {
355
365
  if (!source.startsWith("/")) {
356
- source = `/${source}/${uFlag ? "u" : ""}`;
366
+ source = `/${source}/${flags.unicode ? "u" : ""}${flags.unicodeSets ? "v" : ""}`;
357
367
  }
358
368
  source = `: ${source}`;
359
369
  }
@@ -362,29 +372,102 @@ class RegExpSyntaxError extends SyntaxError {
362
372
  }
363
373
  }
364
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
+ ]);
365
453
  function isSyntaxCharacter(cp) {
366
- return (cp === CIRCUMFLEX_ACCENT ||
367
- cp === DOLLAR_SIGN ||
368
- cp === REVERSE_SOLIDUS ||
369
- cp === FULL_STOP ||
370
- cp === ASTERISK ||
371
- cp === PLUS_SIGN ||
372
- cp === QUESTION_MARK ||
373
- cp === LEFT_PARENTHESIS ||
374
- cp === RIGHT_PARENTHESIS ||
375
- cp === LEFT_SQUARE_BRACKET ||
376
- cp === RIGHT_SQUARE_BRACKET ||
377
- cp === LEFT_CURLY_BRACKET ||
378
- cp === RIGHT_CURLY_BRACKET ||
379
- cp === VERTICAL_LINE);
454
+ return SYNTAX_CHARACTER.has(cp);
380
455
  }
381
- function isRegExpIdentifierStart(cp) {
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);
461
+ }
462
+ function isClassSetReservedPunctuator(cp) {
463
+ return CLASS_SET_RESERVED_PUNCTUATOR.has(cp);
464
+ }
465
+ function isIdentifierStartChar(cp) {
382
466
  return isIdStart(cp) || cp === DOLLAR_SIGN || cp === LOW_LINE;
383
467
  }
384
- function isRegExpIdentifierPart(cp) {
468
+ function isIdentifierPartChar(cp) {
385
469
  return (isIdContinue(cp) ||
386
470
  cp === DOLLAR_SIGN ||
387
- cp === LOW_LINE ||
388
471
  cp === ZERO_WIDTH_NON_JOINER ||
389
472
  cp === ZERO_WIDTH_JOINER);
390
473
  }
@@ -397,14 +480,15 @@ function isUnicodePropertyValueCharacter(cp) {
397
480
  class RegExpValidator {
398
481
  constructor(options) {
399
482
  this._reader = new Reader();
400
- this._uFlag = false;
483
+ this._unicodeMode = false;
484
+ this._unicodeSetsMode = false;
401
485
  this._nFlag = false;
402
486
  this._lastIntValue = 0;
403
- this._lastMinValue = 0;
404
- this._lastMaxValue = 0;
487
+ this._lastRange = {
488
+ min: 0,
489
+ max: Number.POSITIVE_INFINITY,
490
+ };
405
491
  this._lastStrValue = "";
406
- this._lastKeyValue = "";
407
- this._lastValValue = "";
408
492
  this._lastAssertionIsQuantifiable = false;
409
493
  this._numCapturingParens = 0;
410
494
  this._groupNames = new Set();
@@ -412,14 +496,18 @@ class RegExpValidator {
412
496
  this._options = options !== null && options !== void 0 ? options : {};
413
497
  }
414
498
  validateLiteral(source, start = 0, end = source.length) {
415
- this._uFlag = this._nFlag = false;
499
+ this._unicodeSetsMode = this._unicodeMode = this._nFlag = false;
416
500
  this.reset(source, start, end);
417
501
  this.onLiteralEnter(start);
418
502
  if (this.eat(SOLIDUS) && this.eatRegExpBody() && this.eat(SOLIDUS)) {
419
503
  const flagStart = this.index;
420
- const uFlag = source.includes("u", flagStart);
504
+ const unicode = source.includes("u", flagStart);
505
+ const unicodeSets = source.includes("v", flagStart);
421
506
  this.validateFlags(source, flagStart, end);
422
- this.validatePattern(source, start + 1, flagStart - 1, uFlag);
507
+ this.validatePattern(source, start + 1, flagStart - 1, {
508
+ unicode,
509
+ unicodeSets,
510
+ });
423
511
  }
424
512
  else if (start >= end) {
425
513
  this.raise("Empty");
@@ -439,6 +527,7 @@ class RegExpValidator {
439
527
  let unicode = false;
440
528
  let dotAll = false;
441
529
  let hasIndices = false;
530
+ let unicodeSets = false;
442
531
  for (let i = start; i < end; ++i) {
443
532
  const flag = source.charCodeAt(i);
444
533
  if (existingFlags.has(flag)) {
@@ -470,6 +559,10 @@ class RegExpValidator {
470
559
  this.ecmaVersion >= 2022) {
471
560
  hasIndices = true;
472
561
  }
562
+ else if (flag === LATIN_SMALL_LETTER_V &&
563
+ this.ecmaVersion >= 2024) {
564
+ unicodeSets = true;
565
+ }
473
566
  else {
474
567
  this.raise(`Invalid flag '${source[i]}'`);
475
568
  }
@@ -482,13 +575,14 @@ class RegExpValidator {
482
575
  sticky,
483
576
  dotAll,
484
577
  hasIndices,
578
+ unicodeSets,
485
579
  });
486
580
  }
487
- validatePattern(source, start = 0, end = source.length, uFlag = false) {
488
- this._uFlag = uFlag && this.ecmaVersion >= 2015;
489
- this._nFlag =
490
- (uFlag && this.ecmaVersion >= 2018) ||
491
- Boolean(this._options.strict && this.ecmaVersion >= 2023);
581
+ validatePattern(source, start = 0, end = source.length, uFlagOrFlags = undefined) {
582
+ const mode = this._parseFlagsOptionToMode(uFlagOrFlags, source, end);
583
+ this._unicodeMode = mode.unicodeMode;
584
+ this._nFlag = mode.nFlag;
585
+ this._unicodeSetsMode = mode.unicodeSetsMode;
492
586
  this.reset(source, start, end);
493
587
  this.consumePattern();
494
588
  if (!this._nFlag &&
@@ -499,12 +593,36 @@ class RegExpValidator {
499
593
  this.consumePattern();
500
594
  }
501
595
  }
596
+ _parseFlagsOptionToMode(uFlagOrFlags, source, sourceEnd) {
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
+ throw new RegExpSyntaxError(source, { unicode, unicodeSets }, sourceEnd + 1, "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
+ }
502
620
  get strict() {
503
- return Boolean(this._options.strict) || this._uFlag;
621
+ return Boolean(this._options.strict) || this._unicodeMode;
504
622
  }
505
623
  get ecmaVersion() {
506
624
  var _a;
507
- return (_a = this._options.ecmaVersion) !== null && _a !== void 0 ? _a : 2023;
625
+ return (_a = this._options.ecmaVersion) !== null && _a !== void 0 ? _a : latestEcmaVersion;
508
626
  }
509
627
  onLiteralEnter(start) {
510
628
  if (this._options.onLiteralEnter) {
@@ -609,9 +727,9 @@ class RegExpValidator {
609
727
  this._options.onEscapeCharacterSet(start, end, kind, negate);
610
728
  }
611
729
  }
612
- onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
730
+ onUnicodePropertyCharacterSet(start, end, kind, key, value, negate, strings) {
613
731
  if (this._options.onUnicodePropertyCharacterSet) {
614
- this._options.onUnicodePropertyCharacterSet(start, end, kind, key, value, negate);
732
+ this._options.onUnicodePropertyCharacterSet(start, end, kind, key, value, negate, strings);
615
733
  }
616
734
  }
617
735
  onCharacter(start, end, value) {
@@ -624,9 +742,9 @@ class RegExpValidator {
624
742
  this._options.onBackreference(start, end, ref);
625
743
  }
626
744
  }
627
- onCharacterClassEnter(start, negate) {
745
+ onCharacterClassEnter(start, negate, unicodeSets) {
628
746
  if (this._options.onCharacterClassEnter) {
629
- this._options.onCharacterClassEnter(start, negate);
747
+ this._options.onCharacterClassEnter(start, negate, unicodeSets);
630
748
  }
631
749
  }
632
750
  onCharacterClassLeave(start, end, negate) {
@@ -639,6 +757,36 @@ class RegExpValidator {
639
757
  this._options.onCharacterClassRange(start, end, min, max);
640
758
  }
641
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
+ }
642
790
  get source() {
643
791
  return this._reader.source;
644
792
  }
@@ -658,7 +806,7 @@ class RegExpValidator {
658
806
  return this._reader.nextCodePoint3;
659
807
  }
660
808
  reset(source, start, end) {
661
- this._reader.reset(source, start, end, this._uFlag);
809
+ this._reader.reset(source, start, end, this._unicodeMode);
662
810
  }
663
811
  rewind(index) {
664
812
  this._reader.rewind(index);
@@ -676,7 +824,10 @@ class RegExpValidator {
676
824
  return this._reader.eat3(cp1, cp2, cp3);
677
825
  }
678
826
  raise(message) {
679
- throw new RegExpSyntaxError(this.source, this._uFlag, this.index, message);
827
+ throw new RegExpSyntaxError(this.source, {
828
+ unicode: this._unicodeMode && !this._unicodeSetsMode,
829
+ unicodeSets: this._unicodeSetsMode,
830
+ }, this.index, message);
680
831
  }
681
832
  eatRegExpBody() {
682
833
  const start = this.index;
@@ -791,7 +942,7 @@ class RegExpValidator {
791
942
  this.onAlternativeLeave(start, this.index, i);
792
943
  }
793
944
  consumeTerm() {
794
- if (this._uFlag || this.strict) {
945
+ if (this._unicodeMode || this.strict) {
795
946
  return (this.consumeAssertion() ||
796
947
  (this.consumeAtom() && this.consumeOptionalQuantifier()));
797
948
  }
@@ -860,8 +1011,7 @@ class RegExpValidator {
860
1011
  max = 1;
861
1012
  }
862
1013
  else if (this.eatBracedQuantifier(noConsume)) {
863
- min = this._lastMinValue;
864
- max = this._lastMaxValue;
1014
+ ({ min, max } = this._lastRange);
865
1015
  }
866
1016
  else {
867
1017
  return false;
@@ -875,23 +1025,23 @@ class RegExpValidator {
875
1025
  eatBracedQuantifier(noError) {
876
1026
  const start = this.index;
877
1027
  if (this.eat(LEFT_CURLY_BRACKET)) {
878
- this._lastMinValue = 0;
879
- this._lastMaxValue = Number.POSITIVE_INFINITY;
880
1028
  if (this.eatDecimalDigits()) {
881
- this._lastMinValue = this._lastMaxValue = this._lastIntValue;
1029
+ const min = this._lastIntValue;
1030
+ let max = min;
882
1031
  if (this.eat(COMMA)) {
883
- this._lastMaxValue = this.eatDecimalDigits()
1032
+ max = this.eatDecimalDigits()
884
1033
  ? this._lastIntValue
885
1034
  : Number.POSITIVE_INFINITY;
886
1035
  }
887
1036
  if (this.eat(RIGHT_CURLY_BRACKET)) {
888
- if (!noError && this._lastMaxValue < this._lastMinValue) {
1037
+ if (!noError && max < min) {
889
1038
  this.raise("numbers out of order in {} quantifier");
890
1039
  }
1040
+ this._lastRange = { min, max };
891
1041
  return true;
892
1042
  }
893
1043
  }
894
- if (!noError && (this._uFlag || this.strict)) {
1044
+ if (!noError && (this._unicodeMode || this.strict)) {
895
1045
  this.raise("Incomplete quantifier");
896
1046
  }
897
1047
  this.rewind(start);
@@ -902,7 +1052,7 @@ class RegExpValidator {
902
1052
  return (this.consumePatternCharacter() ||
903
1053
  this.consumeDot() ||
904
1054
  this.consumeReverseSolidusAtomEscape() ||
905
- this.consumeCharacterClass() ||
1055
+ Boolean(this.consumeCharacterClass()) ||
906
1056
  this.consumeUncapturingGroup() ||
907
1057
  this.consumeCapturingGroup());
908
1058
  }
@@ -962,7 +1112,7 @@ class RegExpValidator {
962
1112
  return (this.consumeDot() ||
963
1113
  this.consumeReverseSolidusAtomEscape() ||
964
1114
  this.consumeReverseSolidusFollowedByC() ||
965
- this.consumeCharacterClass() ||
1115
+ Boolean(this.consumeCharacterClass()) ||
966
1116
  this.consumeUncapturingGroup() ||
967
1117
  this.consumeCapturingGroup() ||
968
1118
  this.consumeInvalidBracedQuantifier() ||
@@ -1036,7 +1186,7 @@ class RegExpValidator {
1036
1186
  (this._nFlag && this.consumeKGroupName())) {
1037
1187
  return true;
1038
1188
  }
1039
- if (this.strict || this._uFlag) {
1189
+ if (this.strict || this._unicodeMode) {
1040
1190
  this.raise("Invalid escape");
1041
1191
  }
1042
1192
  return false;
@@ -1049,7 +1199,7 @@ class RegExpValidator {
1049
1199
  this.onBackreference(start - 1, this.index, n);
1050
1200
  return true;
1051
1201
  }
1052
- if (this.strict || this._uFlag) {
1202
+ if (this.strict || this._unicodeMode) {
1053
1203
  this.raise("Invalid escape");
1054
1204
  }
1055
1205
  this.rewind(start);
@@ -1057,52 +1207,57 @@ class RegExpValidator {
1057
1207
  return false;
1058
1208
  }
1059
1209
  consumeCharacterClassEscape() {
1210
+ var _a;
1060
1211
  const start = this.index;
1061
1212
  if (this.eat(LATIN_SMALL_LETTER_D)) {
1062
1213
  this._lastIntValue = -1;
1063
1214
  this.onEscapeCharacterSet(start - 1, this.index, "digit", false);
1064
- return true;
1215
+ return {};
1065
1216
  }
1066
1217
  if (this.eat(LATIN_CAPITAL_LETTER_D)) {
1067
1218
  this._lastIntValue = -1;
1068
1219
  this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
1069
- return true;
1220
+ return {};
1070
1221
  }
1071
1222
  if (this.eat(LATIN_SMALL_LETTER_S)) {
1072
1223
  this._lastIntValue = -1;
1073
1224
  this.onEscapeCharacterSet(start - 1, this.index, "space", false);
1074
- return true;
1225
+ return {};
1075
1226
  }
1076
1227
  if (this.eat(LATIN_CAPITAL_LETTER_S)) {
1077
1228
  this._lastIntValue = -1;
1078
1229
  this.onEscapeCharacterSet(start - 1, this.index, "space", true);
1079
- return true;
1230
+ return {};
1080
1231
  }
1081
1232
  if (this.eat(LATIN_SMALL_LETTER_W)) {
1082
1233
  this._lastIntValue = -1;
1083
1234
  this.onEscapeCharacterSet(start - 1, this.index, "word", false);
1084
- return true;
1235
+ return {};
1085
1236
  }
1086
1237
  if (this.eat(LATIN_CAPITAL_LETTER_W)) {
1087
1238
  this._lastIntValue = -1;
1088
1239
  this.onEscapeCharacterSet(start - 1, this.index, "word", true);
1089
- return true;
1240
+ return {};
1090
1241
  }
1091
1242
  let negate = false;
1092
- if (this._uFlag &&
1243
+ if (this._unicodeMode &&
1093
1244
  this.ecmaVersion >= 2018 &&
1094
1245
  (this.eat(LATIN_SMALL_LETTER_P) ||
1095
1246
  (negate = this.eat(LATIN_CAPITAL_LETTER_P)))) {
1096
1247
  this._lastIntValue = -1;
1248
+ let result = null;
1097
1249
  if (this.eat(LEFT_CURLY_BRACKET) &&
1098
- this.eatUnicodePropertyValueExpression() &&
1250
+ (result = this.eatUnicodePropertyValueExpression()) &&
1099
1251
  this.eat(RIGHT_CURLY_BRACKET)) {
1100
- this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", this._lastKeyValue, this._lastValValue || null, negate);
1101
- return true;
1252
+ if (negate && result.strings) {
1253
+ this.raise("Invalid property name");
1254
+ }
1255
+ this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", result.key, result.value, negate, (_a = result.strings) !== null && _a !== void 0 ? _a : false);
1256
+ return { mayContainStrings: result.strings };
1102
1257
  }
1103
1258
  this.raise("Invalid property name");
1104
1259
  }
1105
- return false;
1260
+ return null;
1106
1261
  }
1107
1262
  consumeCharacterEscape() {
1108
1263
  const start = this.index;
@@ -1112,7 +1267,7 @@ class RegExpValidator {
1112
1267
  this.eatHexEscapeSequence() ||
1113
1268
  this.eatRegExpUnicodeEscapeSequence() ||
1114
1269
  (!this.strict &&
1115
- !this._uFlag &&
1270
+ !this._unicodeMode &&
1116
1271
  this.eatLegacyOctalEscapeSequence()) ||
1117
1272
  this.eatIdentityEscape()) {
1118
1273
  this.onCharacter(start - 1, this.index, this._lastIntValue);
@@ -1137,18 +1292,31 @@ class RegExpValidator {
1137
1292
  const start = this.index;
1138
1293
  if (this.eat(LEFT_SQUARE_BRACKET)) {
1139
1294
  const negate = this.eat(CIRCUMFLEX_ACCENT);
1140
- this.onCharacterClassEnter(start, negate);
1141
- this.consumeClassRanges();
1295
+ this.onCharacterClassEnter(start, negate, this._unicodeSetsMode);
1296
+ const result = this.consumeClassContents();
1142
1297
  if (!this.eat(RIGHT_SQUARE_BRACKET)) {
1143
- this.raise("Unterminated character class");
1298
+ if (this.currentCodePoint === -1) {
1299
+ this.raise("Unterminated character class");
1300
+ }
1301
+ this.raise("Invalid character in character class");
1302
+ }
1303
+ if (negate && result.mayContainStrings) {
1304
+ this.raise("Negated character class may contain strings");
1144
1305
  }
1145
1306
  this.onCharacterClassLeave(start, this.index, negate);
1146
- return true;
1307
+ return result;
1147
1308
  }
1148
- return false;
1309
+ return null;
1149
1310
  }
1150
- consumeClassRanges() {
1151
- const strict = this.strict || this._uFlag;
1311
+ consumeClassContents() {
1312
+ if (this._unicodeSetsMode) {
1313
+ if (this.currentCodePoint === RIGHT_SQUARE_BRACKET) {
1314
+ return {};
1315
+ }
1316
+ const result = this.consumeClassSetExpression();
1317
+ return result;
1318
+ }
1319
+ const strict = this.strict || this._unicodeMode;
1152
1320
  for (;;) {
1153
1321
  const rangeStart = this.index;
1154
1322
  if (!this.consumeClassAtom()) {
@@ -1174,6 +1342,7 @@ class RegExpValidator {
1174
1342
  }
1175
1343
  this.onCharacterClassRange(rangeStart, this.index, min, max);
1176
1344
  }
1345
+ return {};
1177
1346
  }
1178
1347
  consumeClassAtom() {
1179
1348
  const start = this.index;
@@ -1196,7 +1365,7 @@ class RegExpValidator {
1196
1365
  this.onCharacter(start, this.index, this._lastIntValue);
1197
1366
  return true;
1198
1367
  }
1199
- if (this.strict || this._uFlag) {
1368
+ if (this.strict || this._unicodeMode) {
1200
1369
  this.raise("Invalid escape");
1201
1370
  }
1202
1371
  this.rewind(start);
@@ -1210,14 +1379,14 @@ class RegExpValidator {
1210
1379
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1211
1380
  return true;
1212
1381
  }
1213
- if (this._uFlag && this.eat(HYPHEN_MINUS)) {
1382
+ if (this._unicodeMode && this.eat(HYPHEN_MINUS)) {
1214
1383
  this._lastIntValue = HYPHEN_MINUS;
1215
1384
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1216
1385
  return true;
1217
1386
  }
1218
1387
  let cp = 0;
1219
1388
  if (!this.strict &&
1220
- !this._uFlag &&
1389
+ !this._unicodeMode &&
1221
1390
  this.currentCodePoint === LATIN_SMALL_LETTER_C &&
1222
1391
  (isDecimalDigit((cp = this.nextCodePoint)) || cp === LOW_LINE)) {
1223
1392
  this.advance();
@@ -1226,7 +1395,196 @@ class RegExpValidator {
1226
1395
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1227
1396
  return true;
1228
1397
  }
1229
- return (this.consumeCharacterClassEscape() || this.consumeCharacterEscape());
1398
+ return (Boolean(this.consumeCharacterClassEscape()) ||
1399
+ this.consumeCharacterEscape());
1400
+ }
1401
+ consumeClassSetExpression() {
1402
+ const start = this.index;
1403
+ let mayContainStrings = false;
1404
+ let result = null;
1405
+ if (this.consumeClassSetCharacter()) {
1406
+ if (this.consumeClassSetRangeFromOperator(start)) {
1407
+ this.consumeClassUnionRight({});
1408
+ return {};
1409
+ }
1410
+ mayContainStrings = false;
1411
+ }
1412
+ else if ((result = this.consumeClassSetOperand())) {
1413
+ mayContainStrings = result.mayContainStrings;
1414
+ }
1415
+ else {
1416
+ const cp = this.currentCodePoint;
1417
+ if (cp === REVERSE_SOLIDUS) {
1418
+ this.advance();
1419
+ this.raise("Invalid escape");
1420
+ }
1421
+ if (cp === this.nextCodePoint &&
1422
+ isClassSetReservedDoublePunctuatorCharacter(cp)) {
1423
+ this.raise("Invalid set operation in character class");
1424
+ }
1425
+ this.raise("Invalid character in character class");
1426
+ }
1427
+ if (this.eat2(AMPERSAND, AMPERSAND)) {
1428
+ while (this.currentCodePoint !== AMPERSAND &&
1429
+ (result = this.consumeClassSetOperand())) {
1430
+ this.onClassIntersection(start, this.index);
1431
+ if (!result.mayContainStrings) {
1432
+ mayContainStrings = false;
1433
+ }
1434
+ if (this.eat2(AMPERSAND, AMPERSAND)) {
1435
+ continue;
1436
+ }
1437
+ return { mayContainStrings };
1438
+ }
1439
+ this.raise("Invalid character in character class");
1440
+ }
1441
+ if (this.eat2(HYPHEN_MINUS, HYPHEN_MINUS)) {
1442
+ while (this.consumeClassSetOperand()) {
1443
+ this.onClassSubtraction(start, this.index);
1444
+ if (this.eat2(HYPHEN_MINUS, HYPHEN_MINUS)) {
1445
+ continue;
1446
+ }
1447
+ return { mayContainStrings };
1448
+ }
1449
+ this.raise("Invalid character in character class");
1450
+ }
1451
+ return this.consumeClassUnionRight({ mayContainStrings });
1452
+ }
1453
+ consumeClassUnionRight(leftResult) {
1454
+ let mayContainStrings = leftResult.mayContainStrings;
1455
+ for (;;) {
1456
+ const start = this.index;
1457
+ if (this.consumeClassSetCharacter()) {
1458
+ this.consumeClassSetRangeFromOperator(start);
1459
+ continue;
1460
+ }
1461
+ const result = this.consumeClassSetOperand();
1462
+ if (result) {
1463
+ if (result.mayContainStrings) {
1464
+ mayContainStrings = true;
1465
+ }
1466
+ continue;
1467
+ }
1468
+ break;
1469
+ }
1470
+ return { mayContainStrings };
1471
+ }
1472
+ consumeClassSetRangeFromOperator(start) {
1473
+ const currentStart = this.index;
1474
+ const min = this._lastIntValue;
1475
+ if (this.eat(HYPHEN_MINUS)) {
1476
+ if (this.consumeClassSetCharacter()) {
1477
+ const max = this._lastIntValue;
1478
+ if (min === -1 || max === -1) {
1479
+ this.raise("Invalid character class");
1480
+ }
1481
+ if (min > max) {
1482
+ this.raise("Range out of order in character class");
1483
+ }
1484
+ this.onCharacterClassRange(start, this.index, min, max);
1485
+ return true;
1486
+ }
1487
+ this.rewind(currentStart);
1488
+ }
1489
+ return false;
1490
+ }
1491
+ consumeClassSetOperand() {
1492
+ let result = null;
1493
+ if ((result = this.consumeNestedClass())) {
1494
+ return result;
1495
+ }
1496
+ if ((result = this.consumeClassStringDisjunction())) {
1497
+ return result;
1498
+ }
1499
+ if (this.consumeClassSetCharacter()) {
1500
+ return {};
1501
+ }
1502
+ return null;
1503
+ }
1504
+ consumeNestedClass() {
1505
+ const start = this.index;
1506
+ if (this.eat(LEFT_SQUARE_BRACKET)) {
1507
+ const negate = this.eat(CIRCUMFLEX_ACCENT);
1508
+ this.onCharacterClassEnter(start, negate, true);
1509
+ const result = this.consumeClassContents();
1510
+ if (!this.eat(RIGHT_SQUARE_BRACKET)) {
1511
+ this.raise("Unterminated character class");
1512
+ }
1513
+ if (negate && result.mayContainStrings) {
1514
+ this.raise("Negated character class may contain strings");
1515
+ }
1516
+ this.onCharacterClassLeave(start, this.index, negate);
1517
+ return result;
1518
+ }
1519
+ if (this.eat(REVERSE_SOLIDUS)) {
1520
+ const result = this.consumeCharacterClassEscape();
1521
+ if (result) {
1522
+ return result;
1523
+ }
1524
+ this.rewind(start);
1525
+ }
1526
+ return null;
1527
+ }
1528
+ consumeClassStringDisjunction() {
1529
+ const start = this.index;
1530
+ if (this.eat3(REVERSE_SOLIDUS, LATIN_SMALL_LETTER_Q, LEFT_CURLY_BRACKET)) {
1531
+ this.onClassStringDisjunctionEnter(start);
1532
+ let i = 0;
1533
+ let mayContainStrings = false;
1534
+ do {
1535
+ if (this.consumeClassString(i++).mayContainStrings) {
1536
+ mayContainStrings = true;
1537
+ }
1538
+ } while (this.eat(VERTICAL_LINE));
1539
+ if (this.eat(RIGHT_CURLY_BRACKET)) {
1540
+ this.onClassStringDisjunctionLeave(start, this.index);
1541
+ return { mayContainStrings };
1542
+ }
1543
+ this.raise("Unterminated class string disjunction");
1544
+ }
1545
+ return null;
1546
+ }
1547
+ consumeClassString(i) {
1548
+ const start = this.index;
1549
+ let count = 0;
1550
+ this.onStringAlternativeEnter(start, i);
1551
+ while (this.currentCodePoint !== -1 &&
1552
+ this.consumeClassSetCharacter()) {
1553
+ count++;
1554
+ }
1555
+ this.onStringAlternativeLeave(start, this.index, i);
1556
+ return { mayContainStrings: count !== 1 };
1557
+ }
1558
+ consumeClassSetCharacter() {
1559
+ const start = this.index;
1560
+ const cp = this.currentCodePoint;
1561
+ if (cp !== this.nextCodePoint ||
1562
+ !isClassSetReservedDoublePunctuatorCharacter(cp)) {
1563
+ if (cp !== -1 && !isClassSetSyntaxCharacter(cp)) {
1564
+ this._lastIntValue = cp;
1565
+ this.advance();
1566
+ this.onCharacter(start, this.index, this._lastIntValue);
1567
+ return true;
1568
+ }
1569
+ }
1570
+ if (this.eat(REVERSE_SOLIDUS)) {
1571
+ if (this.consumeCharacterEscape()) {
1572
+ return true;
1573
+ }
1574
+ if (isClassSetReservedPunctuator(this.currentCodePoint)) {
1575
+ this._lastIntValue = this.currentCodePoint;
1576
+ this.advance();
1577
+ this.onCharacter(start, this.index, this._lastIntValue);
1578
+ return true;
1579
+ }
1580
+ if (this.eat(LATIN_SMALL_LETTER_B)) {
1581
+ this._lastIntValue = BACKSPACE;
1582
+ this.onCharacter(start, this.index, this._lastIntValue);
1583
+ return true;
1584
+ }
1585
+ this.rewind(start);
1586
+ }
1587
+ return false;
1230
1588
  }
1231
1589
  eatGroupName() {
1232
1590
  if (this.eat(LESS_THAN_SIGN)) {
@@ -1249,7 +1607,7 @@ class RegExpValidator {
1249
1607
  }
1250
1608
  eatRegExpIdentifierStart() {
1251
1609
  const start = this.index;
1252
- const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1610
+ const forceUFlag = !this._unicodeMode && this.ecmaVersion >= 2020;
1253
1611
  let cp = this.currentCodePoint;
1254
1612
  this.advance();
1255
1613
  if (cp === REVERSE_SOLIDUS &&
@@ -1262,7 +1620,7 @@ class RegExpValidator {
1262
1620
  cp = combineSurrogatePair(cp, this.currentCodePoint);
1263
1621
  this.advance();
1264
1622
  }
1265
- if (isRegExpIdentifierStart(cp)) {
1623
+ if (isIdentifierStartChar(cp)) {
1266
1624
  this._lastIntValue = cp;
1267
1625
  return true;
1268
1626
  }
@@ -1273,7 +1631,7 @@ class RegExpValidator {
1273
1631
  }
1274
1632
  eatRegExpIdentifierPart() {
1275
1633
  const start = this.index;
1276
- const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1634
+ const forceUFlag = !this._unicodeMode && this.ecmaVersion >= 2020;
1277
1635
  let cp = this.currentCodePoint;
1278
1636
  this.advance();
1279
1637
  if (cp === REVERSE_SOLIDUS &&
@@ -1286,7 +1644,7 @@ class RegExpValidator {
1286
1644
  cp = combineSurrogatePair(cp, this.currentCodePoint);
1287
1645
  this.advance();
1288
1646
  }
1289
- if (isRegExpIdentifierPart(cp)) {
1647
+ if (isIdentifierPartChar(cp)) {
1290
1648
  this._lastIntValue = cp;
1291
1649
  return true;
1292
1650
  }
@@ -1348,7 +1706,7 @@ class RegExpValidator {
1348
1706
  }
1349
1707
  eatRegExpUnicodeEscapeSequence(forceUFlag = false) {
1350
1708
  const start = this.index;
1351
- const uFlag = forceUFlag || this._uFlag;
1709
+ const uFlag = forceUFlag || this._unicodeMode;
1352
1710
  if (this.eat(LATIN_SMALL_LETTER_U)) {
1353
1711
  if ((uFlag && this.eatRegExpUnicodeSurrogatePairEscape()) ||
1354
1712
  this.eatFixedHexDigits(4) ||
@@ -1404,7 +1762,7 @@ class RegExpValidator {
1404
1762
  if (cp === -1) {
1405
1763
  return false;
1406
1764
  }
1407
- if (this._uFlag) {
1765
+ if (this._unicodeMode) {
1408
1766
  return isSyntaxCharacter(cp) || cp === SOLIDUS;
1409
1767
  }
1410
1768
  if (this.strict) {
@@ -1431,11 +1789,14 @@ class RegExpValidator {
1431
1789
  eatUnicodePropertyValueExpression() {
1432
1790
  const start = this.index;
1433
1791
  if (this.eatUnicodePropertyName() && this.eat(EQUALS_SIGN)) {
1434
- this._lastKeyValue = this._lastStrValue;
1792
+ const key = this._lastStrValue;
1435
1793
  if (this.eatUnicodePropertyValue()) {
1436
- this._lastValValue = this._lastStrValue;
1437
- if (isValidUnicodeProperty(this.ecmaVersion, this._lastKeyValue, this._lastValValue)) {
1438
- return true;
1794
+ const value = this._lastStrValue;
1795
+ if (isValidUnicodeProperty(this.ecmaVersion, key, value)) {
1796
+ return {
1797
+ key,
1798
+ value: value || null,
1799
+ };
1439
1800
  }
1440
1801
  this.raise("Invalid property name");
1441
1802
  }
@@ -1444,18 +1805,28 @@ class RegExpValidator {
1444
1805
  if (this.eatLoneUnicodePropertyNameOrValue()) {
1445
1806
  const nameOrValue = this._lastStrValue;
1446
1807
  if (isValidUnicodeProperty(this.ecmaVersion, "General_Category", nameOrValue)) {
1447
- this._lastKeyValue = "General_Category";
1448
- this._lastValValue = nameOrValue;
1449
- return true;
1808
+ return {
1809
+ key: "General_Category",
1810
+ value: nameOrValue || null,
1811
+ };
1450
1812
  }
1451
1813
  if (isValidLoneUnicodeProperty(this.ecmaVersion, nameOrValue)) {
1452
- this._lastKeyValue = nameOrValue;
1453
- this._lastValValue = "";
1454
- return true;
1814
+ return {
1815
+ key: nameOrValue,
1816
+ value: null,
1817
+ };
1818
+ }
1819
+ if (this._unicodeSetsMode &&
1820
+ isValidLoneUnicodePropertyOfString(this.ecmaVersion, nameOrValue)) {
1821
+ return {
1822
+ key: nameOrValue,
1823
+ value: null,
1824
+ strings: true,
1825
+ };
1455
1826
  }
1456
1827
  this.raise("Invalid property name");
1457
1828
  }
1458
- return false;
1829
+ return null;
1459
1830
  }
1460
1831
  eatUnicodePropertyName() {
1461
1832
  this._lastStrValue = "";
@@ -1482,7 +1853,7 @@ class RegExpValidator {
1482
1853
  if (this.eatFixedHexDigits(2)) {
1483
1854
  return true;
1484
1855
  }
1485
- if (this._uFlag || this.strict) {
1856
+ if (this._unicodeMode || this.strict) {
1486
1857
  this.raise("Invalid escape");
1487
1858
  }
1488
1859
  this.rewind(start);
@@ -1557,16 +1928,24 @@ class RegExpValidator {
1557
1928
  const DUMMY_PATTERN = {};
1558
1929
  const DUMMY_FLAGS = {};
1559
1930
  const DUMMY_CAPTURING_GROUP = {};
1931
+ function isClassSetOperand(node) {
1932
+ return (node.type === "Character" ||
1933
+ node.type === "CharacterSet" ||
1934
+ node.type === "CharacterClass" ||
1935
+ node.type === "ExpressionCharacterClass" ||
1936
+ node.type === "ClassStringDisjunction");
1937
+ }
1560
1938
  class RegExpParserState {
1561
1939
  constructor(options) {
1562
1940
  var _a;
1563
1941
  this._node = DUMMY_PATTERN;
1942
+ this._expressionBuffer = null;
1564
1943
  this._flags = DUMMY_FLAGS;
1565
1944
  this._backreferences = [];
1566
1945
  this._capturingGroups = [];
1567
1946
  this.source = "";
1568
1947
  this.strict = Boolean(options === null || options === void 0 ? void 0 : options.strict);
1569
- this.ecmaVersion = (_a = options === null || options === void 0 ? void 0 : options.ecmaVersion) !== null && _a !== void 0 ? _a : 2023;
1948
+ this.ecmaVersion = (_a = options === null || options === void 0 ? void 0 : options.ecmaVersion) !== null && _a !== void 0 ? _a : latestEcmaVersion;
1570
1949
  }
1571
1950
  get pattern() {
1572
1951
  if (this._node.type !== "Pattern") {
@@ -1580,7 +1959,7 @@ class RegExpParserState {
1580
1959
  }
1581
1960
  return this._flags;
1582
1961
  }
1583
- onRegExpFlags(start, end, { global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices, }) {
1962
+ onRegExpFlags(start, end, { global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices, unicodeSets, }) {
1584
1963
  this._flags = {
1585
1964
  type: "Flags",
1586
1965
  parent: null,
@@ -1594,6 +1973,7 @@ class RegExpParserState {
1594
1973
  sticky,
1595
1974
  dotAll,
1596
1975
  hasIndices,
1976
+ unicodeSets,
1597
1977
  };
1598
1978
  }
1599
1979
  onPatternEnter(start) {
@@ -1808,26 +2188,33 @@ class RegExpParserState {
1808
2188
  negate,
1809
2189
  });
1810
2190
  }
1811
- onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
2191
+ onUnicodePropertyCharacterSet(start, end, kind, key, value, negate, strings) {
1812
2192
  const parent = this._node;
1813
- if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
2193
+ if ((parent.type !== "Alternative" &&
2194
+ parent.type !== "CharacterClass") ||
2195
+ (strings && (negate || value))) {
1814
2196
  throw new Error("UnknownError");
1815
2197
  }
1816
- parent.elements.push({
2198
+ const base = {
1817
2199
  type: "CharacterSet",
1818
2200
  parent,
1819
2201
  start,
1820
2202
  end,
1821
2203
  raw: this.source.slice(start, end),
1822
2204
  kind,
2205
+ strings,
1823
2206
  key,
1824
- value,
1825
- negate,
1826
- });
2207
+ };
2208
+ const node = strings
2209
+ ? Object.assign(Object.assign({}, base), { value: null, negate: false, strings: true }) : Object.assign(Object.assign({}, base), { value,
2210
+ negate, strings: false });
2211
+ parent.elements.push(node);
1827
2212
  }
1828
2213
  onCharacter(start, end, value) {
1829
2214
  const parent = this._node;
1830
- if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
2215
+ if (parent.type !== "Alternative" &&
2216
+ parent.type !== "CharacterClass" &&
2217
+ parent.type !== "StringAlternative") {
1831
2218
  throw new Error("UnknownError");
1832
2219
  }
1833
2220
  parent.elements.push({
@@ -1856,31 +2243,66 @@ class RegExpParserState {
1856
2243
  parent.elements.push(node);
1857
2244
  this._backreferences.push(node);
1858
2245
  }
1859
- onCharacterClassEnter(start, negate) {
2246
+ onCharacterClassEnter(start, negate, unicodeSets) {
1860
2247
  const parent = this._node;
1861
- if (parent.type !== "Alternative") {
1862
- throw new Error("UnknownError");
1863
- }
1864
- this._node = {
2248
+ const base = {
1865
2249
  type: "CharacterClass",
1866
2250
  parent,
1867
2251
  start,
1868
2252
  end: start,
1869
2253
  raw: "",
2254
+ unicodeSets,
1870
2255
  negate,
1871
2256
  elements: [],
1872
2257
  };
1873
- parent.elements.push(this._node);
2258
+ if (parent.type === "Alternative") {
2259
+ const node = Object.assign(Object.assign({}, base), { parent });
2260
+ this._node = node;
2261
+ parent.elements.push(node);
2262
+ }
2263
+ else if (parent.type === "CharacterClass" &&
2264
+ parent.unicodeSets &&
2265
+ unicodeSets) {
2266
+ const node = Object.assign(Object.assign({}, base), { parent,
2267
+ unicodeSets });
2268
+ this._node = node;
2269
+ parent.elements.push(node);
2270
+ }
2271
+ else {
2272
+ throw new Error("UnknownError");
2273
+ }
1874
2274
  }
1875
2275
  onCharacterClassLeave(start, end) {
1876
2276
  const node = this._node;
1877
2277
  if (node.type !== "CharacterClass" ||
1878
- node.parent.type !== "Alternative") {
2278
+ (node.parent.type !== "Alternative" &&
2279
+ node.parent.type !== "CharacterClass") ||
2280
+ (this._expressionBuffer && node.elements.length > 0)) {
1879
2281
  throw new Error("UnknownError");
1880
2282
  }
2283
+ const parent = node.parent;
1881
2284
  node.end = end;
1882
2285
  node.raw = this.source.slice(start, end);
1883
- this._node = node.parent;
2286
+ this._node = parent;
2287
+ const expression = this._expressionBuffer;
2288
+ this._expressionBuffer = null;
2289
+ if (!expression) {
2290
+ return;
2291
+ }
2292
+ const newNode = {
2293
+ type: "ExpressionCharacterClass",
2294
+ parent,
2295
+ start: node.start,
2296
+ end: node.end,
2297
+ raw: node.raw,
2298
+ negate: node.negate,
2299
+ expression,
2300
+ };
2301
+ expression.parent = newNode;
2302
+ if (node !== parent.elements.pop()) {
2303
+ throw new Error("UnknownError");
2304
+ }
2305
+ parent.elements.push(newNode);
1884
2306
  }
1885
2307
  onCharacterClassRange(start, end) {
1886
2308
  const parent = this._node;
@@ -1889,15 +2311,19 @@ class RegExpParserState {
1889
2311
  }
1890
2312
  const elements = parent.elements;
1891
2313
  const max = elements.pop();
1892
- const hyphen = elements.pop();
2314
+ if (!max || max.type !== "Character") {
2315
+ throw new Error("UnknownError");
2316
+ }
2317
+ if (!parent.unicodeSets) {
2318
+ const hyphen = elements.pop();
2319
+ if (!hyphen ||
2320
+ hyphen.type !== "Character" ||
2321
+ hyphen.value !== HYPHEN_MINUS) {
2322
+ throw new Error("UnknownError");
2323
+ }
2324
+ }
1893
2325
  const min = elements.pop();
1894
- if (!min ||
1895
- !max ||
1896
- !hyphen ||
1897
- min.type !== "Character" ||
1898
- max.type !== "Character" ||
1899
- hyphen.type !== "Character" ||
1900
- hyphen.value !== HYPHEN_MINUS) {
2326
+ if (!min || min.type !== "Character") {
1901
2327
  throw new Error("UnknownError");
1902
2328
  }
1903
2329
  const node = {
@@ -1913,6 +2339,111 @@ class RegExpParserState {
1913
2339
  max.parent = node;
1914
2340
  elements.push(node);
1915
2341
  }
2342
+ onClassIntersection(start, end) {
2343
+ var _a;
2344
+ const parent = this._node;
2345
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2346
+ throw new Error("UnknownError");
2347
+ }
2348
+ const right = parent.elements.pop();
2349
+ const left = (_a = this._expressionBuffer) !== null && _a !== void 0 ? _a : parent.elements.pop();
2350
+ if (!left ||
2351
+ !right ||
2352
+ left.type === "ClassSubtraction" ||
2353
+ (left.type !== "ClassIntersection" && !isClassSetOperand(left)) ||
2354
+ !isClassSetOperand(right)) {
2355
+ throw new Error("UnknownError");
2356
+ }
2357
+ const node = {
2358
+ type: "ClassIntersection",
2359
+ parent: parent,
2360
+ start,
2361
+ end,
2362
+ raw: this.source.slice(start, end),
2363
+ left,
2364
+ right,
2365
+ };
2366
+ left.parent = node;
2367
+ right.parent = node;
2368
+ this._expressionBuffer = node;
2369
+ }
2370
+ onClassSubtraction(start, end) {
2371
+ var _a;
2372
+ const parent = this._node;
2373
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2374
+ throw new Error("UnknownError");
2375
+ }
2376
+ const right = parent.elements.pop();
2377
+ const left = (_a = this._expressionBuffer) !== null && _a !== void 0 ? _a : parent.elements.pop();
2378
+ if (!left ||
2379
+ !right ||
2380
+ left.type === "ClassIntersection" ||
2381
+ (left.type !== "ClassSubtraction" && !isClassSetOperand(left)) ||
2382
+ !isClassSetOperand(right)) {
2383
+ throw new Error("UnknownError");
2384
+ }
2385
+ const node = {
2386
+ type: "ClassSubtraction",
2387
+ parent: parent,
2388
+ start,
2389
+ end,
2390
+ raw: this.source.slice(start, end),
2391
+ left,
2392
+ right,
2393
+ };
2394
+ left.parent = node;
2395
+ right.parent = node;
2396
+ this._expressionBuffer = node;
2397
+ }
2398
+ onClassStringDisjunctionEnter(start) {
2399
+ const parent = this._node;
2400
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2401
+ throw new Error("UnknownError");
2402
+ }
2403
+ this._node = {
2404
+ type: "ClassStringDisjunction",
2405
+ parent,
2406
+ start,
2407
+ end: start,
2408
+ raw: "",
2409
+ alternatives: [],
2410
+ };
2411
+ parent.elements.push(this._node);
2412
+ }
2413
+ onClassStringDisjunctionLeave(start, end) {
2414
+ const node = this._node;
2415
+ if (node.type !== "ClassStringDisjunction" ||
2416
+ node.parent.type !== "CharacterClass") {
2417
+ throw new Error("UnknownError");
2418
+ }
2419
+ node.end = end;
2420
+ node.raw = this.source.slice(start, end);
2421
+ this._node = node.parent;
2422
+ }
2423
+ onStringAlternativeEnter(start) {
2424
+ const parent = this._node;
2425
+ if (parent.type !== "ClassStringDisjunction") {
2426
+ throw new Error("UnknownError");
2427
+ }
2428
+ this._node = {
2429
+ type: "StringAlternative",
2430
+ parent,
2431
+ start,
2432
+ end: start,
2433
+ raw: "",
2434
+ elements: [],
2435
+ };
2436
+ parent.alternatives.push(this._node);
2437
+ }
2438
+ onStringAlternativeLeave(start, end) {
2439
+ const node = this._node;
2440
+ if (node.type !== "StringAlternative") {
2441
+ throw new Error("UnknownError");
2442
+ }
2443
+ node.end = end;
2444
+ node.raw = this.source.slice(start, end);
2445
+ this._node = node.parent;
2446
+ }
1916
2447
  }
1917
2448
  class RegExpParser {
1918
2449
  constructor(options) {
@@ -1942,9 +2473,9 @@ class RegExpParser {
1942
2473
  this._validator.validateFlags(source, start, end);
1943
2474
  return this._state.flags;
1944
2475
  }
1945
- parsePattern(source, start = 0, end = source.length, uFlag = false) {
2476
+ parsePattern(source, start = 0, end = source.length, uFlagOrFlags = undefined) {
1946
2477
  this._state.source = source;
1947
- this._validator.validatePattern(source, start, end, uFlag);
2478
+ this._validator.validatePattern(source, start, end, uFlagOrFlags);
1948
2479
  return this._state.pattern;
1949
2480
  }
1950
2481
  }
@@ -1979,6 +2510,18 @@ class RegExpVisitor {
1979
2510
  case "CharacterSet":
1980
2511
  this.visitCharacterSet(node);
1981
2512
  break;
2513
+ case "ClassIntersection":
2514
+ this.visitClassIntersection(node);
2515
+ break;
2516
+ case "ClassStringDisjunction":
2517
+ this.visitClassStringDisjunction(node);
2518
+ break;
2519
+ case "ClassSubtraction":
2520
+ this.visitClassSubtraction(node);
2521
+ break;
2522
+ case "ExpressionCharacterClass":
2523
+ this.visitExpressionCharacterClass(node);
2524
+ break;
1982
2525
  case "Flags":
1983
2526
  this.visitFlags(node);
1984
2527
  break;
@@ -1994,6 +2537,9 @@ class RegExpVisitor {
1994
2537
  case "RegExpLiteral":
1995
2538
  this.visitRegExpLiteral(node);
1996
2539
  break;
2540
+ case "StringAlternative":
2541
+ this.visitStringAlternative(node);
2542
+ break;
1997
2543
  default:
1998
2544
  throw new Error(`Unknown type: ${node.type}`);
1999
2545
  }
@@ -2070,6 +2616,44 @@ class RegExpVisitor {
2070
2616
  this._handlers.onCharacterSetLeave(node);
2071
2617
  }
2072
2618
  }
2619
+ visitClassIntersection(node) {
2620
+ if (this._handlers.onClassIntersectionEnter) {
2621
+ this._handlers.onClassIntersectionEnter(node);
2622
+ }
2623
+ this.visit(node.left);
2624
+ this.visit(node.right);
2625
+ if (this._handlers.onClassIntersectionLeave) {
2626
+ this._handlers.onClassIntersectionLeave(node);
2627
+ }
2628
+ }
2629
+ visitClassStringDisjunction(node) {
2630
+ if (this._handlers.onClassStringDisjunctionEnter) {
2631
+ this._handlers.onClassStringDisjunctionEnter(node);
2632
+ }
2633
+ node.alternatives.forEach(this.visit, this);
2634
+ if (this._handlers.onClassStringDisjunctionLeave) {
2635
+ this._handlers.onClassStringDisjunctionLeave(node);
2636
+ }
2637
+ }
2638
+ visitClassSubtraction(node) {
2639
+ if (this._handlers.onClassSubtractionEnter) {
2640
+ this._handlers.onClassSubtractionEnter(node);
2641
+ }
2642
+ this.visit(node.left);
2643
+ this.visit(node.right);
2644
+ if (this._handlers.onClassSubtractionLeave) {
2645
+ this._handlers.onClassSubtractionLeave(node);
2646
+ }
2647
+ }
2648
+ visitExpressionCharacterClass(node) {
2649
+ if (this._handlers.onExpressionCharacterClassEnter) {
2650
+ this._handlers.onExpressionCharacterClassEnter(node);
2651
+ }
2652
+ this.visit(node.expression);
2653
+ if (this._handlers.onExpressionCharacterClassLeave) {
2654
+ this._handlers.onExpressionCharacterClassLeave(node);
2655
+ }
2656
+ }
2073
2657
  visitFlags(node) {
2074
2658
  if (this._handlers.onFlagsEnter) {
2075
2659
  this._handlers.onFlagsEnter(node);
@@ -2115,6 +2699,15 @@ class RegExpVisitor {
2115
2699
  this._handlers.onRegExpLiteralLeave(node);
2116
2700
  }
2117
2701
  }
2702
+ visitStringAlternative(node) {
2703
+ if (this._handlers.onStringAlternativeEnter) {
2704
+ this._handlers.onStringAlternativeEnter(node);
2705
+ }
2706
+ node.elements.forEach(this.visit, this);
2707
+ if (this._handlers.onStringAlternativeLeave) {
2708
+ this._handlers.onStringAlternativeLeave(node);
2709
+ }
2710
+ }
2118
2711
  }
2119
2712
 
2120
2713
  function parseRegExpLiteral(source, options) {