webpack 5.102.0 → 5.103.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.
Files changed (146) hide show
  1. package/README.md +121 -134
  2. package/lib/ChunkGraph.js +2 -2
  3. package/lib/CodeGenerationResults.js +1 -1
  4. package/lib/CompatibilityPlugin.js +25 -2
  5. package/lib/Compilation.js +30 -13
  6. package/lib/ConcatenationScope.js +0 -15
  7. package/lib/ContextModule.js +3 -1
  8. package/lib/CssModule.js +6 -1
  9. package/lib/DefinePlugin.js +12 -12
  10. package/lib/Dependency.js +8 -1
  11. package/lib/DependencyTemplate.js +1 -0
  12. package/lib/DependencyTemplates.js +1 -1
  13. package/lib/DotenvPlugin.js +457 -0
  14. package/lib/EnvironmentPlugin.js +19 -16
  15. package/lib/EvalSourceMapDevToolPlugin.js +16 -0
  16. package/lib/ExportsInfo.js +6 -2
  17. package/lib/ExternalModule.js +20 -28
  18. package/lib/ExternalModuleFactoryPlugin.js +10 -8
  19. package/lib/ExternalsPlugin.js +2 -1
  20. package/lib/FileSystemInfo.js +9 -12
  21. package/lib/ManifestPlugin.js +235 -0
  22. package/lib/Module.js +3 -0
  23. package/lib/ModuleFilenameHelpers.js +1 -1
  24. package/lib/ModuleGraph.js +2 -1
  25. package/lib/ModuleSourceTypesConstants.js +0 -6
  26. package/lib/MultiCompiler.js +1 -1
  27. package/lib/NodeStuffPlugin.js +419 -121
  28. package/lib/NormalModule.js +18 -17
  29. package/lib/NormalModuleFactory.js +75 -4
  30. package/lib/RuntimeGlobals.js +22 -4
  31. package/lib/RuntimePlugin.js +27 -6
  32. package/lib/RuntimeTemplate.js +125 -57
  33. package/lib/SourceMapDevToolPlugin.js +26 -8
  34. package/lib/WebpackOptionsApply.js +33 -9
  35. package/lib/asset/AssetBytesGenerator.js +2 -1
  36. package/lib/asset/AssetGenerator.js +3 -5
  37. package/lib/asset/AssetSourceGenerator.js +1 -1
  38. package/lib/cache/getLazyHashedEtag.js +1 -1
  39. package/lib/config/browserslistTargetHandler.js +82 -76
  40. package/lib/config/defaults.js +105 -20
  41. package/lib/config/normalization.js +2 -1
  42. package/lib/config/target.js +7 -1
  43. package/lib/css/CssGenerator.js +283 -57
  44. package/lib/css/CssLoadingRuntimeModule.js +2 -0
  45. package/lib/css/CssMergeStyleSheetsRuntimeModule.js +56 -0
  46. package/lib/css/CssModulesPlugin.js +86 -40
  47. package/lib/css/CssParser.js +1174 -667
  48. package/lib/css/walkCssTokens.js +98 -1
  49. package/lib/dependencies/CommonJsImportsParserPlugin.js +0 -9
  50. package/lib/dependencies/CommonJsPlugin.js +12 -0
  51. package/lib/dependencies/ContextElementDependency.js +2 -2
  52. package/lib/dependencies/CssIcssExportDependency.js +247 -8
  53. package/lib/dependencies/CssIcssFromIdentifierDependency.js +124 -0
  54. package/lib/dependencies/CssIcssGlobalIdentifierDependency.js +48 -0
  55. package/lib/dependencies/CssIcssImportDependency.js +60 -54
  56. package/lib/dependencies/CssIcssLocalIdentifierDependency.js +61 -0
  57. package/lib/dependencies/{CssSelfLocalIdentifierDependency.js → CssIcssSelfLocalIdentifierDependency.js} +88 -10
  58. package/lib/dependencies/CssIcssSymbolDependency.js +31 -29
  59. package/lib/dependencies/CssImportDependency.js +15 -5
  60. package/lib/dependencies/ExternalModuleInitFragment.js +1 -1
  61. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +95 -0
  62. package/lib/dependencies/HarmonyAcceptDependency.js +6 -1
  63. package/lib/dependencies/HarmonyAcceptImportDependency.js +2 -1
  64. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +12 -1
  65. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +32 -21
  66. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +12 -8
  67. package/lib/dependencies/HarmonyImportDependency.js +27 -28
  68. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +28 -69
  69. package/lib/dependencies/HarmonyImportSideEffectDependency.js +4 -3
  70. package/lib/dependencies/HarmonyImportSpecifierDependency.js +10 -8
  71. package/lib/dependencies/ImportContextDependency.js +13 -0
  72. package/lib/dependencies/ImportDependency.js +10 -4
  73. package/lib/dependencies/ImportEagerDependency.js +6 -3
  74. package/lib/dependencies/ImportMetaPlugin.js +98 -10
  75. package/lib/dependencies/ImportParserPlugin.js +19 -21
  76. package/lib/dependencies/ImportPhase.js +121 -0
  77. package/lib/dependencies/ImportWeakDependency.js +6 -3
  78. package/lib/dependencies/ModuleDependency.js +5 -1
  79. package/lib/dependencies/ModuleHotAcceptDependency.js +1 -1
  80. package/lib/dependencies/WorkerPlugin.js +1 -3
  81. package/lib/esm/ExportWebpackRequireRuntimeModule.js +1 -8
  82. package/lib/hmr/LazyCompilationPlugin.js +1 -0
  83. package/lib/ids/HashedModuleIdsPlugin.js +5 -7
  84. package/lib/ids/IdHelpers.js +5 -2
  85. package/lib/index.js +6 -0
  86. package/lib/javascript/ChunkHelpers.js +16 -5
  87. package/lib/javascript/JavascriptGenerator.js +101 -101
  88. package/lib/javascript/JavascriptModulesPlugin.js +25 -16
  89. package/lib/javascript/JavascriptParser.js +143 -39
  90. package/lib/json/JsonParser.js +7 -1
  91. package/lib/library/ModuleLibraryPlugin.js +0 -10
  92. package/lib/library/SystemLibraryPlugin.js +19 -5
  93. package/lib/library/UmdLibraryPlugin.js +1 -1
  94. package/lib/node/NodeTargetPlugin.js +9 -1
  95. package/lib/node/ReadFileCompileWasmPlugin.js +0 -2
  96. package/lib/optimize/ConcatenatedModule.js +161 -135
  97. package/lib/optimize/RealContentHashPlugin.js +5 -3
  98. package/lib/runtime/AsyncModuleRuntimeModule.js +28 -18
  99. package/lib/runtime/AutoPublicPathRuntimeModule.js +8 -3
  100. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +89 -55
  101. package/lib/serialization/FileMiddleware.js +1 -1
  102. package/lib/serialization/ObjectMiddleware.js +1 -1
  103. package/lib/stats/DefaultStatsFactoryPlugin.js +1 -1
  104. package/lib/util/Hash.js +35 -5
  105. package/lib/util/comparators.js +4 -3
  106. package/lib/util/create-schema-validation.js +1 -1
  107. package/lib/util/createHash.js +85 -15
  108. package/lib/util/hash/BatchedHash.js +47 -8
  109. package/lib/util/hash/wasm-hash.js +53 -13
  110. package/lib/util/internalSerializables.js +4 -4
  111. package/lib/util/jsonParseEvenBetterErrors.js +10 -0
  112. package/lib/wasm/EnableWasmLoadingPlugin.js +10 -4
  113. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +8 -5
  114. package/lib/wasm-async/AsyncWebAssemblyParser.js +0 -9
  115. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +8 -4
  116. package/lib/wasm-sync/WebAssemblyParser.js +0 -9
  117. package/lib/web/FetchCompileWasmPlugin.js +0 -2
  118. package/lib/web/JsonpChunkLoadingRuntimeModule.js +1 -1
  119. package/lib/webpack.js +85 -82
  120. package/module.d.ts +5 -0
  121. package/package.json +28 -26
  122. package/schemas/WebpackOptions.check.js +1 -1
  123. package/schemas/WebpackOptions.json +110 -15
  124. package/schemas/plugins/{HashedModuleIdsPlugin.check.d.ts → ManifestPlugin.check.d.ts} +1 -1
  125. package/schemas/plugins/ManifestPlugin.check.js +6 -0
  126. package/schemas/plugins/ManifestPlugin.json +98 -0
  127. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  128. package/schemas/plugins/SourceMapDevToolPlugin.json +16 -3
  129. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  130. package/schemas/plugins/container/ContainerReferencePlugin.json +4 -1
  131. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  132. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  133. package/schemas/plugins/container/ModuleFederationPlugin.json +4 -1
  134. package/schemas/plugins/css/CssAutoParserOptions.check.js +1 -1
  135. package/schemas/plugins/css/CssGlobalGeneratorOptions.check.js +1 -1
  136. package/schemas/plugins/css/CssGlobalParserOptions.check.js +1 -1
  137. package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +1 -1
  138. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  139. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  140. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.d.ts +7 -0
  141. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +6 -0
  142. package/schemas/plugins/{HashedModuleIdsPlugin.json → ids/HashedModuleIdsPlugin.json} +15 -2
  143. package/schemas/plugins/json/JsonModulesPluginParser.check.js +1 -1
  144. package/types.d.ts +788 -127
  145. package/lib/dependencies/CssLocalIdentifierDependency.js +0 -252
  146. package/schemas/plugins/HashedModuleIdsPlugin.check.js +0 -6
@@ -7,6 +7,7 @@
7
7
 
8
8
  const vm = require("vm");
9
9
  const CommentCompilationWarning = require("../CommentCompilationWarning");
10
+ const CssModule = require("../CssModule");
10
11
  const ModuleDependencyWarning = require("../ModuleDependencyWarning");
11
12
  const { CSS_MODULE_TYPE_AUTO } = require("../ModuleTypeConstants");
12
13
  const Parser = require("../Parser");
@@ -14,11 +15,13 @@ const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
14
15
  const WebpackError = require("../WebpackError");
15
16
  const ConstDependency = require("../dependencies/ConstDependency");
16
17
  const CssIcssExportDependency = require("../dependencies/CssIcssExportDependency");
18
+ const CssIcssFromIdentifierDependency = require("../dependencies/CssIcssFromIdentifierDependency");
19
+ const CssIcssGlobalIdentifierDependency = require("../dependencies/CssIcssGlobalIdentifierDependency");
17
20
  const CssIcssImportDependency = require("../dependencies/CssIcssImportDependency");
21
+ const CssIcssLocalIdentifierDependency = require("../dependencies/CssIcssLocalIdentifierDependency");
22
+ const CssIcssSelfLocalIdentifierDependency = require("../dependencies/CssIcssSelfLocalIdentifierDependency");
18
23
  const CssIcssSymbolDependency = require("../dependencies/CssIcssSymbolDependency");
19
24
  const CssImportDependency = require("../dependencies/CssImportDependency");
20
- const CssLocalIdentifierDependency = require("../dependencies/CssLocalIdentifierDependency");
21
- const CssSelfLocalIdentifierDependency = require("../dependencies/CssSelfLocalIdentifierDependency");
22
25
  const CssUrlDependency = require("../dependencies/CssUrlDependency");
