webpack 5.82.0 → 5.82.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of webpack might be problematic. Click here for more details.

@@ -120,21 +120,15 @@ class LocConverter {
120
120
  }
121
121
 
122
122
  const CSS_MODE_TOP_LEVEL = 0;
123
- const CSS_MODE_IN_RULE = 1;
124
- const CSS_MODE_IN_LOCAL_RULE = 2;
125
- const CSS_MODE_AT_IMPORT_EXPECT_URL = 3;
126
- const CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA = 4;
127
- const CSS_MODE_AT_IMPORT_INVALID = 5;
128
- const CSS_MODE_AT_NAMESPACE_INVALID = 6;
123
+ const CSS_MODE_IN_BLOCK = 1;
124
+ const CSS_MODE_AT_IMPORT_EXPECT_URL = 2;
125
+ const CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA = 3;
126
+ const CSS_MODE_AT_IMPORT_INVALID = 4;
127
+ const CSS_MODE_AT_NAMESPACE_INVALID = 5;
129
128
 
130
129
  class CssParser extends Parser {
131
- constructor({
132
- allowPseudoBlocks = true,
133
- allowModeSwitch = true,
134
- defaultMode = "global"
135
- } = {}) {
130
+ constructor({ allowModeSwitch = true, defaultMode = "global" } = {}) {
136
131
  super();
137
- this.allowPseudoBlocks = allowPseudoBlocks;
138
132
  this.allowModeSwitch = allowModeSwitch;
139
133
  this.defaultMode = defaultMode;
140
134
  }
@@ -174,30 +168,57 @@ class CssParser extends Parser {
174
168
  }
175
169
 
176
170
  const module = state.module;
177
-
178
- const declaredCssVariables = new Set();
179
-
180
171
  const locConverter = new LocConverter(source);
172
+ /** @type {Set<string>}*/
173
+ const declaredCssVariables = new Set();
181
174
  /** @type {number} */
182
- let mode = CSS_MODE_TOP_LEVEL;
175
+ let scope = CSS_MODE_TOP_LEVEL;
183
176
  /** @type {number} */
184
- let modeNestingLevel = 0;
177
+ let blockNestingLevel = 0;
185
178
  /** @type {boolean} */
186
179
  let allowImportAtRule = true;
180
+ /** @type {"local" | "global" | undefined} */
187
181
  let modeData = undefined;
188
- /** @type {string | boolean | undefined} */
189
- let singleClassSelector = undefined;
190
182
  /** @type {[number, number] | undefined} */
191
183
  let lastIdentifier = undefined;
192
- /** @type {boolean} */
193
- let awaitRightParenthesis = false;
194
184
  /** @type [string, number, number][] */
195
185
  let balanced = [];
196
- const modeStack = [];
186
+ /** @type {undefined | { start: number, end: number, url?: string, media?: string, supports?: string, layer?: string }} */
187
+ let importData = undefined;
188
+ /** @type {boolean} */
189
+ let inAnimationProperty = false;
190
+ /** @type {boolean} */
191
+ let isNextRulePrelude = true;
192
+
193
+ /**
194
+ * @param {string} input input
195
+ * @param {number} pos position
196
+ * @returns {boolean} true, when next is nested syntax
197
+ */
198
+ const isNextNestedSyntax = (input, pos) => {
199
+ pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
197
200
 
198
- const isTopLevelLocal = () =>
201
+ if (input[pos] === "}") {
202
+ return false;
203
+ }
204
+
205
+ // According spec only identifier can be used as a property name
206
+ const isIdentifier = walkCssTokens.isIdentStartCodePoint(
207
+ input.charCodeAt(pos)
208
+ );
209
+
210
+ return !isIdentifier;
211
+ };
212
+ /**
213
+ * @returns {boolean} true, when in local scope
214
+ */
215
+ const isLocalMode = () =>
199
216
  modeData === "local" ||
200
217
  (this.defaultMode === "local" && modeData === undefined);
218
+ /**
219
+ * @param {string} chars characters
220
+ * @returns {(input: string, pos: number) => number} function to eat characters
221
+ */
201
222
  const eatUntil = chars => {
202
223
  const charCodes = Array.from({ length: chars.length }, (_, i) =>
203
224
  chars.charCodeAt(i)
@@ -218,6 +239,12 @@ class CssParser extends Parser {
218
239
  }
219
240
  };
220
241
  };
242
+ /**
243
+ * @param {string} input input
244
+ * @param {number} pos start position
245
+ * @param {(input: string, pos: number) => number} eater eater
246
+ * @returns {[number,string]} new position and text
247
+ */
221
248
  const eatText = (input, pos, eater) => {
222
249
  let text = "";
223
250
  for (;;) {
@@ -245,6 +272,11 @@ class CssParser extends Parser {
245
272
  };
246
273
  const eatExportName = eatUntil(":};/");
247
274
  const eatExportValue = eatUntil("};/");
275
+ /**
276
+ * @param {string} input input
277
+ * @param {number} pos start position
278
+ * @returns {number} position after parse
279
+ */
248
280
  const parseExports = (input, pos) => {
249
281
  pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
250
282
  const cc = input.charCodeAt(pos);
@@ -313,9 +345,14 @@ class CssParser extends Parser {
313
345
  return pos;
314
346
  };
315
347
  const eatPropertyName = eatUntil(":{};");
316
- const processLocalDeclaration = (input, pos) => {
348
+ /**
349
+ * @param {string} input input
350
+ * @param {number} pos name start position
351
+ * @param {number} end name end position
352
+ * @returns {number} position after handling
353
+ */
354
+ const processLocalDeclaration = (input, pos, end) => {
317
355
  modeData = undefined;
318
- const start = pos;
319
356
  pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
320
357
  const propertyNameStart = pos;
321
358
  const [propertyNameEnd, propertyName] = eatText(
@@ -323,7 +360,7 @@ class CssParser extends Parser {
323
360
  pos,
324
361
  eatPropertyName
325
362
  );
326
- if (input.charCodeAt(propertyNameEnd) !== CC_COLON) return start;
363
+ if (input.charCodeAt(propertyNameEnd) !== CC_COLON) return end;
327
364
  pos = propertyNameEnd + 1;
328
365
  if (propertyName.startsWith("--")) {
329
366
  // CSS Variable
@@ -339,44 +376,40 @@ class CssParser extends Parser {
339
376
  module.addDependency(dep);
340
377
  declaredCssVariables.add(name);
341
378
  } else if (
379
+ !propertyName.startsWith("--") &&
342
380
  OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY.test(propertyName)
343
381
  ) {
344
- modeData = "animation";
345
- lastIdentifier = undefined;
382
+ inAnimationProperty = true;
346
383
  }
347
384
  return pos;
348
385
  };
349
- const processDeclarationValueDone = (input, pos) => {
350
- if (modeData === "animation" && lastIdentifier) {
386
+ /**
387
+ * @param {string} input input
388
+ */
389
+ const processDeclarationValueDone = input => {
390
+ if (inAnimationProperty && lastIdentifier) {
351
391
  const { line: sl, column: sc } = locConverter.get(lastIdentifier[0]);
352
392
  const { line: el, column: ec } = locConverter.get(lastIdentifier[1]);
353
393
  const name = input.slice(lastIdentifier[0], lastIdentifier[1]);
354
394
  const dep = new CssSelfLocalIdentifierDependency(name, lastIdentifier);
355
395
  dep.setLoc(sl, sc, el, ec);
356
396
  module.addDependency(dep);
397
+ lastIdentifier = undefined;
357
398
  }
358
399
  };
359
- const eatAtRuleNested = eatUntil("{};/");
360
400
  const eatKeyframes = eatUntil("{};/");
361
401
  const eatNameInVar = eatUntil(",)};/");
362
402
  walkCssTokens(source, {
363
403
  isSelector: () => {
364
- return (
365
- mode !== CSS_MODE_IN_RULE &&
366
- mode !== CSS_MODE_IN_LOCAL_RULE &&
367
- mode !== CSS_MODE_AT_IMPORT_EXPECT_URL &&
368
- mode !== CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA &&
369
- mode !== CSS_MODE_AT_IMPORT_INVALID &&
370
- mode !== CSS_MODE_AT_NAMESPACE_INVALID
371
- );
404
+ return isNextRulePrelude;
372
405
  },
373
406
  url: (input, start, end, contentStart, contentEnd) => {
374
407
  let value = normalizeUrl(input.slice(contentStart, contentEnd), false);
375
- switch (mode) {
408
+ switch (scope) {
376
409
  case CSS_MODE_AT_IMPORT_EXPECT_URL: {
377
- modeData.url = value;
378
- modeData.lastPos = end;
379
- mode = CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA;
410
+ importData.url = value;
411
+ importData.end = end;
412
+ scope = CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA;
380
413
  break;
381
414
  }
382
415
  // Do not parse URLs in `supports(...)`
@@ -388,7 +421,7 @@ class CssParser extends Parser {
388
421
  case CSS_MODE_AT_IMPORT_INVALID: {
389
422
  break;
390
423
  }
391
- default: {
424
+ case CSS_MODE_IN_BLOCK: {
392
425
  // Ignore `url()`, `url('')` and `url("")`, they are valid by spec
393
426
  if (value.length === 0) {
394
427
  break;
@@ -406,16 +439,19 @@ class CssParser extends Parser {
406
439
  return end;
407
440
  },
408
441
  string: (input, start, end) => {
409
- switch (mode) {
442
+ switch (scope) {
410
443
  case CSS_MODE_AT_IMPORT_EXPECT_URL: {
411
- modeData.url = normalizeUrl(input.slice(start + 1, end - 1), true);
412
- modeData.lastPos = end;
444
+ importData.url = normalizeUrl(
445
+ input.slice(start + 1, end - 1),
446
+ true
447
+ );
448
+ importData.end = end;
413
449
  const insideURLFunction =
414
450
  balanced[balanced.length - 1] &&
415
451
  balanced[balanced.length - 1][0] === "url";
416
452
 
417
453
  if (!insideURLFunction) {
418
- mode = CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA;
454
+ scope = CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA;
419
455
  }
420
456
  break;
421
457
  }
@@ -423,7 +459,7 @@ class CssParser extends Parser {
423
459
  case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
424
460
  break;
425
461
  }
426
- default: {
462
+ case CSS_MODE_IN_BLOCK: {
427
463
  // TODO move escaped parsing to tokenizer
428
464
  const last = balanced[balanced.length - 1];
429
465
 
@@ -458,7 +494,7 @@ class CssParser extends Parser {
458
494
  atKeyword: (input, start, end) => {
459
495
  const name = input.slice(start, end).toLowerCase();
460
496
  if (name === "@namespace") {
461
- mode = CSS_MODE_AT_NAMESPACE_INVALID;
497
+ scope = CSS_MODE_AT_NAMESPACE_INVALID;
462
498
  this._emitWarning(
463
499
  state,
464
500
  "@namespace is not supported in bundled CSS",
@@ -469,7 +505,7 @@ class CssParser extends Parser {
469
505
  return end;
470
506
  } else if (name === "@import") {
471
507
  if (!allowImportAtRule) {
472
- mode = CSS_MODE_AT_IMPORT_INVALID;
508
+ scope = CSS_MODE_AT_IMPORT_INVALID;
473
509
  this._emitWarning(
474
510
  state,
475
511
  "Any @import rules must precede all other rules",
@@ -480,17 +516,10 @@ class CssParser extends Parser {
480
516
  return end;
481
517
  }
482
518
 
483
- mode = CSS_MODE_AT_IMPORT_EXPECT_URL;
484
- modeData = {
485
- atRuleStart: start,
486
- lastPos: end,
487
- url: undefined,
488
- layer: undefined,
489
- supports: undefined,
490
- media: undefined
491
- };
519
+ scope = CSS_MODE_AT_IMPORT_EXPECT_URL;
520
+ importData = { start, end };
492
521
  } else if (
493
- isTopLevelLocal() &&
522
+ this.allowModeSwitch &&
494
523
  OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE.test(name)
495
524
  ) {
496
525
  let pos = end;
@@ -515,31 +544,60 @@ class CssParser extends Parser {
515
544
  dep.setLoc(sl, sc, el, ec);
516
545
  module.addDependency(dep);
517
546
  pos = newPos;
518
- mode = CSS_MODE_IN_LOCAL_RULE;
519
- modeNestingLevel = 1;
520
547
  return pos + 1;
521
- } else if (name === "@media" || name === "@supports") {
522
- // TODO handle nested CSS syntax
548
+ } else if (this.allowModeSwitch && name === "@property") {
523
549
  let pos = end;
524
- const [newPos] = eatText(input, pos, eatAtRuleNested);
525
- pos = newPos;
550
+ pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
526
551
  if (pos === input.length) return pos;
527
- if (input.charCodeAt(pos) !== CC_LEFT_CURLY) {
552
+ const propertyNameStart = pos;
553
+ const [propertyNameEnd, propertyName] = eatText(
554
+ input,
555
+ pos,
556
+ eatKeyframes
557
+ );
558
+ if (propertyNameEnd === input.length) return propertyNameEnd;
559
+ if (!propertyName.startsWith("--")) return propertyNameEnd;
560
+ if (input.charCodeAt(propertyNameEnd) !== CC_LEFT_CURLY) {
528
561
  this._emitWarning(
529
562
  state,
530
- `Unexpected ${input[pos]} at ${pos} during parsing of @media or @supports (expected '{')`,
563
+ `Unexpected '${input[propertyNameEnd]}' at ${propertyNameEnd} during parsing of @property (expected '{')`,
531
564
  locConverter,
532
565
  start,
533
- pos
566
+ end
534
567
  );
535
- return pos;
568
+
569
+ return propertyNameEnd;
536
570
  }
571
+ const { line: sl, column: sc } = locConverter.get(pos);
572
+ const { line: el, column: ec } = locConverter.get(propertyNameEnd);
573
+ const name = propertyName.slice(2);
574
+ const dep = new CssLocalIdentifierDependency(
575
+ name,
576
+ [propertyNameStart, propertyNameEnd],
577
+ "--"
578
+ );
579
+ dep.setLoc(sl, sc, el, ec);
580
+ module.addDependency(dep);
581
+ declaredCssVariables.add(name);
582
+ pos = propertyNameEnd;
537
583
  return pos + 1;
584
+ } else if (
585
+ name === "@media" ||
586
+ name === "@supports" ||
587
+ name === "@layer" ||
588
+ name === "@container"
589
+ ) {
590
+ modeData = isLocalMode() ? "local" : "global";
591
+ isNextRulePrelude = true;
592
+ return end;
593
+ } else if (this.allowModeSwitch) {
594
+ modeData = "global";
595
+ isNextRulePrelude = false;
538
596
  }
539
597
  return end;
540
598
  },
541
599
  semicolon: (input, start, end) => {
542
- switch (mode) {
600
+ switch (scope) {
543
601
  case CSS_MODE_AT_IMPORT_EXPECT_URL: {
544
602
  this._emitWarning(
545
603
  state,
@@ -551,124 +609,119 @@ class CssParser extends Parser {
551
609
  return end;
552
610
  }
553
611
  case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
554
- if (modeData.url === undefined) {
612
+ if (!importData.url === undefined) {
555
613
  this._emitWarning(
556
614
  state,
557
- `Expected URL for @import at ${modeData.atRuleStart}`,
615
+ `Expected URL for @import at ${importData.start}`,
558
616
  locConverter,
559
- modeData.atRuleStart,
560
- modeData.lastPos
617
+ importData.start,
618
+ importData.end
561
619
  );
562
620
  return end;
563
621
  }
564
622
  const semicolonPos = end;
565
623
  end = walkCssTokens.eatWhiteLine(input, end + 1);
566
- const { line: sl, column: sc } = locConverter.get(
567
- modeData.atRuleStart
568
- );
624
+ const { line: sl, column: sc } = locConverter.get(importData.start);
569
625
  const { line: el, column: ec } = locConverter.get(end);
570
626
  const pos = walkCssTokens.eatWhitespaceAndComments(
571
627
  input,
572
- modeData.lastPos
628
+ importData.end
573
629
  );
574
630
  // Prevent to consider comments as a part of media query
575
631
  if (pos !== semicolonPos - 1) {
576
- modeData.media = input
577
- .slice(modeData.lastPos, semicolonPos - 1)
632
+ importData.media = input
633
+ .slice(importData.end, semicolonPos - 1)
578
634
  .trim();
579
635
  }
580
636
  const dep = new CssImportDependency(
581
- modeData.url.trim(),
582
- [modeData.start, end],
583
- modeData.layer,
584
- modeData.supports,
585
- modeData.media && modeData.media.length > 0
586
- ? modeData.media
637
+ importData.url.trim(),
638
+ [importData.start, end],
639
+ importData.layer,
640
+ importData.supports,
641
+ importData.media && importData.media.length > 0
642
+ ? importData.media
587
643
  : undefined
588
644
  );
589
645
  dep.setLoc(sl, sc, el, ec);
590
646
  module.addDependency(dep);
591
- modeData = undefined;
592
- mode = CSS_MODE_TOP_LEVEL;
647
+ importData = undefined;
648
+ scope = CSS_MODE_TOP_LEVEL;
593
649
  break;
594
650
  }
595
- case CSS_MODE_IN_LOCAL_RULE: {
596
- processDeclarationValueDone(input, start);
597
- return processLocalDeclaration(input, end);
598
- }
599
- case CSS_MODE_IN_RULE: {
600
- return end;
651
+ case CSS_MODE_IN_BLOCK: {
652
+ if (this.allowModeSwitch) {
653
+ processDeclarationValueDone(input);
654
+ inAnimationProperty = false;
655
+ isNextRulePrelude = isNextNestedSyntax(input, end);
656
+ }
657
+ break;
601
658
  }
602
659
  }
603
- mode = CSS_MODE_TOP_LEVEL;
604
- modeData = undefined;
605
- singleClassSelector = undefined;
606
660
  return end;
607
661
  },
608
662
  leftCurlyBracket: (input, start, end) => {
609
- switch (mode) {
610
- case CSS_MODE_TOP_LEVEL:
663
+ switch (scope) {
664
+ case CSS_MODE_TOP_LEVEL: {
611
665
  allowImportAtRule = false;
612
- mode = isTopLevelLocal()
613
- ? CSS_MODE_IN_LOCAL_RULE
614
- : CSS_MODE_IN_RULE;
615
- modeNestingLevel = 1;
616
- if (mode === CSS_MODE_IN_LOCAL_RULE)
617
- return processLocalDeclaration(input, end);
666
+ scope = CSS_MODE_IN_BLOCK;
667
+ blockNestingLevel = 1;
668
+
669
+ if (this.allowModeSwitch) {
670
+ isNextRulePrelude = isNextNestedSyntax(input, end);
671
+ }
672
+
618
673
  break;
619
- case CSS_MODE_IN_RULE:
620
- case CSS_MODE_IN_LOCAL_RULE:
621
- modeNestingLevel++;
674
+ }
675
+ case CSS_MODE_IN_BLOCK: {
676
+ blockNestingLevel++;
677
+
678
+ if (this.allowModeSwitch) {
679
+ isNextRulePrelude = isNextNestedSyntax(input, end);
680
+ }
622
681
  break;
682
+ }
623
683
  }
624
684
  return end;
625
685
  },
626
686
  rightCurlyBracket: (input, start, end) => {
627
- switch (mode) {
628
- case CSS_MODE_IN_LOCAL_RULE:
629
- processDeclarationValueDone(input, start);
630
- /* falls through */
631
- case CSS_MODE_IN_RULE:
632
- if (--modeNestingLevel === 0) {
633
- mode = CSS_MODE_TOP_LEVEL;
634
- modeData = undefined;
635
- singleClassSelector = undefined;
687
+ switch (scope) {
688
+ case CSS_MODE_IN_BLOCK: {
689
+ if (isLocalMode()) {
690
+ processDeclarationValueDone(input);
691
+ inAnimationProperty = false;
636
692
  }
637
- break;
638
- }
639
- return end;
640
- },
641
- id: (input, start, end) => {
642
- singleClassSelector = false;
643
- switch (mode) {
644
- case CSS_MODE_TOP_LEVEL:
645
- if (isTopLevelLocal()) {
646
- const name = input.slice(start + 1, end);
647
- const dep = new CssLocalIdentifierDependency(name, [
648
- start + 1,
649
- end
650
- ]);
651
- const { line: sl, column: sc } = locConverter.get(start);
652
- const { line: el, column: ec } = locConverter.get(end);
653
- dep.setLoc(sl, sc, el, ec);
654
- module.addDependency(dep);
693
+ if (--blockNestingLevel === 0) {
694
+ scope = CSS_MODE_TOP_LEVEL;
695
+
696
+ if (this.allowModeSwitch) {
697
+ isNextRulePrelude = true;
698
+ modeData = undefined;
699
+ }
700
+ } else if (this.allowModeSwitch) {
701
+ isNextRulePrelude = isNextNestedSyntax(input, end);
655
702
  }
656
703
  break;
704
+ }
657
705
  }
658
706
  return end;
659
707
  },
660
708
  identifier: (input, start, end) => {
661
- singleClassSelector = false;
662
- switch (mode) {
663
- case CSS_MODE_IN_LOCAL_RULE:
664
- if (modeData === "animation") {
665
- lastIdentifier = [start, end];
709
+ switch (scope) {
710
+ case CSS_MODE_IN_BLOCK: {
711
+ if (isLocalMode()) {
712
+ // Handle only top level values and not inside functions
713
+ if (inAnimationProperty && balanced.length === 0) {
714
+ lastIdentifier = [start, end];
715
+ } else {
716
+ return processLocalDeclaration(input, start, end);
717
+ }
666
718
  }
667
719
  break;
720
+ }
668
721
  case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
669
722
  if (input.slice(start, end).toLowerCase() === "layer") {
670
- modeData.layer = "";
671
- modeData.lastPos = end;
723
+ importData.layer = "";
724
+ importData.end = end;
672
725
  }
673
726
  break;
674
727
  }
@@ -676,24 +729,25 @@ class CssParser extends Parser {
676
729
  return end;
677
730
  },
678
731
  class: (input, start, end) => {
679
- switch (mode) {
680
- case CSS_MODE_TOP_LEVEL: {
681
- if (isTopLevelLocal()) {
682
- const name = input.slice(start + 1, end);
683
- const dep = new CssLocalIdentifierDependency(name, [
684
- start + 1,
685
- end
686
- ]);
687
- const { line: sl, column: sc } = locConverter.get(start);
688
- const { line: el, column: ec } = locConverter.get(end);
689
- dep.setLoc(sl, sc, el, ec);
690
- module.addDependency(dep);
691
- if (singleClassSelector === undefined) singleClassSelector = name;
692
- } else {
693
- singleClassSelector = false;
694
- }
695
- break;
696
- }
732
+ if (isLocalMode()) {
733
+ const name = input.slice(start + 1, end);
734
+ const dep = new CssLocalIdentifierDependency(name, [start + 1, end]);
735
+ const { line: sl, column: sc } = locConverter.get(start);
736
+ const { line: el, column: ec } = locConverter.get(end);
737
+ dep.setLoc(sl, sc, el, ec);
738
+ module.addDependency(dep);
739
+ }
740
+
741
+ return end;
742
+ },
743
+ id: (input, start, end) => {
744
+ if (isLocalMode()) {
745
+ const name = input.slice(start + 1, end);
746
+ const dep = new CssLocalIdentifierDependency(name, [start + 1, end]);
747
+ const { line: sl, column: sc } = locConverter.get(start);
748
+ const { line: el, column: ec } = locConverter.get(end);
749
+ dep.setLoc(sl, sc, el, ec);
750
+ module.addDependency(dep);
697
751
  }
698
752
  return end;
699
753
  },
@@ -702,75 +756,74 @@ class CssParser extends Parser {
702
756
 
703
757
  balanced.push([name, start, end]);
704
758
 
705
- switch (mode) {
706
- case CSS_MODE_IN_LOCAL_RULE: {
707
- name = name.toLowerCase();
708
-
709
- if (name === "var") {
710
- let pos = walkCssTokens.eatWhitespaceAndComments(input, end);
711
- if (pos === input.length) return pos;
712
- const [newPos, name] = eatText(input, pos, eatNameInVar);
713
- if (!name.startsWith("--")) return end;
714
- const { line: sl, column: sc } = locConverter.get(pos);
715
- const { line: el, column: ec } = locConverter.get(newPos);
716
- const dep = new CssSelfLocalIdentifierDependency(
717
- name.slice(2),
718
- [pos, newPos],
719
- "--",
720
- declaredCssVariables
721
- );
722
- dep.setLoc(sl, sc, el, ec);
723
- module.addDependency(dep);
724
- return newPos;
725
- }
726
- break;
759
+ if (isLocalMode()) {
760
+ name = name.toLowerCase();
761
+
762
+ // Don't rename animation name when we have `var()` function
763
+ if (inAnimationProperty && balanced.length === 1) {
764
+ lastIdentifier = undefined;
765
+ }
766
+
767
+ if (name === "var") {
768
+ let pos = walkCssTokens.eatWhitespaceAndComments(input, end);
769
+ if (pos === input.length) return pos;
770
+ const [newPos, name] = eatText(input, pos, eatNameInVar);
771
+ if (!name.startsWith("--")) return end;
772
+ const { line: sl, column: sc } = locConverter.get(pos);
773
+ const { line: el, column: ec } = locConverter.get(newPos);
774
+ const dep = new CssSelfLocalIdentifierDependency(
775
+ name.slice(2),
776
+ [pos, newPos],
777
+ "--",
778
+ declaredCssVariables
779
+ );
780
+ dep.setLoc(sl, sc, el, ec);
781
+ module.addDependency(dep);
782
+ return newPos;
727
783
  }
728
784
  }
785
+
729
786
  return end;
730
787
  },
731
788
  leftParenthesis: (input, start, end) => {
732
789
  balanced.push(["(", start, end]);
733
790
 
734
- switch (mode) {
735
- case CSS_MODE_TOP_LEVEL: {
736
- modeStack.push(false);
737
- break;
738
- }
739
- }
740
791
  return end;
741
792
  },
742
793
  rightParenthesis: (input, start, end) => {
743
794
  const last = balanced[balanced.length - 1];
795
+ const popped = balanced.pop();
744
796
 
745
- balanced.pop();
797
+ if (
798
+ this.allowModeSwitch &&
799
+ popped &&
800
+ (popped[0] === ":local" || popped[0] === ":global")
801
+ ) {
802
+ modeData = balanced[balanced.length - 1]
803
+ ? /** @type {"local" | "global"} */
804
+ (balanced[balanced.length - 1][0])
805
+ : undefined;
806
+ const dep = new ConstDependency("", [start, end]);
807
+ module.addPresentationalDependency(dep);
746
808
 
747
- switch (mode) {
748
- case CSS_MODE_TOP_LEVEL: {
749
- if (awaitRightParenthesis) {
750
- awaitRightParenthesis = false;
751
- }
752
- const newModeData = modeStack.pop();
753
- if (newModeData !== false) {
754
- modeData = newModeData;
755
- const dep = new ConstDependency("", [start, end]);
756
- module.addPresentationalDependency(dep);
757
- }
758
- break;
759
- }
809
+ return end;
810
+ }
811
+
812
+ switch (scope) {
760
813
  case CSS_MODE_AT_IMPORT_EXPECT_URL: {
761
814
  if (last && last[0] === "url") {
762
- modeData.lastPos = end;
763
- mode = CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA;
815
+ importData.end = end;
816
+ scope = CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA;
764
817
  }
765
818
  break;
766
819
  }
767
820
  case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
768
821
  if (last && last[0].toLowerCase() === "layer") {
769
- modeData.layer = input.slice(last[2], end - 1).trim();
770
- modeData.lastPos = end;
822
+ importData.layer = input.slice(last[2], end - 1).trim();
823
+ importData.end = end;
771
824
  } else if (last && last[0].toLowerCase() === "supports") {
772
- modeData.supports = input.slice(last[2], end - 1).trim();
773
- modeData.lastPos = end;
825
+ importData.supports = input.slice(last[2], end - 1).trim();
826
+ importData.end = end;
774
827
  }
775
828
  break;
776
829
  }
@@ -779,27 +832,38 @@ class CssParser extends Parser {
779
832
  return end;
780
833
  },
781
834
  pseudoClass: (input, start, end) => {
782
- singleClassSelector = false;
783
- switch (mode) {
784
- case CSS_MODE_TOP_LEVEL: {
785
- const name = input.slice(start, end).toLowerCase();
786
- if (this.allowModeSwitch && name === ":global") {
787
- modeData = "global";
788
- const dep = new ConstDependency("", [start, end]);
789
- module.addPresentationalDependency(dep);
790
- } else if (this.allowModeSwitch && name === ":local") {
791
- modeData = "local";
792
- const dep = new ConstDependency("", [start, end]);
793
- module.addPresentationalDependency(dep);
794
- } else if (this.allowPseudoBlocks && name === ":export") {
795
- const pos = parseExports(input, end);
796
- const dep = new ConstDependency("", [start, pos]);
797
- module.addPresentationalDependency(dep);
798
- return pos;
835
+ if (this.allowModeSwitch) {
836
+ const name = input.slice(start, end).toLowerCase();
837
+
838
+ if (name === ":global") {
839
+ modeData = "global";
840
+ // Eat extra whitespace and comments
841
+ end = walkCssTokens.eatWhitespace(input, end);
842
+ const dep = new ConstDependency("", [start, end]);
843
+ module.addPresentationalDependency(dep);
844
+ return end;
845
+ } else if (name === ":local") {
846
+ modeData = "local";
847
+ // Eat extra whitespace and comments
848
+ end = walkCssTokens.eatWhitespace(input, end);
849
+ const dep = new ConstDependency("", [start, end]);
850
+ module.addPresentationalDependency(dep);
851
+ return end;
852
+ }
853
+
854
+ switch (scope) {
855
+ case CSS_MODE_TOP_LEVEL: {
856
+ if (name === ":export") {
857
+ const pos = parseExports(input, end);
858
+ const dep = new ConstDependency("", [start, pos]);
859
+ module.addPresentationalDependency(dep);
860
+ return pos;
861
+ }
862
+ break;
799
863
  }
800
- break;
801
864
  }
802
865
  }
866
+
803
867
  return end;
804
868
  },
805
869
  pseudoFunction: (input, start, end) => {
@@ -807,40 +871,36 @@ class CssParser extends Parser {
807
871
 
808
872
  balanced.push([name, start, end]);
809
873
 
810
- switch (mode) {
811
- case CSS_MODE_TOP_LEVEL: {
812
- name = name.toLowerCase();
813
-
814
- if (this.allowModeSwitch && name === ":global") {
815
- modeStack.push(modeData);
816
- modeData = "global";
817
- const dep = new ConstDependency("", [start, end]);
818
- module.addPresentationalDependency(dep);
819
- } else if (this.allowModeSwitch && name === ":local") {
820
- modeStack.push(modeData);
821
- modeData = "local";
822
- const dep = new ConstDependency("", [start, end]);
823
- module.addPresentationalDependency(dep);
824
- } else {
825
- awaitRightParenthesis = true;
826
- modeStack.push(false);
827
- }
828
- break;
874
+ if (this.allowModeSwitch) {
875
+ name = name.toLowerCase();
876
+
877
+ if (name === ":global") {
878
+ modeData = "global";
879
+ const dep = new ConstDependency("", [start, end]);
880
+ module.addPresentationalDependency(dep);
881
+ } else if (name === ":local") {
882
+ modeData = "local";
883
+ const dep = new ConstDependency("", [start, end]);
884
+ module.addPresentationalDependency(dep);
829
885
  }
830
886
  }
887
+
831
888
  return end;
832
889
  },
833
890
  comma: (input, start, end) => {
834
- switch (mode) {
835
- case CSS_MODE_TOP_LEVEL:
836
- if (!awaitRightParenthesis) {
837
- modeData = undefined;
838
- modeStack.length = 0;
891
+ if (this.allowModeSwitch) {
892
+ // Reset stack for `:global .class :local .class-other` selector after
893
+ modeData = undefined;
894
+
895
+ switch (scope) {
896
+ case CSS_MODE_IN_BLOCK: {
897
+ if (isLocalMode()) {
898
+ processDeclarationValueDone(input);
899
+ }
900
+
901
+ break;
839
902
  }
840
- break;
841
- case CSS_MODE_IN_LOCAL_RULE:
842
- processDeclarationValueDone(input, start);
843
- break;
903
+ }
844
904
  }
845
905
  return end;
846
906
  }