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