23
26
  const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
24
27
  const binarySearchBounds = require("../util/binarySearchBounds");
@@ -34,17 +37,21 @@ const walkCssTokens = require("./walkCssTokens");
34
37
  /** @typedef {import("../Parser").ParserState} ParserState */
35
38
  /** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
36
39
  /** @typedef {import("./walkCssTokens").CssTokenCallbacks} CssTokenCallbacks */
40
+ /** @typedef {import("../../declarations/WebpackOptions").CssParserExportType} CssParserExportType */
37
41
 
38
42
  /** @typedef {[number, number]} Range */
39
43
  /** @typedef {{ line: number, column: number }} Position */
40
44
  /** @typedef {{ value: string, range: Range, loc: { start: Position, end: Position } }} Comment */
41
45
 
42
46
  const CC_COLON = ":".charCodeAt(0);
47
+ const CC_SEMICOLON = ";".charCodeAt(0);
48
+ const CC_COMMA = ",".charCodeAt(0);
43
49
  const CC_SLASH = "/".charCodeAt(0);
44
50
  const CC_LEFT_PARENTHESIS = "(".charCodeAt(0);
45
51
  const CC_RIGHT_PARENTHESIS = ")".charCodeAt(0);
46
52
  const CC_LOWER_F = "f".charCodeAt(0);
47
53
  const CC_UPPER_F = "F".charCodeAt(0);
54
+ const CC_RIGHT_CURLY = "}".charCodeAt(0);
48
55
 
49
56
  // https://www.w3.org/TR/css-syntax-3/#newline
50
57
  // We don't have `preprocessing` stage, so we need specify all of them
@@ -56,6 +63,7 @@ const IMAGE_SET_FUNCTION = /^(-\w+-)?image-set$/i;
56
63
  const OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE = /^@(-\w+-)?keyframes$/;
57
64
  const OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY =
58
65
  /^(-\w+-)?animation(-name)?$/i;
66
+ const COMPOSES_PROPERTY = /^(composes|compose-with)$/i;
59
67
  const IS_MODULES = /\.module(s)?\.[^.]+$/i;
60
68
  const CSS_COMMENT = /\/\*((?!\*\/).*?)\*\//g;
61
69
 
@@ -230,6 +238,40 @@ const unescapeIdentifier = (str) => {
230
238
  return ret;
231
239
  };
232
240
 
