@eslint-community/regexpp 4.5.1 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -6,6 +6,8 @@ var ast = /*#__PURE__*/Object.freeze({
6
6
  __proto__: null
7
7
  });
8
8
 
9
+ const latestEcmaVersion = 2024;
10
+
9
11
  let largeIdStartRanges = undefined;
10
12
  let largeIdContinueRanges = undefined;
11
13
  function isIdStart(cp) {
@@ -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;
@@ -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);
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 = undefined) {
597
+ let unicode = false;
598
+ let unicodeSets = false;
599
+ if (uFlagOrFlags && this.ecmaVersion >= 2015) {
600
+ if (typeof uFlagOrFlags === "object") {
601
+ unicode = Boolean(uFlagOrFlags.unicode);
602
+ if (this.ecmaVersion >= 2024) {
603
+ unicodeSets = Boolean(uFlagOrFlags.unicodeSets);
604
+ }
605
+ }
606
+ else {
607
+ unicode = uFlagOrFlags;
608
+ }
609
+ }
610
+ if (unicode && unicodeSets) {
611
+ this.raise("Invalid regular expression flags");
612
+ }
613
+ const unicodeMode = unicode || unicodeSets;
614
+ const nFlag = (unicode && this.ecmaVersion >= 2018) ||
615
+ unicodeSets ||
616
+ Boolean(this._options.strict && this.ecmaVersion >= 2023);
617
+ const unicodeSetsMode = unicodeSets;
618
+ return { unicodeMode, nFlag, unicodeSetsMode };
619
+ }
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,7 @@ 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, this._unicodeMode, this.index, message);
680
828
  }
