webpack 5.65.0 → 5.68.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 (117) hide show
  1. package/README.md +1 -1
  2. package/lib/APIPlugin.js +33 -0
  3. package/lib/Cache.js +1 -1
  4. package/lib/CacheFacade.js +4 -11
  5. package/lib/Chunk.js +2 -0
  6. package/lib/CleanPlugin.js +1 -1
  7. package/lib/Compilation.js +91 -47
  8. package/lib/Compiler.js +57 -3
  9. package/lib/ContextModule.js +21 -17
  10. package/lib/DelegatedModule.js +1 -1
  11. package/lib/Dependency.js +10 -0
  12. package/lib/DependencyTemplate.js +9 -0
  13. package/lib/DependencyTemplates.js +1 -1
  14. package/lib/DllModule.js +1 -1
  15. package/lib/EvalDevToolModulePlugin.js +16 -1
  16. package/lib/EvalSourceMapDevToolPlugin.js +18 -1
  17. package/lib/ExternalModule.js +93 -53
  18. package/lib/ExternalModuleFactoryPlugin.js +1 -1
  19. package/lib/FileSystemInfo.js +29 -25
  20. package/lib/Generator.js +2 -0
  21. package/lib/HookWebpackError.js +1 -1
  22. package/lib/Module.js +25 -4
  23. package/lib/ModuleFilenameHelpers.js +5 -1
  24. package/lib/MultiCompiler.js +1 -1
  25. package/lib/MultiWatching.js +1 -1
  26. package/lib/NormalModule.js +9 -5
  27. package/lib/RawModule.js +1 -1
  28. package/lib/RuntimeGlobals.js +29 -1
  29. package/lib/RuntimeModule.js +1 -1
  30. package/lib/RuntimePlugin.js +50 -0
  31. package/lib/RuntimeTemplate.js +21 -0
  32. package/lib/Template.js +2 -1
  33. package/lib/Watching.js +2 -2
  34. package/lib/WebpackOptionsApply.js +43 -2
  35. package/lib/asset/AssetGenerator.js +64 -24
  36. package/lib/asset/AssetModulesPlugin.js +3 -0
  37. package/lib/asset/RawDataUrlModule.js +148 -0
  38. package/lib/async-modules/AwaitDependenciesInitFragment.js +4 -4
  39. package/lib/cache/ResolverCachePlugin.js +1 -1
  40. package/lib/cli.js +44 -3
  41. package/lib/config/defaults.js +79 -5
  42. package/lib/config/normalization.js +5 -0
  43. package/lib/container/ContainerEntryModule.js +4 -2
  44. package/lib/container/FallbackModule.js +4 -4
  45. package/lib/container/RemoteModule.js +4 -2
  46. package/lib/css/CssExportsGenerator.js +139 -0
  47. package/lib/css/CssGenerator.js +109 -0
  48. package/lib/css/CssLoadingRuntimeModule.js +447 -0
  49. package/lib/css/CssModulesPlugin.js +461 -0
  50. package/lib/css/CssParser.js +618 -0
  51. package/lib/css/walkCssTokens.js +659 -0
  52. package/lib/debug/ProfilingPlugin.js +12 -10
  53. package/lib/dependencies/CreateScriptUrlDependency.js +12 -0
  54. package/lib/dependencies/CssExportDependency.js +85 -0
  55. package/lib/dependencies/CssImportDependency.js +75 -0
  56. package/lib/dependencies/CssLocalIdentifierDependency.js +119 -0
  57. package/lib/dependencies/CssSelfLocalIdentifierDependency.js +101 -0
  58. package/lib/dependencies/CssUrlDependency.js +132 -0
  59. package/lib/dependencies/HarmonyCompatibilityDependency.js +5 -5
  60. package/lib/dependencies/ImportMetaPlugin.js +22 -3
  61. package/lib/dependencies/LoaderPlugin.js +2 -2
  62. package/lib/dependencies/URLDependency.js +3 -8
  63. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +1 -1
  64. package/lib/hmr/LazyCompilationPlugin.js +45 -21
  65. package/lib/hmr/lazyCompilationBackend.js +4 -2
  66. package/lib/ids/DeterministicModuleIdsPlugin.js +55 -35
  67. package/lib/ids/HashedModuleIdsPlugin.js +9 -12
  68. package/lib/ids/IdHelpers.js +24 -10
  69. package/lib/ids/NamedModuleIdsPlugin.js +6 -9
  70. package/lib/ids/NaturalModuleIdsPlugin.js +10 -13
  71. package/lib/ids/OccurrenceModuleIdsPlugin.js +13 -10
  72. package/lib/ids/SyncModuleIdsPlugin.js +140 -0
  73. package/lib/index.js +5 -0
  74. package/lib/javascript/JavascriptGenerator.js +1 -0
  75. package/lib/javascript/StartupHelpers.js +3 -3
  76. package/lib/library/AssignLibraryPlugin.js +26 -3
  77. package/lib/library/EnableLibraryPlugin.js +11 -0
  78. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +1 -1
  79. package/lib/node/RequireChunkLoadingRuntimeModule.js +1 -1
  80. package/lib/optimize/ConcatenatedModule.js +11 -5
  81. package/lib/runtime/AsyncModuleRuntimeModule.js +25 -15
  82. package/lib/runtime/CreateScriptRuntimeModule.js +36 -0
  83. package/lib/runtime/CreateScriptUrlRuntimeModule.js +9 -34
  84. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +76 -0
  85. package/lib/schemes/HttpUriPlugin.js +8 -8
  86. package/lib/sharing/ConsumeSharedModule.js +4 -2
  87. package/lib/sharing/ProvideSharedModule.js +4 -2
  88. package/lib/sharing/utils.js +1 -1
  89. package/lib/stats/DefaultStatsFactoryPlugin.js +112 -67
  90. package/lib/stats/DefaultStatsPrinterPlugin.js +88 -23
  91. package/lib/util/ArrayHelpers.js +18 -4
  92. package/lib/util/AsyncQueue.js +1 -1
  93. package/lib/util/hash/xxhash64.js +2 -2
  94. package/lib/util/internalSerializables.js +11 -0
  95. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +9 -3
  96. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -2
  97. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +3 -11
  98. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +1 -1
  99. package/package.json +4 -11
  100. package/schemas/WebpackOptions.check.js +1 -1
  101. package/schemas/WebpackOptions.json +96 -1
  102. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  103. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  104. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  105. package/schemas/plugins/container/ContainerPlugin.json +2 -1
  106. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  107. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  108. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  109. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  110. package/schemas/plugins/container/ModuleFederationPlugin.json +3 -1
  111. package/schemas/plugins/css/CssGeneratorOptions.check.d.ts +7 -0
  112. package/schemas/plugins/css/CssGeneratorOptions.check.js +6 -0
  113. package/schemas/plugins/css/CssGeneratorOptions.json +3 -0
  114. package/schemas/plugins/css/CssParserOptions.check.d.ts +7 -0
  115. package/schemas/plugins/css/CssParserOptions.check.js +6 -0
  116. package/schemas/plugins/css/CssParserOptions.json +3 -0
  117. package/types.d.ts +249 -39
