webpack 5.79.0 → 5.81.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.

Potentially problematic release.


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

Files changed (115) hide show
  1. package/README.md +3 -0
  2. package/lib/AsyncDependenciesBlock.js +8 -0
  3. package/lib/CodeGenerationResults.js +2 -2
  4. package/lib/Compilation.js +2 -2
  5. package/lib/ContextModule.js +8 -0
  6. package/lib/CssModule.js +137 -0
  7. package/lib/DefinePlugin.js +81 -44
  8. package/lib/DelegatedModule.js +5 -0
  9. package/lib/DependenciesBlock.js +8 -0
  10. package/lib/Dependency.js +8 -0
  11. package/lib/DllModule.js +8 -0
  12. package/lib/ExportsInfo.js +3 -0
  13. package/lib/ExternalModule.js +8 -0
  14. package/lib/FileSystemInfo.js +8 -0
  15. package/lib/LoaderOptionsPlugin.js +12 -2
  16. package/lib/Module.js +8 -0
  17. package/lib/ModuleBuildError.js +9 -0
  18. package/lib/ModuleError.js +9 -0
  19. package/lib/ModuleFilenameHelpers.js +113 -4
  20. package/lib/ModuleParseError.js +9 -0
  21. package/lib/ModuleTypeConstants.js +21 -0
  22. package/lib/ModuleWarning.js +9 -0
  23. package/lib/NormalModule.js +8 -0
  24. package/lib/NormalModuleFactory.js +26 -4
  25. package/lib/RawModule.js +8 -0
  26. package/lib/WarnCaseSensitiveModulesPlugin.js +12 -0
  27. package/lib/WebpackError.js +8 -0
  28. package/lib/asset/AssetGenerator.js +11 -3
  29. package/lib/asset/RawDataUrlModule.js +8 -0
  30. package/lib/cache/ResolverCachePlugin.js +3 -0
  31. package/lib/config/normalization.js +1 -0
  32. package/lib/container/ContainerEntryModule.js +5 -0
  33. package/lib/container/ContainerExposedDependency.js +9 -0
  34. package/lib/container/FallbackDependency.js +6 -0
  35. package/lib/container/FallbackModule.js +5 -0
  36. package/lib/container/RemoteModule.js +5 -0
  37. package/lib/css/CssModulesPlugin.js +91 -50
  38. package/lib/css/CssParser.js +226 -72
  39. package/lib/css/walkCssTokens.js +152 -117
  40. package/lib/dependencies/AMDDefineDependency.js +8 -0
  41. package/lib/dependencies/AMDRequireArrayDependency.js +8 -0
  42. package/lib/dependencies/AMDRequireContextDependency.js +9 -0
  43. package/lib/dependencies/AMDRequireDependency.js +8 -0
  44. package/lib/dependencies/CachedConstDependency.js +8 -0
  45. package/lib/dependencies/CommonJsDependencyHelpers.js +9 -0
  46. package/lib/dependencies/CommonJsExportRequireDependency.js +8 -0
  47. package/lib/dependencies/CommonJsExportsDependency.js +8 -0
  48. package/lib/dependencies/CommonJsExportsParserPlugin.js +65 -3
  49. package/lib/dependencies/CommonJsFullRequireDependency.js +8 -0
  50. package/lib/dependencies/CommonJsRequireContextDependency.js +9 -0
  51. package/lib/dependencies/CommonJsSelfReferenceDependency.js +8 -0
  52. package/lib/dependencies/ConstDependency.js +8 -0
  53. package/lib/dependencies/ContextDependency.js +8 -0
  54. package/lib/dependencies/ContextElementDependency.js +8 -0
  55. package/lib/dependencies/CreateScriptUrlDependency.js +8 -0
  56. package/lib/dependencies/CssExportDependency.js +8 -0
  57. package/lib/dependencies/CssImportDependency.js +52 -1
  58. package/lib/dependencies/CssLocalIdentifierDependency.js +8 -0
  59. package/lib/dependencies/CssSelfLocalIdentifierDependency.js +8 -0
  60. package/lib/dependencies/CssUrlDependency.js +38 -18
  61. package/lib/dependencies/DllEntryDependency.js +9 -0
  62. package/lib/dependencies/ExportsInfoDependency.js +5 -0
  63. package/lib/dependencies/HarmonyAcceptDependency.js +8 -0
  64. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +8 -0
  65. package/lib/dependencies/HarmonyExportExpressionDependency.js +8 -0
  66. package/lib/dependencies/HarmonyExportHeaderDependency.js +8 -0
  67. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +14 -0
  68. package/lib/dependencies/HarmonyExportSpecifierDependency.js +8 -0
  69. package/lib/dependencies/HarmonyImportDependency.js +8 -0
  70. package/lib/dependencies/HarmonyImportSpecifierDependency.js +8 -0
  71. package/lib/dependencies/ImportContextDependency.js +9 -0
  72. package/lib/dependencies/ImportDependency.js +8 -0
  73. package/lib/dependencies/ImportMetaPlugin.js +56 -26
  74. package/lib/dependencies/ImportParserPlugin.js +17 -1
  75. package/lib/dependencies/JsonExportsDependency.js +8 -0
  76. package/lib/dependencies/LocalModuleDependency.js +8 -0
  77. package/lib/dependencies/ModuleDecoratorDependency.js +8 -0
  78. package/lib/dependencies/ModuleDependency.js +8 -0
  79. package/lib/dependencies/ProvidedDependency.js +8 -0
  80. package/lib/dependencies/PureExpressionDependency.js +8 -0
  81. package/lib/dependencies/RequireEnsureDependency.js +8 -0
  82. package/lib/dependencies/RequireHeaderDependency.js +5 -0
  83. package/lib/dependencies/RequireResolveContextDependency.js +9 -0
  84. package/lib/dependencies/RequireResolveHeaderDependency.js +5 -0
  85. package/lib/dependencies/RuntimeRequirementsDependency.js +8 -0
  86. package/lib/dependencies/StaticExportsDependency.js +8 -0
  87. package/lib/dependencies/URLDependency.js +8 -0
  88. package/lib/dependencies/UnsupportedDependency.js +8 -0
  89. package/lib/dependencies/WebAssemblyExportImportedDependency.js +8 -0
  90. package/lib/dependencies/WebAssemblyImportDependency.js +8 -0
  91. package/lib/dependencies/WorkerDependency.js +8 -0
  92. package/lib/ids/OccurrenceModuleIdsPlugin.js +1 -1
  93. package/lib/index.js +1 -0
  94. package/lib/javascript/JavascriptParser.js +14 -4
  95. package/lib/optimize/RealContentHashPlugin.js +6 -0
  96. package/lib/runtime/AutoPublicPathRuntimeModule.js +6 -1
  97. package/lib/schemes/DataUriPlugin.js +12 -3
  98. package/lib/serialization/ObjectMiddleware.js +2 -0
  99. package/lib/sharing/ConsumeSharedModule.js +8 -0
  100. package/lib/sharing/ConsumeSharedRuntimeModule.js +9 -3
  101. package/lib/sharing/ProvideSharedDependency.js +6 -0
  102. package/lib/sharing/ProvideSharedModule.js +5 -0
  103. package/lib/sharing/ShareRuntimeModule.js +7 -4
  104. package/lib/stats/DefaultStatsFactoryPlugin.js +98 -25
  105. package/lib/stats/DefaultStatsPresetPlugin.js +9 -0
  106. package/lib/stats/DefaultStatsPrinterPlugin.js +4 -0
  107. package/lib/util/LazySet.js +10 -2
  108. package/lib/util/MapHelpers.js +19 -5
  109. package/lib/util/binarySearchBounds.js +49 -0
  110. package/lib/util/internalSerializables.js +1 -0
  111. package/lib/util/semver.js +1 -1
  112. package/package.json +19 -22
  113. package/schemas/WebpackOptions.check.js +1 -1
  114. package/schemas/WebpackOptions.json +16 -0
  115. package/types.d.ts +108 -39