681
829
  eatRegExpBody() {
682
830
  const start = this.index;
@@ -791,7 +939,7 @@ class RegExpValidator {
791
939
  this.onAlternativeLeave(start, this.index, i);
792
940
  }
793
941
  consumeTerm() {
794
- if (this._uFlag || this.strict) {
942
+ if (this._unicodeMode || this.strict) {
795
943
  return (this.consumeAssertion() ||
796
944
  (this.consumeAtom() && this.consumeOptionalQuantifier()));
797
945
  }
@@ -860,8 +1008,7 @@ class RegExpValidator {
860
1008
  max = 1;
861
1009
  }
862
1010
  else if (this.eatBracedQuantifier(noConsume)) {
863
- min = this._lastMinValue;
864
- max = this._lastMaxValue;
1011
+ ({ min, max } = this._lastRange);
865
1012
  }
866
1013
  else {
867
1014
  return false;
@@ -875,23 +1022,23 @@ class RegExpValidator {
875
1022
  eatBracedQuantifier(noError) {
876
1023
  const start = this.index;
877
1024
  if (this.eat(LEFT_CURLY_BRACKET)) {
878
- this._lastMinValue = 0;
879
- this._lastMaxValue = Number.POSITIVE_INFINITY;
880
1025
  if (this.eatDecimalDigits()) {
881
- this._lastMinValue = this._lastMaxValue = this._lastIntValue;
1026
+ const min = this._lastIntValue;
1027
+ let max = min;
882
1028
  if (this.eat(COMMA)) {
883
- this._lastMaxValue = this.eatDecimalDigits()
1029
+ max = this.eatDecimalDigits()
884
1030
  ? this._lastIntValue
885
1031
  : Number.POSITIVE_INFINITY;
886
1032
  }
887
1033
  if (this.eat(RIGHT_CURLY_BRACKET)) {
888
- if (!noError && this._lastMaxValue < this._lastMinValue) {
1034
+ if (!noError && max < min) {
889
1035
  this.raise("numbers out of order in {} quantifier");
890
1036
  }
1037
+ this._lastRange = { min, max };
891
1038
  return true;
892
1039
  }
893
1040
  }
894
- if (!noError && (this._uFlag || this.strict)) {
1041
+ if (!noError && (this._unicodeMode || this.strict)) {
895
1042
  this.raise("Incomplete quantifier");
896
1043
  }
897
1044
  this.rewind(start);
@@ -902,7 +1049,7 @@ class RegExpValidator {
902
1049
  return (this.consumePatternCharacter() ||
903
1050
  this.consumeDot() ||
904
1051
  this.consumeReverseSolidusAtomEscape() ||
905
- this.consumeCharacterClass() ||
1052
+ Boolean(this.consumeCharacterClass()) ||
906
1053
  this.consumeUncapturingGroup() ||
907
1054
  this.consumeCapturingGroup());
908
1055
  }
@@ -962,7 +1109,7 @@ class RegExpValidator {
962
1109
  return (this.consumeDot() ||
963
1110
  this.consumeReverseSolidusAtomEscape() ||
964
1111
  this.consumeReverseSolidusFollowedByC() ||
965
- this.consumeCharacterClass() ||
1112
+ Boolean(this.consumeCharacterClass()) ||
966
1113
  this.consumeUncapturingGroup() ||
967
1114
  this.consumeCapturingGroup() ||
968
1115
  this.consumeInvalidBracedQuantifier() ||
@@ -1036,7 +1183,7 @@ class RegExpValidator {
1036
1183
  (this._nFlag && this.consumeKGroupName())) {
1037
1184
  return true;
1038
1185
  }
1039
- if (this.strict || this._uFlag) {
1186
+ if (this.strict || this._unicodeMode) {
1040
1187
  this.raise("Invalid escape");
1041
1188
  }
1042
1189
  return false;
@@ -1049,7 +1196,7 @@ class RegExpValidator {
1049
1196
  this.onBackreference(start - 1, this.index, n);
1050
1197
  return true;
1051
1198
  }
1052
- if (this.strict || this._uFlag) {
1199
+ if (this.strict || this._unicodeMode) {
1053
1200
  this.raise("Invalid escape");
1054
1201
  }
1055
1202
  this.rewind(start);
@@ -1057,52 +1204,57 @@ class RegExpValidator {
1057
1204
  return false;
1058
1205
  }
1059
1206
  consumeCharacterClassEscape() {
1207
+ var _a;
1060
1208
  const start = this.index;
1061
1209
  if (this.eat(LATIN_SMALL_LETTER_D)) {
1062
1210
  this._lastIntValue = -1;
1063
1211
  this.onEscapeCharacterSet(start - 1, this.index, "digit", false);
1064
- return true;
1212
+ return {};
1065
1213
  }
1066
1214
  if (this.eat(LATIN_CAPITAL_LETTER_D)) {
1067
1215
  this._lastIntValue = -1;
1068
1216
  this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
1069
- return true;
1217
+ return {};
1070
1218
  }
1071
1219
  if (this.eat(LATIN_SMALL_LETTER_S)) {
1072
1220
  this._lastIntValue = -1;
1073
1221
  this.onEscapeCharacterSet(start - 1, this.index, "space", false);
1074
- return true;
1222
+ return {};
1075
1223
  }
1076
1224
  if (this.eat(LATIN_CAPITAL_LETTER_S)) {
1077
1225
  this._lastIntValue = -1;
1078
1226
  this.onEscapeCharacterSet(start - 1, this.index, "space", true);
1079
- return true;
1227
+ return {};
1080
1228
  }
1081
1229
  if (this.eat(LATIN_SMALL_LETTER_W)) {
1082
1230
  this._lastIntValue = -1;
1083
1231
  this.onEscapeCharacterSet(start - 1, this.index, "word", false);
1084
- return true;
1232
+ return {};
1085
1233
  }
1086
1234
  if (this.eat(LATIN_CAPITAL_LETTER_W)) {
1087
1235
  this._lastIntValue = -1;
1088
1236
  this.onEscapeCharacterSet(start - 1, this.index, "word", true);
1089
- return true;
1237
+ return {};
1090
1238
  }
1091
1239
  let negate = false;
1092
- if (this._uFlag &&
1240
+ if (this._unicodeMode &&
1093
1241
  this.ecmaVersion >= 2018 &&
1094
1242
  (this.eat(LATIN_SMALL_LETTER_P) ||
1095
1243
  (negate = this.eat(LATIN_CAPITAL_LETTER_P)))) {
1096
1244
  this._lastIntValue = -1;
1245
+ let result = null;
1097
1246
  if (this.eat(LEFT_CURLY_BRACKET) &&
1098
- this.eatUnicodePropertyValueExpression() &&
1247
+ (result = this.eatUnicodePropertyValueExpression()) &&
1099
1248
  this.eat(RIGHT_CURLY_BRACKET)) {
1100
- this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", this._lastKeyValue, this._lastValValue || null, negate);
1101
- return true;
1249
+ if (negate && result.strings) {
1250
+ this.raise("Invalid property name");
1251
+ }
1252
+ this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", result.key, result.value, negate, (_a = result.strings) !== null && _a !== void 0 ? _a : false);
1253
+ return { mayContainStrings: result.strings };
1102
1254
  }
1103
1255
  this.raise("Invalid property name");
1104
1256
  }
1105
- return false;
1257
+ return null;
1106
1258
  }
1107
1259
  consumeCharacterEscape() {
1108
1260
  const start = this.index;
@@ -1112,7 +1264,7 @@ class RegExpValidator {
1112
1264
  this.eatHexEscapeSequence() ||
1113
1265
  this.eatRegExpUnicodeEscapeSequence() ||
1114
1266
  (!this.strict &&
1115
- !this._uFlag &&
1267
+ !this._unicodeMode &&
1116
1268
  this.eatLegacyOctalEscapeSequence()) ||
1117
1269
  this.eatIdentityEscape()) {
1118
1270
  this.onCharacter(start - 1, this.index, this._lastIntValue);
@@ -1137,18 +1289,31 @@ class RegExpValidator {
1137
1289
  const start = this.index;
1138
1290
  if (this.eat(LEFT_SQUARE_BRACKET)) {
1139
1291
  const negate = this.eat(CIRCUMFLEX_ACCENT);
1140
- this.onCharacterClassEnter(start, negate);
1141
- this.consumeClassRanges();
1292
+ this.onCharacterClassEnter(start, negate, this._unicodeSetsMode);
1293
+ const result = this.consumeClassContents();
1142
1294
  if (!this.eat(RIGHT_SQUARE_BRACKET)) {
1143
- this.raise("Unterminated character class");
1295
+ if (this.currentCodePoint === -1) {
1296
+ this.raise("Unterminated character class");
1297
+ }
1298
+ this.raise("Invalid character in character class");
1299
+ }
1300
+ if (negate && result.mayContainStrings) {
1301
+ this.raise("Negated character class may contain strings");
1144
1302
  }
1145
1303
  this.onCharacterClassLeave(start, this.index, negate);
1146
- return true;
1304
+ return result;
1147
1305
  }
1148
- return false;
1306
+ return null;
1149
1307
  }
1150
- consumeClassRanges() {
1151
- const strict = this.strict || this._uFlag;
1308
+ consumeClassContents() {
1309
+ if (this._unicodeSetsMode) {
1310
+ if (this.currentCodePoint === RIGHT_SQUARE_BRACKET) {
1311
+ return {};
1312
+ }
1313
+ const result = this.consumeClassSetExpression();
1314
+ return result;
1315
+ }
1316
+ const strict = this.strict || this._unicodeMode;
1152
1317
  for (;;) {
1153
1318
  const rangeStart = this.index;
1154
1319
  if (!this.consumeClassAtom()) {
@@ -1174,6 +1339,7 @@ class RegExpValidator {
1174
1339
  }
1175
1340
  this.onCharacterClassRange(rangeStart, this.index, min, max);
1176
1341
  }
1342
+ return {};
1177
1343
  }
1178
1344
  consumeClassAtom() {
1179
1345
  const start = this.index;
@@ -1196,7 +1362,7 @@ class RegExpValidator {
1196
1362
  this.onCharacter(start, this.index, this._lastIntValue);
1197
1363
  return true;
1198
1364
  }
1199
- if (this.strict || this._uFlag) {
1365
+ if (this.strict || this._unicodeMode) {
1200
1366
  this.raise("Invalid escape");
1201
1367
  }
1202
1368
  this.rewind(start);
@@ -1210,14 +1376,14 @@ class RegExpValidator {
1210
1376
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1211
1377
  return true;
1212
1378
  }
1213
- if (this._uFlag && this.eat(HYPHEN_MINUS)) {
1379
+ if (this._unicodeMode && this.eat(HYPHEN_MINUS)) {
1214
1380
  this._lastIntValue = HYPHEN_MINUS;
1215
1381
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1216
1382
  return true;
1217
1383
  }
1218
1384
  let cp = 0;
1219
1385
  if (!this.strict &&
1220
- !this._uFlag &&
1386
+ !this._unicodeMode &&
1221
1387
  this.currentCodePoint === LATIN_SMALL_LETTER_C &&
1222
1388
  (isDecimalDigit((cp = this.nextCodePoint)) || cp === LOW_LINE)) {
1223
1389
  this.advance();
@@ -1226,7 +1392,196 @@ class RegExpValidator {
1226
1392
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1227
1393
  return true;
1228
1394
  }
1229
- return (this.consumeCharacterClassEscape() || this.consumeCharacterEscape());
1395
+ return (Boolean(this.consumeCharacterClassEscape()) ||
1396
+ this.consumeCharacterEscape());
1397
+ }
1398
+ consumeClassSetExpression() {
1399
+ const start = this.index;
1400
+ let mayContainStrings = false;
1401
+ let result = null;
1402
+ if (this.consumeClassSetCharacter()) {
1403
+ if (this.consumeClassSetRangeFromOperator(start)) {
1404
+ this.consumeClassUnionRight({});
1405
+ return {};
1406
+ }
1407
+ mayContainStrings = false;
1408
+ }
1409
+ else if ((result = this.consumeClassSetOperand())) {
1410
+ mayContainStrings = result.mayContainStrings;
1411
+ }
1412
+ else {
1413
+ const cp = this.currentCodePoint;
1414
+ if (cp === REVERSE_SOLIDUS) {
1415
+ this.advance();
1416
+ this.raise("Invalid escape");
1417
+ }
1418
+ if (cp === this.nextCodePoint &&
1419
+ isClassSetReservedDoublePunctuatorCharacter(cp)) {
1420
+ this.raise("Invalid set operation in character class");
1421
+ }
1422
+ this.raise("Invalid character in character class");
1423
+ }
1424
+ if (this.eat2(AMPERSAND, AMPERSAND)) {
1425
+ while (this.currentCodePoint !== AMPERSAND &&
1426
+ (result = this.consumeClassSetOperand())) {
1427
+ this.onClassIntersection(start, this.index);
1428
+ if (!result.mayContainStrings) {
1429
+ mayContainStrings = false;
1430
+ }
1431
+ if (this.eat2(AMPERSAND, AMPERSAND)) {
1432
+ continue;
1433
+ }
1434
+ return { mayContainStrings };
1435
+ }
1436
+ this.raise("Invalid character in character class");
1437
+ }
1438
+ if (this.eat2(HYPHEN_MINUS, HYPHEN_MINUS)) {
1439
+ while (this.consumeClassSetOperand()) {
1440
+ this.onClassSubtraction(start, this.index);
1441
+ if (this.eat2(HYPHEN_MINUS, HYPHEN_MINUS)) {
1442
+ continue;
1443
+ }
1444
+ return { mayContainStrings };
1445
+ }
1446
+ this.raise("Invalid character in character class");
1447
+ }
1448
+ return this.consumeClassUnionRight({ mayContainStrings });
1449
+ }
1450
+ consumeClassUnionRight(leftResult) {
1451
+ let mayContainStrings = leftResult.mayContainStrings;
1452
+ for (;;) {
1453
+ const start = this.index;
1454
+ if (this.consumeClassSetCharacter()) {
1455
+ this.consumeClassSetRangeFromOperator(start);
1456
+ continue;
1457
+ }
1458
+ const result = this.consumeClassSetOperand();
1459
+ if (result) {
1460
+ if (result.mayContainStrings) {
1461
+ mayContainStrings = true;
1462
+ }
1463
+ continue;
1464
+ }
1465
+ break;
1466
+ }
1467
+ return { mayContainStrings };
1468
+ }
1469
+ consumeClassSetRangeFromOperator(start) {
1470
+ const currentStart = this.index;
1471
+ const min = this._lastIntValue;
1472
+ if (this.eat(HYPHEN_MINUS)) {
1473
+ if (this.consumeClassSetCharacter()) {
1474
+ const max = this._lastIntValue;
1475
+ if (min === -1 || max === -1) {
1476
+ this.raise("Invalid character class");
1477
+ }
1478
+ if (min > max) {
1479
+ this.raise("Range out of order in character class");
1480
+ }
1481
+ this.onCharacterClassRange(start, this.index, min, max);
1482
+ return true;
1483
+ }
1484
+ this.rewind(currentStart);
1485
+ }
1486
+ return false;
1487
+ }
1488
+ consumeClassSetOperand() {
1489
+ let result = null;
1490
+ if ((result = this.consumeNestedClass())) {
1491
+ return result;
1492
+ }
1493
+ if ((result = this.consumeClassStringDisjunction())) {
1494
+ return result;
1495
+ }
1496
+ if (this.consumeClassSetCharacter()) {
1497
+ return {};
1498
+ }
1499
+ return null;
1500
+ }
1501
+ consumeNestedClass() {
1502
+ const start = this.index;
1503
+ if (this.eat(LEFT_SQUARE_BRACKET)) {
1504
+ const negate = this.eat(CIRCUMFLEX_ACCENT);
1505
+ this.onCharacterClassEnter(start, negate, true);
1506
+ const result = this.consumeClassContents();
1507
+ if (!this.eat(RIGHT_SQUARE_BRACKET)) {
1508
+ this.raise("Unterminated character class");
1509
+ }
1510
+ if (negate && result.mayContainStrings) {
1511
+ this.raise("Negated character class may contain strings");
1512
+ }
1513
+ this.onCharacterClassLeave(start, this.index, negate);
1514
+ return result;
1515
+ }
1516
+ if (this.eat(REVERSE_SOLIDUS)) {
1517
+ const result = this.consumeCharacterClassEscape();
1518
+ if (result) {
1519
+ return result;
1520
+ }
1521
+ this.rewind(start);
1522
+ }
1523
+ return null;
1524
+ }
1525
+ consumeClassStringDisjunction() {
1526
+ const start = this.index;
1527
+ if (this.eat3(REVERSE_SOLIDUS, LATIN_SMALL_LETTER_Q, LEFT_CURLY_BRACKET)) {
1528
+ this.onClassStringDisjunctionEnter(start);
1529
+ let i = 0;
1530
+ let mayContainStrings = false;
1531
+ do {
1532
+ if (this.consumeClassString(i++).mayContainStrings) {
1533
+ mayContainStrings = true;
1534
+ }
1535
+ } while (this.eat(VERTICAL_LINE));
1536
+ if (this.eat(RIGHT_CURLY_BRACKET)) {
1537
+ this.onClassStringDisjunctionLeave(start, this.index);
1538
+ return { mayContainStrings };
1539
+ }
1540
+ this.raise("Unterminated class string disjunction");
1541
+ }
1542
+ return null;
1543
+ }
1544
+ consumeClassString(i) {
1545
+ const start = this.index;
1546
+ let count = 0;
1547
+ this.onStringAlternativeEnter(start, i);
1548
+ while (this.currentCodePoint !== -1 &&
1549
+ this.consumeClassSetCharacter()) {
1550
+ count++;
1551
+ }
1552
+ this.onStringAlternativeLeave(start, this.index, i);
1553
+ return { mayContainStrings: count !== 1 };
1554
+ }
1555
+ consumeClassSetCharacter() {
1556
+ const start = this.index;
1557
+ const cp = this.currentCodePoint;
1558
+ if (cp !== this.nextCodePoint ||
1559
+ !isClassSetReservedDoublePunctuatorCharacter(cp)) {
1560
+ if (cp !== -1 && !isClassSetSyntaxCharacter(cp)) {
1561
+ this._lastIntValue = cp;
1562
+ this.advance();
1563
+ this.onCharacter(start, this.index, this._lastIntValue);
1564
+ return true;
1565
+ }
1566
+ }
1567
+ if (this.eat(REVERSE_SOLIDUS)) {
1568
+ if (this.consumeCharacterEscape()) {
1569
+ return true;
1570
+ }
1571
+ if (isClassSetReservedPunctuator(this.currentCodePoint)) {
1572
+ this._lastIntValue = this.currentCodePoint;
1573
+ this.advance();
1574
+ this.onCharacter(start, this.index, this._lastIntValue);
1575
+ return true;
1576
+ }
1577
+ if (this.eat(LATIN_SMALL_LETTER_B)) {
1578
+ this._lastIntValue = BACKSPACE;
1579
+ this.onCharacter(start, this.index, this._lastIntValue);
1580
+ return true;
1581
+ }
1582
+ this.rewind(start);
1583
+ }
1584
+ return false;
1230
1585
  }
1231
1586
  eatGroupName() {
1232
1587
  if (this.eat(LESS_THAN_SIGN)) {
@@ -1249,7 +1604,7 @@ class RegExpValidator {
1249
1604
  }
1250
1605
  eatRegExpIdentifierStart() {
1251
1606
  const start = this.index;
1252
- const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1607
+ const forceUFlag = !this._unicodeMode && this.ecmaVersion >= 2020;
1253
1608
  let cp = this.currentCodePoint;
1254
1609
  this.advance();
1255
1610
  if (cp === REVERSE_SOLIDUS &&
@@ -1262,7 +1617,7 @@ class RegExpValidator {
1262
1617
  cp = combineSurrogatePair(cp, this.currentCodePoint);
1263
1618
  this.advance();
1264
1619
  }
1265
- if (isRegExpIdentifierStart(cp)) {
1620
+ if (isIdentifierStartChar(cp)) {
1266
1621
  this._lastIntValue = cp;
1267
1622
  return true;
1268
1623
  }
@@ -1273,7 +1628,7 @@ class RegExpValidator {
1273
1628
  }
1274
1629
  eatRegExpIdentifierPart() {
1275
1630
  const start = this.index;
1276
- const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1631
+ const forceUFlag = !this._unicodeMode && this.ecmaVersion >= 2020;
1277
1632
  let cp = this.currentCodePoint;
1278
1633
  this.advance();
1279
1634
  if (cp === REVERSE_SOLIDUS &&
@@ -1286,7 +1641,7 @@ class RegExpValidator {
1286
1641
  cp = combineSurrogatePair(cp, this.currentCodePoint);
1287
1642
  this.advance();
1288
1643
  }
1289
- if (isRegExpIdentifierPart(cp)) {
1644
+ if (isIdentifierPartChar(cp)) {
1290
1645
  this._lastIntValue = cp;
1291
1646
  return true;
1292
1647
  }
@@ -1348,7 +1703,7 @@ class RegExpValidator {
1348
1703
  }
1349
1704
  eatRegExpUnicodeEscapeSequence(forceUFlag = false) {
1350
1705
  const start = this.index;
1351
- const uFlag = forceUFlag || this._uFlag;
1706
+ const uFlag = forceUFlag || this._unicodeMode;
1352
1707
  if (this.eat(LATIN_SMALL_LETTER_U)) {
1353
1708
  if ((uFlag && this.eatRegExpUnicodeSurrogatePairEscape()) ||
1354
1709
  this.eatFixedHexDigits(4) ||
@@ -1404,7 +1759,7 @@ class RegExpValidator {
1404
1759
  if (cp === -1) {
1405
1760
  return false;
1406
1761
  }
1407
- if (this._uFlag) {
1762
+ if (this._unicodeMode) {
1408
1763
  return isSyntaxCharacter(cp) || cp === SOLIDUS;
1409
1764
  }
1410
1765
  if (this.strict) {
@@ -1431,11 +1786,14 @@ class RegExpValidator {
1431
1786
  eatUnicodePropertyValueExpression() {
1432
1787
  const start = this.index;
1433
1788
  if (this.eatUnicodePropertyName() && this.eat(EQUALS_SIGN)) {
1434
- this._lastKeyValue = this._lastStrValue;
1789
+ const key = this._lastStrValue;
1435
1790
  if (this.eatUnicodePropertyValue()) {
1436
- this._lastValValue = this._lastStrValue;
1437
- if (isValidUnicodeProperty(this.ecmaVersion, this._lastKeyValue, this._lastValValue)) {
1438
- return true;
1791
+ const value = this._lastStrValue;
1792
+ if (isValidUnicodeProperty(this.ecmaVersion, key, value)) {
1793
+ return {
1794
+ key,
1795
+ value: value || null,
1796
+ };
1439
1797
  }
1440
1798
  this.raise("Invalid property name");
1441
1799
  }
@@ -1444,18 +1802,28 @@ class RegExpValidator {
1444
1802
  if (this.eatLoneUnicodePropertyNameOrValue()) {
1445
1803
  const nameOrValue = this._lastStrValue;
1446
1804
  if (isValidUnicodeProperty(this.ecmaVersion, "General_Category", nameOrValue)) {
1447
- this._lastKeyValue = "General_Category";
1448
- this._lastValValue = nameOrValue;
1449
- return true;
1805
+ return {
1806
+ key: "General_Category",
1807
+ value: nameOrValue || null,
1808
+ };
1450
1809
  }
1451
1810
  if (isValidLoneUnicodeProperty(this.ecmaVersion, nameOrValue)) {
1452
- this._lastKeyValue = nameOrValue;
1453
- this._lastValValue = "";
1454
- return true;
1811
+ return {
1812
+ key: nameOrValue,
1813
+ value: null,
1814
+ };
1815
+ }
1816
+ if (this._unicodeSetsMode &&
1817
+ isValidLoneUnicodePropertyOfString(this.ecmaVersion, nameOrValue)) {
1818
+ return {
1819
+ key: nameOrValue,
1820
+ value: null,
1821
+ strings: true,
1822
+ };
1455
1823
  }
1456
1824
  this.raise("Invalid property name");
1457
1825
  }
1458
- return false;
1826
+ return null;
1459
1827
  }
1460
1828
  eatUnicodePropertyName() {
1461
1829
  this._lastStrValue = "";
@@ -1482,7 +1850,7 @@ class RegExpValidator {
1482
1850
  if (this.eatFixedHexDigits(2)) {
1483
1851
  return true;
1484
1852
  }
1485
- if (this._uFlag || this.strict) {
1853
+ if (this._unicodeMode || this.strict) {
1486
1854
  this.raise("Invalid escape");
1487
1855
  }
1488
1856
  this.rewind(start);
@@ -1557,16 +1925,24 @@ class RegExpValidator {
1557
1925
  const DUMMY_PATTERN = {};
1558
1926
  const DUMMY_FLAGS = {};
1559
1927
  const DUMMY_CAPTURING_GROUP = {};
1928
+ function isClassSetOperand(node) {
1929
+ return (node.type === "Character" ||
1930
+ node.type === "CharacterSet" ||
1931
+ node.type === "CharacterClass" ||
1932
+ node.type === "ExpressionCharacterClass" ||
1933
+ node.type === "ClassStringDisjunction");
1934
+ }
1560
1935
  class RegExpParserState {
1561
1936
  constructor(options) {
1562
1937
  var _a;
1563
1938
  this._node = DUMMY_PATTERN;
1939
+ this._expressionBuffer = null;
1564
1940
  this._flags = DUMMY_FLAGS;
1565
1941
  this._backreferences = [];
1566
1942
  this._capturingGroups = [];
1567
1943
  this.source = "";
1568
1944
  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;
1945
+ this.ecmaVersion = (_a = options === null || options === void 0 ? void 0 : options.ecmaVersion) !== null && _a !== void 0 ? _a : latestEcmaVersion;
1570
1946
  }
1571
1947
  get pattern() {
1572
1948
  if (this._node.type !== "Pattern") {
@@ -1580,7 +1956,7 @@ class RegExpParserState {
1580
1956
  }
1581
1957
  return this._flags;
1582
1958
  }
1583
- onRegExpFlags(start, end, { global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices, }) {
1959
+ onRegExpFlags(start, end, { global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices, unicodeSets, }) {
1584
1960
  this._flags = {
1585
1961
  type: "Flags",
1586
1962
  parent: null,
@@ -1594,6 +1970,7 @@ class RegExpParserState {
1594
1970
  sticky,
1595
1971
  dotAll,
1596
1972
  hasIndices,
1973
+ unicodeSets,
1597
1974
  };
1598
1975
  }
1599
1976
  onPatternEnter(start) {
@@ -1808,26 +2185,33 @@ class RegExpParserState {
1808
2185
  negate,
1809
2186
  });
1810
2187
  }
1811
- onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
2188
+ onUnicodePropertyCharacterSet(start, end, kind, key, value, negate, strings) {
1812
2189
  const parent = this._node;
1813
- if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
2190
+ if ((parent.type !== "Alternative" &&
2191
+ parent.type !== "CharacterClass") ||
2192
+ (strings && (negate || value))) {
1814
2193
  throw new Error("UnknownError");
1815
2194
  }
1816
- parent.elements.push({
2195
+ const base = {
1817
2196
  type: "CharacterSet",
1818
2197
  parent,
1819
2198
  start,
1820
2199
  end,
1821
2200
  raw: this.source.slice(start, end),
1822
2201
  kind,
2202
+ strings,
1823
2203
  key,
1824
- value,
1825
- negate,
1826
- });
2204
+ };
2205
+ const node = strings
2206
+ ? Object.assign(Object.assign({}, base), { value: null, negate: false, strings: true }) : Object.assign(Object.assign({}, base), { value,
2207
+ negate, strings: false });
2208
+ parent.elements.push(node);
1827
2209
  }
1828
2210
  onCharacter(start, end, value) {
1829
2211
  const parent = this._node;
1830
- if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
2212
+ if (parent.type !== "Alternative" &&
2213
+ parent.type !== "CharacterClass" &&
2214
+ parent.type !== "StringAlternative") {
1831
2215
  throw new Error("UnknownError");
1832
2216
  }
1833
2217
  parent.elements.push({
@@ -1856,31 +2240,66 @@ class RegExpParserState {
1856
2240
  parent.elements.push(node);
1857
2241
  this._backreferences.push(node);
1858
2242
  }
1859
- onCharacterClassEnter(start, negate) {
2243
+ onCharacterClassEnter(start, negate, unicodeSets) {
1860
2244
  const parent = this._node;
1861
- if (parent.type !== "Alternative") {
1862
- throw new Error("UnknownError");
1863
- }
1864
- this._node = {
2245
+ const base = {
1865
2246
  type: "CharacterClass",
1866
2247
  parent,
1867
2248
  start,
1868
2249
  end: start,
1869
2250
  raw: "",
2251
+ unicodeSets,
1870
2252
  negate,
1871
2253
  elements: [],
1872
2254
  };
1873
- parent.elements.push(this._node);
2255
+ if (parent.type === "Alternative") {
2256
+ const node = Object.assign(Object.assign({}, base), { parent });
2257
+ this._node = node;
2258
+ parent.elements.push(node);
2259
+ }
2260
+ else if (parent.type === "CharacterClass" &&
2261
+ parent.unicodeSets &&
2262
+ unicodeSets) {
2263
+ const node = Object.assign(Object.assign({}, base), { parent,
2264
+ unicodeSets });
2265
+ this._node = node;
2266
+ parent.elements.push(node);
2267
+ }
2268
+ else {
2269
+ throw new Error("UnknownError");
2270
+ }
1874
2271
  }
1875
2272
  onCharacterClassLeave(start, end) {
1876
2273
  const node = this._node;
1877
2274
  if (node.type !== "CharacterClass" ||
1878
- node.parent.type !== "Alternative") {
2275
+ (node.parent.type !== "Alternative" &&
2276
+ node.parent.type !== "CharacterClass") ||
2277
+ (this._expressionBuffer && node.elements.length > 0)) {
1879
2278
  throw new Error("UnknownError");
1880
2279
  }
2280
+ const parent = node.parent;
1881
2281
  node.end = end;
1882
2282
  node.raw = this.source.slice(start, end);
1883
- this._node = node.parent;
2283
+ this._node = parent;
2284
+ const expression = this._expressionBuffer;
2285
+ this._expressionBuffer = null;
2286
+ if (!expression) {
2287
+ return;
2288
+ }
2289
+ const newNode = {
2290
+ type: "ExpressionCharacterClass",
2291
+ parent,
2292
+ start: node.start,
2293
+ end: node.end,
2294
+ raw: node.raw,
2295
+ negate: node.negate,
2296
+ expression,
2297
+ };
2298
+ expression.parent = newNode;
2299
+ if (node !== parent.elements.pop()) {
2300
+ throw new Error("UnknownError");
2301
+ }
2302
+ parent.elements.push(newNode);
1884
2303
  }
1885
2304
  onCharacterClassRange(start, end) {
1886
2305
  const parent = this._node;
@@ -1889,15 +2308,19 @@ class RegExpParserState {
1889
2308
  }
1890
2309
  const elements = parent.elements;
1891
2310
  const max = elements.pop();
1892
- const hyphen = elements.pop();
2311
+ if (!max || max.type !== "Character") {
2312
+ throw new Error("UnknownError");
2313
+ }
2314
+ if (!parent.unicodeSets) {
2315
+ const hyphen = elements.pop();
2316
+ if (!hyphen ||
2317
+ hyphen.type !== "Character" ||
2318
+ hyphen.value !== HYPHEN_MINUS) {
2319
+ throw new Error("UnknownError");
2320
+ }
2321
+ }
1893
2322
  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) {
2323
+ if (!min || min.type !== "Character") {
1901
2324
  throw new Error("UnknownError");
1902
2325
  }
1903
2326
  const node = {
@@ -1913,6 +2336,111 @@ class RegExpParserState {
1913
2336
  max.parent = node;
1914
2337
  elements.push(node);
1915
2338
  }
2339
+ onClassIntersection(start, end) {
2340
+ var _a;
2341
+ const parent = this._node;
2342
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2343
+ throw new Error("UnknownError");
2344
+ }
2345
+ const right = parent.elements.pop();
2346
+ const left = (_a = this._expressionBuffer) !== null && _a !== void 0 ? _a : parent.elements.pop();
2347
+ if (!left ||
2348
+ !right ||
2349
+ left.type === "ClassSubtraction" ||
2350
+ (left.type !== "ClassIntersection" && !isClassSetOperand(left)) ||
2351
+ !isClassSetOperand(right)) {
2352
+ throw new Error("UnknownError");
2353
+ }
2354
+ const node = {
2355
+ type: "ClassIntersection",
2356
+ parent: parent,
2357
+ start,
2358
+ end,
2359
+ raw: this.source.slice(start, end),
2360
+ left,
2361
+ right,
2362
+ };
2363
+ left.parent = node;
2364
+ right.parent = node;
2365
+ this._expressionBuffer = node;
2366
+ }
2367
+ onClassSubtraction(start, end) {
2368
+ var _a;
2369
+ const parent = this._node;
2370
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2371
+ throw new Error("UnknownError");
2372
+ }
2373
+ const right = parent.elements.pop();
2374
+ const left = (_a = this._expressionBuffer) !== null && _a !== void 0 ? _a : parent.elements.pop();
2375
+ if (!left ||
2376
+ !right ||
2377
+ left.type === "ClassIntersection" ||
2378
+ (left.type !== "ClassSubtraction" && !isClassSetOperand(left)) ||
2379
+ !isClassSetOperand(right)) {
2380
+ throw new Error("UnknownError");
2381
+ }
2382
+ const node = {
2383
+ type: "ClassSubtraction",
2384
+ parent: parent,
2385
+ start,
2386
+ end,
2387
+ raw: this.source.slice(start, end),
2388
+ left,
2389
+ right,
2390
+ };
2391
+ left.parent = node;
2392
+ right.parent = node;
2393
+ this._expressionBuffer = node;
2394
+ }
2395
+ onClassStringDisjunctionEnter(start) {
2396
+ const parent = this._node;
2397
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2398
+ throw new Error("UnknownError");
2399
+ }
2400
+ this._node = {
2401
+ type: "ClassStringDisjunction",
2402
+ parent,
2403
+ start,
2404
+ end: start,
2405
+ raw: "",
2406
+ alternatives: [],
2407
+ };
2408
+ parent.elements.push(this._node);
2409
+ }
2410
+ onClassStringDisjunctionLeave(start, end) {
2411
+ const node = this._node;
2412
+ if (node.type !== "ClassStringDisjunction" ||
2413
+ node.parent.type !== "CharacterClass") {
2414
+ throw new Error("UnknownError");
2415
+ }
2416
+ node.end = end;
2417
+ node.raw = this.source.slice(start, end);
2418
+ this._node = node.parent;
2419
+ }
2420
+ onStringAlternativeEnter(start) {
2421
+ const parent = this._node;
2422
+ if (parent.type !== "ClassStringDisjunction") {
2423
+ throw new Error("UnknownError");
2424
+ }
2425
+ this._node = {
2426
+ type: "StringAlternative",
2427
+ parent,
2428
+ start,
2429
+ end: start,
2430
+ raw: "",
2431
+ elements: [],
2432
+ };
2433
+ parent.alternatives.push(this._node);
2434
+ }
2435
+ onStringAlternativeLeave(start, end) {
2436
+ const node = this._node;
2437
+ if (node.type !== "StringAlternative") {
2438
+ throw new Error("UnknownError");
2439
+ }
2440
+ node.end = end;
2441
+ node.raw = this.source.slice(start, end);
2442
+ this._node = node.parent;
2443
+ }
1916
2444
  }
1917
2445
  class RegExpParser {
1918
2446
  constructor(options) {
@@ -1942,9 +2470,9 @@ class RegExpParser {
1942
2470
  this._validator.validateFlags(source, start, end);
1943
2471
  return this._state.flags;
1944
2472
  }
1945
- parsePattern(source, start = 0, end = source.length, uFlag = false) {
2473
+ parsePattern(source, start = 0, end = source.length, uFlagOrFlags = undefined) {
1946
2474
  this._state.source = source;
1947
- this._validator.validatePattern(source, start, end, uFlag);
2475
+ this._validator.validatePattern(source, start, end, uFlagOrFlags);
1948
2476
  return this._state.pattern;
1949
2477
  }
1950
2478
  }
@@ -1979,6 +2507,18 @@ class RegExpVisitor {
1979
2507
  case "CharacterSet":
1980
2508
  this.visitCharacterSet(node);
1981
2509
  break;
2510
+ case "ClassIntersection":
2511
+ this.visitClassIntersection(node);
2512
+ break;
2513
+ case "ClassStringDisjunction":
2514
+ this.visitClassStringDisjunction(node);
2515
+ break;
2516
+ case "ClassSubtraction":
2517
+ this.visitClassSubtraction(node);
2518
+ break;
2519
+ case "ExpressionCharacterClass":
2520
+ this.visitExpressionCharacterClass(node);
2521
+ break;
1982
2522
  case "Flags":
1983
2523
  this.visitFlags(node);
1984
2524
  break;
@@ -1994,6 +2534,9 @@ class RegExpVisitor {
1994
2534
  case "RegExpLiteral":
1995
2535
  this.visitRegExpLiteral(node);
1996
2536
  break;
2537
+ case "StringAlternative":
2538
+ this.visitStringAlternative(node);
2539
+ break;
1997
2540
  default:
1998
2541
  throw new Error(`Unknown type: ${node.type}`);
1999
2542
  }
@@ -2070,6 +2613,44 @@ class RegExpVisitor {
2070
2613
  this._handlers.onCharacterSetLeave(node);
2071
2614
  }
2072
2615
  }
2616
+ visitClassIntersection(node) {
2617
+ if (this._handlers.onClassIntersectionEnter) {
2618
+ this._handlers.onClassIntersectionEnter(node);
2619
+ }
2620
+ this.visit(node.left);
2621
+ this.visit(node.right);
2622
+ if (this._handlers.onClassIntersectionLeave) {
2623
+ this._handlers.onClassIntersectionLeave(node);
2624
+ }
2625
+ }
2626
+ visitClassStringDisjunction(node) {
2627
+ if (this._handlers.onClassStringDisjunctionEnter) {
2628
+ this._handlers.onClassStringDisjunctionEnter(node);
2629
+ }
2630
+ node.alternatives.forEach(this.visit, this);
2631
+ if (this._handlers.onClassStringDisjunctionLeave) {
2632
+ this._handlers.onClassStringDisjunctionLeave(node);
2633
+ }
2634
+ }
2635
+ visitClassSubtraction(node) {
2636
+ if (this._handlers.onClassSubtractionEnter) {
2637
+ this._handlers.onClassSubtractionEnter(node);
2638
+ }
2639
+ this.visit(node.left);
2640
+ this.visit(node.right);
2641
+ if (this._handlers.onClassSubtractionLeave) {
2642
+ this._handlers.onClassSubtractionLeave(node);
2643
+ }
2644
+ }
2645
+ visitExpressionCharacterClass(node) {
2646
+ if (this._handlers.onExpressionCharacterClassEnter) {
2647
+ this._handlers.onExpressionCharacterClassEnter(node);
2648
+ }
2649
+ this.visit(node.expression);
2650
+ if (this._handlers.onExpressionCharacterClassLeave) {
2651
+ this._handlers.onExpressionCharacterClassLeave(node);
2652
+ }
2653
+ }
2073
2654
  visitFlags(node) {
2074
2655
  if (this._handlers.onFlagsEnter) {
2075
2656
  this._handlers.onFlagsEnter(node);
@@ -2115,6 +2696,15 @@ class RegExpVisitor {
2115
2696
  this._handlers.onRegExpLiteralLeave(node);
2116
2697
  }
2117
2698
  }
2699
+ visitStringAlternative(node) {
2700
+ if (this._handlers.onStringAlternativeEnter) {
2701
+ this._handlers.onStringAlternativeEnter(node);
2702
+ }
2703
+ node.elements.forEach(this.visit, this);
2704
+ if (this._handlers.onStringAlternativeLeave) {
2705
+ this._handlers.onStringAlternativeLeave(node);
2706
+ }
2707
+ }
2118
2708
  }
2119
2709
 
2120
2710
  function parseRegExpLiteral(source, options) {