@@ -164,10 +164,17 @@ exports.scriptNonce = "__webpack_require__.nc";
164
164
  * function to load a script tag.
165
165
  * Arguments: (url: string, done: (event) => void), key?: string | number, chunkId?: string | number) => void
166
166
  * done function is called when loading has finished or timeout occurred.
167
- * It will attach to existing script tags with data-webpack == key or src == url.
167
+ * It will attach to existing script tags with data-webpack == uniqueName + ":" + key or src == url.
168
168
  */
169
169
  exports.loadScript = "__webpack_require__.l";
170
170
 
171
+ /**
172
+ * function to promote a string to a TrustedScript using webpack's Trusted
173
+ * Types policy
174
+ * Arguments: (script: string) => TrustedScript
175
+ */
176
+ exports.createScript = "__webpack_require__.ts";
177
+
171
178
  /**
172
179
  * function to promote a string to a TrustedScriptURL using webpack's Trusted
173
180
  * Types policy
@@ -175,6 +182,12 @@ exports.loadScript = "__webpack_require__.l";
175
182
  */
176
183
  exports.createScriptUrl = "__webpack_require__.tu";
177
184
 
185
+ /**
186
+ * function to return webpack's Trusted Types policy
187
+ * Arguments: () => TrustedTypePolicy
188
+ */
189
+ exports.getTrustedTypesPolicy = "__webpack_require__.tt";
190
+
178
191
  /**
179
192
  * the chunk name of the chunk with the runtime
180
193
  */
@@ -190,11 +203,26 @@ exports.runtimeId = "__webpack_require__.j";
190
203
  */
191
204
  exports.getChunkScriptFilename = "__webpack_require__.u";
192
205
 