@@ -8,6 +8,9 @@
8
8
  const Dependency = require("../Dependency");
9
9
  const makeSerializable = require("../util/makeSerializable");
10
10
 
11
+ /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
12
+ /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
13
+
11
14
  class FallbackDependency extends Dependency {
12
15
  constructor(requests) {
13
16
  super();
@@ -29,6 +32,9 @@ class FallbackDependency extends Dependency {
29
32
  return "esm";
30
33
  }
31
34
 
35
+ /**
36
+ * @param {ObjectSerializerContext} context context
37
+ */
32
38
  serialize(context) {
33
39
  const { write } = context;
34
40
  write(this.requests);
@@ -24,6 +24,8 @@ const FallbackItemDependency = require("./FallbackItemDependency");
24
24
  /** @typedef {import("../RequestShortener")} RequestShortener */
25
25
  /** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
26
26
  /** @typedef {import("../WebpackError")} WebpackError */
27
+ /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
28
+ /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
27
29
  /** @typedef {import("../util/Hash")} Hash */
28
30
  /** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
29
31
 
@@ -154,6 +156,9 @@ class FallbackModule extends Module {
154
156
  return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS };
155
157
  }
156
158
 
159
+ /**
160
+ * @param {ObjectSerializerContext} context context
161
+ */
157
162
  serialize(context) {
158
163
  const { write } = context;
159
164
  write(this.requests);
@@ -23,6 +23,8 @@ const RemoteToExternalDependency = require("./RemoteToExternalDependency");
23
23
  /** @typedef {import("../RequestShortener")} RequestShortener */
24
24
  /** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
25
25
  /** @typedef {import("../WebpackError")} WebpackError */
26
+ /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
27
+ /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
26
28
  /** @typedef {import("../util/Hash")} Hash */
27
29
  /** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
28
30
 
@@ -149,6 +151,9 @@ class RemoteModule extends Module {
149
151
  return { sources, data, runtimeRequirements: RUNTIME_REQUIREMENTS };
150
152
  }
151
153
 
154
+ /**
155
+ * @param {ObjectSerializerContext} context context
156
+ */
152
157
  serialize(context) {
153
158
  const { write } = context;
154
159
  write(this.request);
@@ -5,8 +5,14 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const { ConcatSource } = require("webpack-sources");
8
+ const { ConcatSource, PrefixSource } = require("webpack-sources");
9
+ const CssModule = require("../CssModule");
9
10
  const HotUpdateChunk = require("../HotUpdateChunk");
11
+ const {
12
+ CSS_MODULE_TYPE,
13
+ CSS_MODULE_TYPE_GLOBAL,
14
+ CSS_MODULE_TYPE_MODULE
15
+ } = require("../ModuleTypeConstants");
10
16
  const RuntimeGlobals = require("../RuntimeGlobals");
11
17
  const SelfModuleFactory = require("../SelfModuleFactory");
12
18
  const CssExportDependency = require("../dependencies/CssExportDependency");
@@ -125,53 +131,56 @@ class CssModulesPlugin {
125
131
  StaticExportsDependency,
126
132
  new StaticExportsDependency.Template()
127
133
  );
128
- normalModuleFactory.hooks.createParser
129
- .for("css")
130
- .tap(plugin, parserOptions => {
131
- validateParserOptions(parserOptions);
132
- return new CssParser();
133
- });
134
- normalModuleFactory.hooks.createParser
135
- .for("css/global")
136
- .tap(plugin, parserOptions => {
137
- validateParserOptions(parserOptions);
138
- return new CssParser({
139
- allowPseudoBlocks: false,
140
- allowModeSwitch: false
134
+ for (const type of [
135
+ CSS_MODULE_TYPE,
136
+ CSS_MODULE_TYPE_GLOBAL,
137
+ CSS_MODULE_TYPE_MODULE
138
+ ]) {
139
+ normalModuleFactory.hooks.createParser
140
+ .for(type)
141
+ .tap(plugin, parserOptions => {
142
+ validateParserOptions(parserOptions);
143
+
144
+ switch (type) {
145
+ case CSS_MODULE_TYPE:
146
+ return new CssParser();
147
+ case CSS_MODULE_TYPE_GLOBAL:
148
+ return new CssParser({
149
+ allowPseudoBlocks: false,
150
+ allowModeSwitch: false
151
+ });
152
+ case CSS_MODULE_TYPE_MODULE:
153
+ return new CssParser({
154
+ defaultMode: "local"
155
+ });
156
+ }
141
157
  });
142
- });
143
- normalModuleFactory.hooks.createParser
144
- .for("css/module")
145
- .tap(plugin, parserOptions => {
146
- validateParserOptions(parserOptions);
147
- return new CssParser({
148
- defaultMode: "local"
158
+ normalModuleFactory.hooks.createGenerator
159
+ .for(type)
160
+ .tap(plugin, generatorOptions => {
161
+ validateGeneratorOptions(generatorOptions);
162
+ return this._exportsOnly
163
+ ? new CssExportsGenerator()
164
+ : new CssGenerator();
149
165
  });
150
- });
151
- normalModuleFactory.hooks.createGenerator
152
- .for("css")
153
- .tap(plugin, generatorOptions => {
154
- validateGeneratorOptions(generatorOptions);
155
- return this._exportsOnly
156
- ? new CssExportsGenerator()
157
- : new CssGenerator();
158
- });
159
- normalModuleFactory.hooks.createGenerator
160
- .for("css/global")
161
- .tap(plugin, generatorOptions => {
162
- validateGeneratorOptions(generatorOptions);
163
- return this._exportsOnly
164
- ? new CssExportsGenerator()
165
- : new CssGenerator();
166
- });
167
- normalModuleFactory.hooks.createGenerator
168
- .for("css/module")
169
- .tap(plugin, generatorOptions => {
170
- validateGeneratorOptions(generatorOptions);
171
- return this._exportsOnly
172
- ? new CssExportsGenerator()
173
- : new CssGenerator();
174
- });
166
+ normalModuleFactory.hooks.createModuleClass
167
+ .for(type)
168
+ .tap(plugin, (createData, resolveData) => {
169
+ if (resolveData.dependencies.length > 0) {
170
+ // When CSS is imported from CSS there is only one dependency
171
+ const dependency = resolveData.dependencies[0];
172
+
173
+ return new CssModule({
174
+ ...createData,
175
+ cssLayer: dependency.layer,
176
+ supports: dependency.supports,
177
+ media: dependency.media
178
+ });
179
+ }
180
+
181
+ return new CssModule(createData);
182
+ });
183
+ }
175
184
  const orderedCssModulesPerChunk = new WeakMap();
176
185
  compilation.hooks.afterCodeGeneration.tap("CssModulesPlugin", () => {
177
186
  const { chunkGraph } = compilation;
@@ -401,16 +410,48 @@ class CssModulesPlugin {
401
410
  try {
402
411
  const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
403
412
 
404
- const s =
413
+ let moduleSource =
405
414
  codeGenResult.sources.get("css") ||
406
415
  codeGenResult.sources.get("css-import");
407
- if (s) {
408
- source.add(s);
416
+
417
+ if (module.media) {
418
+ moduleSource = new ConcatSource(
419
+ `@media ${module.media} {\n`,
420
+ new PrefixSource("\t", moduleSource),
421
+ "}"
422
+ );
423
+ }
424
+
425
+ if (module.supports) {
426
+ moduleSource = new ConcatSource(
427
+ `@supports (${module.supports}) {\n`,
428
+ new PrefixSource("\t", moduleSource),
429
+ "}"
430
+ );
431
+ }
432
+
433
+ // Layer can be anonymous
434
+ if (module.cssLayer !== undefined && module.cssLayer !== null) {
435
+ moduleSource = new ConcatSource(
436
+ `@layer${module.cssLayer ? ` (${module.cssLayer})` : ""} {\n`,
437
+ new PrefixSource("\t", moduleSource),
438
+ "}"
439
+ );
440
+ }
441
+
442
+ if (moduleSource) {
443
+ source.add(moduleSource);
409
444
  source.add("\n");
410
445
  }
411
446
  const exports =
412
447
  codeGenResult.data && codeGenResult.data.get("css-exports");
413
- const moduleId = chunkGraph.getModuleId(module) + "";
448
+ let moduleId = chunkGraph.getModuleId(module) + "";
449
+
450
+ // When `optimization.moduleIds` is `named` the module id is a path, so we need to normalize it between platforms
451
+ if (typeof moduleId === "string") {
452
+ moduleId = moduleId.replace(/\\/g, "/");
453
+ }
454
+
414
455
  metaData.push(
415
456
  `${
416
457
  exports
@@ -17,21 +17,57 @@ const walkCssTokens = require("./walkCssTokens");
17
17
 
18
18
  /** @typedef {import("../Parser").ParserState} ParserState */
19
19
  /** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
20
-
21
20
  const CC_LEFT_CURLY = "{".charCodeAt(0);
22
21
  const CC_RIGHT_CURLY = "}".charCodeAt(0);
23
22
  const CC_COLON = ":".charCodeAt(0);
24
23
  const CC_SLASH = "/".charCodeAt(0);
25
24
  const CC_SEMICOLON = ";".charCodeAt(0);
26
25
 
27
- const cssUnescape = str => {
28
- return str.replace(/\\([0-9a-fA-F]{1,6}[ \t\n\r\f]?|[\s\S])/g, match => {
29
- if (match.length > 2) {
30
- return String.fromCharCode(parseInt(match.slice(1).trim(), 16));
31
- } else {
32
- return match[1];
26
+ // https://www.w3.org/TR/css-syntax-3/#newline
27
+ // We don't have `preprocessing` stage, so we need specify all of them
28
+ const STRING_MULTILINE = /\\[\n\r\f]/g;
29
+ // https://www.w3.org/TR/css-syntax-3/#whitespace
30
+ const TRIM_WHITE_SPACES = /(^[ \t\n\r\f]*|[ \t\n\r\f]*$)/g;
31
+ const UNESCAPE = /\\([0-9a-fA-F]{1,6}[ \t\n\r\f]?|[\s\S])/g;
32
+ const IMAGE_SET_FUNCTION = /^(-\w+-)?image-set$/i;
33
+ const OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE = /^@(-\w+-)?keyframes$/;
34
+ const OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY =
35
+ /^(-\w+-)?animation(-name)?$/i;
36
+
37
+ const normalizeUrl = (str, isString) => {
38
+ // Remove extra spaces and newlines:
39
+ // `url("im\
40
+ // g.png")`
41
+ if (isString) {
42
+ str = str.replace(STRING_MULTILINE, "");
43
+ }
44
+
45
+ str = str
46
+ // Remove unnecessary spaces from `url(" img.png ")`
47
+ .replace(TRIM_WHITE_SPACES, "")
48
+ // Unescape
49
+ .replace(UNESCAPE, match => {
50
+ if (match.length > 2) {
51
+ return String.fromCharCode(parseInt(match.slice(1).trim(), 16));
52
+ } else {
53
+ return match[1];
54
+ }
55
+ });
56
+
57
+ if (/^data:/i.test(str)) {
58
+ return str;
59
+ }
60
+
61
+ if (str.includes("%")) {
62
+ // Convert `url('%2E/img.png')` -> `url('./img.png')`
63
+ try {
64
+ str = decodeURIComponent(str);
65
+ } catch (error) {
66
+ // Ignore
33
67
  }
34
- });
68
+ }
69
+
70
+ return str;
35
71
  };
36
72
 
37
73
  class LocConverter {
@@ -73,10 +109,8 @@ const CSS_MODE_TOP_LEVEL = 0;
73
109
  const CSS_MODE_IN_RULE = 1;
74
110
  const CSS_MODE_IN_LOCAL_RULE = 2;
75
111
  const CSS_MODE_AT_IMPORT_EXPECT_URL = 3;
76
- // TODO implement layer and supports for @import
77
- const CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS = 4;
78
- const CSS_MODE_AT_IMPORT_EXPECT_MEDIA = 5;
79
- const CSS_MODE_AT_OTHER = 6;
112
+ const CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA = 4;
113
+ const CSS_MODE_AT_OTHER = 5;
80
114
 
81
115
  const explainMode = mode => {
82
116
  switch (mode) {
@@ -88,10 +122,8 @@ const explainMode = mode => {
88
122
  return "parsing css rule content (local)";
89
123
  case CSS_MODE_AT_IMPORT_EXPECT_URL:
90
124
  return "parsing @import (expecting url)";
91
- case CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS:
92
- return "parsing @import (expecting optionally supports or media query)";
93
- case CSS_MODE_AT_IMPORT_EXPECT_MEDIA:
94
- return "parsing @import (expecting optionally media query)";
125
+ case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA:
126
+ return "parsing @import (expecting optionally layer, supports or media query)";
95
127
  case CSS_MODE_AT_OTHER:
96
128
  return "parsing at-rule";
97
129
  default:
@@ -132,13 +164,15 @@ class CssParser extends Parser {
132
164
 
133
165
  const locConverter = new LocConverter(source);
134
166
  let mode = CSS_MODE_TOP_LEVEL;
135
- let modePos = 0;
136
167
  let modeNestingLevel = 0;
137
168
  let modeData = undefined;
138
169
  let singleClassSelector = undefined;
139
170
  let lastIdentifier = undefined;
140
- const modeStack = [];
141
171
  let awaitRightParenthesis = false;
172
+ /** @type [string, number, number][] */
173
+ let balanced = [];
174
+ const modeStack = [];
175
+
142
176
  const isTopLevelLocal = () =>
143
177
  modeData === "local" ||
144
178
  (this.defaultMode === "local" && modeData === undefined);
@@ -279,8 +313,7 @@ class CssParser extends Parser {
279
313
  module.addDependency(dep);
280
314
  declaredCssVariables.add(name);
281
315
  } else if (
282
- propertyName.toLowerCase() === "animation-name" ||
283
- propertyName.toLowerCase() === "animation"
316
+ OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY.test(propertyName)
284
317
  ) {
285
318
  modeData = "animation";
286
319
  lastIdentifier = undefined;
@@ -302,25 +335,39 @@ class CssParser extends Parser {
302
335
  const eatNameInVar = eatUntil(",)};/");
303
336
  walkCssTokens(source, {
304
337
  isSelector: () => {
305
- return mode !== CSS_MODE_IN_RULE && mode !== CSS_MODE_IN_LOCAL_RULE;
338
+ return (
339
+ mode !== CSS_MODE_IN_RULE &&
340
+ mode !== CSS_MODE_IN_LOCAL_RULE &&
341
+ mode !== CSS_MODE_AT_IMPORT_EXPECT_URL &&
342
+ mode !== CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA
343
+ );
306
344
  },
307
- url: (input, start, end, contentStart, contentEnd) => {
308
- const value = cssUnescape(input.slice(contentStart, contentEnd));
345
+ url: (input, start, end, contentStart, contentEnd, isString) => {
346
+ let value = normalizeUrl(
347
+ input.slice(contentStart, contentEnd),
348
+ isString
349
+ );
309
350
  switch (mode) {
310
351
  case CSS_MODE_AT_IMPORT_EXPECT_URL: {
311
352
  modeData.url = value;
312
- mode = CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS;
353
+ modeData.lastPos = end;
354
+ mode = CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA;
355
+ break;
356
+ }
357
+ // Do not parse URLs in `supports(...)`
358
+ case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
313
359
  break;
314
360
  }
315
- case CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS:
316
- case CSS_MODE_AT_IMPORT_EXPECT_MEDIA:
317
- throw new Error(
318
- `Unexpected ${input.slice(
319
- start,
320
- end
321
- )} at ${start} during ${explainMode(mode)}`
322
- );
323
361
  default: {
362
+ if (
363
+ // Ignore `url(#highlight)` URLs
364
+ /^#/.test(value) ||
365
+ // Ignore `url()`, `url('')` and `url("")`, they are valid by spec
366
+ value.length === 0
367
+ ) {
368
+ break;
369
+ }
370
+
324
371
  const dep = new CssUrlDependency(value, [start, end], "url");
325
372
  const { line: sl, column: sc } = locConverter.get(start);
326
373
  const { line: el, column: ec } = locConverter.get(end);
@@ -335,10 +382,54 @@ class CssParser extends Parser {
335
382
  string: (input, start, end) => {
336
383
  switch (mode) {
337
384
  case CSS_MODE_AT_IMPORT_EXPECT_URL: {
338
- modeData.url = cssUnescape(input.slice(start + 1, end - 1));
339
- mode = CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS;
385
+ modeData.url = normalizeUrl(input.slice(start + 1, end - 1), true);
386
+ modeData.lastPos = end;
387
+ const insideURLFunction =
388
+ balanced[balanced.length - 1] &&
389
+ balanced[balanced.length - 1][0] === "url";
390
+
391
+ if (!insideURLFunction) {
392
+ mode = CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA;
393
+ }
340
394
  break;
341
395
  }
396
+ // Do not parse URLs in `supports(...)`
397
+ case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
398
+ break;
399
+ }
400
+ default: {
401
+ // TODO move escaped parsing to tokenizer
402
+ const last = balanced[balanced.length - 1];
403
+
404
+ if (
405
+ last &&
406
+ (last[0].replace(/\\/g, "").toLowerCase() === "url" ||
407
+ IMAGE_SET_FUNCTION.test(last[0].replace(/\\/g, "")))
408
+ ) {
409
+ let value = normalizeUrl(input.slice(start + 1, end - 1), true);
410
+
411
+ if (
412
+ // Ignore `url(#highlight)` URLs
413
+ /^#/.test(value) ||
414
+ // Ignore `url()`, `url('')` and `url("")`, they are valid by spec
415
+ value.length === 0
416
+ ) {
417
+ break;
418
+ }
419
+
420
+ const isUrl = last[0].replace(/\\/g, "").toLowerCase() === "url";
421
+ const dep = new CssUrlDependency(
422
+ value,
423
+ [start, end],
424
+ isUrl ? "string" : "url"
425
+ );
426
+ const { line: sl, column: sc } = locConverter.get(start);
427
+ const { line: el, column: ec } = locConverter.get(end);
428
+ dep.setLoc(sl, sc, el, ec);
429
+ module.addDependency(dep);
430
+ module.addCodeGenerationDependency(dep);
431
+ }
432
+ }
342
433
  }
343
434
  return end;
344
435
  },
@@ -354,14 +445,16 @@ class CssParser extends Parser {
354
445
  );
355
446
  }
356
447
  mode = CSS_MODE_AT_IMPORT_EXPECT_URL;
357
- modePos = end;
358
448
  modeData = {
359
- start: start,
449
+ atRuleStart: start,
450
+ lastPos: end,
360
451
  url: undefined,
361
- supports: undefined
452
+ layer: undefined,
453
+ supports: undefined,
454
+ media: undefined
362
455
  };
363
456
  }
364
- if (name === "@keyframes") {
457
+ if (OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE.test(name)) {
365
458
  let pos = end;
366
459
  pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
367
460
  if (pos === input.length) return pos;
@@ -400,20 +493,40 @@ class CssParser extends Parser {
400
493
  switch (mode) {
401
494
  case CSS_MODE_AT_IMPORT_EXPECT_URL:
402
495
  throw new Error(`Expected URL for @import at ${start}`);
403
- case CSS_MODE_AT_IMPORT_EXPECT_MEDIA:
404
- case CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS: {
405
- const { line: sl, column: sc } = locConverter.get(modeData.start);
496
+ case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
497
+ if (modeData.url === undefined) {
498
+ throw new Error(
499
+ `Expected URL for @import at ${modeData.atRuleStart}`
500
+ );
501
+ }
502
+ const semicolonPos = end;
503
+ const { line: sl, column: sc } = locConverter.get(
504
+ modeData.atRuleStart
505
+ );
406
506
  const { line: el, column: ec } = locConverter.get(end);
407
- end = eatWhiteLine(input, end);
408
- const media = input.slice(modePos, start).trim();
507
+ const pos = walkCssTokens.eatWhitespaceAndComments(
508
+ input,
509
+ modeData.lastPos
510
+ );
511
+ // Prevent to consider comments as a part of media query
512
+ if (pos !== semicolonPos - 1) {
513
+ modeData.media = input
514
+ .slice(modeData.lastPos, semicolonPos - 1)
515
+ .trim();
516
+ }
409
517
  const dep = new CssImportDependency(
410
- modeData.url,
518
+ modeData.url.trim(),
411
519
  [modeData.start, end],
520
+ modeData.layer,
412
521
  modeData.supports,
413
- media
522
+ modeData.media && modeData.media.length > 0
523
+ ? modeData.media
524
+ : undefined
414
525
  );
415
526
  dep.setLoc(sl, sc, el, ec);
416
527
  module.addDependency(dep);
528
+ modeData = undefined;
529
+ mode = CSS_MODE_TOP_LEVEL;
417
530
  break;
418
531
  }
419
532
  case CSS_MODE_IN_LOCAL_RULE: {
@@ -488,6 +601,13 @@ class CssParser extends Parser {
488
601
  lastIdentifier = [start, end];
489
602
  }
490
603
  break;
604
+ case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
605
+ if (input.slice(start, end).toLowerCase() === "layer") {
606
+ modeData.layer = "";
607
+ modeData.lastPos = end;
608
+ }
609
+ break;
610
+ }
491
611
  }
492
612
  return end;
493
613
  },
@@ -513,7 +633,40 @@ class CssParser extends Parser {
513
633
  }
514
634
  return end;
515
635
  },
636
+ function: (input, start, end) => {
637
+ let name = input.slice(start, end - 1);
638
+
639
+ balanced.push([name, start, end]);
640
+
641
+ switch (mode) {
642
+ case CSS_MODE_IN_LOCAL_RULE: {
643
+ name = name.toLowerCase();
644
+
645
+ if (name === "var") {
646
+ let pos = walkCssTokens.eatWhitespaceAndComments(input, end);
647
+ if (pos === input.length) return pos;
648
+ const [newPos, name] = eatText(input, pos, eatNameInVar);
649
+ if (!name.startsWith("--")) return end;
650
+ const { line: sl, column: sc } = locConverter.get(pos);
651
+ const { line: el, column: ec } = locConverter.get(newPos);
652
+ const dep = new CssSelfLocalIdentifierDependency(
653
+ name.slice(2),
654
+ [pos, newPos],
655
+ "--",
656
+ declaredCssVariables
657
+ );
658
+ dep.setLoc(sl, sc, el, ec);
659
+ module.addDependency(dep);
660
+ return newPos;
661
+ }
662
+ break;
663
+ }
664
+ }
665
+ return end;
666
+ },
516
667
  leftParenthesis: (input, start, end) => {
668
+ balanced.push(["(", start, end]);
669
+
517
670
  switch (mode) {
518
671
  case CSS_MODE_TOP_LEVEL: {
519
672
  modeStack.push(false);
@@ -523,6 +676,10 @@ class CssParser extends Parser {
523
676
  return end;
524
677
  },
525
678
  rightParenthesis: (input, start, end) => {
679
+ const last = balanced[balanced.length - 1];
680
+
681
+ balanced.pop();
682
+
526
683
  switch (mode) {
527
684
  case CSS_MODE_TOP_LEVEL: {
528
685
  if (awaitRightParenthesis) {
@@ -536,7 +693,25 @@ class CssParser extends Parser {
536
693
  }
537
694
  break;
538
695
  }
696
+ case CSS_MODE_AT_IMPORT_EXPECT_URL: {
697
+ if (last && last[0] === "url") {
698
+ modeData.lastPos = end;
699
+ mode = CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA;
700
+ }
701
+ break;
702
+ }
703
+ case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
704
+ if (last && last[0].toLowerCase() === "layer") {
705
+ modeData.layer = input.slice(last[2], end - 1).trim();
706
+ modeData.lastPos = end;
707
+ } else if (last && last[0].toLowerCase() === "supports") {
708
+ modeData.supports = input.slice(last[2], end - 1).trim();
709
+ modeData.lastPos = end;
710
+ }
711
+ break;
712
+ }
539
713
  }
714
+
540
715
  return end;
541
716
  },
542
717
  pseudoClass: (input, start, end) => {
@@ -564,9 +739,14 @@ class CssParser extends Parser {
564
739
  return end;
565
740
  },
566
741
  pseudoFunction: (input, start, end) => {
742
+ let name = input.slice(start, end - 1);
743
+
744
+ balanced.push([name, start, end]);
745
+
567
746
  switch (mode) {
568
747
  case CSS_MODE_TOP_LEVEL: {
569
- const name = input.slice(start, end - 1).toLowerCase();
748
+ name = name.toLowerCase();
749
+
570
750
  if (this.allowModeSwitch && name === ":global") {
571
751
  modeStack.push(modeData);
572
752
  modeData = "global";
@@ -586,32 +766,6 @@ class CssParser extends Parser {
586
766
  }
587
767
  return end;
588
768
  },
589
- function: (input, start, end) => {
590
- switch (mode) {
591
- case CSS_MODE_IN_LOCAL_RULE: {
592
- const name = input.slice(start, end - 1).toLowerCase();
593
- if (name === "var") {
594
- let pos = walkCssTokens.eatWhitespaceAndComments(input, end);
595
- if (pos === input.length) return pos;
596
- const [newPos, name] = eatText(input, pos, eatNameInVar);
597
- if (!name.startsWith("--")) return end;
598
- const { line: sl, column: sc } = locConverter.get(pos);
599
- const { line: el, column: ec } = locConverter.get(newPos);
600
- const dep = new CssSelfLocalIdentifierDependency(
601
- name.slice(2),
602
- [pos, newPos],
603
- "--",
604
- declaredCssVariables
605
- );
606
- dep.setLoc(sl, sc, el, ec);
607
- module.addDependency(dep);
608
- return newPos;
609
- }
610
- break;
611
- }
612
- }
613
- return end;
614
- },
615
769
  comma: (input, start, end) => {
616
770
  switch (mode) {
617
771
  case CSS_MODE_TOP_LEVEL: