webpack 5.110.3 → 5.111.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 (208) hide show
  1. package/README.md +5 -0
  2. package/lib/APIPlugin.js +23 -7
  3. package/lib/AutomaticPrefetchPlugin.js +1 -1
  4. package/lib/Cache.js +8 -3
  5. package/lib/CacheFacade.js +1 -1
  6. package/lib/CircularModulesPlugin.js +157 -55
  7. package/lib/CleanPlugin.js +2 -2
  8. package/lib/Compilation.js +320 -302
  9. package/lib/Compiler.js +209 -46
  10. package/lib/ContextModule.js +17 -81
  11. package/lib/ContextModuleFactory.js +1 -1
  12. package/lib/CopyPlugin.js +1054 -0
  13. package/lib/DefinePlugin.js +24 -8
  14. package/lib/ExternalModule.js +41 -14
  15. package/lib/FileSystemInfo.js +17 -14
  16. package/lib/FlagDependencyExportsPlugin.js +45 -21
  17. package/lib/HotModuleReplacementPlugin.js +53 -7
  18. package/lib/JavascriptMetaInfoPlugin.js +5 -3
  19. package/lib/MainTemplate.js +5 -1
  20. package/lib/Module.js +16 -7
  21. package/lib/MultiCompiler.js +1 -1
  22. package/lib/MultiWatching.js +1 -1
  23. package/lib/NormalModule.js +45 -12
  24. package/lib/NormalModuleFactory.js +1 -1
  25. package/lib/RuntimeGlobals.js +21 -7
  26. package/lib/RuntimeModule.js +28 -12
  27. package/lib/RuntimePlugin.js +30 -3
  28. package/lib/RuntimeTemplate.js +780 -475
  29. package/lib/SourceMapDevToolPlugin.js +1 -1
  30. package/lib/Watching.js +9 -0
  31. package/lib/WebpackOptionsApply.js +84 -91
  32. package/lib/asset/AssetGenerator.js +25 -8
  33. package/lib/asset/AssetModule.js +3 -0
  34. package/lib/asset/WebManifestParser.js +7 -5
  35. package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
  36. package/lib/cache/IdleFileCachePlugin.js +2 -2
  37. package/lib/cache/PackFileCacheStrategy.js +14 -1
  38. package/lib/config/browserslistTargetHandler.js +19 -0
  39. package/lib/config/defaults.js +86 -50
  40. package/lib/config/normalization.js +82 -12
  41. package/lib/config/target.js +10 -0
  42. package/lib/container/ContainerReferencePlugin.js +6 -0
  43. package/lib/container/RemoteRuntimeModule.js +9 -0
  44. package/lib/container/declaredRemotes.js +39 -0
  45. package/lib/css/CssGenerator.js +8 -0
  46. package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
  47. package/lib/css/CssLoadingRuntimeModule.js +94 -36
  48. package/lib/css/CssModule.js +1 -1
  49. package/lib/css/CssModulesPlugin.js +7 -6
  50. package/lib/css/CssParser.js +144 -11
  51. package/lib/css/CssServerStylesRuntimeModule.js +9 -0
  52. package/lib/css/cssMinify.js +11 -3
  53. package/lib/css/data.js +2814 -678
  54. package/lib/css/syntax.js +4082 -248
  55. package/lib/debug/ProfilingPlugin.js +4 -0
  56. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
  57. package/lib/dependencies/AMDRuntimeModules.js +18 -0
  58. package/lib/dependencies/CommonJsExportRequireDependency.js +3 -1
  59. package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
  60. package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -0
  61. package/lib/dependencies/CommonJsPlugin.js +19 -3
  62. package/lib/dependencies/CommonJsRequireDependency.js +14 -5
  63. package/lib/dependencies/CssIcssExportDependency.js +7 -1
  64. package/lib/dependencies/HarmonyCompatibilityDependency.js +58 -4
  65. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +8 -3
  66. package/lib/dependencies/HarmonyExportExpressionDependency.js +44 -29
  67. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +71 -13
  68. package/lib/dependencies/HarmonyExportInitFragment.js +99 -19
  69. package/lib/dependencies/HarmonyExportSpecifierDependency.js +18 -30
  70. package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
  71. package/lib/dependencies/HarmonyImportDependency.js +6 -1
  72. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +8 -1
  73. package/lib/dependencies/HarmonyImportSpecifierDependency.js +24 -1
  74. package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
  75. package/lib/dependencies/HtmlEntryDependency.js +50 -0
  76. package/lib/dependencies/ImportMetaMainDependency.js +104 -0
  77. package/lib/dependencies/ImportMetaPlugin.js +59 -15
  78. package/lib/dependencies/SystemRuntimeModule.js +9 -0
  79. package/lib/dependencies/WorkerDependency.js +1 -2
  80. package/lib/dependencies/WorkletDependency.js +1 -2
  81. package/lib/dll/DelegatedModule.js +18 -1
  82. package/lib/dll/DllReferencePlugin.js +11 -8
  83. package/lib/dll/LibManifestPlugin.js +1 -1
  84. package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
  85. package/lib/errors/DuplicateModulesWarning.js +12 -7
  86. package/lib/errors/EmptyCopyPatternWarning.js +26 -0
  87. package/lib/errors/ExternalStarReexportError.js +44 -0
  88. package/lib/errors/MissingSourceMapsWarning.js +36 -0
  89. package/lib/errors/ModuleParseError.js +2 -1
  90. package/lib/errors/UnusedAssetsWarning.js +36 -0
  91. package/lib/errors/UnusedFederationWarning.js +35 -0
  92. package/lib/errors/UnusedModulesWarning.js +38 -0
  93. package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
  94. package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
  95. package/lib/esm/ModuleChunkLoadingPlugin.js +30 -11
  96. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +92 -60
  97. package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
  98. package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
  99. package/lib/html/HtmlGenerator.js +11 -5
  100. package/lib/html/HtmlModulesPlugin.js +331 -62
  101. package/lib/html/HtmlParser.js +13 -6
  102. package/lib/html/builtinEmbeddedRenderer.js +107 -0
  103. package/lib/html/data.js +121 -7
  104. package/lib/html/htmlMinify.js +84 -113
  105. package/lib/html/syntax.js +763 -426
  106. package/lib/ids/HashedModuleIdsPlugin.js +2 -1
  107. package/lib/index.js +3 -0
  108. package/lib/javascript/JavascriptModule.js +1 -0
  109. package/lib/javascript/JavascriptModulesPlugin.js +52 -24
  110. package/lib/javascript/JavascriptParser.js +1255 -728
  111. package/lib/javascript/StartupHelpers.js +27 -3
  112. package/lib/javascript/data.js +172 -0
  113. package/lib/javascript/grammar.js +5546 -0
  114. package/lib/javascript/parser.js +1494 -0
  115. package/lib/javascript/regexp.js +1762 -0
  116. package/lib/javascript/regexpData.js +51 -0
  117. package/lib/javascript/syntax.js +8696 -5225
  118. package/lib/library/ModuleLibraryPlugin.js +116 -5
  119. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
  120. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
  121. package/lib/optimize/ConcatenatedModule.js +97 -20
  122. package/lib/optimize/ConstExportsPlugin.js +50 -39
  123. package/lib/optimize/InlineExports.js +20 -123
  124. package/lib/optimize/MangleExportsPlugin.js +10 -0
  125. package/lib/optimize/ModuleConcatenationPlugin.js +24 -1
  126. package/lib/optimize/RealContentHashPlugin.js +68 -9
  127. package/lib/optimize/SideEffectsFlagPlugin.js +17 -9
  128. package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
  129. package/lib/performance/CacheEffectivenessPlugin.js +4 -3
  130. package/lib/performance/DuplicateModulesPlugin.js +57 -13
  131. package/lib/performance/EvalUsagePlugin.js +5 -2
  132. package/lib/performance/MissingSourceMapsPlugin.js +115 -0
  133. package/lib/performance/PureAnnotationsPlugin.js +6 -3
  134. package/lib/performance/TopLevelThisPlugin.js +5 -4
  135. package/lib/performance/UnusedAssetsPlugin.js +109 -0
  136. package/lib/performance/UnusedFederationPlugin.js +147 -0
  137. package/lib/performance/UnusedModulesPlugin.js +141 -0
  138. package/lib/performance/UnusedReexportsPlugin.js +1 -55
  139. package/lib/performance/isOnlyReexported.js +65 -0
  140. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
  141. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +2 -0
  142. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
  143. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
  144. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
  145. package/lib/prefetch/ResourceHintPlugin.js +1 -2
  146. package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
  147. package/lib/prefetch/StartupAssetHintRuntimeModule.js +9 -0
  148. package/lib/rules/RuleSetCompiler.js +211 -4
  149. package/lib/runtime/AsyncModuleRuntimeModule.js +100 -66
  150. package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
  151. package/lib/runtime/BaseUriRuntimeModule.js +9 -0
  152. package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
  153. package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
  154. package/lib/runtime/GetChunkFilenameRuntimeModule.js +9 -0
  155. package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
  156. package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
  157. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
  158. package/lib/runtime/GlobalRuntimeModule.js +9 -0
  159. package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
  160. package/lib/runtime/HelperRuntimeModule.js +10 -0
  161. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +330 -219
  162. package/lib/runtime/NonceRuntimeModule.js +9 -0
  163. package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
  164. package/lib/runtime/PublicPathRuntimeModule.js +9 -0
  165. package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
  166. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
  167. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
  168. package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
  169. package/lib/runtime/SystemContextRuntimeModule.js +9 -0
  170. package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
  171. package/lib/serialization/ObjectMiddleware.js +138 -106
  172. package/lib/sharing/ConsumeSharedPlugin.js +12 -0
  173. package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
  174. package/lib/sharing/ShareRuntimeModule.js +9 -0
  175. package/lib/sharing/declaredShared.js +47 -0
  176. package/lib/stats/DefaultStatsFactoryPlugin.js +3 -1
  177. package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
  178. package/lib/util/SourceProcessor.js +76 -69
  179. package/lib/util/async.js +292 -0
  180. package/lib/util/buildDiagnostics.js +69 -0
  181. package/lib/util/fs.js +27 -1
  182. package/lib/util/handlerKeys.js +40 -0
  183. package/lib/util/identifier.js +20 -0
  184. package/lib/util/internalSerializables.js +4 -0
  185. package/lib/util/registerExternalSerializer.js +6 -45
  186. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
  187. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
  188. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +9 -0
  189. package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
  190. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
  191. package/package.json +22 -16
  192. package/schemas/WebpackOptions.check.js +1 -1
  193. package/schemas/WebpackOptions.json +379 -66
  194. package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
  195. package/schemas/plugins/ManifestPlugin.check.js +1 -1
  196. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  197. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  198. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  199. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  200. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  201. package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
  202. package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
  203. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
  204. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  205. package/types.d.ts +1414 -314
  206. package/lib/dependencies/ExportBindingInitFragment.js +0 -191
  207. package/lib/errors/EntrypointOverlapWarning.js +0 -45
  208. package/lib/performance/EntrypointOverlapPlugin.js +0 -122