206
+ /**
207
+ * the filename of the css part of the chunk
208
+ */
209
+ exports.getChunkCssFilename = "__webpack_require__.k";
210
+
211
+ /**
212
+ * a flag when a module/chunk/tree has css modules
213
+ */
214
+ exports.hasCssModules = "has css modules";
215
+
193
216
  /**
194
217
  * the filename of the script part of the hot update chunk
195
218
  */
196
219
  exports.getChunkUpdateScriptFilename = "__webpack_require__.hu";
197
220
 
221
+ /**
222
+ * the filename of the css part of the hot update chunk
223
+ */
224
+ exports.getChunkUpdateCssFilename = "__webpack_require__.hk";
225
+
198
226
  /**
199
227
  * startup signal from runtime
200
228
  * This will be called when the runtime chunk has been loaded.
@@ -78,7 +78,7 @@ class RuntimeModule extends Module {
78
78
 
79
79
  /**
80
80
  * @param {NeedBuildContext} context context info
81
- * @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
81
+ * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
82
82
  * @returns {void}
83
83
  */
84
84
  needBuild(context, callback) {
@@ -6,6 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const RuntimeGlobals = require("./RuntimeGlobals");
9
+ const { getChunkFilenameTemplate } = require("./css/CssModulesPlugin");
9
10
  const RuntimeRequirementsDependency = require("./dependencies/RuntimeRequirementsDependency");
10
11
  const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
11
12
  const AsyncModuleRuntimeModule = require("./runtime/AsyncModuleRuntimeModule");
@@ -13,11 +14,13 @@ const AutoPublicPathRuntimeModule = require("./runtime/AutoPublicPathRuntimeModu
13
14
  const CompatGetDefaultExportRuntimeModule = require("./runtime/CompatGetDefaultExportRuntimeModule");
14
15
  const CompatRuntimeModule = require("./runtime/CompatRuntimeModule");
15
16
  const CreateFakeNamespaceObjectRuntimeModule = require("./runtime/CreateFakeNamespaceObjectRuntimeModule");
17
+ const CreateScriptRuntimeModule = require("./runtime/CreateScriptRuntimeModule");
16
18
  const CreateScriptUrlRuntimeModule = require("./runtime/CreateScriptUrlRuntimeModule");
17
19
  const DefinePropertyGettersRuntimeModule = require("./runtime/DefinePropertyGettersRuntimeModule");
18
20
  const EnsureChunkRuntimeModule = require("./runtime/EnsureChunkRuntimeModule");
19
21
  const GetChunkFilenameRuntimeModule = require("./runtime/GetChunkFilenameRuntimeModule");
20
22
  const GetMainFilenameRuntimeModule = require("./runtime/GetMainFilenameRuntimeModule");
23
+ const GetTrustedTypesPolicyRuntimeModule = require("./runtime/GetTrustedTypesPolicyRuntimeModule");
21
24
  const GlobalRuntimeModule = require("./runtime/GlobalRuntimeModule");
22
25
  const HasOwnPropertyRuntimeModule = require("./runtime/HasOwnPropertyRuntimeModule");
23
26
  const LoadScriptRuntimeModule = require("./runtime/LoadScriptRuntimeModule");
@@ -39,7 +42,9 @@ const GLOBALS_ON_REQUIRE = [
39
42
  RuntimeGlobals.runtimeId,
40
43
  RuntimeGlobals.compatGetDefaultExport,
41
44
  RuntimeGlobals.createFakeNamespaceObject,
45
+ RuntimeGlobals.createScript,
42
46
  RuntimeGlobals.createScriptUrl,
47
+ RuntimeGlobals.getTrustedTypesPolicy,
43
48
  RuntimeGlobals.definePropertyGetters,
44
49
  RuntimeGlobals.ensureChunk,
45
50
  RuntimeGlobals.entryModuleId,
@@ -261,6 +266,30 @@ class RuntimePlugin {
261
266
  );
262
267
  return true;
263
268
  });
269
+ compilation.hooks.runtimeRequirementInTree
270
+ .for(RuntimeGlobals.getChunkCssFilename)
271
+ .tap("RuntimePlugin", (chunk, set) => {
272
+ if (
273
+ typeof compilation.outputOptions.cssChunkFilename === "string" &&
274
+ /\[(full)?hash(:\d+)?\]/.test(
275
+ compilation.outputOptions.cssChunkFilename
276
+ )
277
+ ) {
278
+ set.add(RuntimeGlobals.getFullHash);
279
+ }
280
+ compilation.addRuntimeModule(
281
+ chunk,
282
+ new GetChunkFilenameRuntimeModule(
283
+ "css",
284
+ "css",
285
+ RuntimeGlobals.getChunkCssFilename,
286
+ chunk =>
287
+ getChunkFilenameTemplate(chunk, compilation.outputOptions),
288
+ set.has(RuntimeGlobals.hmrDownloadUpdateHandlers)
289
+ )
290
+ );
291
+ return true;
292
+ });
264
293
  compilation.hooks.runtimeRequirementInTree
265
294
  .for(RuntimeGlobals.getChunkUpdateScriptFilename)
266
295
  .tap("RuntimePlugin", (chunk, set) => {
@@ -339,15 +368,36 @@ class RuntimePlugin {
339
368
  );
340
369
  return true;
341
370
  });
371
+ compilation.hooks.runtimeRequirementInTree
372
+ .for(RuntimeGlobals.createScript)
373
+ .tap("RuntimePlugin", (chunk, set) => {
374
+ if (compilation.outputOptions.trustedTypes) {
375
+ set.add(RuntimeGlobals.getTrustedTypesPolicy);
376
+ }
377
+ compilation.addRuntimeModule(chunk, new CreateScriptRuntimeModule());
378
+ return true;
379
+ });
342
380
  compilation.hooks.runtimeRequirementInTree
343
381
  .for(RuntimeGlobals.createScriptUrl)
344
382
  .tap("RuntimePlugin", (chunk, set) => {
383
+ if (compilation.outputOptions.trustedTypes) {
384
+ set.add(RuntimeGlobals.getTrustedTypesPolicy);
385
+ }
345
386
  compilation.addRuntimeModule(
346
387
  chunk,
347
388
  new CreateScriptUrlRuntimeModule()
348
389
  );
349
390
  return true;
350
391
  });
392
+ compilation.hooks.runtimeRequirementInTree
393
+ .for(RuntimeGlobals.getTrustedTypesPolicy)
394
+ .tap("RuntimePlugin", (chunk, set) => {
395
+ compilation.addRuntimeModule(
396
+ chunk,
397
+ new GetTrustedTypesPolicyRuntimeModule(set)
398
+ );
399
+ return true;
400
+ });
351
401
  compilation.hooks.runtimeRequirementInTree
352
402
  .for(RuntimeGlobals.relativeUrl)
353
403
  .tap("RuntimePlugin", (chunk, set) => {
@@ -16,6 +16,7 @@ const { forEachRuntime, subtractRuntime } = require("./util/runtime");
16
16
  /** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
17
17
  /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
18
18
  /** @typedef {import("./ChunkGraph")} ChunkGraph */
19
+ /** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
19
20
  /** @typedef {import("./Compilation")} Compilation */
20
21
  /** @typedef {import("./Dependency")} Dependency */
21
22
  /** @typedef {import("./Module")} Module */
@@ -1014,6 +1015,26 @@ class RuntimeTemplate {
1014
1015
  runtimeRequirements.add(RuntimeGlobals.exports);
1015
1016
  return `${RuntimeGlobals.makeNamespaceObject}(${exportsArgument});\n`;
1016
1017
  }
1018
+
1019
+ /**
1020
+ * @param {Object} options options object
1021
+ * @param {Module} options.module the module
1022
+ * @param {string} options.publicPath the public path
1023
+ * @param {RuntimeSpec=} options.runtime runtime
1024
+ * @param {CodeGenerationResults} options.codeGenerationResults the code generation results
1025
+ * @returns {string} the url of the asset
1026
+ */
1027
+ assetUrl({ publicPath, runtime, module, codeGenerationResults }) {
1028
+ if (!module) {
1029
+ return "data:,";
1030
+ }
1031
+ const codeGen = codeGenerationResults.get(module, runtime);
1032
+ const { data } = codeGen;
1033
+ const url = data.get("url");
1034
+ if (url) return url.toString();
1035
+ const filename = data.get("filename");
1036
+ return publicPath + filename;
1037
+ }
1017
1038
  }
1018
1039
 
1019
1040
  module.exports = RuntimeTemplate;
package/lib/Template.js CHANGED
@@ -370,7 +370,8 @@ class Template {
370
370
  dependencyTemplates: renderContext.dependencyTemplates,
371
371
  moduleGraph: renderContext.moduleGraph,
372
372
  runtimeTemplate: renderContext.runtimeTemplate,
373
- runtime: renderContext.chunk.runtime
373
+ runtime: renderContext.chunk.runtime,
374
+ codeGenerationResults
374
375
  });
375
376
  if (!codeGenResult) continue;
376
377
  runtimeSource = codeGenResult.sources.get("runtime");
package/lib/Watching.js CHANGED
@@ -15,7 +15,7 @@ const Stats = require("./Stats");
15
15
  /**
16
16
  * @template T
17
17
  * @callback Callback
18
- * @param {Error=} err
18
+ * @param {(Error | null)=} err
19
19
  * @param {T=} result
20
20
  */
21
21
 
@@ -49,7 +49,7 @@ class Watching {
49
49
  this.watchOptions = {};
50
50
  }
51
51
  if (typeof this.watchOptions.aggregateTimeout !== "number") {
52
- this.watchOptions.aggregateTimeout = 200;
52
+ this.watchOptions.aggregateTimeout = 20;
53
53
  }
54
54
  this.compiler = compiler;
55
55
  this.running = false;
@@ -118,11 +118,47 @@ class WebpackOptionsApply extends OptionsApply {
118
118
  if (options.externalsPresets.webAsync) {
119
119
  //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
120
120
  const ExternalsPlugin = require("./ExternalsPlugin");
121
- new ExternalsPlugin("import", /^(https?:\/\/|std:)/).apply(compiler);
121
+ new ExternalsPlugin(
122
+ "import",
123
+ options.experiments.css
124
+ ? ({ request, dependencyType }, callback) => {
125
+ if (dependencyType === "url") {
126
+ if (/^(\/\/|https?:\/\/)/.test(request))
127
+ return callback(null, `asset ${request}`);
128
+ } else if (dependencyType === "css-import") {
129
+ if (/^(\/\/|https?:\/\/)/.test(request))
130
+ return callback(null, `css-import ${request}`);
131
+ } else if (/^(\/\/|https?:\/\/|std:)/.test(request)) {
132
+ if (/^\.css(\?|$)/.test(request))
133
+ return callback(null, `css-import ${request}`);
134
+ return callback(null, `import ${request}`);
135
+ }
136
+ callback();
137
+ }
138
+ : /^(\/\/|https?:\/\/|std:)/
139
+ ).apply(compiler);
122
140
  } else if (options.externalsPresets.web) {
123
141
  //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
124
142
  const ExternalsPlugin = require("./ExternalsPlugin");
125
- new ExternalsPlugin("module", /^(https?:\/\/|std:)/).apply(compiler);
143
+ new ExternalsPlugin(
144
+ "module",
145
+ options.experiments.css
146
+ ? ({ request, dependencyType }, callback) => {
147
+ if (dependencyType === "url") {
148
+ if (/^(\/\/|https?:\/\/)/.test(request))
149
+ return callback(null, `asset ${request}`);
150
+ } else if (dependencyType === "css-import") {
151
+ if (/^(\/\/|https?:\/\/)/.test(request))
152
+ return callback(null, `css-import ${request}`);
153
+ } else if (/^(\/\/|https?:\/\/|std:)/.test(request)) {
154
+ if (/^\.css(\?|$)/.test(request))
155
+ return callback(null, `css-import ${request}`);
156
+ return callback(null, `module ${request}`);
157
+ }
158
+ callback();
159
+ }
160
+ : /^(\/\/|https?:\/\/|std:)/
161
+ ).apply(compiler);
126
162
  }
127
163
 
128
164
  new ChunkPrefetchPreloadPlugin().apply(compiler);
@@ -253,6 +289,11 @@ class WebpackOptionsApply extends OptionsApply {
253
289
  }).apply(compiler);
254
290
  }