241
+ /** @type {Record<string, number>} */
242
+ const ANIMATION_KEYWORDS = {
243
+ // animation-direction
244
+ normal: 1,
245
+ reverse: 1,
246
+ alternate: 1,
247
+ "alternate-reverse": 1,
248
+ // animation-fill-mode
249
+ forwards: 1,
250
+ backwards: 1,
251
+ both: 1,
252
+ // animation-iteration-count
253
+ infinite: 1,
254
+ // animation-play-state
255
+ paused: 1,
256
+ running: 1,
257
+ // animation-timing-function
258
+ ease: 1,
259
+ "ease-in": 1,
260
+ "ease-out": 1,
261
+ "ease-in-out": 1,
262
+ linear: 1,
263
+ "step-end": 1,
264
+ "step-start": 1,
265
+ // Special
266
+ none: Infinity, // No matter how many times you write none, it will never be an animation name
267
+ // Global values
268
+ initial: Infinity,
269
+ inherit: Infinity,
270
+ unset: Infinity,
271
+ revert: Infinity,
272
+ "revert-layer": Infinity
273
+ };
274
+
233
275
  class LocConverter {
234
276
  /**
235
277
  * @param {string} input input
@@ -291,6 +333,7 @@ const eatSemi = walkCssTokens.eatUntil(";");
291
333
  * @property {boolean=} url need handle URLs
292
334
  * @property {("pure" | "global" | "local" | "auto")=} defaultMode default mode
293
335
  * @property {boolean=} namedExports is named exports
336
+ * @property {CssParserExportType=} exportType export type
294
337
  */
295
338
 
296
339
  class CssParser extends Parser {
@@ -301,13 +344,15 @@ class CssParser extends Parser {
301
344
  defaultMode = "pure",
302
345
  importOption = true,
303
346
  url = true,
304
- namedExports = true
347
+ namedExports = true,
348
+ exportType
305
349
  } = {}) {
306
350
  super();
307
351
  this.defaultMode = defaultMode;
308
352
  this.import = importOption;
309
353
  this.url = url;
310
354
  this.namedExports = namedExports;
355
+ this.exportType = exportType;
311
356
  /** @type {Comment[] | undefined} */
312
357
  this.comments = undefined;
313
358
  this.magicCommentContext = createMagicCommentContext();
@@ -382,13 +427,13 @@ class CssParser extends Parser {
382
427
  let blockNestingLevel = 0;
383
428
  /** @type {"local" | "global" | undefined} */
384
429
  let modeData;
385
- /** @type {boolean} */
386
- let inAnimationProperty = false;
387
- /** @type {[number, number, boolean] | undefined} */
388
- let lastIdentifier;
389
430
  /** @type {Set<string>} */
390
431
  const declaredCssVariables = new Set();
391
- /** @typedef {{ path?: string, value: string }} IcssDefinition */
432
+
433
+ /** @type {string[]} */
434
+ let lastLocalIdentifiers = [];
435
+
436
+ /** @typedef {{ value: string, isReference?: boolean }} IcssDefinition */
392
437
  /** @type {Map<string, IcssDefinition>} */
393
438
  const icssDefinitions = new Map();
394
439
 
@@ -449,16 +494,338 @@ class CssParser extends Parser {
449
494
  return [pos, text.trimEnd()];
450
495
  };
451
496
 
497
+ const eatPropertyName = walkCssTokens.eatUntil(":{};");
498
+
499
+ /**
500
+ * @param {string} input input
501
+ * @param {number} start start
502
+ * @param {number} end end
503
+ * @returns {number} end
504
+ */
505
+ const comment = (input, start, end) => {
506
+ if (!this.comments) this.comments = [];
507
+ const { line: sl, column: sc } = locConverter.get(start);
508
+ const { line: el, column: ec } = locConverter.get(end);
509
+
510
+ /** @type {Comment} */
511
+ const comment = {
512
+ value: input.slice(start + 2, end - 2),
513
+ range: [start, end],
514
+ loc: {
515
+ start: { line: sl, column: sc },
516
+ end: { line: el, column: ec }
517
+ }
518
+ };
519
+ this.comments.push(comment);
520
+ return end;
521
+ };
522
+
523
+ // Vanilla CSS stuff
524
+
525
+ /**
526
+ * @param {string} input input
527
+ * @param {number} start name start position
528
+ * @param {number} end name end position
529
+ * @returns {number} position after handling
530
+ */
531
+ const processAtImport = (input, start, end) => {
532
+ const tokens = walkCssTokens.eatImportTokens(input, end, {
533
+ comment
534
+ });
535
+ if (!tokens[3]) return end;
536
+ const semi = tokens[3][1];
537
+ if (!tokens[0]) {
538
+ this._emitWarning(
539
+ state,
540
+ `Expected URL in '${input.slice(start, semi)}'`,
541
+ locConverter,
542
+ start,
543
+ semi
544
+ );
545
+ return end;
546
+ }
547
+
548
+ const urlToken = tokens[0];
549
+ const url = normalizeUrl(input.slice(urlToken[2], urlToken[3]), true);
550
+ const newline = walkCssTokens.eatWhiteLine(input, semi);
551
+ const { options, errors: commentErrors } = this.parseCommentOptions([
552
+ end,
553
+ urlToken[1]
554
+ ]);
555
+ if (commentErrors) {
556
+ for (const e of commentErrors) {
557
+ const { comment } = e;
558
+ state.module.addWarning(
559
+ new CommentCompilationWarning(
560
+ `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
561
+ comment.loc
562
+ )
563
+ );
564
+ }
565
+ }
566
+ if (options && options.webpackIgnore !== undefined) {
567
+ if (typeof options.webpackIgnore !== "boolean") {
568
+ const { line: sl, column: sc } = locConverter.get(start);
569
+ const { line: el, column: ec } = locConverter.get(newline);
570
+
571
+ state.module.addWarning(
572
+ new UnsupportedFeatureWarning(
573
+ `\`webpackIgnore\` expected a boolean, but received: ${options.webpackIgnore}.`,
574
+ {
575
+ start: { line: sl, column: sc },
576
+ end: { line: el, column: ec }
577
+ }
578
+ )
579
+ );
580
+ } else if (options.webpackIgnore) {
581
+ return newline;
582
+ }
583
+ }
584
+ if (url.length === 0) {
585
+ const { line: sl, column: sc } = locConverter.get(start);
586
+ const { line: el, column: ec } = locConverter.get(newline);
587
+ const dep = new ConstDependency("", [start, newline]);
588
+ module.addPresentationalDependency(dep);
589
+ dep.setLoc(sl, sc, el, ec);
590
+
591
+ return newline;
592
+ }
593
+
594
+ let layer;
595
+
596
+ if (tokens[1]) {
597
+ layer = input.slice(tokens[1][0] + 6, tokens[1][1] - 1).trim();
598
+ }
599
+
600
+ let supports;
601
+
602
+ if (tokens[2]) {
603
+ supports = input.slice(tokens[2][0] + 9, tokens[2][1] - 1).trim();
604
+ }
605
+
606
+ const last = tokens[2] || tokens[1] || tokens[0];
607
+ const mediaStart = walkCssTokens.eatWhitespaceAndComments(input, last[1]);
608
+
609
+ let media;
610
+
611
+ if (mediaStart !== semi - 1) {
612
+ media = input.slice(mediaStart, semi - 1).trim();
613
+ }
614
+
615
+ const { line: sl, column: sc } = locConverter.get(start);
616
+ const { line: el, column: ec } = locConverter.get(newline);
617
+ const dep = new CssImportDependency(
618
+ url,
619
+ [start, newline],
620
+ mode === "local" || mode === "global" ? mode : undefined,
621
+ layer,
622
+ supports && supports.length > 0 ? supports : undefined,
623
+ media && media.length > 0 ? media : undefined
624
+ );
625
+ dep.setLoc(sl, sc, el, ec);
626
+ module.addDependency(dep);
627
+
628
+ return newline;
629
+ };
630
+
631
+ /**
632
+ * @param {string} input input
633
+ * @param {number} end end position
634
+ * @param {string} name the name of function
635
+ * @returns {number} position after handling
636
+ */
637
+ const processURLFunction = (input, end, name) => {
638
+ const string = walkCssTokens.eatString(input, end);
639
+ if (!string) return end;
640
+ const { options, errors: commentErrors } = this.parseCommentOptions([
641
+ lastTokenEndForComments,
642
+ end
643
+ ]);
644
+ if (commentErrors) {
645
+ for (const e of commentErrors) {
646
+ const { comment } = e;
647
+ state.module.addWarning(
648
+ new CommentCompilationWarning(
649
+ `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
650
+ comment.loc
651
+ )
652
+ );
653
+ }
654
+ }
655
+ if (options && options.webpackIgnore !== undefined) {
656
+ if (typeof options.webpackIgnore !== "boolean") {
657
+ const { line: sl, column: sc } = locConverter.get(string[0]);
658
+ const { line: el, column: ec } = locConverter.get(string[1]);
659
+
660
+ state.module.addWarning(
661
+ new UnsupportedFeatureWarning(
662
+ `\`webpackIgnore\` expected a boolean, but received: ${options.webpackIgnore}.`,
663
+ {
664
+ start: { line: sl, column: sc },
665
+ end: { line: el, column: ec }
666
+ }
667
+ )
668
+ );
669
+ } else if (options.webpackIgnore) {
670
+ return end;
671
+ }
672
+ }
673
+ const value = normalizeUrl(
674
+ input.slice(string[0] + 1, string[1] - 1),
675
+ true
676
+ );
677
+ // Ignore `url()`, `url('')` and `url("")`, they are valid by spec
678
+ if (value.length === 0) return end;
679
+ const isUrl = name === "url" || name === "src";
680
+ const dep = new CssUrlDependency(
681
+ value,
682
+ [string[0], string[1]],
683
+ isUrl ? "string" : "url"
684
+ );
685
+ const { line: sl, column: sc } = locConverter.get(string[0]);
686
+ const { line: el, column: ec } = locConverter.get(string[1]);
687
+ dep.setLoc(sl, sc, el, ec);
688
+ module.addDependency(dep);
689
+ module.addCodeGenerationDependency(dep);
690
+ return string[1];
691
+ };
692
+
693
+ /**
694
+ * @param {string} input input
695
+ * @param {number} start start position
696
+ * @param {number} end end position
697
+ * @param {number} contentStart start position
698
+ * @param {number} contentEnd end position
699
+ * @returns {number} position after handling
700
+ */
701
+ const processOldURLFunction = (
702
+ input,
703
+ start,
704
+ end,
705
+ contentStart,
706
+ contentEnd
707
+ ) => {
708
+ const { options, errors: commentErrors } = this.parseCommentOptions([
709
+ lastTokenEndForComments,
710
+ end
711
+ ]);
712
+ if (commentErrors) {
713
+ for (const e of commentErrors) {
714
+ const { comment } = e;
715
+ state.module.addWarning(
716
+ new CommentCompilationWarning(
717
+ `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
718
+ comment.loc
719
+ )
720
+ );
721
+ }
722
+ }
723
+ if (options && options.webpackIgnore !== undefined) {
724
+ if (typeof options.webpackIgnore !== "boolean") {
725
+ const { line: sl, column: sc } = locConverter.get(
726
+ lastTokenEndForComments
727
+ );
728
+ const { line: el, column: ec } = locConverter.get(end);
729
+
730
+ state.module.addWarning(
731
+ new UnsupportedFeatureWarning(
732
+ `\`webpackIgnore\` expected a boolean, but received: ${options.webpackIgnore}.`,
733
+ {
734
+ start: { line: sl, column: sc },
735
+ end: { line: el, column: ec }
736
+ }
737
+ )
738
+ );
739
+ } else if (options.webpackIgnore) {
740
+ return end;
741
+ }
742
+ }
743
+ const value = normalizeUrl(input.slice(contentStart, contentEnd), false);
744
+ // Ignore `url()`, `url('')` and `url("")`, they are valid by spec
745
+ if (value.length === 0) return end;
746
+ const dep = new CssUrlDependency(value, [start, end], "url");
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);
751
+ module.addCodeGenerationDependency(dep);
752
+ return end;
753
+ };
754
+
755
+ /**
756
+ * @param {string} input input
757
+ * @param {number} start start position
758
+ * @param {number} end end position
759
+ * @returns {number} position after handling
760
+ */
761
+ const processImageSetFunction = (input, start, end) => {
762
+ lastTokenEndForComments = end;
763
+ const values = walkCssTokens.eatImageSetStrings(input, end, {
764
+ comment
765
+ });
766
+ if (values.length === 0) return end;
767
+ for (const [index, string] of values.entries()) {
768
+ const value = normalizeUrl(
769
+ input.slice(string[0] + 1, string[1] - 1),
770
+ true
771
+ );
772
+ if (value.length === 0) return end;
773
+ const { options, errors: commentErrors } = this.parseCommentOptions([
774
+ index === 0 ? start : values[index - 1][1],
775
+ string[1]
776
+ ]);
777
+ if (commentErrors) {
778
+ for (const e of commentErrors) {
779
+ const { comment } = e;
780
+ state.module.addWarning(
781
+ new CommentCompilationWarning(
782
+ `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
783
+ comment.loc
784
+ )
785
+ );
786
+ }
787
+ }
788
+ if (options && options.webpackIgnore !== undefined) {
789
+ if (typeof options.webpackIgnore !== "boolean") {
790
+ const { line: sl, column: sc } = locConverter.get(string[0]);
791
+ const { line: el, column: ec } = locConverter.get(string[1]);
792
+
793
+ state.module.addWarning(
794
+ new UnsupportedFeatureWarning(
795
+ `\`webpackIgnore\` expected a boolean, but received: ${options.webpackIgnore}.`,
796
+ {
797
+ start: { line: sl, column: sc },
798
+ end: { line: el, column: ec }
799
+ }
800
+ )
801
+ );
802
+ } else if (options.webpackIgnore) {
803
+ continue;
804
+ }
805
+ }
806
+ const dep = new CssUrlDependency(value, [string[0], string[1]], "url");
807
+ const { line: sl, column: sc } = locConverter.get(string[0]);
808
+ const { line: el, column: ec } = locConverter.get(string[1]);
809
+ dep.setLoc(sl, sc, el, ec);
810
+ module.addDependency(dep);
811
+ module.addCodeGenerationDependency(dep);
812
+ }
813
+ // Can contain `url()` inside, so let's return end to allow parse them
814
+ return end;
815
+ };
816
+
817
+ // CSS modules stuff
818
+
452
819
  /**
453
820
  * @param {0 | 1} type import or export
454
821
  * @param {string} input input
455
822
  * @param {number} pos start position
456
823
  * @returns {number} position after parse
457
824
  */
458
- const parseImportOrExport = (type, input, pos) => {
825
+ const processImportOrExport = (type, input, pos) => {
459
826
  pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
460
827
  /** @type {string | undefined} */
461
- let importPath;
828
+ let request;
462
829
  if (type === 0) {
463
830
  let cc = input.charCodeAt(pos);
464
831
  if (cc !== CC_LEFT_PARENTHESIS) {
@@ -477,14 +844,14 @@ class CssParser extends Parser {
477
844
  if (!str) {
478
845
  this._emitWarning(
479
846
  state,
480
- `Unexpected '${input[pos]}' at ${pos} during parsing of ':import' (expected string)`,
847
+ `Unexpected '${input[pos]}' at ${pos} during parsing of '${type ? ":import" : ":export"}' (expected string)`,
481
848
  locConverter,
482
849
  stringStart,
483
850
  pos
484
851
  );
485
852
  return pos;
486
853
  }
487
- importPath = input.slice(str[0] + 1, str[1] - 1);
854
+ request = input.slice(str[0] + 1, str[1] - 1);
488
855
  pos = str[1];
489
856
  pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
490
857
  cc = input.charCodeAt(pos);
@@ -510,12 +877,28 @@ class CssParser extends Parser {
510
877
  */
511
878
  const createDep = (name, value, start, end) => {
512
879
  if (type === 0) {
513
- icssDefinitions.set(name, {
514
- path: /** @type {string} */ (importPath),
880
+ const dep = new CssIcssImportDependency(
881
+ /** @type {string} */
882
+ (request),
883
+ [0, 0],
884
+ /** @type {"local" | "global"} */
885
+ (mode),
515
886
  value
516
- });
887
+ );
888
+ const { line: sl, column: sc } = locConverter.get(start);
889
+ const { line: el, column: ec } = locConverter.get(end);
890
+ dep.setLoc(sl, sc, el, ec);
891
+ module.addDependency(dep);
892
+
893
+ icssDefinitions.set(name, { value, isReference: true });
517
894
  } else if (type === 1) {
518
- const dep = new CssIcssExportDependency(name, value);
895
+ const reexport = icssDefinitions.get(value);
896
+ const dep = new CssIcssExportDependency(
897
+ name,
898
+ value,
899
+ reexport && reexport.isReference ? reexport.value : undefined,
900
+ undefined
901
+ );
519
902
  const { line: sl, column: sc } = locConverter.get(start);
520
903
  const { line: el, column: ec } = locConverter.get(end);
521
904
  dep.setLoc(sl, sc, el, ec);
@@ -605,131 +988,732 @@ class CssParser extends Parser {
605
988
 
606
989
  return pos;
607
990
  };
608
- const eatPropertyName = walkCssTokens.eatUntil(":{};");
991
+
609
992
  /**
610
993
  * @param {string} input input
611
- * @param {number} pos name start position
994
+ * @param {number} start name start position
612
995
  * @param {number} end name end position
613
996
  * @returns {number} position after handling
614
997
  */
615
- const processLocalDeclaration = (input, pos, end) => {
616
- modeData = undefined;
617
- pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
618
- const propertyNameStart = pos;
619
- const [propertyNameEnd, propertyName] = eatText(
620
- input,
621
- pos,
622
- eatPropertyName
623
- );
624
- if (input.charCodeAt(propertyNameEnd) !== CC_COLON) return end;
625
- pos = propertyNameEnd + 1;
626
- if (propertyName.startsWith("--") && propertyName.length >= 3) {
627
- // CSS Variable
628
- const { line: sl, column: sc } = locConverter.get(propertyNameStart);
629
- const { line: el, column: ec } = locConverter.get(propertyNameEnd);
630
- const name = unescapeIdentifier(propertyName.slice(2));
631
- const dep = new CssLocalIdentifierDependency(
632
- name,
633
- [propertyNameStart, propertyNameEnd],
634
- "--"
635
- );
636
- dep.setLoc(sl, sc, el, ec);
637
- module.addDependency(dep);
638
- declaredCssVariables.add(name);
639
- } else if (
640
- OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY.test(propertyName)
641
- ) {
642
- inAnimationProperty = true;
643
- }
644
- return pos;
645
- };
646
- /**
647
- * @param {string} input input
648
- */
649
- const processDeclarationValueDone = (input) => {
650
- if (inAnimationProperty && lastIdentifier) {
651
- const { line: sl, column: sc } = locConverter.get(lastIdentifier[0]);
652
- const { line: el, column: ec } = locConverter.get(lastIdentifier[1]);
653
- const name = unescapeIdentifier(
654
- lastIdentifier[2]
655
- ? input.slice(lastIdentifier[0], lastIdentifier[1])
656
- : input.slice(lastIdentifier[0] + 1, lastIdentifier[1] - 1)
657
- );
658
- const dep = new CssSelfLocalIdentifierDependency(name, [
659
- lastIdentifier[0],
660
- lastIdentifier[1]
661
- ]);
662
- dep.setLoc(sl, sc, el, ec);
663
- module.addDependency(dep);
664
- lastIdentifier = undefined;
665
- }
666
- };
998
+ const processAtValue = (input, start, end) => {
999
+ const semi = eatUntilSemi(input, end);
1000
+ const atRuleEnd = semi + 1;
1001
+ const params = input.slice(end, semi);
1002
+ let [alias, request] = params.split(/\s*from\s*/);
667
1003
 
668
- /**
669
- * @param {string} input input
670
- * @param {number} start start
671
- * @param {number} end end
672
- * @returns {number} end
673
- */
674
- const comment = (input, start, end) => {
675
- if (!this.comments) this.comments = [];
676
- const { line: sl, column: sc } = locConverter.get(start);
677
- const { line: el, column: ec } = locConverter.get(end);
1004
+ if (request) {
1005
+ const aliases = alias
1006
+ .replace(CSS_COMMENT, " ")
1007
+ .trim()
1008
+ .replace(/^\(\s*|\s*\)$/g, "")
1009
+ .split(/\s*,\s*/);
678
1010
 
679
- /** @type {Comment} */
680
- const comment = {
681
- value: input.slice(start + 2, end - 2),
682
- range: [start, end],
683
- loc: {
684
- start: { line: sl, column: sc },
685
- end: { line: el, column: ec }
1011
+ request = request.replace(CSS_COMMENT, "").trim();
1012
+
1013
+ const isExplicitImport = request[0] === "'" || request[0] === '"';
1014
+
1015
+ if (isExplicitImport) {
1016
+ request = request.slice(1, -1);
686
1017
  }
687
- };
688
- this.comments.push(comment);
689
- return end;
690
- };
691
1018
 
692
- walkCssTokens(source, 0, {
693
- comment,
694
- leftCurlyBracket: (input, start, end) => {
695
- switch (scope) {
696
- case CSS_MODE_TOP_LEVEL: {
697
- allowImportAtRule = false;
698
- scope = CSS_MODE_IN_BLOCK;
1019
+ for (const alias of aliases) {
1020
+ const [name, aliasName] = alias.split(/\s+as\s+/);
699
1021
 
700
- if (isModules) {
701
- blockNestingLevel = 1;
702
- isNextRulePrelude = isNextNestedSyntax(input, end);
703
- }
1022
+ {
1023
+ const reexport = icssDefinitions.get(request);
704
1024
 
705
- break;
706
- }
707
- case CSS_MODE_IN_BLOCK: {
708
- if (isModules) {
709
- blockNestingLevel++;
710
- isNextRulePrelude = isNextNestedSyntax(input, end);
1025
+ if (reexport) {
1026
+ request = reexport.value.slice(1, -1);
711
1027
  }
712
- break;
713
- }
714
- }
715
- return end;
716
- },
717
- rightCurlyBracket: (input, start, end) => {
718
- switch (scope) {
719
- case CSS_MODE_IN_BLOCK: {
720
- if (--blockNestingLevel === 0) {
721
- scope = CSS_MODE_TOP_LEVEL;
722
1028
 
723
- if (isModules) {
724
- isNextRulePrelude = true;
1029
+ const dep = new CssIcssImportDependency(
1030
+ request,
1031
+ [0, 0],
1032
+ /** @type {"local" | "global"} */
1033
+ (mode),
1034
+ name
1035
+ );
1036
+ const { line: sl, column: sc } = locConverter.get(start);
1037
+ const { line: el, column: ec } = locConverter.get(end);
1038
+ dep.setLoc(sl, sc, el, ec);
1039
+ module.addDependency(dep);
1040
+
1041
+ icssDefinitions.set(aliasName || name, {
1042
+ value: name,
1043
+ isReference: true
1044
+ });
1045
+ }
1046
+
1047
+ if (aliasName) {
1048
+ const reexport = icssDefinitions.get(aliasName);
1049
+ const dep = new CssIcssExportDependency(
1050
+ aliasName,
1051
+ name,
1052
+ reexport && reexport.isReference ? reexport.value : undefined,
1053
+ undefined
1054
+ );
1055
+ const { line: sl, column: sc } = locConverter.get(start);
1056
+ const { line: el, column: ec } = locConverter.get(end);
1057
+ dep.setLoc(sl, sc, el, ec);
1058
+ module.addDependency(dep);
1059
+ }
1060
+
1061
+ {
1062
+ const reexport = icssDefinitions.get(name);
1063
+ const dep = new CssIcssExportDependency(
1064
+ name,
1065
+ name,
1066
+ reexport && reexport.isReference ? reexport.value : undefined,
1067
+ undefined
1068
+ );
1069
+ const { line: sl, column: sc } = locConverter.get(start);
1070
+ const { line: el, column: ec } = locConverter.get(end);
1071
+ dep.setLoc(sl, sc, el, ec);
1072
+ module.addDependency(dep);
1073
+ }
1074
+ }
1075
+ } else {
1076
+ const ident = walkCssTokens.eatIdentSequence(alias, 0);
1077
+
1078
+ if (!ident) {
1079
+ this._emitWarning(
1080
+ state,
1081
+ `Broken '@value' at-rule: ${input.slice(start, atRuleEnd)}'`,
1082
+ locConverter,
1083
+ start,
1084
+ atRuleEnd
1085
+ );
1086
+
1087
+ const dep = new ConstDependency("", [start, atRuleEnd]);
1088
+ module.addPresentationalDependency(dep);
1089
+ return atRuleEnd;
1090
+ }
1091
+
1092
+ const pos = walkCssTokens.eatWhitespaceAndComments(alias, ident[1]);
1093
+
1094
+ const name = alias.slice(ident[0], ident[1]);
1095
+ let value =
1096
+ alias.charCodeAt(pos) === CC_COLON
1097
+ ? alias.slice(pos + 1)
1098
+ : alias.slice(ident[1]);
1099
+
1100
+ if (value && !/^\s+$/.test(value.replace(CSS_COMMENT, ""))) {
1101
+ value = value.trim();
1102
+ }
1103
+
1104
+ if (icssDefinitions.has(value)) {
1105
+ const def =
1106
+ /** @type {IcssDefinition} */
1107
+ (icssDefinitions.get(value));
1108
+
1109
+ value = def.value;
1110
+ }
1111
+
1112
+ icssDefinitions.set(name, { value });
1113
+
1114
+ const dep = new CssIcssExportDependency(name, value);
1115
+ const { line: sl, column: sc } = locConverter.get(start);
1116
+ const { line: el, column: ec } = locConverter.get(end);
1117
+ dep.setLoc(sl, sc, el, ec);
1118
+ module.addDependency(dep);
1119
+ }
1120
+
1121
+ const dep = new ConstDependency("", [start, atRuleEnd]);
1122
+ module.addPresentationalDependency(dep);
1123
+ return atRuleEnd;
1124
+ };
1125
+
1126
+ /**
1127
+ * @param {string} name ICSS symbol name
1128
+ * @param {number} start start position
1129
+ * @param {number} end end position
1130
+ * @returns {number} position after handling
1131
+ */
1132
+ const processICSSSymbol = (name, start, end) => {
1133
+ const { value, isReference } =
1134
+ /** @type {IcssDefinition} */
1135
+ (icssDefinitions.get(name));
1136
+ const { line: sl, column: sc } = locConverter.get(start);
1137
+ const { line: el, column: ec } = locConverter.get(end);
1138
+ const dep = new CssIcssSymbolDependency(
1139
+ name,
1140
+ value,
1141
+ [start, end],
1142
+ isReference
1143
+ );
1144
+ dep.setLoc(sl, sc, el, ec);
1145
+ module.addDependency(dep);
1146
+ return end;
1147
+ };
1148
+
1149
+ /**
1150
+ * @param {string} input input
1151
+ * @param {1 | 2} type type of function
1152
+ * @param {number} start start position
1153
+ * @param {number} end end position
1154
+ * @returns {number} position after handling
1155
+ */
1156
+ const processLocalOrGlobalFunction = (input, type, start, end) => {
1157
+ // Replace `local(`/` or `global(` (handle legacy `:local(` or `:global(` too)
1158
+ {
1159
+ const isColon = input.charCodeAt(start - 1) === CC_COLON;
1160
+ const dep = new ConstDependency("", [isColon ? start - 1 : start, end]);
1161
+ module.addPresentationalDependency(dep);
1162
+ }
1163
+
1164
+ end = walkCssTokens.consumeUntil(
1165
+ input,
1166
+ start,
1167
+ type === 1
1168
+ ? {
1169
+ identifier(input, start, end) {
1170
+ const name = unescapeIdentifier(input.slice(start, end));
1171
+ const { line: sl, column: sc } = locConverter.get(start);
1172
+ const { line: el, column: ec } = locConverter.get(end);
1173
+ const dep = new CssIcssLocalIdentifierDependency(name, [
1174
+ start,
1175
+ end
1176
+ ]);
1177
+ dep.setLoc(sl, sc, el, ec);
1178
+ module.addDependency(dep);
1179
+
1180
+ return end;
1181
+ }
1182
+ }
1183
+ : {},
1184
+ {},
1185
+ { onlyTopLevel: true, functionValue: true }
1186
+ );
1187
+
1188
+ {
1189
+ // Replace the last `)`
1190
+ const dep = new ConstDependency("", [end, end + 1]);
1191
+ module.addPresentationalDependency(dep);
1192
+ }
1193
+
1194
+ return end;
1195
+ };
1196
+
1197
+ /**
1198
+ * @param {string} input input
1199
+ * @param {number} end name end position
1200
+ * @param {{ string?: boolean, identifier: boolean, validate?: (name: string) => boolean, dashed?: boolean }} options types which allowed to handle
1201
+ * @returns {number} position after handling
1202
+ */
1203
+ const processLocalAtRule = (input, end, options) => {
1204
+ /** @type {[number, number, boolean] | undefined} */
1205
+ let value;
1206
+ let found = false;
1207
+
1208
+ walkCssTokens.consumeUntil(
1209
+ input,
1210
+ end,
1211
+ {
1212
+ string(_input, start, end) {
1213
+ if (!found && options.string) {
1214
+ found = true;
1215
+ value = [start, end, true];
1216
+ }
1217
+ return end;
1218
+ },
1219
+ identifier(_input, start, end) {
1220
+ if (!found && options.identifier) {
1221
+ found = true;
1222
+ value = [start, end, false];
1223
+ }
1224
+ return end;
1225
+ }
1226
+ },
1227
+ {
1228
+ function(input, start, end) {
1229
+ // No need to handle `:` (COLON), because it's always a function
1230
+ const name = input
1231
+ .slice(start, end - 1)
1232
+ .replace(/\\/g, "")
1233
+ .toLowerCase();
1234
+
1235
+ const type =
1236
+ name === "local" ? 1 : name === "global" ? 2 : undefined;
1237
+
1238
+ if (!found && type) {
1239
+ found = true;
1240
+ return processLocalOrGlobalFunction(input, type, start, end);
1241
+ }
1242
+
1243
+ return end;
1244
+ }
1245
+ },
1246
+ { onlyTopLevel: true, atRulePrelude: true }
1247
+ );
1248
+ if (!value) return end;
1249
+ let name = value[2]
1250
+ ? input.slice(value[0] + 1, value[1] - 1)
1251
+ : input.slice(value[0], value[1]);
1252
+ if (options.validate && !options.validate(name)) return end;
1253
+ name = unescapeIdentifier(name);
1254
+ const { line: sl, column: sc } = locConverter.get(value[0]);
1255
+ const { line: el, column: ec } = locConverter.get(value[1]);
1256
+ if (options.dashed) {
1257
+ name = name.slice(2);
1258
+ declaredCssVariables.add(name);
1259
+ }
1260
+ const dep = new CssIcssLocalIdentifierDependency(
1261
+ name,
1262
+ [value[0], value[1]],
1263
+ options.dashed ? "--" : ""
1264
+ );
1265
+ dep.setLoc(sl, sc, el, ec);
1266
+ module.addDependency(dep);
1267
+ return value[1];
1268
+ };
1269
+ /**
1270
+ * @param {string} input input
1271
+ * @param {number} end end position
1272
+ * @returns {number} position after handling
1273
+ */
1274
+ const processVarFunction = (input, end) => {
1275
+ const customIdent = walkCssTokens.eatIdentSequence(input, end);
1276
+ if (!customIdent) return end;
1277
+ let name = input.slice(customIdent[0], customIdent[1]);
1278
+ // A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
1279
+ // The <custom-property-name> production corresponds to this:
1280
+ // it’s defined as any <dashed-ident> (a valid identifier that starts with two dashes),
1281
+ // except -- itself, which is reserved for future use by CSS.
1282
+ if (!name.startsWith("--") || name.length < 3) return end;
1283
+ name = unescapeIdentifier(
1284
+ input.slice(customIdent[0] + 2, customIdent[1])
1285
+ );
1286
+ const afterCustomIdent = walkCssTokens.eatWhitespaceAndComments(
1287
+ input,
1288
+ customIdent[1]
1289
+ );
1290
+ if (
1291
+ input.charCodeAt(afterCustomIdent) === CC_LOWER_F ||
1292
+ input.charCodeAt(afterCustomIdent) === CC_UPPER_F
1293
+ ) {
1294
+ const fromWord = walkCssTokens.eatIdentSequence(
1295
+ input,
1296
+ afterCustomIdent
1297
+ );
1298
+ if (
1299
+ !fromWord ||
1300
+ input.slice(fromWord[0], fromWord[1]).toLowerCase() !== "from"
1301
+ ) {
1302
+ return end;
1303
+ }
1304
+ const from = walkCssTokens.eatIdentSequenceOrString(
1305
+ input,
1306
+ walkCssTokens.eatWhitespaceAndComments(input, fromWord[1])
1307
+ );
1308
+ if (!from) {
1309
+ return end;
1310
+ }
1311
+ const path = input.slice(from[0], from[1]);
1312
+ if (from[2] === true && path === "global") {
1313
+ const dep = new ConstDependency("", [customIdent[1], from[1]]);
1314
+ module.addPresentationalDependency(dep);
1315
+ return end;
1316
+ } else if (from[2] === false) {
1317
+ const { line: sl, column: sc } = locConverter.get(customIdent[0]);
1318
+ const { line: el, column: ec } = locConverter.get(from[1] - 1);
1319
+ const dep = new CssIcssFromIdentifierDependency(
1320
+ path.slice(1, -1),
1321
+ /** @type {"local" | "global"} */
1322
+ (mode),
1323
+ [customIdent[0], from[1] - 1],
1324
+ name,
1325
+ name,
1326
+ "--"
1327
+ );
1328
+
1329
+ dep.setLoc(sl, sc, el, ec);
1330
+ module.addDependency(dep);
1331
+
1332
+ {
1333
+ const dep = new ConstDependency("", [fromWord[0], from[1]]);
1334
+ module.addPresentationalDependency(dep);
1335
+ return end;
1336
+ }
1337
+ }
1338
+ } else {
1339
+ const { line: sl, column: sc } = locConverter.get(customIdent[0]);
1340
+ const { line: el, column: ec } = locConverter.get(customIdent[1]);
1341
+ const dep = new CssIcssSelfLocalIdentifierDependency(
1342
+ name,
1343
+ undefined,
1344
+ [customIdent[0], customIdent[1]],
1345
+ "--",
1346
+ declaredCssVariables
1347
+ );
1348
+ dep.setLoc(sl, sc, el, ec);
1349
+ module.addDependency(dep);
1350
+ return end;
1351
+ }
1352
+
1353
+ return end;
1354
+ };
1355
+ /**
1356
+ * @param {string} input input
1357
+ * @param {number} pos name start position
1358
+ * @param {number} end name end position
1359
+ * @returns {number} position after handling
1360
+ */
1361
+ const processLocalDeclaration = (input, pos, end) => {
1362
+ modeData = undefined;
1363
+ pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
1364
+ const propertyNameStart = pos;
1365
+ const [propertyNameEnd, propertyName] = eatText(
1366
+ input,
1367
+ pos,
1368
+ eatPropertyName
1369
+ );
1370
+ if (input.charCodeAt(propertyNameEnd) !== CC_COLON) return end;
1371
+ pos = propertyNameEnd + 1;
1372
+ if (propertyName.startsWith("--") && propertyName.length >= 3) {
1373
+ // CSS Variable
1374
+ const { line: sl, column: sc } = locConverter.get(propertyNameStart);
1375
+ const { line: el, column: ec } = locConverter.get(propertyNameEnd);
1376
+ const name = unescapeIdentifier(propertyName.slice(2));
1377
+ const dep = new CssIcssLocalIdentifierDependency(
1378
+ name,
1379
+ [propertyNameStart, propertyNameEnd],
1380
+ "--"
1381
+ );
1382
+ dep.setLoc(sl, sc, el, ec);
1383
+ module.addDependency(dep);
1384
+ declaredCssVariables.add(name);
1385
+ } else if (
1386
+ OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY.test(propertyName)
1387
+ ) {
1388
+ /** @type {[number, number, boolean][]} */
1389
+ const animationNames = [];
1390
+ /** @type {Record<string, number>} */
1391
+ let parsedAnimationKeywords = Object.create(null);
1392
+
1393
+ const end = walkCssTokens.consumeUntil(
1394
+ input,
1395
+ pos,
1396
+ {
1397
+ string(_input, start, end) {
1398
+ animationNames.push([start, end, true]);
1399
+
1400
+ return end;
1401
+ },
1402
+ identifier(input, start, end) {
1403
+ const keyword = input.slice(start, end).toLowerCase();
1404
+
1405
+ parsedAnimationKeywords[keyword] =
1406
+ typeof parsedAnimationKeywords[keyword] !== "undefined"
1407
+ ? parsedAnimationKeywords[keyword] + 1
1408
+ : 0;
1409
+
1410
+ if (
1411
+ ANIMATION_KEYWORDS[keyword] &&
1412
+ parsedAnimationKeywords[keyword] < ANIMATION_KEYWORDS[keyword]
1413
+ ) {
1414
+ return end;
1415
+ }
1416
+
1417
+ animationNames.push([start, end, false]);
1418
+ return end;
1419
+ },
1420
+ comma(_input, _start, end) {
1421
+ parsedAnimationKeywords = {};
1422
+
1423
+ return end;
1424
+ }
1425
+ },
1426
+ {
1427
+ function(input, start, end) {
1428
+ const name = input
1429
+ .slice(start, end - 1)
1430
+ .replace(/\\/g, "")
1431
+ .toLowerCase();
1432
+
1433
+ if (isLocalMode() && name === "var") {
1434
+ return processVarFunction(input, end);
1435
+ }
1436
+
1437
+ const type =
1438
+ name === "local" ? 1 : name === "global" ? 2 : undefined;
1439
+
1440
+ if (type) {
1441
+ return processLocalOrGlobalFunction(input, type, start, end);
1442
+ }
1443
+
1444
+ return end;
1445
+ }
1446
+ },
1447
+ { onlyTopLevel: true, declarationValue: true }
1448
+ );
1449
+
1450
+ if (animationNames.length > 0) {
1451
+ for (const animationName of animationNames) {
1452
+ const { line: sl, column: sc } = locConverter.get(animationName[0]);
1453
+ const { line: el, column: ec } = locConverter.get(animationName[1]);
1454
+ const [start, end, isString] = animationName;
1455
+ const name = unescapeIdentifier(
1456
+ isString
1457
+ ? input.slice(start + 1, end - 1)
1458
+ : input.slice(start, end)
1459
+ );
1460
+ const dep = new CssIcssSelfLocalIdentifierDependency(
1461
+ name,
1462
+ undefined,
1463
+ [start, end]
1464
+ );
1465
+ dep.setLoc(sl, sc, el, ec);
1466
+ module.addDependency(dep);
1467
+ }
1468
+ }
1469
+
1470
+ return end;
1471
+ } else if (COMPOSES_PROPERTY.test(propertyName)) {
1472
+ if (lastLocalIdentifiers.length > 1) {
1473
+ const end = eatUntilSemi(input, pos);
1474
+ this._emitWarning(
1475
+ state,
1476
+ `Composition is only allowed when selector is single local class name not in "${lastLocalIdentifiers.join('", "')}"`,
1477
+ locConverter,
1478
+ pos,
1479
+ end
1480
+ );
1481
+
1482
+ return end;
1483
+ }
1484
+
1485
+ if (lastLocalIdentifiers.length !== 1) return pos;
1486
+
1487
+ const lastLocalIdentifier = lastLocalIdentifiers[0];
1488
+ let end = pos;
1489
+
1490
+ /** @type {Set<[number, number]>} */
1491
+ const classNames = new Set();
1492
+
1493
+ while (true) {
1494
+ pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
1495
+
1496
+ let className = walkCssTokens.eatIdentSequence(input, pos);
1497
+
1498
+ const ifFunction =
1499
+ className && input.charCodeAt(className[1]) === CC_LEFT_PARENTHESIS;
1500
+ let isGlobalFunction = false;
1501
+
1502
+ if (className && ifFunction) {
1503
+ const name = input
1504
+ .slice(className[0], className[1])
1505
+ .replace(/\\/g, "")
1506
+ .toLowerCase();
1507
+
1508
+ isGlobalFunction = name === "global";
1509
+ pos = walkCssTokens.eatWhitespaceAndComments(
1510
+ input,
1511
+ className[1] + 1
1512
+ );
1513
+ className = walkCssTokens.eatIdentSequence(input, pos);
1514
+ if (className) {
1515
+ pos = walkCssTokens.eatWhitespaceAndComments(input, className[1]);
1516
+ pos += 1;
1517
+ }
1518
+ } else if (className) {
1519
+ pos = walkCssTokens.eatWhitespaceAndComments(input, className[1]);
1520
+ pos = className[1];
1521
+ }
1522
+
1523
+ // True when we have multiple values
1524
+ const isComma = input.charCodeAt(pos) === CC_COMMA;
1525
+ const isSemicolon = input.charCodeAt(pos) === CC_SEMICOLON;
1526
+ const isRightCurly = input.charCodeAt(pos) === CC_RIGHT_CURLY;
1527
+
1528
+ if (isComma || isSemicolon || isRightCurly) {
1529
+ if (className) {
1530
+ classNames.add(className);
1531
+ }
1532
+
1533
+ for (const className of classNames) {
1534
+ const [start, end] = className;
1535
+ const identifier = unescapeIdentifier(input.slice(start, end));
1536
+ const reexport = icssDefinitions.get(identifier);
1537
+ const dep = isGlobalFunction
1538
+ ? new CssIcssGlobalIdentifierDependency(
1539
+ lastLocalIdentifier,
1540
+ identifier,
1541
+ reexport && reexport.isReference
1542
+ ? reexport.value
1543
+ : undefined,
1544
+ [start, end]
1545
+ )
1546
+ : new CssIcssSelfLocalIdentifierDependency(
1547
+ lastLocalIdentifier,
1548
+ identifier,
1549
+ [start, end],
1550
+ undefined,
1551
+ undefined,
1552
+ reexport && reexport.isReference
1553
+ ? reexport.value
1554
+ : undefined
1555
+ );
1556
+ const { line: sl, column: sc } = locConverter.get(start);
1557
+ const { line: el, column: ec } = locConverter.get(end);
1558
+ dep.setLoc(sl, sc, el, ec);
1559
+ module.addDependency(dep);
1560
+ }
1561
+
1562
+ classNames.clear();
1563
+
1564
+ if (isSemicolon || isRightCurly) {
1565
+ end = isSemicolon
1566
+ ? walkCssTokens.eatWhitespace(input, pos + 1)
1567
+ : pos;
1568
+ break;
1569
+ }
1570
+
1571
+ pos += 1;
1572
+ } else if (
1573
+ classNames.size > 0 &&
1574
+ className &&
1575
+ input.slice(className[0], className[1]).toLowerCase() === "from"
1576
+ ) {
1577
+ let from = walkCssTokens.eatString(input, pos);
1578
+
1579
+ if (from) {
1580
+ const request = input.slice(from[0] + 1, from[1] - 1);
1581
+
1582
+ for (const className of classNames) {
1583
+ const [start, end] = className;
1584
+ const identifier = unescapeIdentifier(input.slice(start, end));
1585
+ const dep = new CssIcssFromIdentifierDependency(
1586
+ request,
1587
+ /** @type {"local" | "global"} */
1588
+ (mode),
1589
+ [start, end],
1590
+ identifier,
1591
+ /** @type {string} */
1592
+ (lastLocalIdentifier)
1593
+ );
1594
+ const { line: sl, column: sc } = locConverter.get(start);
1595
+ const { line: el, column: ec } = locConverter.get(end);
1596
+ dep.setLoc(sl, sc, el, ec);
1597
+ module.addDependency(dep);
1598
+ }
1599
+
1600
+ classNames.clear();
1601
+ pos = from[1];
1602
+ } else {
1603
+ from = walkCssTokens.eatIdentSequence(input, pos);
1604
+
1605
+ if (from && input.slice(from[0], from[1]) === "global") {
1606
+ for (const className of classNames) {
1607
+ const [start, end] = className;
1608
+ const identifier = unescapeIdentifier(
1609
+ input.slice(start, end)
1610
+ );
1611
+ const reexport = icssDefinitions.get(identifier);
1612
+ const dep = new CssIcssGlobalIdentifierDependency(
1613
+ /** @type {string} */
1614
+ (lastLocalIdentifier),
1615
+ identifier,
1616
+ reexport && reexport.isReference
1617
+ ? reexport.value
1618
+ : undefined,
1619
+ [start, end]
1620
+ );
1621
+ const { line: sl, column: sc } = locConverter.get(start);
1622
+ const { line: el, column: ec } = locConverter.get(end);
1623
+ dep.setLoc(sl, sc, el, ec);
1624
+ module.addDependency(dep);
1625
+ }
1626
+
1627
+ classNames.clear();
1628
+ pos = from[1];
1629
+ } else {
1630
+ const end = eatUntilSemi(input, pos);
1631
+ this._emitWarning(
1632
+ state,
1633
+ "Incorrect composition, expected global keyword or string value",
1634
+ locConverter,
1635
+ pos,
1636
+ end
1637
+ );
1638
+ return end;
1639
+ }
1640
+ }
1641
+ } else if (className) {
1642
+ classNames.add(className);
1643
+ } else {
1644
+ const end = eatUntilSemi(input, pos);
1645
+ this._emitWarning(
1646
+ state,
1647
+ "Incorrect composition, expected class named",
1648
+ locConverter,
1649
+ pos,
1650
+ end
1651
+ );
1652
+ return end;
1653
+ }
1654
+ }
1655
+
1656
+ // Remove `composes` from source code
1657
+ const dep = new ConstDependency("", [propertyNameStart, end]);
1658
+ module.addPresentationalDependency(dep);
1659
+ }
1660
+ return pos;
1661
+ };
1662
+
1663
+ /**
1664
+ * @param {string} input input
1665
+ * @param {number} start start position
1666
+ * @param {number} end end position
1667
+ * @returns {number} position after handling
1668
+ */
1669
+ const processHashID = (input, start, end) => {
1670
+ const valueStart = start + 1;
1671
+ const name = unescapeIdentifier(input.slice(valueStart, end));
1672
+ const dep = new CssIcssLocalIdentifierDependency(name, [valueStart, end]);
1673
+ const { line: sl, column: sc } = locConverter.get(start);
1674
+ const { line: el, column: ec } = locConverter.get(end);
1675
+ dep.setLoc(sl, sc, el, ec);
1676
+ module.addDependency(dep);
1677
+ return end;
1678
+ };
1679
+
1680
+ walkCssTokens(source, 0, {
1681
+ comment,
1682
+ leftCurlyBracket: (input, start, end) => {
1683
+ switch (scope) {
1684
+ case CSS_MODE_TOP_LEVEL: {
1685
+ allowImportAtRule = false;
1686
+ scope = CSS_MODE_IN_BLOCK;
1687
+
1688
+ if (isModules) {
1689
+ blockNestingLevel = 1;
1690
+ isNextRulePrelude = isNextNestedSyntax(input, end);
1691
+ }
1692
+
1693
+ break;
1694
+ }
1695
+ case CSS_MODE_IN_BLOCK: {
1696
+ if (isModules) {
1697
+ blockNestingLevel++;
1698
+ isNextRulePrelude = isNextNestedSyntax(input, end);
1699
+ }
1700
+ break;
1701
+ }
1702
+ }
1703
+ return end;
1704
+ },
1705
+ rightCurlyBracket: (input, start, end) => {
1706
+ switch (scope) {
1707
+ case CSS_MODE_IN_BLOCK: {
1708
+ if (--blockNestingLevel === 0) {
1709
+ scope = CSS_MODE_TOP_LEVEL;
1710
+
1711
+ if (isModules) {
1712
+ isNextRulePrelude = true;
725
1713
  modeData = undefined;
1714
+ lastLocalIdentifiers = [];
726
1715
  }
727
1716
  } else if (isModules) {
728
- if (isLocalMode()) {
729
- processDeclarationValueDone(input);
730
- inAnimationProperty = false;
731
- }
732
-
733
1717
  isNextRulePrelude = isNextNestedSyntax(input, end);
734
1718
  }
735
1719
  break;
@@ -742,64 +1726,13 @@ class CssParser extends Parser {
742
1726
  return end;
743
1727
  }
744
1728
 
745
- const { options, errors: commentErrors } = this.parseCommentOptions([
746
- lastTokenEndForComments,
747
- end
748
- ]);
749
- if (commentErrors) {
750
- for (const e of commentErrors) {
751
- const { comment } = e;
752
- state.module.addWarning(
753
- new CommentCompilationWarning(
754
- `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
755
- comment.loc
756
- )
757
- );
758
- }
759
- }
760
- if (options && options.webpackIgnore !== undefined) {
761
- if (typeof options.webpackIgnore !== "boolean") {
762
- const { line: sl, column: sc } = locConverter.get(
763
- lastTokenEndForComments
764
- );
765
- const { line: el, column: ec } = locConverter.get(end);
766
-
767
- state.module.addWarning(
768
- new UnsupportedFeatureWarning(
769
- `\`webpackIgnore\` expected a boolean, but received: ${options.webpackIgnore}.`,
770
- {
771
- start: { line: sl, column: sc },
772
- end: { line: el, column: ec }
773
- }
774
- )
775
- );
776
- } else if (options.webpackIgnore) {
777
- return end;
778
- }
779
- }
780
- const value = normalizeUrl(
781
- input.slice(contentStart, contentEnd),
782
- false
1729
+ return processOldURLFunction(
1730
+ input,
1731
+ start,
1732
+ end,
1733
+ contentStart,
1734
+ contentEnd
783
1735
  );
784
- // Ignore `url()`, `url('')` and `url("")`, they are valid by spec
785
- if (value.length === 0) return end;
786
- const dep = new CssUrlDependency(value, [start, end], "url");
787
- const { line: sl, column: sc } = locConverter.get(start);
788
- const { line: el, column: ec } = locConverter.get(end);
789
- dep.setLoc(sl, sc, el, ec);
790
- module.addDependency(dep);
791
- module.addCodeGenerationDependency(dep);
792
- return end;
793
- },
794
- string: (_input, start, end) => {
795
- switch (scope) {
796
- case CSS_MODE_IN_BLOCK: {
797
- if (inAnimationProperty && balanced.length === 0) {
798
- lastIdentifier = [start, end, false];
799
- }
800
- }
801
- }
802
- return end;
803
1736
  },
804
1737
  atKeyword: (input, start, end) => {
805
1738
  const name = input.slice(start, end).toLowerCase();
@@ -832,234 +1765,26 @@ class CssParser extends Parser {
832
1765
  return end;
833
1766
  }
834
1767
 
835
- const tokens = walkCssTokens.eatImportTokens(input, end, {
836
- comment
837
- });
838
- if (!tokens[3]) return end;
839
- const semi = tokens[3][1];
840
- if (!tokens[0]) {
841
- this._emitWarning(
842
- state,
843
- `Expected URL in '${input.slice(start, semi)}'`,
844
- locConverter,
845
- start,
846
- semi
847
- );
848
- return end;
849
- }
850
-
851
- const urlToken = tokens[0];
852
- const url = normalizeUrl(
853
- input.slice(urlToken[2], urlToken[3]),
854
- true
855
- );
856
- const newline = walkCssTokens.eatWhiteLine(input, semi);
857
- const { options, errors: commentErrors } = this.parseCommentOptions(
858
- [end, urlToken[1]]
859
- );
860
- if (commentErrors) {
861
- for (const e of commentErrors) {
862
- const { comment } = e;
863
- state.module.addWarning(
864
- new CommentCompilationWarning(
865
- `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
866
- comment.loc
867
- )
868
- );
869
- }
870
- }
871
- if (options && options.webpackIgnore !== undefined) {
872
- if (typeof options.webpackIgnore !== "boolean") {
873
- const { line: sl, column: sc } = locConverter.get(start);
874
- const { line: el, column: ec } = locConverter.get(newline);
875
-
876
- state.module.addWarning(
877
- new UnsupportedFeatureWarning(
878
- `\`webpackIgnore\` expected a boolean, but received: ${options.webpackIgnore}.`,
879
- {
880
- start: { line: sl, column: sc },
881
- end: { line: el, column: ec }
882
- }
883
- )
884
- );
885
- } else if (options.webpackIgnore) {
886
- return newline;
887
- }
888
- }
889
- if (url.length === 0) {
890
- const { line: sl, column: sc } = locConverter.get(start);
891
- const { line: el, column: ec } = locConverter.get(newline);
892
- const dep = new ConstDependency("", [start, newline]);
893
- module.addPresentationalDependency(dep);
894
- dep.setLoc(sl, sc, el, ec);
895
-
896
- return newline;
897
- }
898
-
899
- let layer;
900
-
901
- if (tokens[1]) {
902
- layer = input.slice(tokens[1][0] + 6, tokens[1][1] - 1).trim();
903
- }
904
-
905
- let supports;
906
-
907
- if (tokens[2]) {
908
- supports = input.slice(tokens[2][0] + 9, tokens[2][1] - 1).trim();
909
- }
910
-
911
- const last = tokens[2] || tokens[1] || tokens[0];
912
- const mediaStart = walkCssTokens.eatWhitespaceAndComments(
913
- input,
914
- last[1]
915
- );
916
-
917
- let media;
918
-
919
- if (mediaStart !== semi - 1) {
920
- media = input.slice(mediaStart, semi - 1).trim();
921
- }
922
-
923
- const { line: sl, column: sc } = locConverter.get(start);
924
- const { line: el, column: ec } = locConverter.get(newline);
925
- const dep = new CssImportDependency(
926
- url,
927
- [start, newline],
928
- layer,
929
- supports && supports.length > 0 ? supports : undefined,
930
- media && media.length > 0 ? media : undefined
931
- );
932
- dep.setLoc(sl, sc, el, ec);
933
- module.addDependency(dep);
934
-
935
- return newline;
1768
+ return processAtImport(input, start, end);
936
1769
  }
937
1770
  default: {
938
1771
  if (isModules) {
939
1772
  if (name === "@value") {
940
- const semi = eatUntilSemi(input, end);
941
- const atRuleEnd = semi + 1;
942
- const params = input.slice(end, semi);
943
- let [alias, from] = params.split(/\s*from\s*/);
944
-
945
- if (from) {
946
- const aliases = alias
947
- .replace(CSS_COMMENT, " ")
948
- .trim()
949
- .replace(/^\(|\)$/g, "")
950
- .split(/\s*,\s*/);
951
-
952
- from = from.replace(CSS_COMMENT, "").trim();
953
-
954
- const isExplicitImport = from[0] === "'" || from[0] === '"';
955
-
956
- if (isExplicitImport) {
957
- from = from.slice(1, -1);
958
- }
959
-
960
- for (const alias of aliases) {
961
- const [name, aliasName] = alias.split(/\s*as\s*/);
962
-
963
- icssDefinitions.set(aliasName || name, {
964
- value: name,
965
- path: from
966
- });
967
- }
968
- } else {
969
- const ident = walkCssTokens.eatIdentSequence(alias, 0);
970
-
971
- if (!ident) {
972
- this._emitWarning(
973
- state,
974
- `Broken '@value' at-rule: ${input.slice(
975
- start,
976
- atRuleEnd
977
- )}'`,
978
- locConverter,
979
- start,
980
- atRuleEnd
981
- );
982
-
983
- const dep = new ConstDependency("", [start, atRuleEnd]);
984
- module.addPresentationalDependency(dep);
985
- return atRuleEnd;
986
- }
987
-
988
- const pos = walkCssTokens.eatWhitespaceAndComments(
989
- alias,
990
- ident[1]
991
- );
992
-
993
- const name = alias.slice(ident[0], ident[1]);
994
- let value =
995
- alias.charCodeAt(pos) === CC_COLON
996
- ? alias.slice(pos + 1)
997
- : alias.slice(ident[1]);
998
-
999
- if (value && !/^\s+$/.test(value)) {
1000
- value = value.trim();
1001
- }
1002
-
1003
- if (icssDefinitions.has(value)) {
1004
- const def =
1005
- /** @type {IcssDefinition} */
1006
- (icssDefinitions.get(value));
1007
-
1008
- value = def.value;
1009
- }
1010
-
1011
- icssDefinitions.set(name, { value });
1012
-
1013
- const dep = new CssIcssExportDependency(name, value);
1014
- const { line: sl, column: sc } = locConverter.get(start);
1015
- const { line: el, column: ec } = locConverter.get(end);
1016
- dep.setLoc(sl, sc, el, ec);
1017
- module.addDependency(dep);
1018
- }
1019
-
1020
- const dep = new ConstDependency("", [start, atRuleEnd]);
1021
- module.addPresentationalDependency(dep);
1022
- return atRuleEnd;
1773
+ return processAtValue(input, start, end);
1023
1774
  } else if (
1024
1775
  OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE.test(name) &&
1025
1776
  isLocalMode()
1026
1777
  ) {
1027
- const ident = walkCssTokens.eatIdentSequenceOrString(
1028
- input,
1029
- end
1030
- );
1031
- if (!ident) return end;
1032
- const name = unescapeIdentifier(
1033
- ident[2] === true
1034
- ? input.slice(ident[0], ident[1])
1035
- : input.slice(ident[0] + 1, ident[1] - 1)
1036
- );
1037
- const { line: sl, column: sc } = locConverter.get(ident[0]);
1038
- const { line: el, column: ec } = locConverter.get(ident[1]);
1039
- const dep = new CssLocalIdentifierDependency(name, [
1040
- ident[0],
1041
- ident[1]
1042
- ]);
1043
- dep.setLoc(sl, sc, el, ec);
1044
- module.addDependency(dep);
1045
- return ident[1];
1778
+ return processLocalAtRule(input, end, {
1779
+ string: true,
1780
+ identifier: true
1781
+ });
1046
1782
  } else if (name === "@property" && isLocalMode()) {
1047
- const ident = walkCssTokens.eatIdentSequence(input, end);
1048
- if (!ident) return end;
1049
- let name = input.slice(ident[0], ident[1]);
1050
- if (!name.startsWith("--") || name.length < 3) return end;
1051
- name = unescapeIdentifier(name.slice(2));
1052
- declaredCssVariables.add(name);
1053
- const { line: sl, column: sc } = locConverter.get(ident[0]);
1054
- const { line: el, column: ec } = locConverter.get(ident[1]);
1055
- const dep = new CssLocalIdentifierDependency(
1056
- name,
1057
- [ident[0], ident[1]],
1058
- "--"
1059
- );
1060
- dep.setLoc(sl, sc, el, ec);
1061
- module.addDependency(dep);
1062
- return ident[1];
1783
+ return processLocalAtRule(input, end, {
1784
+ identifier: true,
1785
+ dashed: true,
1786
+ validate: (name) => name.startsWith("--") && name.length >= 3
1787
+ });
1063
1788
  } else if (name === "@scope") {
1064
1789
  isNextRulePrelude = true;
1065
1790
  return end;
@@ -1074,11 +1799,6 @@ class CssParser extends Parser {
1074
1799
  },
1075
1800
  semicolon: (input, start, end) => {
1076
1801
  if (isModules && scope === CSS_MODE_IN_BLOCK) {
1077
- if (isLocalMode()) {
1078
- processDeclarationValueDone(input);
1079
- inAnimationProperty = false;
1080
- }
1081
-
1082
1802
  isNextRulePrelude = isNextNestedSyntax(input, end);
1083
1803
  }
1084
1804
  return end;
@@ -1088,50 +1808,14 @@ class CssParser extends Parser {
1088
1808
  const name = input.slice(start, end);
1089
1809
 
1090
1810
  if (icssDefinitions.has(name)) {
1091
- let { path, value } =
1092
- /** @type {IcssDefinition} */
1093
- (icssDefinitions.get(name));
1094
-
1095
- if (path) {
1096
- if (icssDefinitions.has(path)) {
1097
- const definition =
1098
- /** @type {IcssDefinition} */
1099
- (icssDefinitions.get(path));
1100
-
1101
- path = definition.value.slice(1, -1);
1102
- }
1103
-
1104
- const dep = new CssIcssImportDependency(path, value, [
1105
- start,
1106
- end - 1
1107
- ]);
1108
- const { line: sl, column: sc } = locConverter.get(start);
1109
- const { line: el, column: ec } = locConverter.get(end - 1);
1110
- dep.setLoc(sl, sc, el, ec);
1111
- module.addDependency(dep);
1112
- } else {
1113
- const { line: sl, column: sc } = locConverter.get(start);
1114
- const { line: el, column: ec } = locConverter.get(end);
1115
- const dep = new CssIcssSymbolDependency(name, value, [
1116
- start,
1117
- end
1118
- ]);
1119
- dep.setLoc(sl, sc, el, ec);
1120
- module.addDependency(dep);
1121
- }
1122
-
1123
- return end;
1811
+ return processICSSSymbol(name, start, end);
1124
1812
  }
1125
1813
 
1126
1814
  switch (scope) {
1127
1815
  case CSS_MODE_IN_BLOCK: {
1128
1816
  if (isLocalMode()) {
1129
1817
  // Handle only top level values and not inside functions
1130
- if (inAnimationProperty && balanced.length === 0) {
1131
- lastIdentifier = [start, end, true];
1132
- } else {
1133
- return processLocalDeclaration(input, start, end);
1134
- }
1818
+ return processLocalDeclaration(input, start, end);
1135
1819
  }
1136
1820
  break;
1137
1821
  }
@@ -1148,7 +1832,8 @@ class CssParser extends Parser {
1148
1832
  );
1149
1833
  if (!ident) return end;
1150
1834
  const name = unescapeIdentifier(input.slice(ident[0], ident[1]));
1151
- const dep = new CssLocalIdentifierDependency(name, [
1835
+ lastLocalIdentifiers.push(name);
1836
+ const dep = new CssIcssLocalIdentifierDependency(name, [
1152
1837
  ident[0],
1153
1838
  ident[1]
1154
1839
  ]);
@@ -1163,13 +1848,7 @@ class CssParser extends Parser {
1163
1848
  },
1164
1849
  hash: (input, start, end, isID) => {
1165
1850
  if (isNextRulePrelude && isLocalMode() && isID) {
1166
- const valueStart = start + 1;
1167
- const name = unescapeIdentifier(input.slice(valueStart, end));
1168
- const dep = new CssLocalIdentifierDependency(name, [valueStart, end]);
1169
- const { line: sl, column: sc } = locConverter.get(start);
1170
- const { line: el, column: ec } = locConverter.get(end);
1171
- dep.setLoc(sl, sc, el, ec);
1172
- module.addDependency(dep);
1851
+ return processHashID(input, start, end);
1173
1852
  }
1174
1853
 
1175
1854
  return end;
@@ -1186,12 +1865,12 @@ class CssParser extends Parser {
1186
1865
  switch (scope) {
1187
1866
  case CSS_MODE_TOP_LEVEL: {
1188
1867
  if (name === "import") {
1189
- const pos = parseImportOrExport(0, input, ident[1]);
1868
+ const pos = processImportOrExport(0, input, ident[1]);
1190
1869
  const dep = new ConstDependency("", [start, pos]);
1191
1870
  module.addPresentationalDependency(dep);
1192
1871
  return pos;
1193
1872
  } else if (name === "export") {
1194
- const pos = parseImportOrExport(1, input, ident[1]);
1873
+ const pos = processImportOrExport(1, input, ident[1]);
1195
1874
  const dep = new ConstDependency("", [start, pos]);
1196
1875
  module.addPresentationalDependency(dep);
1197
1876
  return pos;
@@ -1203,7 +1882,8 @@ class CssParser extends Parser {
1203
1882
  const isFn = input.charCodeAt(ident[1]) === CC_LEFT_PARENTHESIS;
1204
1883
 
1205
1884
  if (isFn && name === "local") {
1206
- const end = ident[1] + 1;
1885
+ // Eat extra whitespace
1886
+ const end = walkCssTokens.eatWhitespace(input, ident[1] + 1);
1207
1887
  modeData = "local";
1208
1888
  const dep = new ConstDependency("", [start, end]);
1209
1889
  module.addPresentationalDependency(dep);
@@ -1231,7 +1911,8 @@ class CssParser extends Parser {
1231
1911
  module.addPresentationalDependency(dep);
1232
1912
  return end;
1233
1913
  } else if (isFn && name === "global") {
1234
- const end = ident[1] + 1;
1914
+ // Eat extra whitespace
1915
+ const end = walkCssTokens.eatWhitespace(input, ident[1] + 1);
1235
1916
  modeData = "global";
1236
1917
  const dep = new ConstDependency("", [start, end]);
1237
1918
  module.addPresentationalDependency(dep);
@@ -1283,208 +1964,13 @@ class CssParser extends Parser {
1283
1964
  return end;
1284
1965
  }
1285
1966
 
1286
- const string = walkCssTokens.eatString(input, end);
1287
- if (!string) return end;
1288
- const { options, errors: commentErrors } = this.parseCommentOptions(
1289
- [lastTokenEndForComments, end]
1290
- );
1291
- if (commentErrors) {
1292
- for (const e of commentErrors) {
1293
- const { comment } = e;
1294
- state.module.addWarning(
1295
- new CommentCompilationWarning(
1296
- `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
1297
- comment.loc
1298
- )
1299
- );
1300
- }
1301
- }
1302
- if (options && options.webpackIgnore !== undefined) {
1303
- if (typeof options.webpackIgnore !== "boolean") {
1304
- const { line: sl, column: sc } = locConverter.get(string[0]);
1305
- const { line: el, column: ec } = locConverter.get(string[1]);
1306
-
1307
- state.module.addWarning(
1308
- new UnsupportedFeatureWarning(
1309
- `\`webpackIgnore\` expected a boolean, but received: ${options.webpackIgnore}.`,
1310
- {
1311
- start: { line: sl, column: sc },
1312
- end: { line: el, column: ec }
1313
- }
1314
- )
1315
- );
1316
- } else if (options.webpackIgnore) {
1317
- return end;
1318
- }
1319
- }
1320
- const value = normalizeUrl(
1321
- input.slice(string[0] + 1, string[1] - 1),
1322
- true
1323
- );
1324
- // Ignore `url()`, `url('')` and `url("")`, they are valid by spec
1325
- if (value.length === 0) return end;
1326
- const isUrl = name === "url" || name === "src";
1327
- const dep = new CssUrlDependency(
1328
- value,
1329
- [string[0], string[1]],
1330
- isUrl ? "string" : "url"
1331
- );
1332
- const { line: sl, column: sc } = locConverter.get(string[0]);
1333
- const { line: el, column: ec } = locConverter.get(string[1]);
1334
- dep.setLoc(sl, sc, el, ec);
1335
- module.addDependency(dep);
1336
- module.addCodeGenerationDependency(dep);
1337
- return string[1];
1967
+ return processURLFunction(input, end, name);
1338
1968
  }
1339
1969
  default: {
1340
1970
  if (this.url && IMAGE_SET_FUNCTION.test(name)) {
1341
- lastTokenEndForComments = end;
1342
- const values = walkCssTokens.eatImageSetStrings(input, end, {
1343
- comment
1344
- });
1345
- if (values.length === 0) return end;
1346
- for (const [index, string] of values.entries()) {
1347
- const value = normalizeUrl(
1348
- input.slice(string[0] + 1, string[1] - 1),
1349
- true
1350
- );
1351
- if (value.length === 0) return end;
1352
- const { options, errors: commentErrors } =
1353
- this.parseCommentOptions([
1354
- index === 0 ? start : values[index - 1][1],
1355
- string[1]
1356
- ]);
1357
- if (commentErrors) {
1358
- for (const e of commentErrors) {
1359
- const { comment } = e;
1360
- state.module.addWarning(
1361
- new CommentCompilationWarning(
1362
- `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
1363
- comment.loc
1364
- )
1365
- );
1366
- }
1367
- }
1368
- if (options && options.webpackIgnore !== undefined) {
1369
- if (typeof options.webpackIgnore !== "boolean") {
1370
- const { line: sl, column: sc } = locConverter.get(
1371
- string[0]
1372
- );
1373
- const { line: el, column: ec } = locConverter.get(
1374
- string[1]
1375
- );
1376
-
1377
- state.module.addWarning(
1378
- new UnsupportedFeatureWarning(
1379
- `\`webpackIgnore\` expected a boolean, but received: ${options.webpackIgnore}.`,
1380
- {
1381
- start: { line: sl, column: sc },
1382
- end: { line: el, column: ec }
1383
- }
1384
- )
1385
- );
1386
- } else if (options.webpackIgnore) {
1387
- continue;
1388
- }
1389
- }
1390
- const dep = new CssUrlDependency(
1391
- value,
1392
- [string[0], string[1]],
1393
- "url"
1394
- );
1395
- const { line: sl, column: sc } = locConverter.get(string[0]);
1396
- const { line: el, column: ec } = locConverter.get(string[1]);
1397
- dep.setLoc(sl, sc, el, ec);
1398
- module.addDependency(dep);
1399
- module.addCodeGenerationDependency(dep);
1400
- }
1401
- // Can contain `url()` inside, so let's return end to allow parse them
1402
- return end;
1403
- } else if (isLocalMode()) {
1404
- // Don't rename animation name when we have `var()` function
1405
- if (inAnimationProperty && balanced.length === 1) {
1406
- lastIdentifier = undefined;
1407
- }
1408
-
1409
- if (name === "var") {
1410
- const customIdent = walkCssTokens.eatIdentSequence(input, end);
1411
- if (!customIdent) return end;
1412
- let name = input.slice(customIdent[0], customIdent[1]);
1413
- // A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
1414
- // The <custom-property-name> production corresponds to this:
1415
- // it’s defined as any <dashed-ident> (a valid identifier that starts with two dashes),
1416
- // except -- itself, which is reserved for future use by CSS.
1417
- if (!name.startsWith("--") || name.length < 3) return end;
1418
- name = unescapeIdentifier(
1419
- input.slice(customIdent[0] + 2, customIdent[1])
1420
- );
1421
- const afterCustomIdent = walkCssTokens.eatWhitespaceAndComments(
1422
- input,
1423
- customIdent[1]
1424
- );
1425
- if (
1426
- input.charCodeAt(afterCustomIdent) === CC_LOWER_F ||
1427
- input.charCodeAt(afterCustomIdent) === CC_UPPER_F
1428
- ) {
1429
- const fromWord = walkCssTokens.eatIdentSequence(
1430
- input,
1431
- afterCustomIdent
1432
- );
1433
- if (
1434
- !fromWord ||
1435
- input.slice(fromWord[0], fromWord[1]).toLowerCase() !==
1436
- "from"
1437
- ) {
1438
- return end;
1439
- }
1440
- const from = walkCssTokens.eatIdentSequenceOrString(
1441
- input,
1442
- walkCssTokens.eatWhitespaceAndComments(input, fromWord[1])
1443
- );
1444
- if (!from) {
1445
- return end;
1446
- }
1447
- const path = input.slice(from[0], from[1]);
1448
- if (from[2] === true && path === "global") {
1449
- const dep = new ConstDependency("", [
1450
- customIdent[1],
1451
- from[1]
1452
- ]);
1453
- module.addPresentationalDependency(dep);
1454
- return end;
1455
- } else if (from[2] === false) {
1456
- const dep = new CssIcssImportDependency(
1457
- path.slice(1, -1),
1458
- name,
1459
- [customIdent[0], from[1] - 1]
1460
- );
1461
- const { line: sl, column: sc } = locConverter.get(
1462
- customIdent[0]
1463
- );
1464
- const { line: el, column: ec } = locConverter.get(
1465
- from[1] - 1
1466
- );
1467
- dep.setLoc(sl, sc, el, ec);
1468
- module.addDependency(dep);
1469
- }
1470
- } else {
1471
- const { line: sl, column: sc } = locConverter.get(
1472
- customIdent[0]
1473
- );
1474
- const { line: el, column: ec } = locConverter.get(
1475
- customIdent[1]
1476
- );
1477
- const dep = new CssSelfLocalIdentifierDependency(
1478
- name,
1479
- [customIdent[0], customIdent[1]],
1480
- "--",
1481
- declaredCssVariables
1482
- );
1483
- dep.setLoc(sl, sc, el, ec);
1484
- module.addDependency(dep);
1485
- return end;
1486
- }
1487
- }
1971
+ return processImageSetFunction(input, start, end);
1972
+ } else if (isLocalMode() && name === "var") {
1973
+ return processVarFunction(input, end);
1488
1974
  }
1489
1975
  }
1490
1976
  }
@@ -1516,11 +2002,11 @@ class CssParser extends Parser {
1516
2002
  },
1517
2003
  comma: (input, start, end) => {
1518
2004
  if (isModules) {
1519
- // Reset stack for `:global .class :local .class-other` selector after
1520
- modeData = undefined;
2005
+ const popped = balanced.pop();
1521
2006
 
1522
- if (scope === CSS_MODE_IN_BLOCK && isLocalMode()) {
1523
- processDeclarationValueDone(input);
2007
+ if (!popped) {
2008
+ // Reset stack for `:global .class :local .class-other` selector after
2009
+ modeData = undefined;
1524
2010
  }
1525
2011
  }
1526
2012
 
@@ -1532,17 +2018,38 @@ class CssParser extends Parser {
1532
2018
 
1533
2019
  /** @type {BuildInfo} */
1534
2020
  (module.buildInfo).strict = true;
1535
- /** @type {BuildMeta} */
1536
- (module.buildMeta).exportsType = this.namedExports
1537
- ? "namespace"
1538
- : "default";
1539
2021
 
1540
- if (!this.namedExports) {
1541
- /** @type {BuildMeta} */
1542
- (module.buildMeta).defaultObject = "redirect";
2022
+ const buildMeta = /** @type {BuildMeta} */ (state.module.buildMeta);
2023
+
2024
+ buildMeta.exportsType = this.namedExports ? "namespace" : "default";
2025
+ buildMeta.defaultObject = this.namedExports ? false : "redirect-warn";
2026
+ buildMeta.exportType = this.exportType;
2027
+
2028
+ if (!buildMeta.exportType) {
2029
+ // Inherit exportType from parent module to ensure consistency.
2030
+ // When a CSS file is imported with syntax like `import "./basic.css" with { type: "css" }`,
2031
+ // the parent module's exportType is set to "css-style-sheet".
2032
+ // Child modules imported via @import should inherit this exportType
2033
+ // instead of using the default "link", ensuring that the entire
2034
+ // import chain uses the same export format.
2035
+ const parent = state.compilation.moduleGraph.getIssuer(module);
2036
+ if (parent instanceof CssModule) {
2037
+ buildMeta.exportType = /** @type {BuildMeta} */ (
2038
+ parent.buildMeta
2039
+ ).exportType;
2040
+ }
2041
+ }
2042
+
2043
+ // TODO this.namedExports?
2044
+ if (
2045
+ buildMeta.exportType === "text" ||
2046
+ buildMeta.exportType === "css-style-sheet"
2047
+ ) {
2048
+ module.addDependency(new StaticExportsDependency(["default"], true));
2049
+ } else {
2050
+ module.addDependency(new StaticExportsDependency([], true));
1543
2051
  }
1544
2052
 
1545
- module.addDependency(new StaticExportsDependency([], true));
1546
2053
  return state;
1547
2054
  }
1548
2055