@@ -0,0 +1,107 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Alexander Akait @alexander-akait
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const { CSS_TYPE } = require("../ModuleSourceTypeConstants");
9
+
10
+ /** @import { CssProcessOptions } from "../css/syntax" */
11
+ /** @import { EmbeddedSourceRenderer } from "./syntax" */
12
+
13
+ /**
14
+ * What this minifies inline CSS with: the CSS minifier's own options, so an
15
+ * inline declaration is held to the rules a `.css` asset is.
16
+ * @typedef {Pick<CssProcessOptions, "environment" | "convertLengthUnits" | "rewriteCustomProperties" | "transforms" | "unusedSymbols" | "pseudoClasses">} BuiltinEmbeddedRendererOptions
17
+ */
18
+
19
+ // Both are loaded on first render rather than at module load: a document that
20
+ // embeds no CSS and no JSON pays for neither.
21
+ /** @type {typeof import("../css/syntax") | undefined} */
22
+ let _cssSyntax;
23
+ /** @type {typeof import("./syntax") | undefined} */
24
+ let _htmlSyntax;
25
+
26
+ /**
27
+ * Strip the whitespace between a JSON body's tokens, every literal copied byte
28
+ * for byte. Re-serializing would round numbers, drop a duplicate key and rewrite
29
+ * the escapes that keep a string from closing the `<script>` early.
30
+ * @param {string} json a `<script>` body
31
+ * @returns {string} the stripped body, or the body as written where it is not JSON
32
+ */
33
+ const stripJsonWhitespace = (json) => {
34
+ try {
35
+ JSON.parse(json);
36
+ } catch (_err) {
37
+ // Not JSON after all (a template, a placeholder) — not ours to touch.
38
+ return json;
39
+ }
40
+ let out = "";
41
+ let inString = false;
42
+ let escaped = false;
43
+ for (let i = 0; i < json.length; i++) {
44
+ const c = json.charCodeAt(i);
45
+ if (inString) {
46
+ out += json[i];
47
+ if (escaped) escaped = false;
48
+ else if (c === 0x5c) escaped = true;
49
+ else if (c === 0x22) inString = false;
50
+ continue;
51
+ }
52
+ if (c === 0x22) {
53
+ inString = true;
54
+ out += json[i];
55
+ continue;
56
+ }
57
+ // JSON whitespace (RFC 8259): tab, LF, CR, space.
58
+ if (c === 0x09 || c === 0x0a || c === 0x0d || c === 0x20) continue;
59
+ out += json[i];
60
+ }
61
+ return out;
62
+ };
63
+
64
+ /**
65
+ * The renderer webpack ships for what a document embeds: its own CSS minifier
66
+ * for a `<style>` or `style=""` and `stripJsonWhitespace` for JSON, declining
67
+ * every other language. A caller passes it where it has no renderer of its own,
68
+ * or behind one for the languages that one declines — the HTML printer minifies
69
+ * none of this itself.
70
+ * @param {BuiltinEmbeddedRendererOptions=} options the CSS minifier's options, so an inline declaration is minified as the `.css` assets are
71
+ * @returns {EmbeddedSourceRenderer} the renderer
72
+ */
73
+ const builtinEmbeddedRenderer = (options = {}) => {
74
+ const { BLOCK_CONTENTS, JSON_TYPE } =
75
+ _htmlSyntax || (_htmlSyntax = require("./syntax"));
76
+ const sheet = { mode: /** @type {"minify"} */ ("minify"), ...options };
77
+ const block = { ...sheet, as: BLOCK_CONTENTS };
78
+ // A `style=""` repeats across a document far more often than it varies.
79
+ /** @type {Map<string, string>} */
80
+ const blocks = new Map();
81
+ return (source, info) => {
82
+ if (info.type === JSON_TYPE) return stripJsonWhitespace(source);
83
+ if (info.type !== CSS_TYPE) return undefined;
84
+ const isBlock = info.as === BLOCK_CONTENTS;
85
+ if (isBlock) {
86
+ const memoized = blocks.get(source);
87
+ if (memoized !== undefined) return memoized;
88
+ }
89
+ const { SourceProcessor } =
90
+ _cssSyntax || (_cssSyntax = require("../css/syntax"));
91
+ let code;
92
+ try {
93
+ code = new SourceProcessor().process(
94
+ source,
95
+ isBlock ? block : sheet
96
+ ).code;
97
+ } catch (_err) {
98
+ // Text the minifier cannot read is left as written, by declining.
99
+ return undefined;
100
+ }
101
+ if (isBlock) blocks.set(source, code);
102
+ return code;
103
+ };
104
+ };
105
+
106
+ module.exports.builtinEmbeddedRenderer = builtinEmbeddedRenderer;
107
+ module.exports.stripJsonWhitespace = stripJsonWhitespace;
package/lib/html/data.js CHANGED
@@ -6,7 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  // GENERATED by tooling/generate-html-data.js — do not edit.
9
- // cspell:ignore advasoft altglyph altglyphdef altglyphitem animatecolor animatemotion animatetransform arcrole aswedit attributename attributetype basefrequency baseprofile bgsound calcmode clippathunits contenteditable diffuseconstant enterkeyhint fedropshadow filterunits formenctype formmethod formtarget glyphref gradienttransform gradientunits hotjava hotmetal inputmode jscript kernelmatrix kernelunitlength keypoints keysplines keytimes limitingconeangle livescript markerheight markerwidth maskcontentunits maskunits metrius mtext numoctaves pathlength patterncontentunits patterntransform patternunits pointsatx pointsaty pointsatz preservealpha primitiveunits refx refy repeatcount repeatdur requiredextensions requiredfeatures silmaril softquad specularconstant specularexponent startoffset stddeviation stitchtiles surfacescale systemlanguage tablevalues targetx targety textlength viewbox viewtarget webtechs writingsuggestions xchannelselector ychannelselector
9
+ // cspell:ignore advasoft altglyph altglyphdef altglyphitem animatecolor animatemotion animatetransform arcrole aswedit attributename attributetype basefrequency baseprofile bgsound calcmode clippathunits contenteditable diffuseconstant enterkeyhint fedropshadow filterunits formenctype formmethod formtarget glyphref gradienttransform gradientunits hotjava hotmetal inputmode jscript kernelmatrix kernelunitlength keypoints keysplines keytimes limitingconeangle livescript markerheight markerwidth maskcontentunits maskunits metrius mtext numoctaves pathlength patterncontentunits patterntransform patternunits pointsatx pointsaty pointsatz preservealpha primitiveunits refx refy repeatcount repeatdur requiredextensions requiredfeatures silmaril softquad specularconstant specularexponent startoffset stddeviation stitchtiles surfacescale systemlanguage tablevalues targetx targety textlength viewbox viewtarget webtechs writingsuggestions xchannelselector ychannelselector onabort onafterprint onauxclick onbeforeinput onbeforematch onbeforeprint onbeforetoggle onbeforeunload onblur oncancel oncanplay oncanplaythrough onchange onclick onclose oncommand oncontextlost oncontextmenu oncontextrestored oncopy oncuechange oncut ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended onerror onfocus onformdata onhashchange oninput oninvalid onkeydown onkeypress onkeyup onlanguagechange onload onloadeddata onloadedmetadata onloadstart onmessage onmessageerror onmousedown onmouseenter onmouseleave onmousemove onmouseout onmouseover onmouseup onoffline ononline onpagehide onpagereveal onpageshow onpageswap onpaste onpause onplay onplaying onpopstate onprogress onratechange onrejectionhandled onreset onresize onscroll onscrollend onsecuritypolicyviolation onseeked onseeking onselect onslotchange onstalled onstorage onsubmit onsuspend ontimeupdate ontoggle onunhandledrejection onunload onvolumechange onwaiting onwebkitanimationend onwebkitanimationiteration onwebkitanimationstart onwebkittransitionend onwheel
10
10
  // Reflected-attribute tables from webref's extraction of the HTML IDL (see tooling/generate-html-data.js); everything else is the