255
291
 
292
+ if (options.experiments.css) {
293
+ const CssModulesPlugin = require("./css/CssModulesPlugin");
294
+ new CssModulesPlugin(options.experiments.css).apply(compiler);
295
+ }
296
+
256
297
  if (options.experiments.lazyCompilation) {
257
298
  const LazyCompilationPlugin = require("./hmr/LazyCompilationPlugin");
258
299
  const lazyOptions =
@@ -15,6 +15,7 @@ const { makePathsRelative } = require("../util/identifier");
15
15
 
16
16
  /** @typedef {import("webpack-sources").Source} Source */
17
17
  /** @typedef {import("../../declarations/WebpackOptions").AssetGeneratorOptions} AssetGeneratorOptions */
18
+ /** @typedef {import("../../declarations/WebpackOptions").AssetModuleOutputPath} AssetModuleOutputPath */
18
19
  /** @typedef {import("../../declarations/WebpackOptions").RawPublicPath} RawPublicPath */
19
20
  /** @typedef {import("../Compilation")} Compilation */
20
21
  /** @typedef {import("../Compiler")} Compiler */
@@ -49,7 +50,7 @@ const mergeAssetInfo = (a, b) => {
49
50
  case "immutable":
50
51
  case "development":
51
52
  case "hotModuleReplacement":
52
- case "javascriptModule ":
53
+ case "javascriptModule":
53
54
  result[key] = a[key] || b[key];
54
55
  break;
55
56
  case "related":
@@ -74,6 +75,41 @@ const mergeRelatedInfo = (a, b) => {
74
75
  return result;
75
76
  };
76
77
 
78
+ const encodeDataUri = (encoding, source) => {
79
+ let encodedContent;
80
+
81
+ switch (encoding) {
82
+ case "base64": {
83
+ encodedContent = source.buffer().toString("base64");
84
+ break;
85
+ }
86
+ case false: {
87
+ const content = source.source();
88
+
89
+ if (typeof content !== "string") {
90
+ encodedContent = content.toString("utf-8");
91
+ }
92
+
93
+ encodedContent = encodeURIComponent(encodedContent).replace(
94
+ /[!'()*]/g,
95
+ character => "%" + character.codePointAt(0).toString(16)
96
+ );
97
+ break;
98
+ }
99
+ default:
100
+ throw new Error(`Unsupported encoding '${encoding}'`);
101
+ }
102
+
103
+ return encodedContent;
104
+ };
105
+
106
+ const decodeDataUriContent = (encoding, content) => {
107
+ const isBase64 = encoding === "base64";
108
+ return isBase64
109
+ ? Buffer.from(content, "base64")
110
+ : Buffer.from(decodeURIComponent(content), "ascii");
111
+ };
112
+
77
113
  const JS_TYPES = new Set(["javascript"]);
78
114
  const JS_AND_ASSET_TYPES = new Set(["javascript", "asset"]);
79
115
 
@@ -82,13 +118,15 @@ class AssetGenerator extends Generator {
82
118
  * @param {AssetGeneratorOptions["dataUrl"]=} dataUrlOptions the options for the data url
83
119
  * @param {string=} filename override for output.assetModuleFilename
84
120
  * @param {RawPublicPath=} publicPath override for output.assetModulePublicPath
121
+ * @param {AssetModuleOutputPath=} outputPath the output path for the emitted file which is not included in the runtime import
85
122
  * @param {boolean=} emit generate output asset
86
123
  */
87
- constructor(dataUrlOptions, filename, publicPath, emit) {
124
+ constructor(dataUrlOptions, filename, publicPath, outputPath, emit) {
88
125
  super();
89
126
  this.dataUrlOptions = dataUrlOptions;
90
127
  this.filename = filename;
91
128
  this.publicPath = publicPath;
129
+ this.outputPath = outputPath;
92
130
  this.emit = emit;
93
131
  }
94
132
 
@@ -158,39 +196,26 @@ class AssetGenerator extends Generator {
158
196
  }
159
197
 
160
198
  let encodedContent;
199
+
161
200
  if (
162
201
  module.resourceResolveData &&
163
- module.resourceResolveData.encoding === encoding
202
+ module.resourceResolveData.encoding === encoding &&
203
+ decodeDataUriContent(
204
+ module.resourceResolveData.encoding,
205
+ module.resourceResolveData.encodedContent
206
+ ).equals(originalSource.buffer())
164
207
  ) {
165
208
  encodedContent = module.resourceResolveData.encodedContent;
166
209
  } else {
167
- switch (encoding) {
168
- case "base64": {
169
- encodedContent = originalSource.buffer().toString("base64");
170
- break;
171
- }
172
- case false: {
173
- const content = originalSource.source();
174
-
175
- if (typeof content !== "string") {
176
- encodedContent = content.toString("utf-8");
177
- }
178
-
179
- encodedContent = encodeURIComponent(encodedContent).replace(
180
- /[!'()*]/g,
181
- character => "%" + character.codePointAt(0).toString(16)
182
- );
183
- break;
184
- }
185
- default:
186
- throw new Error(`Unsupported encoding '${encoding}'`);
187
- }
210
+ encodedContent = encodeDataUri(encoding, originalSource);
188
211
  }
189
212
 
190
213
  encodedSource = `data:${mimeType}${
191
214
  encoding ? `;${encoding}` : ""
192
215
  },${encodedContent}`;
193
216
  }
217
+ const data = getData();
218
+ data.set("url", Buffer.from(encodedSource));
194
219
  return new RawSource(
195
220
  `${RuntimeGlobals.module}.exports = ${JSON.stringify(
196
221
  encodedSource
@@ -254,6 +279,21 @@ class AssetGenerator extends Generator {
254
279
  sourceFilename,
255
280
  ...assetInfo
256
281
  };
282
+ if (this.outputPath) {
283
+ const { path: outputPath, info } =
284
+ runtimeTemplate.compilation.getAssetPathWithInfo(
285
+ this.outputPath,
286
+ {
287
+ module,
288
+ runtime,
289
+ filename: sourceFilename,
290
+ chunkGraph,
291
+ contentHash
292
+ }
293
+ );
294
+ assetInfo = mergeAssetInfo(assetInfo, info);
295
+ filename = path.posix.join(outputPath, filename);
296
+ }
257
297
  module.buildInfo.filename = filename;
258
298
  module.buildInfo.assetInfo = assetInfo;
259
299
  if (getData) {
@@ -137,9 +137,11 @@ class AssetModulesPlugin {
137
137
 
138
138
  let filename = undefined;
139
139
  let publicPath = undefined;
140
+ let outputPath = undefined;
140
141
  if (type !== "asset/inline") {
141
142
  filename = generatorOptions.filename;
142
143
  publicPath = generatorOptions.publicPath;
144
+ outputPath = generatorOptions.outputPath;
143
145
  }
144
146
 
145
147
  const AssetGenerator = getAssetGenerator();
@@ -148,6 +150,7 @@ class AssetModulesPlugin {
148
150
  dataUrl,
149
151
  filename,
150
152
  publicPath,
153
+ outputPath,
151
154
  generatorOptions.emit !== false
152
155
  );
153
156
  });
@@ -0,0 +1,148 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const { RawSource } = require("webpack-sources");
9
+ const Module = require("../Module");
10
+ const RuntimeGlobals = require("../RuntimeGlobals");
11
+ const makeSerializable = require("../util/makeSerializable");
12
+
13
+ /** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
14
+ /** @typedef {import("../Compilation")} Compilation */
15
+ /** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
16
+ /** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
17
+ /** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
18
+ /** @typedef {import("../Module").NeedBuildContext} NeedBuildContext */
19
+ /** @typedef {import("../RequestShortener")} RequestShortener */
20
+ /** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
21
+ /** @typedef {import("../WebpackError")} WebpackError */
22
+ /** @typedef {import("../util/Hash")} Hash */
23
+ /** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
24
+
25
+ const TYPES = new Set(["javascript"]);
26
+
27
+ class RawDataUrlModule extends Module {
28
+ /**
29
+ * @param {string} url raw url
30
+ * @param {string} identifier unique identifier
31
+ * @param {string=} readableIdentifier readable identifier
32
+ */
33
+ constructor(url, identifier, readableIdentifier) {
34
+ super("asset/raw-data-url", null);
35
+ this.url = url;
36
+ this.urlBuffer = url ? Buffer.from(url) : undefined;
37
+ this.identifierStr = identifier || this.url;
38
+ this.readableIdentifierStr = readableIdentifier || this.identifierStr;
39
+ }
40
+
41
+ /**
42
+ * @returns {Set<string>} types available (do not mutate)
43
+ */
44
+ getSourceTypes() {
45
+ return TYPES;
46
+ }
47
+
48
+ /**
49
+ * @returns {string} a unique identifier of the module
50
+ */
51
+ identifier() {
52
+ return this.identifierStr;
53
+ }
54
+
55
+ /**
56
+ * @param {string=} type the source type for which the size should be estimated
57
+ * @returns {number} the estimated size of the module (must be non-zero)
58
+ */
59
+ size(type) {
60
+ if (this.url === undefined) this.url = this.urlBuffer.toString();
61
+ return Math.max(1, this.url.length);
62
+ }
63
+
64
+ /**
65
+ * @param {RequestShortener} requestShortener the request shortener
66
+ * @returns {string} a user readable identifier of the module
67
+ */
68
+ readableIdentifier(requestShortener) {
69
+ return requestShortener.shorten(this.readableIdentifierStr);
70
+ }
71
+
72
+ /**
73
+ * @param {NeedBuildContext} context context info
74
+ * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
75
+ * @returns {void}
76
+ */
77
+ needBuild(context, callback) {
78
+ return callback(null, !this.buildMeta);
79
+ }
80
+
81
+ /**
82
+ * @param {WebpackOptions} options webpack options
83
+ * @param {Compilation} compilation the compilation
84
+ * @param {ResolverWithOptions} resolver the resolver
85
+ * @param {InputFileSystem} fs the file system
86
+ * @param {function(WebpackError=): void} callback callback function
87
+ * @returns {void}
88
+ */
89
+ build(options, compilation, resolver, fs, callback) {
90
+ this.buildMeta = {};
91
+ this.buildInfo = {
92
+ cacheable: true
93
+ };
94
+ callback();
95
+ }
96
+
97
+ /**
98
+ * @param {CodeGenerationContext} context context for code generation
99
+ * @returns {CodeGenerationResult} result
100
+ */
101
+ codeGeneration(context) {
102
+ if (this.url === undefined) this.url = this.urlBuffer.toString();
103
+ const sources = new Map();
104
+ sources.set(
105
+ "javascript",
106
+ new RawSource(`module.exports = ${JSON.stringify(this.url)};`)
107
+ );
108
+ const data = new Map();
109
+ data.set("url", this.urlBuffer);
110
+ const runtimeRequirements = new Set();
111
+ runtimeRequirements.add(RuntimeGlobals.module);
112
+ return { sources, runtimeRequirements, data };
113
+ }
114
+
115
+ /**
116
+ * @param {Hash} hash the hash used to track dependencies
117
+ * @param {UpdateHashContext} context context
118
+ * @returns {void}
119
+ */
120
+ updateHash(hash, context) {
121
+ hash.update(this.urlBuffer);
122
+ super.updateHash(hash, context);
123
+ }
124
+
125
+ serialize(context) {
126
+ const { write } = context;
127
+
128
+ write(this.urlBuffer);
129
+ write(this.identifierStr);
130
+ write(this.readableIdentifierStr);
131
+
132
+ super.serialize(context);
133
+ }
134
+
135
+ deserialize(context) {
136
+ const { read } = context;
137
+
138
+ this.urlBuffer = read();
139
+ this.identifierStr = read();
140
+ this.readableIdentifierStr = read();
141
+
142
+ super.deserialize(context);
143
+ }
144
+ }
145
+
146
+ makeSerializable(RawDataUrlModule, "webpack/lib/asset/RawDataUrlModule");
147
+
148
+ module.exports = RawDataUrlModule;
@@ -30,8 +30,8 @@ class AwaitDependenciesInitFragment extends InitFragment {
30
30
  }
31
31
 
32
32
  merge(other) {
33
- const promises = new Set(this.promises);
34
- for (const p of other.promises) {
33
+ const promises = new Set(other.promises);
34
+ for (const p of this.promises) {
35
35
  promises.add(p);
36
36
  }
37
37
  return new AwaitDependenciesInitFragment(promises);
@@ -51,7 +51,7 @@ class AwaitDependenciesInitFragment extends InitFragment {
51
51
  for (const p of promises) {
52
52
  return Template.asString([
53
53
  `var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([${p}]);`,
54
- `${p} = (__webpack_async_dependencies__.then ? await __webpack_async_dependencies__ : __webpack_async_dependencies__)[0];`,
54
+ `${p} = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];`,
55
55
  ""
56
56
  ]);
57
57
  }
@@ -60,7 +60,7 @@ class AwaitDependenciesInitFragment extends InitFragment {
60
60
  // TODO check if destructuring is supported
61
61
  return Template.asString([
62
62
  `var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([${sepPromises}]);`,
63
- `([${sepPromises}] = __webpack_async_dependencies__.then ? await __webpack_async_dependencies__ : __webpack_async_dependencies__);`,
63
+ `([${sepPromises}] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);`,
64
64
  ""
65
65
  ]);
66
66
  }
@@ -106,7 +106,7 @@ class ResolverCachePlugin {
106
106
  * @param {Resolver} resolver the resolver
107
107
  * @param {Object} resolveContext context for resolving meta info
108
108
  * @param {Object} request the request info object
109
- * @param {function(Error=, Object=): void} callback callback function
109
+ * @param {function((Error | null)=, Object=): void} callback callback function
110
110
  * @returns {void}
111
111
  */
112
112
  const doRealResolve = (