@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.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;
@@ -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);
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 = undefined) {
593
+ let unicode = false;
594
+ let unicodeSets = false;
595
+ if (uFlagOrFlags && this.ecmaVersion >= 2015) {
596
+ if (typeof uFlagOrFlags === "object") {
597
+ unicode = Boolean(uFlagOrFlags.unicode);
598
+ if (this.ecmaVersion >= 2024) {
599
+ unicodeSets = Boolean(uFlagOrFlags.unicodeSets);
600
+ }
601
+ }
602
+ else {
603
+ unicode = uFlagOrFlags;
604
+ }
605
+ }
606
+ if (unicode && unicodeSets) {
607
+ this.raise("Invalid regular expression flags");
608
+ }
609
+ const unicodeMode = unicode || unicodeSets;
610
+ const nFlag = (unicode && this.ecmaVersion >= 2018) ||
611
+ unicodeSets ||
612
+ Boolean(this._options.strict && this.ecmaVersion >= 2023);
613
+ const unicodeSetsMode = unicodeSets;
614
+ return { unicodeMode, nFlag, unicodeSetsMode };
615
+ }
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,7 @@ 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, this._unicodeMode, this.index, message);
676
824
  }
677
825
  eatRegExpBody() {
678
826
  const start = this.index;
@@ -787,7 +935,7 @@ class RegExpValidator {
787
935
  this.onAlternativeLeave(start, this.index, i);
788
936
  }
789
937
  consumeTerm() {
790
- if (this._uFlag || this.strict) {
938
+ if (this._unicodeMode || this.strict) {
791
939
  return (this.consumeAssertion() ||
792
940
  (this.consumeAtom() && this.consumeOptionalQuantifier()));
793
941
  }
@@ -856,8 +1004,7 @@ class RegExpValidator {
856
1004
  max = 1;
857
1005
  }
858
1006
  else if (this.eatBracedQuantifier(noConsume)) {
859
- min = this._lastMinValue;
860
- max = this._lastMaxValue;
1007
+ ({ min, max } = this._lastRange);
861
1008
  }
862
1009
  else {
863
1010
  return false;
@@ -871,23 +1018,23 @@ class RegExpValidator {
871
1018
  eatBracedQuantifier(noError) {
872
1019
  const start = this.index;
873
1020
  if (this.eat(LEFT_CURLY_BRACKET)) {
874
- this._lastMinValue = 0;
875
- this._lastMaxValue = Number.POSITIVE_INFINITY;
876
1021
  if (this.eatDecimalDigits()) {
877
- this._lastMinValue = this._lastMaxValue = this._lastIntValue;
1022
+ const min = this._lastIntValue;
1023
+ let max = min;
878
1024
  if (this.eat(COMMA)) {
879
- this._lastMaxValue = this.eatDecimalDigits()
1025
+ max = this.eatDecimalDigits()
880
1026
  ? this._lastIntValue
881
1027
  : Number.POSITIVE_INFINITY;
882
1028
  }
883
1029
  if (this.eat(RIGHT_CURLY_BRACKET)) {
884
- if (!noError && this._lastMaxValue < this._lastMinValue) {
1030
+ if (!noError && max < min) {
885
1031
  this.raise("numbers out of order in {} quantifier");
886
1032
  }
1033
+ this._lastRange = { min, max };
887
1034
  return true;
888
1035
  }
889
1036
  }
890
- if (!noError && (this._uFlag || this.strict)) {
1037
+ if (!noError && (this._unicodeMode || this.strict)) {
891
1038
  this.raise("Incomplete quantifier");
892
1039
  }
893
1040
  this.rewind(start);
@@ -898,7 +1045,7 @@ class RegExpValidator {
898
1045
  return (this.consumePatternCharacter() ||
899
1046
  this.consumeDot() ||
900
1047
  this.consumeReverseSolidusAtomEscape() ||
901
- this.consumeCharacterClass() ||
1048
+ Boolean(this.consumeCharacterClass()) ||
902
1049
  this.consumeUncapturingGroup() ||
903
1050
  this.consumeCapturingGroup());
904
1051
  }
@@ -958,7 +1105,7 @@ class RegExpValidator {
958
1105
  return (this.consumeDot() ||
959
1106
  this.consumeReverseSolidusAtomEscape() ||
960
1107
  this.consumeReverseSolidusFollowedByC() ||
961
- this.consumeCharacterClass() ||
1108
+ Boolean(this.consumeCharacterClass()) ||
962
1109
  this.consumeUncapturingGroup() ||
963
1110
  this.consumeCapturingGroup() ||
964
1111
  this.consumeInvalidBracedQuantifier() ||
@@ -1032,7 +1179,7 @@ class RegExpValidator {
1032
1179
  (this._nFlag && this.consumeKGroupName())) {
1033
1180
  return true;
1034
1181
  }
1035
- if (this.strict || this._uFlag) {
1182
+ if (this.strict || this._unicodeMode) {
1036
1183
  this.raise("Invalid escape");
1037
1184
  }
1038
1185
  return false;
@@ -1045,7 +1192,7 @@ class RegExpValidator {
1045
1192
  this.onBackreference(start - 1, this.index, n);
1046
1193
  return true;
1047
1194
  }
1048
- if (this.strict || this._uFlag) {
1195
+ if (this.strict || this._unicodeMode) {
1049
1196
  this.raise("Invalid escape");
1050
1197
  }
1051
1198
  this.rewind(start);
@@ -1053,52 +1200,57 @@ class RegExpValidator {
1053
1200
  return false;
1054
1201
  }
1055
1202
  consumeCharacterClassEscape() {
1203
+ var _a;
1056
1204
  const start = this.index;
1057
1205
  if (this.eat(LATIN_SMALL_LETTER_D)) {
1058
1206
  this._lastIntValue = -1;
1059
1207
  this.onEscapeCharacterSet(start - 1, this.index, "digit", false);
1060
- return true;
1208
+ return {};
1061
1209
  }
1062
1210
  if (this.eat(LATIN_CAPITAL_LETTER_D)) {
1063
1211
  this._lastIntValue = -1;
1064
1212
  this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
1065
- return true;
1213
+ return {};
1066
1214
  }
1067
1215
  if (this.eat(LATIN_SMALL_LETTER_S)) {
1068
1216
  this._lastIntValue = -1;
1069
1217
  this.onEscapeCharacterSet(start - 1, this.index, "space", false);
1070
- return true;
1218
+ return {};
1071
1219
  }
1072
1220
  if (this.eat(LATIN_CAPITAL_LETTER_S)) {
1073
1221
  this._lastIntValue = -1;
1074
1222
  this.onEscapeCharacterSet(start - 1, this.index, "space", true);
1075
- return true;
1223
+ return {};
1076
1224
  }
1077
1225
  if (this.eat(LATIN_SMALL_LETTER_W)) {
1078
1226
  this._lastIntValue = -1;
1079
1227
  this.onEscapeCharacterSet(start - 1, this.index, "word", false);
1080
- return true;
1228
+ return {};
1081
1229
  }
1082
1230
  if (this.eat(LATIN_CAPITAL_LETTER_W)) {
1083
1231
  this._lastIntValue = -1;
1084
1232
  this.onEscapeCharacterSet(start - 1, this.index, "word", true);
1085
- return true;
1233
+ return {};
1086
1234
  }
1087
1235
  let negate = false;
1088
- if (this._uFlag &&
1236
+ if (this._unicodeMode &&
1089
1237
  this.ecmaVersion >= 2018 &&
1090
1238
  (this.eat(LATIN_SMALL_LETTER_P) ||
1091
1239
  (negate = this.eat(LATIN_CAPITAL_LETTER_P)))) {
1092
1240
  this._lastIntValue = -1;
1241
+ let result = null;
1093
1242
  if (this.eat(LEFT_CURLY_BRACKET) &&
1094
- this.eatUnicodePropertyValueExpression() &&
1243
+ (result = this.eatUnicodePropertyValueExpression()) &&
1095
1244
  this.eat(RIGHT_CURLY_BRACKET)) {
1096
- this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", this._lastKeyValue, this._lastValValue || null, negate);
1097
- return true;
1245
+ if (negate && result.strings) {
1246
+ this.raise("Invalid property name");
1247
+ }
1248
+ this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", result.key, result.value, negate, (_a = result.strings) !== null && _a !== void 0 ? _a : false);
1249
+ return { mayContainStrings: result.strings };
1098
1250
  }
1099
1251
  this.raise("Invalid property name");
1100
1252
  }
1101
- return false;
1253
+ return null;
1102
1254
  }
1103
1255
  consumeCharacterEscape() {
1104
1256
  const start = this.index;
@@ -1108,7 +1260,7 @@ class RegExpValidator {
1108
1260
  this.eatHexEscapeSequence() ||
1109
1261
  this.eatRegExpUnicodeEscapeSequence() ||
1110
1262
  (!this.strict &&
1111
- !this._uFlag &&
1263
+ !this._unicodeMode &&
1112
1264
  this.eatLegacyOctalEscapeSequence()) ||
1113
1265
  this.eatIdentityEscape()) {
1114
1266
  this.onCharacter(start - 1, this.index, this._lastIntValue);
@@ -1133,18 +1285,31 @@ class RegExpValidator {
1133
1285
  const start = this.index;
1134
1286
  if (this.eat(LEFT_SQUARE_BRACKET)) {
1135
1287
  const negate = this.eat(CIRCUMFLEX_ACCENT);
1136
- this.onCharacterClassEnter(start, negate);
1137
- this.consumeClassRanges();
1288
+ this.onCharacterClassEnter(start, negate, this._unicodeSetsMode);
1289
+ const result = this.consumeClassContents();
1138
1290
  if (!this.eat(RIGHT_SQUARE_BRACKET)) {
1139
- this.raise("Unterminated character class");
1291
+ if (this.currentCodePoint === -1) {
1292
+ this.raise("Unterminated character class");
1293
+ }
1294
+ this.raise("Invalid character in character class");
1295
+ }
1296
+ if (negate && result.mayContainStrings) {
1297
+ this.raise("Negated character class may contain strings");
1140
1298
  }
1141
1299
  this.onCharacterClassLeave(start, this.index, negate);
1142
- return true;
1300
+ return result;
1143
1301
  }
1144
- return false;
1302
+ return null;
1145
1303
  }
1146
- consumeClassRanges() {
1147
- const strict = this.strict || this._uFlag;
1304
+ consumeClassContents() {
1305
+ if (this._unicodeSetsMode) {
1306
+ if (this.currentCodePoint === RIGHT_SQUARE_BRACKET) {
1307
+ return {};
1308
+ }
1309
+ const result = this.consumeClassSetExpression();
1310
+ return result;
1311
+ }
1312
+ const strict = this.strict || this._unicodeMode;
1148
1313
  for (;;) {
1149
1314
  const rangeStart = this.index;
1150
1315
  if (!this.consumeClassAtom()) {
@@ -1170,6 +1335,7 @@ class RegExpValidator {
1170
1335
  }
1171
1336
  this.onCharacterClassRange(rangeStart, this.index, min, max);
1172
1337
  }
1338
+ return {};
1173
1339
  }
1174
1340
  consumeClassAtom() {
1175
1341
  const start = this.index;
@@ -1192,7 +1358,7 @@ class RegExpValidator {
1192
1358
  this.onCharacter(start, this.index, this._lastIntValue);
1193
1359
  return true;
1194
1360
  }
1195
- if (this.strict || this._uFlag) {
1361
+ if (this.strict || this._unicodeMode) {
1196
1362
  this.raise("Invalid escape");
1197
1363
  }
1198
1364
  this.rewind(start);
@@ -1206,14 +1372,14 @@ class RegExpValidator {
1206
1372
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1207
1373
  return true;
1208
1374
  }
1209
- if (this._uFlag && this.eat(HYPHEN_MINUS)) {
1375
+ if (this._unicodeMode && this.eat(HYPHEN_MINUS)) {
1210
1376
  this._lastIntValue = HYPHEN_MINUS;
1211
1377
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1212
1378
  return true;
1213
1379
  }
1214
1380
  let cp = 0;
1215
1381
  if (!this.strict &&
1216
- !this._uFlag &&
1382
+ !this._unicodeMode &&
1217
1383
  this.currentCodePoint === LATIN_SMALL_LETTER_C &&
1218
1384
  (isDecimalDigit((cp = this.nextCodePoint)) || cp === LOW_LINE)) {
1219
1385
  this.advance();
@@ -1222,7 +1388,196 @@ class RegExpValidator {
1222
1388
  this.onCharacter(start - 1, this.index, this._lastIntValue);
1223
1389
  return true;
1224
1390
  }
1225
- return (this.consumeCharacterClassEscape() || this.consumeCharacterEscape());
1391
+ return (Boolean(this.consumeCharacterClassEscape()) ||
1392
+ this.consumeCharacterEscape());
1393
+ }
1394
+ consumeClassSetExpression() {
1395
+ const start = this.index;
1396
+ let mayContainStrings = false;
1397
+ let result = null;
1398
+ if (this.consumeClassSetCharacter()) {
1399
+ if (this.consumeClassSetRangeFromOperator(start)) {
1400
+ this.consumeClassUnionRight({});
1401
+ return {};
1402
+ }
1403
+ mayContainStrings = false;
1404
+ }
1405
+ else if ((result = this.consumeClassSetOperand())) {
1406
+ mayContainStrings = result.mayContainStrings;
1407
+ }
1408
+ else {
1409
+ const cp = this.currentCodePoint;
1410
+ if (cp === REVERSE_SOLIDUS) {
1411
+ this.advance();
1412
+ this.raise("Invalid escape");
1413
+ }
1414
+ if (cp === this.nextCodePoint &&
1415
+ isClassSetReservedDoublePunctuatorCharacter(cp)) {
1416
+ this.raise("Invalid set operation in character class");
1417
+ }
1418
+ this.raise("Invalid character in character class");
1419
+ }
1420
+ if (this.eat2(AMPERSAND, AMPERSAND)) {
1421
+ while (this.currentCodePoint !== AMPERSAND &&
1422
+ (result = this.consumeClassSetOperand())) {
1423
+ this.onClassIntersection(start, this.index);
1424
+ if (!result.mayContainStrings) {
1425
+ mayContainStrings = false;
1426
+ }
1427
+ if (this.eat2(AMPERSAND, AMPERSAND)) {
1428
+ continue;
1429
+ }
1430
+ return { mayContainStrings };
1431
+ }
1432
+ this.raise("Invalid character in character class");
1433
+ }
1434
+ if (this.eat2(HYPHEN_MINUS, HYPHEN_MINUS)) {
1435
+ while (this.consumeClassSetOperand()) {
1436
+ this.onClassSubtraction(start, this.index);
1437
+ if (this.eat2(HYPHEN_MINUS, HYPHEN_MINUS)) {
1438
+ continue;
1439
+ }
1440
+ return { mayContainStrings };
1441
+ }
1442
+ this.raise("Invalid character in character class");
1443
+ }
1444
+ return this.consumeClassUnionRight({ mayContainStrings });
1445
+ }
1446
+ consumeClassUnionRight(leftResult) {
1447
+ let mayContainStrings = leftResult.mayContainStrings;
1448
+ for (;;) {
1449
+ const start = this.index;
1450
+ if (this.consumeClassSetCharacter()) {
1451
+ this.consumeClassSetRangeFromOperator(start);
1452
+ continue;
1453
+ }
1454
+ const result = this.consumeClassSetOperand();
1455
+ if (result) {
1456
+ if (result.mayContainStrings) {
1457
+ mayContainStrings = true;
1458
+ }
1459
+ continue;
1460
+ }
1461
+ break;
1462
+ }
1463
+ return { mayContainStrings };
1464
+ }
1465
+ consumeClassSetRangeFromOperator(start) {
1466
+ const currentStart = this.index;
1467
+ const min = this._lastIntValue;
1468
+ if (this.eat(HYPHEN_MINUS)) {
1469
+ if (this.consumeClassSetCharacter()) {
1470
+ const max = this._lastIntValue;
1471
+ if (min === -1 || max === -1) {
1472
+ this.raise("Invalid character class");
1473
+ }
1474
+ if (min > max) {
1475
+ this.raise("Range out of order in character class");
1476
+ }
1477
+ this.onCharacterClassRange(start, this.index, min, max);
1478
+ return true;
1479
+ }
1480
+ this.rewind(currentStart);
1481
+ }
1482
+ return false;
1483
+ }
1484
+ consumeClassSetOperand() {
1485
+ let result = null;
1486
+ if ((result = this.consumeNestedClass())) {
1487
+ return result;
1488
+ }
1489
+ if ((result = this.consumeClassStringDisjunction())) {
1490
+ return result;
1491
+ }
1492
+ if (this.consumeClassSetCharacter()) {
1493
+ return {};
1494
+ }
1495
+ return null;
1496
+ }
1497
+ consumeNestedClass() {
1498
+ const start = this.index;
1499
+ if (this.eat(LEFT_SQUARE_BRACKET)) {
1500
+ const negate = this.eat(CIRCUMFLEX_ACCENT);
1501
+ this.onCharacterClassEnter(start, negate, true);
1502
+ const result = this.consumeClassContents();
1503
+ if (!this.eat(RIGHT_SQUARE_BRACKET)) {
1504
+ this.raise("Unterminated character class");
1505
+ }
1506
+ if (negate && result.mayContainStrings) {
1507
+ this.raise("Negated character class may contain strings");
1508
+ }
1509
+ this.onCharacterClassLeave(start, this.index, negate);
1510
+ return result;
1511
+ }
1512
+ if (this.eat(REVERSE_SOLIDUS)) {
1513
+ const result = this.consumeCharacterClassEscape();
1514
+ if (result) {
1515
+ return result;
1516
+ }
1517
+ this.rewind(start);
1518
+ }
1519
+ return null;
1520
+ }
1521
+ consumeClassStringDisjunction() {
1522
+ const start = this.index;
1523
+ if (this.eat3(REVERSE_SOLIDUS, LATIN_SMALL_LETTER_Q, LEFT_CURLY_BRACKET)) {
1524
+ this.onClassStringDisjunctionEnter(start);
1525
+ let i = 0;
1526
+ let mayContainStrings = false;
1527
+ do {
1528
+ if (this.consumeClassString(i++).mayContainStrings) {
1529
+ mayContainStrings = true;
1530
+ }
1531
+ } while (this.eat(VERTICAL_LINE));
1532
+ if (this.eat(RIGHT_CURLY_BRACKET)) {
1533
+ this.onClassStringDisjunctionLeave(start, this.index);
1534
+ return { mayContainStrings };
1535
+ }
1536
+ this.raise("Unterminated class string disjunction");
1537
+ }
1538
+ return null;
1539
+ }
1540
+ consumeClassString(i) {
1541
+ const start = this.index;
1542
+ let count = 0;
1543
+ this.onStringAlternativeEnter(start, i);
1544
+ while (this.currentCodePoint !== -1 &&
1545
+ this.consumeClassSetCharacter()) {
1546
+ count++;
1547
+ }
1548
+ this.onStringAlternativeLeave(start, this.index, i);
1549
+ return { mayContainStrings: count !== 1 };
1550
+ }
1551
+ consumeClassSetCharacter() {
1552
+ const start = this.index;
1553
+ const cp = this.currentCodePoint;
1554
+ if (cp !== this.nextCodePoint ||
1555
+ !isClassSetReservedDoublePunctuatorCharacter(cp)) {
1556
+ if (cp !== -1 && !isClassSetSyntaxCharacter(cp)) {
1557
+ this._lastIntValue = cp;
1558
+ this.advance();
1559
+ this.onCharacter(start, this.index, this._lastIntValue);
1560
+ return true;
1561
+ }
1562
+ }
1563
+ if (this.eat(REVERSE_SOLIDUS)) {
1564
+ if (this.consumeCharacterEscape()) {
1565
+ return true;
1566
+ }
1567
+ if (isClassSetReservedPunctuator(this.currentCodePoint)) {
1568
+ this._lastIntValue = this.currentCodePoint;
1569
+ this.advance();
1570
+ this.onCharacter(start, this.index, this._lastIntValue);
1571
+ return true;
1572
+ }
1573
+ if (this.eat(LATIN_SMALL_LETTER_B)) {
1574
+ this._lastIntValue = BACKSPACE;
1575
+ this.onCharacter(start, this.index, this._lastIntValue);
1576
+ return true;
1577
+ }
1578
+ this.rewind(start);
1579
+ }
1580
+ return false;
1226
1581
  }
1227
1582
  eatGroupName() {
1228
1583
  if (this.eat(LESS_THAN_SIGN)) {
@@ -1245,7 +1600,7 @@ class RegExpValidator {
1245
1600
  }
1246
1601
  eatRegExpIdentifierStart() {
1247
1602
  const start = this.index;
1248
- const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1603
+ const forceUFlag = !this._unicodeMode && this.ecmaVersion >= 2020;
1249
1604
  let cp = this.currentCodePoint;
1250
1605
  this.advance();
1251
1606
  if (cp === REVERSE_SOLIDUS &&
@@ -1258,7 +1613,7 @@ class RegExpValidator {
1258
1613
  cp = combineSurrogatePair(cp, this.currentCodePoint);
1259
1614
  this.advance();
1260
1615
  }
1261
- if (isRegExpIdentifierStart(cp)) {
1616
+ if (isIdentifierStartChar(cp)) {
1262
1617
  this._lastIntValue = cp;
1263
1618
  return true;
1264
1619
  }
@@ -1269,7 +1624,7 @@ class RegExpValidator {
1269
1624
  }
1270
1625
  eatRegExpIdentifierPart() {
1271
1626
  const start = this.index;
1272
- const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
1627
+ const forceUFlag = !this._unicodeMode && this.ecmaVersion >= 2020;
1273
1628
  let cp = this.currentCodePoint;
1274
1629
  this.advance();
1275
1630
  if (cp === REVERSE_SOLIDUS &&
@@ -1282,7 +1637,7 @@ class RegExpValidator {
1282
1637
  cp = combineSurrogatePair(cp, this.currentCodePoint);
1283
1638
  this.advance();
1284
1639
  }
1285
- if (isRegExpIdentifierPart(cp)) {
1640
+ if (isIdentifierPartChar(cp)) {
1286
1641
  this._lastIntValue = cp;
1287
1642
  return true;
1288
1643
  }
@@ -1344,7 +1699,7 @@ class RegExpValidator {
1344
1699
  }
1345
1700
  eatRegExpUnicodeEscapeSequence(forceUFlag = false) {
1346
1701
  const start = this.index;
1347
- const uFlag = forceUFlag || this._uFlag;
1702
+ const uFlag = forceUFlag || this._unicodeMode;
1348
1703
  if (this.eat(LATIN_SMALL_LETTER_U)) {
1349
1704
  if ((uFlag && this.eatRegExpUnicodeSurrogatePairEscape()) ||
1350
1705
  this.eatFixedHexDigits(4) ||
@@ -1400,7 +1755,7 @@ class RegExpValidator {
1400
1755
  if (cp === -1) {
1401
1756
  return false;
1402
1757
  }
1403
- if (this._uFlag) {
1758
+ if (this._unicodeMode) {
1404
1759
  return isSyntaxCharacter(cp) || cp === SOLIDUS;
1405
1760
  }
1406
1761
  if (this.strict) {
@@ -1427,11 +1782,14 @@ class RegExpValidator {
1427
1782
  eatUnicodePropertyValueExpression() {
1428
1783
  const start = this.index;
1429
1784
  if (this.eatUnicodePropertyName() && this.eat(EQUALS_SIGN)) {
1430
- this._lastKeyValue = this._lastStrValue;
1785
+ const key = this._lastStrValue;
1431
1786
  if (this.eatUnicodePropertyValue()) {
1432
- this._lastValValue = this._lastStrValue;
1433
- if (isValidUnicodeProperty(this.ecmaVersion, this._lastKeyValue, this._lastValValue)) {
1434
- return true;
1787
+ const value = this._lastStrValue;
1788
+ if (isValidUnicodeProperty(this.ecmaVersion, key, value)) {
1789
+ return {
1790
+ key,
1791
+ value: value || null,
1792
+ };
1435
1793
  }
1436
1794
  this.raise("Invalid property name");
1437
1795
  }
@@ -1440,18 +1798,28 @@ class RegExpValidator {
1440
1798
  if (this.eatLoneUnicodePropertyNameOrValue()) {
1441
1799
  const nameOrValue = this._lastStrValue;
1442
1800
  if (isValidUnicodeProperty(this.ecmaVersion, "General_Category", nameOrValue)) {
1443
- this._lastKeyValue = "General_Category";
1444
- this._lastValValue = nameOrValue;
1445
- return true;
1801
+ return {
1802
+ key: "General_Category",
1803
+ value: nameOrValue || null,
1804
+ };
1446
1805
  }
1447
1806
  if (isValidLoneUnicodeProperty(this.ecmaVersion, nameOrValue)) {
1448
- this._lastKeyValue = nameOrValue;
1449
- this._lastValValue = "";
1450
- return true;
1807
+ return {
1808
+ key: nameOrValue,
1809
+ value: null,
1810
+ };
1811
+ }
1812
+ if (this._unicodeSetsMode &&
1813
+ isValidLoneUnicodePropertyOfString(this.ecmaVersion, nameOrValue)) {
1814
+ return {
1815
+ key: nameOrValue,
1816
+ value: null,
1817
+ strings: true,
1818
+ };
1451
1819
  }
1452
1820
  this.raise("Invalid property name");
1453
1821
  }
1454
- return false;
1822
+ return null;
1455
1823
  }
1456
1824
  eatUnicodePropertyName() {
1457
1825
  this._lastStrValue = "";
@@ -1478,7 +1846,7 @@ class RegExpValidator {
1478
1846
  if (this.eatFixedHexDigits(2)) {
1479
1847
  return true;
1480
1848
  }
1481
- if (this._uFlag || this.strict) {
1849
+ if (this._unicodeMode || this.strict) {
1482
1850
  this.raise("Invalid escape");
1483
1851
  }
1484
1852
  this.rewind(start);
@@ -1553,16 +1921,24 @@ class RegExpValidator {
1553
1921
  const DUMMY_PATTERN = {};
1554
1922
  const DUMMY_FLAGS = {};
1555
1923
  const DUMMY_CAPTURING_GROUP = {};
1924
+ function isClassSetOperand(node) {
1925
+ return (node.type === "Character" ||
1926
+ node.type === "CharacterSet" ||
1927
+ node.type === "CharacterClass" ||
1928
+ node.type === "ExpressionCharacterClass" ||
1929
+ node.type === "ClassStringDisjunction");
1930
+ }
1556
1931
  class RegExpParserState {
1557
1932
  constructor(options) {
1558
1933
  var _a;
1559
1934
  this._node = DUMMY_PATTERN;
1935
+ this._expressionBuffer = null;
1560
1936
  this._flags = DUMMY_FLAGS;
1561
1937
  this._backreferences = [];
1562
1938
  this._capturingGroups = [];
1563
1939
  this.source = "";
1564
1940
  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;
1941
+ this.ecmaVersion = (_a = options === null || options === void 0 ? void 0 : options.ecmaVersion) !== null && _a !== void 0 ? _a : latestEcmaVersion;
1566
1942
  }
1567
1943
  get pattern() {
1568
1944
  if (this._node.type !== "Pattern") {
@@ -1576,7 +1952,7 @@ class RegExpParserState {
1576
1952
  }
1577
1953
  return this._flags;
1578
1954
  }
1579
- onRegExpFlags(start, end, { global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices, }) {
1955
+ onRegExpFlags(start, end, { global, ignoreCase, multiline, unicode, sticky, dotAll, hasIndices, unicodeSets, }) {
1580
1956
  this._flags = {
1581
1957
  type: "Flags",
1582
1958
  parent: null,
@@ -1590,6 +1966,7 @@ class RegExpParserState {
1590
1966
  sticky,
1591
1967
  dotAll,
1592
1968
  hasIndices,
1969
+ unicodeSets,
1593
1970
  };
1594
1971
  }
1595
1972
  onPatternEnter(start) {
@@ -1804,26 +2181,33 @@ class RegExpParserState {
1804
2181
  negate,
1805
2182
  });
1806
2183
  }
1807
- onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
2184
+ onUnicodePropertyCharacterSet(start, end, kind, key, value, negate, strings) {
1808
2185
  const parent = this._node;
1809
- if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
2186
+ if ((parent.type !== "Alternative" &&
2187
+ parent.type !== "CharacterClass") ||
2188
+ (strings && (negate || value))) {
1810
2189
  throw new Error("UnknownError");
1811
2190
  }
1812
- parent.elements.push({
2191
+ const base = {
1813
2192
  type: "CharacterSet",
1814
2193
  parent,
1815
2194
  start,
1816
2195
  end,
1817
2196
  raw: this.source.slice(start, end),
1818
2197
  kind,
2198
+ strings,
1819
2199
  key,
1820
- value,
1821
- negate,
1822
- });
2200
+ };
2201
+ const node = strings
2202
+ ? Object.assign(Object.assign({}, base), { value: null, negate: false, strings: true }) : Object.assign(Object.assign({}, base), { value,
2203
+ negate, strings: false });
2204
+ parent.elements.push(node);
1823
2205
  }
1824
2206
  onCharacter(start, end, value) {
1825
2207
  const parent = this._node;
1826
- if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
2208
+ if (parent.type !== "Alternative" &&
2209
+ parent.type !== "CharacterClass" &&
2210
+ parent.type !== "StringAlternative") {
1827
2211
  throw new Error("UnknownError");
1828
2212
  }
1829
2213
  parent.elements.push({
@@ -1852,31 +2236,66 @@ class RegExpParserState {
1852
2236
  parent.elements.push(node);
1853
2237
  this._backreferences.push(node);
1854
2238
  }
1855
- onCharacterClassEnter(start, negate) {
2239
+ onCharacterClassEnter(start, negate, unicodeSets) {
1856
2240
  const parent = this._node;
1857
- if (parent.type !== "Alternative") {
1858
- throw new Error("UnknownError");
1859
- }
1860
- this._node = {
2241
+ const base = {
1861
2242
  type: "CharacterClass",
1862
2243
  parent,
1863
2244
  start,
1864
2245
  end: start,
1865
2246
  raw: "",
2247
+ unicodeSets,
1866
2248
  negate,
1867
2249
  elements: [],
1868
2250
  };
1869
- parent.elements.push(this._node);
2251
+ if (parent.type === "Alternative") {
2252
+ const node = Object.assign(Object.assign({}, base), { parent });
2253
+ this._node = node;
2254
+ parent.elements.push(node);
2255
+ }
2256
+ else if (parent.type === "CharacterClass" &&
2257
+ parent.unicodeSets &&
2258
+ unicodeSets) {
2259
+ const node = Object.assign(Object.assign({}, base), { parent,
2260
+ unicodeSets });
2261
+ this._node = node;
2262
+ parent.elements.push(node);
2263
+ }
2264
+ else {
2265
+ throw new Error("UnknownError");
2266
+ }
1870
2267
  }
1871
2268
  onCharacterClassLeave(start, end) {
1872
2269
  const node = this._node;
1873
2270
  if (node.type !== "CharacterClass" ||
1874
- node.parent.type !== "Alternative") {
2271
+ (node.parent.type !== "Alternative" &&
2272
+ node.parent.type !== "CharacterClass") ||
2273
+ (this._expressionBuffer && node.elements.length > 0)) {
1875
2274
  throw new Error("UnknownError");
1876
2275
  }
2276
+ const parent = node.parent;
1877
2277
  node.end = end;
1878
2278
  node.raw = this.source.slice(start, end);
1879
- this._node = node.parent;
2279
+ this._node = parent;
2280
+ const expression = this._expressionBuffer;
2281
+ this._expressionBuffer = null;
2282
+ if (!expression) {
2283
+ return;
2284
+ }
2285
+ const newNode = {
2286
+ type: "ExpressionCharacterClass",
2287
+ parent,
2288
+ start: node.start,
2289
+ end: node.end,
2290
+ raw: node.raw,
2291
+ negate: node.negate,
2292
+ expression,
2293
+ };
2294
+ expression.parent = newNode;
2295
+ if (node !== parent.elements.pop()) {
2296
+ throw new Error("UnknownError");
2297
+ }
2298
+ parent.elements.push(newNode);
1880
2299
  }
1881
2300
  onCharacterClassRange(start, end) {
1882
2301
  const parent = this._node;
@@ -1885,15 +2304,19 @@ class RegExpParserState {
1885
2304
  }
1886
2305
  const elements = parent.elements;
1887
2306
  const max = elements.pop();
1888
- const hyphen = elements.pop();
2307
+ if (!max || max.type !== "Character") {
2308
+ throw new Error("UnknownError");
2309
+ }
2310
+ if (!parent.unicodeSets) {
2311
+ const hyphen = elements.pop();
2312
+ if (!hyphen ||
2313
+ hyphen.type !== "Character" ||
2314
+ hyphen.value !== HYPHEN_MINUS) {
2315
+ throw new Error("UnknownError");
2316
+ }
2317
+ }
1889
2318
  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) {
2319
+ if (!min || min.type !== "Character") {
1897
2320
  throw new Error("UnknownError");
1898
2321
  }
1899
2322
  const node = {
@@ -1909,6 +2332,111 @@ class RegExpParserState {
1909
2332
  max.parent = node;
1910
2333
  elements.push(node);
1911
2334
  }
2335
+ onClassIntersection(start, end) {
2336
+ var _a;
2337
+ const parent = this._node;
2338
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2339
+ throw new Error("UnknownError");
2340
+ }
2341
+ const right = parent.elements.pop();
2342
+ const left = (_a = this._expressionBuffer) !== null && _a !== void 0 ? _a : parent.elements.pop();
2343
+ if (!left ||
2344
+ !right ||
2345
+ left.type === "ClassSubtraction" ||
2346
+ (left.type !== "ClassIntersection" && !isClassSetOperand(left)) ||
2347
+ !isClassSetOperand(right)) {
2348
+ throw new Error("UnknownError");
2349
+ }
2350
+ const node = {
2351
+ type: "ClassIntersection",
2352
+ parent: parent,
2353
+ start,
2354
+ end,
2355
+ raw: this.source.slice(start, end),
2356
+ left,
2357
+ right,
2358
+ };
2359
+ left.parent = node;
2360
+ right.parent = node;
2361
+ this._expressionBuffer = node;
2362
+ }
2363
+ onClassSubtraction(start, end) {
2364
+ var _a;
2365
+ const parent = this._node;
2366
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2367
+ throw new Error("UnknownError");
2368
+ }
2369
+ const right = parent.elements.pop();
2370
+ const left = (_a = this._expressionBuffer) !== null && _a !== void 0 ? _a : parent.elements.pop();
2371
+ if (!left ||
2372
+ !right ||
2373
+ left.type === "ClassIntersection" ||
2374
+ (left.type !== "ClassSubtraction" && !isClassSetOperand(left)) ||
2375
+ !isClassSetOperand(right)) {
2376
+ throw new Error("UnknownError");
2377
+ }
2378
+ const node = {
2379
+ type: "ClassSubtraction",
2380
+ parent: parent,
2381
+ start,
2382
+ end,
2383
+ raw: this.source.slice(start, end),
2384
+ left,
2385
+ right,
2386
+ };
2387
+ left.parent = node;
2388
+ right.parent = node;
2389
+ this._expressionBuffer = node;
2390
+ }
2391
+ onClassStringDisjunctionEnter(start) {
2392
+ const parent = this._node;
2393
+ if (parent.type !== "CharacterClass" || !parent.unicodeSets) {
2394
+ throw new Error("UnknownError");
2395
+ }
2396
+ this._node = {
2397
+ type: "ClassStringDisjunction",
2398
+ parent,
2399
+ start,
2400
+ end: start,
2401
+ raw: "",
2402
+ alternatives: [],
2403
+ };
2404
+ parent.elements.push(this._node);
2405
+ }
2406
+ onClassStringDisjunctionLeave(start, end) {
2407
+ const node = this._node;
2408
+ if (node.type !== "ClassStringDisjunction" ||
2409
+ node.parent.type !== "CharacterClass") {
2410
+ throw new Error("UnknownError");
2411
+ }
2412
+ node.end = end;
2413
+ node.raw = this.source.slice(start, end);
2414
+ this._node = node.parent;
2415
+ }
2416
+ onStringAlternativeEnter(start) {
2417
+ const parent = this._node;
2418
+ if (parent.type !== "ClassStringDisjunction") {
2419
+ throw new Error("UnknownError");
2420
+ }
2421
+ this._node = {
2422
+ type: "StringAlternative",
2423
+ parent,
2424
+ start,
2425
+ end: start,
2426
+ raw: "",
2427
+ elements: [],
2428
+ };
2429
+ parent.alternatives.push(this._node);
2430
+ }
2431
+ onStringAlternativeLeave(start, end) {
2432
+ const node = this._node;
2433
+ if (node.type !== "StringAlternative") {
2434
+ throw new Error("UnknownError");
2435
+ }
2436
+ node.end = end;
2437
+ node.raw = this.source.slice(start, end);
2438
+ this._node = node.parent;
2439
+ }
1912
2440
  }
1913
2441
  class RegExpParser {
1914
2442
  constructor(options) {
@@ -1938,9 +2466,9 @@ class RegExpParser {
1938
2466
  this._validator.validateFlags(source, start, end);
1939
2467
  return this._state.flags;
1940
2468
  }
1941
- parsePattern(source, start = 0, end = source.length, uFlag = false) {
2469
+ parsePattern(source, start = 0, end = source.length, uFlagOrFlags = undefined) {
1942
2470
  this._state.source = source;
1943
- this._validator.validatePattern(source, start, end, uFlag);
2471
+ this._validator.validatePattern(source, start, end, uFlagOrFlags);
1944
2472
  return this._state.pattern;
1945
2473
  }
1946
2474
  }
@@ -1975,6 +2503,18 @@ class RegExpVisitor {
1975
2503
  case "CharacterSet":
1976
2504
  this.visitCharacterSet(node);
1977
2505
  break;
2506
+ case "ClassIntersection":
2507
+ this.visitClassIntersection(node);
2508
+ break;
2509
+ case "ClassStringDisjunction":
2510
+ this.visitClassStringDisjunction(node);
2511
+ break;
2512
+ case "ClassSubtraction":
2513
+ this.visitClassSubtraction(node);
2514
+ break;
2515
+ case "ExpressionCharacterClass":
2516
+ this.visitExpressionCharacterClass(node);
2517
+ break;
1978
2518
  case "Flags":
1979
2519
  this.visitFlags(node);
1980
2520
  break;
@@ -1990,6 +2530,9 @@ class RegExpVisitor {
1990
2530
  case "RegExpLiteral":
1991
2531
  this.visitRegExpLiteral(node);
1992
2532
  break;
2533
+ case "StringAlternative":
2534
+ this.visitStringAlternative(node);
2535
+ break;
1993
2536
  default:
1994
2537
  throw new Error(`Unknown type: ${node.type}`);
1995
2538
  }
@@ -2066,6 +2609,44 @@ class RegExpVisitor {
2066
2609
  this._handlers.onCharacterSetLeave(node);
2067
2610
  }
2068
2611
  }
2612
+ visitClassIntersection(node) {
2613
+ if (this._handlers.onClassIntersectionEnter) {
2614
+ this._handlers.onClassIntersectionEnter(node);
2615
+ }
2616
+ this.visit(node.left);
2617
+ this.visit(node.right);
2618
+ if (this._handlers.onClassIntersectionLeave) {
2619
+ this._handlers.onClassIntersectionLeave(node);
2620
+ }
2621
+ }
2622
+ visitClassStringDisjunction(node) {
2623
+ if (this._handlers.onClassStringDisjunctionEnter) {
2624
+ this._handlers.onClassStringDisjunctionEnter(node);
2625
+ }
2626
+ node.alternatives.forEach(this.visit, this);
2627
+ if (this._handlers.onClassStringDisjunctionLeave) {
2628
+ this._handlers.onClassStringDisjunctionLeave(node);
2629
+ }
2630
+ }
2631
+ visitClassSubtraction(node) {
2632
+ if (this._handlers.onClassSubtractionEnter) {
2633
+ this._handlers.onClassSubtractionEnter(node);
2634
+ }
2635
+ this.visit(node.left);
2636
+ this.visit(node.right);
2637
+ if (this._handlers.onClassSubtractionLeave) {
2638
+ this._handlers.onClassSubtractionLeave(node);
2639
+ }
2640
+ }
2641
+ visitExpressionCharacterClass(node) {
2642
+ if (this._handlers.onExpressionCharacterClassEnter) {
2643
+ this._handlers.onExpressionCharacterClassEnter(node);
2644
+ }
2645
+ this.visit(node.expression);
2646
+ if (this._handlers.onExpressionCharacterClassLeave) {
2647
+ this._handlers.onExpressionCharacterClassLeave(node);
2648
+ }
2649
+ }
2069
2650
  visitFlags(node) {
2070
2651
  if (this._handlers.onFlagsEnter) {
2071
2652
  this._handlers.onFlagsEnter(node);
@@ -2111,6 +2692,15 @@ class RegExpVisitor {
2111
2692
  this._handlers.onRegExpLiteralLeave(node);
2112
2693
  }
2113
2694
  }
2695
+ visitStringAlternative(node) {
2696
+ if (this._handlers.onStringAlternativeEnter) {
2697
+ this._handlers.onStringAlternativeEnter(node);
2698
+ }
2699
+ node.elements.forEach(this.visit, this);
2700
+ if (this._handlers.onStringAlternativeLeave) {
2701
+ this._handlers.onStringAlternativeLeave(node);
2702
+ }
2703
+ }
2114
2704
  }
2115
2705
 
2116
2706
  function parseRegExpLiteral(source, options) {