11
11
  // generator's SUPPLEMENT, which carries the spec facts no dataset states.
12
12
 
@@ -178,6 +178,8 @@ const REWRITABLE_ATTRIBUTES = new Set([
178
178
  "rowspan",
179
179
  "sandbox",
180
180
  "scope",
181
+ "scrollamount",
182
+ "scrolldelay",
181
183
  "size",
182
184
  "sizes",
183
185
  "span",
@@ -330,7 +332,7 @@ const BOOLEAN_ATTRIBUTES = new Map([
330
332
  ["autofocus", null],
331
333
  ["autoplay", new Set(["audio", "video"])],
332
334
  ["checked", new Set(["input"])],
333
- ["compact", new Set(["dl", "menu", "ol", "ul"])],
335
+ ["compact", new Set(["dir", "dl", "menu", "ol", "ul"])],
334
336
  ["controls", new Set(["audio", "img", "video"])],
335
337
  ["declare", new Set(["object"])],
336
338
  ["default", new Set(["track"])],
@@ -358,6 +360,7 @@ const BOOLEAN_ATTRIBUTES = new Map([
358
360
  ["muted", new Set(["audio", "video"])],
359
361
  ["nohref", new Set(["area"])],
360
362
  ["nomodule", new Set(["script"])],
363
+ ["noresize", new Set(["frame"])],
361
364
  ["noshade", new Set(["hr"])],
362
365
  ["novalidate", new Set(["form"])],
363
366
  ["nowrap", new Set(["td", "th"])],
@@ -369,7 +372,8 @@ const BOOLEAN_ATTRIBUTES = new Map([
369
372
  ["selected", new Set(["option"])],
370
373
  ["shadowrootclonable", new Set(["template"])],
371
374
  ["shadowrootdelegatesfocus", new Set(["template"])],
372
- ["shadowrootserializable", new Set(["template"])]
375
+ ["shadowrootserializable", new Set(["template"])],
376
+ ["truespeed", new Set(["marquee"])]
373
377
  ]);
374
378
 
375
379
  /**
@@ -435,7 +439,7 @@ const URL_ATTRIBUTES = new Map([
435
439
  ["data", new Set(["object"])],
436
440
  ["formaction", new Set(["button", "input"])],
437
441
  ["href", new Set(["a", "area", "base", "link"])],
438
- ["longdesc", new Set(["iframe", "img"])],
442
+ ["longdesc", new Set(["frame", "iframe", "img"])],
439
443
  ["lowsrc", new Set(["img"])],
440
444
  ["manifest", new Set(["html"])],
441
445
  ["poster", new Set(["video"])],
@@ -444,6 +448,7 @@ const URL_ATTRIBUTES = new Map([
444
448
  new Set([
445
449
  "audio",
446
450
  "embed",
451
+ "frame",
447
452
  "iframe",
448
453
  "img",
449
454
  "input",
@@ -480,17 +485,19 @@ const INTEGER_ATTRIBUTES = new Map([
480
485
  "video"
481
486
  ])
482
487
  ],
483
- ["hspace", new Set(["img", "object"])],
488
+ ["hspace", new Set(["img", "marquee", "object"])],
484
489
  ["maxlength", new Set(["input", "textarea"])],
485
490
  ["minlength", new Set(["input", "textarea"])],
486
491
  ["rows", new Set(["textarea"])],
487
492
  ["rowspan", new Set(["td", "th"])],
493
+ ["scrollamount", new Set(["marquee"])],
494
+ ["scrolldelay", new Set(["marquee"])],
488
495
  ["size", new Set(["input", "select"])],
489
496
  ["span", new Set(["col", "colgroup"])],
490
497
  ["start", new Set(["ol"])],
491
498
  ["tabindex", null],
492
499
  ["value", new Set(["li"])],
493
- ["vspace", new Set(["img", "object"])],
500
+ ["vspace", new Set(["img", "marquee", "object"])],
494
501
  [
495
502
  "width",
496
503
  new Set([
@@ -499,10 +506,12 @@ const INTEGER_ATTRIBUTES = new Map([
499
506
  "iframe",
500
507
  "img",
501
508
  "input",
509
+ "listing",
502
510
  "object",
503
511
  "pre",
504
512
  "source",
505
- "video"
513
+ "video",
514
+ "xmp"
506
515
  ])
507
516
  ]
508
517
  ]);
@@ -524,6 +533,110 @@ const SIGNED_INTEGER_ATTRIBUTES = new Set(["start", "tabindex", "value"]);
524
533
  */
525
534
  const COMMA_LIST_ATTRIBUTES = new Set(["accept", "coords", "sizes"]);
526
535
 
536
+ /**
537
+ * Event handler content attributes, mapped to the elements each is one on
538
+ * (`null` = a global attribute). Elsewhere the same name is an ordinary
539
+ * attribute holding text — `onunload` is a handler on `<body>` and data on a
540
+ * `<div>` — so the value is only read as JavaScript where the table says it is.
541
+ * @type {Map<string, Set<string> | null>}
542
+ */
543
+ const EVENT_HANDLER_ATTRIBUTES = new Map([
544
+ ["onabort", null],
545
+ ["onafterprint", new Set(["body", "frameset"])],
546
+ ["onauxclick", null],
547
+ ["onbeforeinput", null],
548
+ ["onbeforematch", null],
549
+ ["onbeforeprint", new Set(["body", "frameset"])],
550
+ ["onbeforetoggle", null],
551
+ ["onbeforeunload", new Set(["body", "frameset"])],
552
+ ["onblur", null],
553
+ ["oncancel", null],
554
+ ["oncanplay", null],
555
+ ["oncanplaythrough", null],
556
+ ["onchange", null],
557
+ ["onclick", null],
558
+ ["onclose", null],
559
+ ["oncommand", null],
560
+ ["oncontextlost", null],
561
+ ["oncontextmenu", null],
562
+ ["oncontextrestored", null],
563
+ ["oncopy", null],
564
+ ["oncuechange", null],
565
+ ["oncut", null],
566
+ ["ondblclick", null],
567
+ ["ondrag", null],
568
+ ["ondragend", null],
569
+ ["ondragenter", null],
570
+ ["ondragleave", null],
571
+ ["ondragover", null],
572
+ ["ondragstart", null],
573
+ ["ondrop", null],
574
+ ["ondurationchange", null],
575
+ ["onemptied", null],
576
+ ["onended", null],
577
+ ["onerror", null],
578
+ ["onfocus", null],
579
+ ["onformdata", null],
580
+ ["onhashchange", new Set(["body", "frameset"])],
581
+ ["oninput", null],
582
+ ["oninvalid", null],
583
+ ["onkeydown", null],
584
+ ["onkeypress", null],
585
+ ["onkeyup", null],
586
+ ["onlanguagechange", new Set(["body", "frameset"])],
587
+ ["onload", null],
588
+ ["onloadeddata", null],
589
+ ["onloadedmetadata", null],
590
+ ["onloadstart", null],
591
+ ["onmessage", new Set(["body", "frameset"])],
592
+ ["onmessageerror", new Set(["body", "frameset"])],
593
+ ["onmousedown", null],
594
+ ["onmouseenter", null],
595
+ ["onmouseleave", null],
596
+ ["onmousemove", null],
597
+ ["onmouseout", null],
598
+ ["onmouseover", null],
599
+ ["onmouseup", null],
600
+ ["onoffline", new Set(["body", "frameset"])],
601
+ ["ononline", new Set(["body", "frameset"])],
602
+ ["onpagehide", new Set(["body", "frameset"])],
603
+ ["onpagereveal", new Set(["body", "frameset"])],
604
+ ["onpageshow", new Set(["body", "frameset"])],
605
+ ["onpageswap", new Set(["body", "frameset"])],
606
+ ["onpaste", null],
607
+ ["onpause", null],
608
+ ["onplay", null],
609
+ ["onplaying", null],
610
+ ["onpopstate", new Set(["body", "frameset"])],
611
+ ["onprogress", null],
612
+ ["onratechange", null],
613
+ ["onrejectionhandled", new Set(["body", "frameset"])],
614
+ ["onreset", null],
615
+ ["onresize", null],
616
+ ["onscroll", null],
617
+ ["onscrollend", null],
618
+ ["onsecuritypolicyviolation", null],
619
+ ["onseeked", null],
620
+ ["onseeking", null],
621
+ ["onselect", null],
622
+ ["onslotchange", null],
623
+ ["onstalled", null],
624
+ ["onstorage", new Set(["body", "frameset"])],
625
+ ["onsubmit", null],
626
+ ["onsuspend", null],
627
+ ["ontimeupdate", null],
628
+ ["ontoggle", null],
629
+ ["onunhandledrejection", new Set(["body", "frameset"])],
630
+ ["onunload", new Set(["body", "frameset"])],
631
+ ["onvolumechange", null],
632
+ ["onwaiting", null],
633
+ ["onwebkitanimationend", null],
634
+ ["onwebkitanimationiteration", null],
635
+ ["onwebkitanimationstart", null],
636
+ ["onwebkittransitionend", null],
637
+ ["onwheel", null]
638
+ ]);
639
+
527
640
  /**
528
641
  * §13.1.2 void elements: no end tag, and no children to close one over.
529
642
  * @type {Set<string>}
@@ -1863,6 +1976,7 @@ module.exports.EMPTY_METADATA_ELEMENTS = EMPTY_METADATA_ELEMENTS;
1863
1976
  module.exports.EMPTY_REMOVABLE_ATTRIBUTES = EMPTY_REMOVABLE_ATTRIBUTES;
1864
1977
  module.exports.ENUMERATED_ATTRIBUTE_NAMES = ENUMERATED_ATTRIBUTE_NAMES;
1865
1978
  module.exports.ENUMERATED_KEYWORDS = ENUMERATED_KEYWORDS;
1979
+ module.exports.EVENT_HANDLER_ATTRIBUTES = EVENT_HANDLER_ATTRIBUTES;
1866
1980
  module.exports.FONT_BREAKOUT_ATTRS = FONT_BREAKOUT_ATTRS;
1867
1981
  module.exports.FOREIGN_ATTR_NS = FOREIGN_ATTR_NS;
1868
1982
  module.exports.FOREIGN_BREAKOUT = FOREIGN_BREAKOUT;
@@ -5,7 +5,8 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- /** @import { DeferredEmbeddedSource, HtmlPrintOptions } from "../html/syntax" */
8
+ /** @import { HtmlPrintOptions } from "../html/syntax" */
9
+ /** @import { CssEnvironment } from "../css/syntax" */
9
10
 
10
11
  /**
11
12
  * What a renderer made of one embedded body: the minified text, and anything it
@@ -32,9 +33,9 @@
32
33
  * imported at module scope: `minimizer-webpack-plugin` ships this function to its
33
34
  * worker pool as source (a top-level import wouldn't survive), and `require("webpack")`
34
35
  * re-resolves in the worker — via the installed package, or the dev self-link.
35
- * @param {{ [file: string]: string }} input a single `{ filename: code }` entry
36
+ * @param {{ [file: string]: string | Buffer }} input a single `{ filename: code }` entry; a `Buffer` is read as UTF-8
36
37
  * @param {(RawSourceMap | undefined)=} sourceMap input source map (unused: safe serialize keeps positions token-coarse, so no map is produced yet)
37
- * @param {Omit<HtmlPrintOptions, "renderEmbeddedSource" | "deferEmbeddedSource"> & { css?: { convertLengthUnits?: boolean, rewriteCustomProperties?: boolean }, minifyConditionalComments?: boolean, minifySrcdoc?: boolean, renderEmbeddedSource?: AsyncEmbeddedSourceRenderer }=} minimizerOptions minimizer options — `environment` and `css` (`optimization.minimize.css`, whole) reach the CSS minifier this runs over inline CSS; the rest is `optimization.minimize.html`. The two stand apart rather than merged: both languages name a `quotes` and a `comments`, and one flat object would hand each the other's answer. `renderEmbeddedSource` minifies source this document embeds and may be asynchronous — one parse serves both it and the output — and `minifySrcdoc` takes an `<iframe srcdoc>` back off it, since it minifies one already
38
+ * @param {Omit<HtmlPrintOptions, "renderEmbeddedSource" | "deferEmbeddedSource"> & { environment?: CssEnvironment, css?: { convertLengthUnits?: boolean, rewriteCustomProperties?: boolean, unusedSymbols?: string[], pseudoClasses?: { [name: string]: string } }, minifyConditionalComments?: boolean, renderEmbeddedSource?: AsyncEmbeddedSourceRenderer }=} minimizerOptions minimizer options — `environment` and `css` (`optimization.minimize.css`, whole) reach the CSS minifier this runs over inline CSS; the rest is `optimization.minimize.html`. The two stand apart rather than merged: both languages name a `quotes` and a `comments`, and one flat object would hand each the other's answer. `renderEmbeddedSource` minifies source this document embeds and may be asynchronous — one parse serves both it and the output. What it declines this minifies itself, for the languages webpack ships a minifier for
38
39
  * @returns {Promise<{ code: string, warnings?: (Error | string)[], errors?: (Error | string)[] }>} the minified HTML, and what a renderer reported over what it embeds
39
40
  */
40
41
  const htmlMinify = async (input, sourceMap, minimizerOptions = {}) => {
@@ -43,21 +44,20 @@ const htmlMinify = async (input, sourceMap, minimizerOptions = {}) => {
43
44
  require(/** @type {string} */ ("webpack"))
44
45
  );
45
46
 
46
- // TODO widen the value rewrites the switches below name: a boolean attribute
47
- // spelled any other way than its own name, an enumerated value the spec does
48
- // not name.
47
+ // TODO widen the value rewrites the switches below name: an enumerated
48
+ // value the spec does not name.
49
49
  const {
50
50
  askEmbeddedRenderer,
51
+ builtinEmbeddedRenderer,
51
52
  collectEmbeddedDiagnostics,
52
53
  embeddedText,
53
54
  SourceProcessor,
54
55
  NodeType,
55
- NS_HTML,
56
- decodeEntities,
57
- escapeAttribute,
58
56
  pickTransforms
59
57
  } = webpack.html.syntax;
60
- const [[, code]] = Object.entries(input);
58
+ const [[, given]] = Object.entries(input);
59
+ // The plugin hands a text minifier a string; the type admits an image's bytes.
60
+ const code = typeof given === "string" ? given : given.toString("utf8");
61
61
  // The nested CSS minifier gets the abilities and options a `.css` asset
62
62
  // gets, or the inline copy of a declaration would disagree with it.
63
63
  const {
@@ -65,37 +65,39 @@ const htmlMinify = async (input, sourceMap, minimizerOptions = {}) => {
65
65
  css = {},
66
66
  collapseWhitespace,
67
67
  mergeStyles,
68
+ mergeScripts,
68
69
  removeEmptyAttributes,
69
70
  removeEmptyElements,
70
71
  removeRedundantAttributes,
71
72
  minifyConditionalComments,
72
- minifySrcdoc,
73
73
  sortAttributes,
74
74
  sortTokenLists,
75
75
  removeImpliedTags,
76
76
  renderEmbeddedSource
77
77
  } = minimizerOptions;
78
- // A `<iframe srcdoc>` the pre-pass below owns is not offered, or the same
79
- // document would be minified twice — once each, and the pre-pass keeps the
80
- // delimiter and reaches a value written bare, which the printer cannot.
81
- const ownsSrcdoc = Boolean(minifySrcdoc);
82
78
  // One list for the whole run: a nested document reaches this same collector,
83
79
  // so what a renderer reports inside an `<iframe srcdoc>` is reported once at
84
80
  // the top rather than lost at the level that heard it.
85
81
  /** @type {EmbeddedSourceResult[]} */
86
82
  const reported = [];
83
+ // Webpack's own renderer, handed the CSS minifier's options so an inline
84
+ // declaration agrees with the `.css` asset; each language picks its switches.
85
+ const builtin = builtinEmbeddedRenderer({
86
+ environment,
87
+ convertLengthUnits: css.convertLengthUnits,
88
+ rewriteCustomProperties: css.rewriteCustomProperties,
89
+ unusedSymbols: css.unusedSymbols,
90
+ pseudoClasses: css.pseudoClasses,
91
+ transforms: webpack.css.syntax.pickTransforms(css)
92
+ });
87
93
  // One set of options, handed to the document pass and to each conditional
88
94
  // comment's body below.
89
95
  const printOptions = {
90
96
  mode: /** @type {"minify"} */ ("minify"),
91
- environment,
92
- convertLengthUnits: css.convertLengthUnits,
93
- rewriteCustomProperties: css.rewriteCustomProperties,
94
- // Each language picks its own switches out of its own options object.
95
- cssTransforms: webpack.css.syntax.pickTransforms(css),
96
97
  transforms: pickTransforms(minimizerOptions),
97
98
  collapseWhitespace,
98
99
  mergeStyles,
100
+ mergeScripts,
99
101
  removeEmptyAttributes,
100
102
  removeEmptyElements,
101
103
  removeRedundantAttributes,
@@ -106,27 +108,46 @@ const htmlMinify = async (input, sourceMap, minimizerOptions = {}) => {
106
108
  // Handed each body the print offers, with what it reported kept: how the
107
109
  // element or attribute around one is written is decided from the answer, and
108
110
  // a body declined or thrown on is spelled as an untapped run spells it.
109
- const renderer =
110
- renderEmbeddedSource === undefined
111
- ? undefined
112
- : (/** @type {string} */ _source, /** @type {EXPECTED_ANY} */ hole) =>
113
- askEmbeddedRenderer(renderEmbeddedSource, hole, reported).then(
114
- embeddedText
115
- );
111
+ // A caller's renderer is asked first; whatever it declines this minifies
112
+ // itself, for the languages webpack ships a minifier for.
113
+ const renderer = async (
114
+ /** @type {string} */ source,
115
+ /** @type {EXPECTED_ANY} */ hole
116
+ ) => {
117
+ if (renderEmbeddedSource !== undefined) {
118
+ const answered = embeddedText(
119
+ await askEmbeddedRenderer(renderEmbeddedSource, hole, reported)
120
+ );
121
+
122
+ if (typeof answered === "string") return answered;
123
+ }
124
+
125
+ // Webpack's own answers for what the caller's left: CSS and JSON, and a
126
+ // nested document, which is a document minified the same way.
127
+ const own = builtin(source, hole);
128
+ if (own !== undefined) return own;
129
+ return hole.type === "html" ? minifyDocument(source) : undefined;
130
+ };
116
131
  /**
117
132
  * @param {string} text a whole document
118
133
  * @returns {Promise<string>} the same document, printed
119
134
  */
120
- const printDocument = async (text) =>
121
- (
135
+ const printDocument = async (text) => {
136
+ // The built-in renderer is synchronous, so with no caller's renderer only
137
+ // a nested document needs the async pass — and no `srcdoc`, none is there.
138
+ if (renderEmbeddedSource === undefined && !/srcdoc/i.test(text)) {
139
+ return new SourceProcessor().process(text, {
140
+ ...printOptions,
141
+ renderEmbeddedSource: builtin
142
+ }).code;
143
+ }
144
+ return (
122
145
  await new SourceProcessor().processAsync(text, {
123
146
  ...printOptions,
124
- // The pre-pass below minifies the document an `<iframe srcdoc>` holds,
125
- // so one is not offered here as well.
126
- deferSrcdoc: !ownsSrcdoc,
127
147
  renderEmbeddedSource: renderer
128
148
  })
129
149
  ).code;
150
+ };
130
151
 
131
152
  // Recursion goes through this local name, never the module's own: the plugin
132
153
  // ships this function to its workers as source, where that binding is absent.
@@ -140,94 +161,49 @@ const htmlMinify = async (input, sourceMap, minimizerOptions = {}) => {
140
161
  // Put back into the source, not the output: the printer respells an
141
162
  // attribute value, so the recorded text is not what the output holds.
142
163
  let source = text;
143
- // Both are markup this parse cannot start a second one over, so both are
144
- // located in one walk and spliced afterwards. Their ranges never nest: a
145
- // `srcdoc` is an attribute value and a conditional comment's body is a
146
- // comment, neither of which this parse reads as markup.
147
- const wantsSrcdoc = Boolean(minifySrcdoc) && /srcdoc\s*=/i.test(source);
164
+ // A conditional comment's body is markup this parse cannot start a second
165
+ // one over, so each is located in a walk and spliced afterwards.
148
166
  const wantsConditional =
149
167
  Boolean(minifyConditionalComments) && /<!--\[if\s/i.test(source);
150
168
 
151
- if (wantsSrcdoc || wantsConditional) {
152
- /** @type {{ start: number, end: number, srcdoc: boolean, value: string }[]} */
169
+ if (wantsConditional) {
170
+ /** @type {{ start: number, end: number, value: string }[]} */
153
171
  const found = [];
154
172
  /** @type {{ [type: number]: (path: EXPECTED_ANY) => void }} */
155
173
  const visitors = {};
156
174
 
157
- if (wantsSrcdoc) {
158
- visitors[NodeType.Element] = (path) => {
159
- // An `<iframe>` in foreign content is an SVG or MathML element that
160
- // happens to share the name, and its `srcdoc` is not this attribute.
161
- if (path.tagName() !== "iframe" || path.namespace() !== NS_HTML) {
162
- return;
163
- }
164
-
165
- for (const attribute of path.attributes()) {
166
- if (attribute.name !== "srcdoc" || attribute.value === "") continue;
167
-
168
- found.push({
169
- start: attribute.valueStart,
170
- end: attribute.valueEnd,
171
- srcdoc: true,
172
- value: attribute.value
173
- });
174
- }
175
- };
176
- }
175
+ visitors[NodeType.Comment] = (path) => {
176
+ const comment = path.source();
177
+ const opened = comment.indexOf("]>");
178
+ const closes = comment.lastIndexOf("<![endif]");
177
179
 
178
- if (wantsConditional) {
179
- visitors[NodeType.Comment] = (path) => {
180
- const comment = path.source();
181
- const opened = comment.indexOf("]>");
182
- const closes = comment.lastIndexOf("<![endif]");
180
+ if (
181
+ !/^<!--\[if\s/i.test(comment) ||
182
+ opened === -1 ||
183
+ closes <= opened
184
+ ) {
185
+ return;
186
+ }
183
187
 
184
- if (
185
- !/^<!--\[if\s/i.test(comment) ||
186
- opened === -1 ||
187
- closes <= opened
188
- ) {
189
- return;
190
- }
188
+ const start = path.start() + opened + 2;
189
+ const end = path.start() + closes;
191
190
 
192
- const start = path.start() + opened + 2;
193
- const end = path.start() + closes;
194
-
195
- found.push({
196
- start,
197
- end,
198
- srcdoc: false,
199
- value: comment.slice(opened + 2, closes)
200
- });
201
- };
202
- }
191
+ found.push({
192
+ start,
193
+ end,
194
+ value: comment.slice(opened + 2, closes)
195
+ });
196
+ };
203
197
 
204
198
  new SourceProcessor().use(visitors).process(source, {});
205
- // An element's attributes are visited where the element is, so the two
206
- // kinds do not arrive interleaved by position on their own.
207
- found.sort((a, b) => a.start - b.start);
208
199
 
209
200
  // Back to front, so an earlier splice does not move a later range.
210
201
  for (let i = found.length - 1; i >= 0; i--) {
211
- const { start, end, srcdoc, value } = found[i];
202
+ const { start, end, value } = found[i];
212
203
  // Sequential: a later splice must not move an earlier range.
204
+ const inner = await minifyDocument(value);
213
205
 
214
- const inner = await minifyDocument(
215
- srcdoc ? decodeEntities(value, true) : value
216
- );
217
- let written = inner;
218
-
219
- if (srcdoc) {
220
- // A document is not something an unquoted value can hold — a space
221
- // or a `>` in it would end the attribute — so one written bare gets
222
- // quotes.
223
- const delimiter = source.charCodeAt(start - 1);
224
- const quoted = delimiter === 34 || delimiter === 39;
225
- const escaped = escapeAttribute(inner, quoted ? delimiter : 34, true);
226
-
227
- written = quoted ? escaped : `"${escaped}"`;
228
- }
229
-
230
- source = `${source.slice(0, start)}${written}${source.slice(end)}`;
206
+ source = `${source.slice(0, start)}${inner}${source.slice(end)}`;
231
207
  }
232
208
  }
233
209
  // `process` parses once, and with `mode: "minify"` its walk also prints the
@@ -255,24 +231,19 @@ htmlMinify.getTypes = () => ["html"];
255
231
 
256
232
  /**
257
233
  * The languages this can offer a caller through `renderEmbeddedSource` — an
258
- * inline `<style>`, a `<script>`, an `<svg>` subtree and the document an
259
- * `<iframe srcdoc>` holds, less the one `minifySrcdoc` keeps to itself. A
260
- * `style=""` is not among them: how the attribute is written is decided by
261
- * reading the minified text back, so it stays with the built-in CSS minifier,
262
- * which is webpack's own `cssMinify`.
263
- * @param {{ minifySrcdoc?: boolean }=} minimizerOptions the options this will run with
234
+ * inline `<style>`, a `<script>`, every event handler attribute (as the
235
+ * function body it is), an `<svg>` subtree and the document an
236
+ * `<iframe srcdoc>` holds, and every `style=""` as the block's contents it is.
264
237
  * @returns {string[]} the languages
265
238
  */
266
- htmlMinify.getEmbeddedTypes = (minimizerOptions = {}) => {
239
+ htmlMinify.getEmbeddedTypes = () => {
267
240
  /** @type {string[]} */
268
241
  const languages =
269
242
  /** @type {typeof import("../index")} */
270
243
  // eslint-disable-next-line import/no-extraneous-dependencies -- webpack self-require, as the body does
271
244
  require(/** @type {string} */ ("webpack")).html.syntax.EMBEDDED_LANGUAGES;
272
245
 
273
- return minimizerOptions.minifySrcdoc
274
- ? languages.filter((language) => language !== "html")
275
- : languages;
246
+ return languages;
276
247
  };
277
248
 
278
249
  // When several minify functions share one `minimizer-webpack-plugin` instance,