source: frontend/node_modules/webpack/lib/javascript/JavascriptModulesPlugin.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 64.9 KB
RevLine 
[9af201e]1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const vm = require("vm");
9const eslintScope = require("eslint-scope");
10const { SyncBailHook, SyncHook, SyncWaterfallHook } = require("tapable");
11const {
12 CachedSource,
13 ConcatSource,
14 OriginalSource,
15 PrefixSource,
16 RawSource,
17 ReplaceSource
18} = require("webpack-sources");
19const Compilation = require("../Compilation");
20const HotUpdateChunk = require("../HotUpdateChunk");
21const InitFragment = require("../InitFragment");
22const { JAVASCRIPT_TYPE } = require("../ModuleSourceTypeConstants");
23const {
24 JAVASCRIPT_MODULE_TYPE_AUTO,
25 JAVASCRIPT_MODULE_TYPE_DYNAMIC,
26 JAVASCRIPT_MODULE_TYPE_ESM,
27 WEBPACK_MODULE_TYPE_RUNTIME
28} = require("../ModuleTypeConstants");
29const NormalModule = require("../NormalModule");
30const RuntimeGlobals = require("../RuntimeGlobals");
31const Template = require("../Template");
32const { tryRunOrWebpackError } = require("../errors/HookWebpackError");
33const { last, someInIterable } = require("../util/IterableHelpers");
34const StringXor = require("../util/StringXor");
35const { compareModulesByFullName } = require("../util/comparators");
36const {
37 RESERVED_NAMES,
38 addScopeSymbols,
39 findNewName,
40 getAllReferences,
41 getPathInAst,
42 getUsedNamesInScopeInfo
43} = require("../util/concatenate");
44const createHash = require("../util/createHash");
45const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
46const removeBOM = require("../util/removeBOM");
47const { intersectRuntime } = require("../util/runtime");
48const JavascriptGenerator = require("./JavascriptGenerator");
49const JavascriptParser = require("./JavascriptParser");
50
51/** @typedef {import("estree").Program} Program */
52/** @typedef {import("estree").Node} Node */
53/** @typedef {import("estree").Identifier} Identifier */
54/** @typedef {import("estree").CatchClause} CatchClause */
55/** @typedef {import("estree").ClassDeclaration} ClassDeclaration */
56/** @typedef {import("estree").ClassExpression} ClassExpression */
57/** @typedef {import("estree").FunctionDeclaration} FunctionDeclaration */
58/** @typedef {import("estree").FunctionExpression} FunctionExpression */
59/** @typedef {import("estree").ArrowFunctionExpression} ArrowFunctionExpression */
60/** @typedef {import("estree").VariableDeclarator} VariableDeclarator */
61/** @typedef {import("estree").VariableDeclaration} VariableDeclaration */
62/** @typedef {import("estree").ImportDeclaration} ImportDeclaration */
63/** @typedef {import("estree").ImportSpecifier} ImportSpecifier */
64/** @typedef {import("estree").ImportDefaultSpecifier} ImportDefaultSpecifier */
65/** @typedef {import("estree").ImportNamespaceSpecifier} ImportNamespaceSpecifier */
66/** @typedef {import("estree").AssignmentExpression} AssignmentExpression */
67/** @typedef {import("estree").ForInStatement} ForInStatement */
68/** @typedef {import("estree").ForOfStatement} ForOfStatement */
69/** @typedef {import("webpack-sources").Source} Source */
70/** @typedef {import("../config/defaults").OutputNormalizedWithDefaults} OutputOptions */
71/** @typedef {import("../Chunk")} Chunk */
72/** @typedef {import("../ChunkGraph")} ChunkGraph */
73/** @typedef {import("../ChunkGraph").EntryModuleWithChunkGroup} EntryModuleWithChunkGroup */
74/** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
75/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
76/** @typedef {import("../Compilation").ExecuteModuleObject} ExecuteModuleObject */
77/** @typedef {import("../Compilation").WebpackRequire} WebpackRequire */
78/** @typedef {import("../Compiler")} Compiler */
79/** @typedef {import("../DependencyTemplates")} DependencyTemplates */
80/** @typedef {import("../Entrypoint")} Entrypoint */
81/** @typedef {import("../Module")} Module */
82/** @typedef {import("../Module").BuildInfo} BuildInfo */
83/** @typedef {import("../Module").CodeGenerationResultData} CodeGenerationResultData */
84/** @typedef {import("../ModuleGraph")} ModuleGraph */
85/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
86/** @typedef {import("../Chunk").ChunkFilenameTemplate} ChunkFilenameTemplate */
87/** @typedef {import("../errors/WebpackError")} WebpackError */
88/** @typedef {import("../javascript/JavascriptParser").Range} Range */
89/** @typedef {import("../util/Hash")} Hash */
90/** @typedef {import("../util/concatenate").ScopeSet} ScopeSet */
91/** @typedef {import("../util/concatenate").UsedNamesInScopeInfo} UsedNamesInScopeInfo */
92
93// TODO remove these types when we will update `eslint-scope` to the latest version and import them from `eslint-scope`
94/**
95 * @typedef {object} Scope
96 * @property {"block" | "catch" | "class" | "class-field-initializer" | "class-static-block" | "for" | "function" | "function-expression-name" | "global" | "module" | "switch" | "with" | "TDZ"} type
97 * @property {boolean} isStrict
98 * @property {Scope | null} upper
99 * @property {Scope[]} childScopes
100 * @property {Scope} variableScope
101 * @property {Node} block
102 * @property {Variable[]} variables
103 * @property {Map<string, Variable>} set
104 * @property {Reference[]} references
105 * @property {Reference[]} through
106 * @property {boolean} functionExpressionScope
107 * @property {{ variables: Variable[], set: Map<string, Variable> }=} implicit
108 */
109
110/**
111 * @typedef {
112 * | { type: "CatchClause", node: CatchClause, parent: null }
113 * | { type: "ClassName", node: ClassDeclaration | ClassExpression, parent: null }
114 * | { type: "FunctionName", node: FunctionDeclaration | FunctionExpression, parent: null }
115 * | { type: "ImplicitGlobalVariable", node: AssignmentExpression | ForInStatement | ForOfStatement, parent: null }
116 * | { type: "ImportBinding", node: ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier, parent: ImportDeclaration }
117 * | { type: "Parameter", node: FunctionDeclaration | FunctionExpression | ArrowFunctionExpression, parent: null }
118 * | { type: "TDZ", node: any, parent: null }
119 * | { type: "Variable", node: VariableDeclarator, parent: VariableDeclaration }
120 * } DefinitionType
121 */
122
123/** @typedef {DefinitionType & { name: Identifier }} Definition */
124
125/**
126 * @typedef {object} Variable
127 * @property {string} name
128 * @property {Scope} scope
129 * @property {Identifier[]} identifiers
130 * @property {Reference[]} references
131 * @property {Definition[]} defs
132 */
133
134/**
135 * @typedef {object} Reference
136 * @property {Identifier} identifier
137 * @property {Scope} from
138 * @property {Variable | null} resolved
139 * @property {Node | null} writeExpr
140 * @property {boolean} init
141 * @property {() => boolean} isWrite
142 * @property {() => boolean} isRead
143 * @property {() => boolean} isWriteOnly
144 * @property {() => boolean} isReadOnly
145 * @property {() => boolean} isReadWrite
146 */
147
148/** @type {WeakMap<ChunkGraph, WeakMap<Chunk, boolean>>} */
149const chunkHasJsCache = new WeakMap();
150
151/**
152 * Returns true, when a JS file is needed for this chunk.
153 * @param {Chunk} chunk a chunk
154 * @param {ChunkGraph} chunkGraph the chunk graph
155 * @returns {boolean} true, when a JS file is needed for this chunk
156 */
157const _chunkHasJs = (chunk, chunkGraph) => {
158 if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
159 for (const module of chunkGraph.getChunkEntryModulesIterable(chunk)) {
160 if (chunkGraph.getModuleSourceTypes(module).has(JAVASCRIPT_TYPE)) {
161 return true;
162 }
163 }
164 }
165
166 return Boolean(
167 chunkGraph.getChunkModulesIterableBySourceType(chunk, JAVASCRIPT_TYPE)
168 );
169};
170
171/**
172 * Returns true, when a JS file is needed for this chunk.
173 * @param {Chunk} chunk a chunk
174 * @param {ChunkGraph} chunkGraph the chunk graph
175 * @returns {boolean} true, when a JS file is needed for this chunk
176 */
177const chunkHasJs = (chunk, chunkGraph) => {
178 let innerCache = chunkHasJsCache.get(chunkGraph);
179 if (innerCache === undefined) {
180 innerCache = new WeakMap();
181 chunkHasJsCache.set(chunkGraph, innerCache);
182 }
183
184 const cachedResult = innerCache.get(chunk);
185 if (cachedResult !== undefined) {
186 return cachedResult;
187 }
188
189 const result = _chunkHasJs(chunk, chunkGraph);
190 innerCache.set(chunk, result);
191 return result;
192};
193
194/**
195 * Chunk has runtime or js.
196 * @param {Chunk} chunk a chunk
197 * @param {ChunkGraph} chunkGraph the chunk graph
198 * @returns {boolean} true, when a JS file is needed for this chunk
199 */
200const chunkHasRuntimeOrJs = (chunk, chunkGraph) => {
201 if (chunkHasJs(chunk, chunkGraph)) {
202 return true;
203 }
204
205 if (
206 chunkGraph.getChunkModulesIterableBySourceType(
207 chunk,
208 WEBPACK_MODULE_TYPE_RUNTIME
209 )
210 ) {
211 for (const chunkGroup of chunk.groupsIterable) {
212 for (const c of chunkGroup.chunks) {
213 if (chunkHasJs(c, chunkGraph)) return true;
214 }
215 }
216 return false;
217 }
218
219 return false;
220};
221
222/**
223 * Print generated code for stack.
224 * @param {Module} module a module
225 * @param {string} code the code
226 * @returns {string} generated code for the stack
227 */
228const printGeneratedCodeForStack = (module, code) => {
229 const lines = code.split("\n");
230 const n = `${lines.length}`.length;
231 return `\n\nGenerated code for ${module.identifier()}\n${lines
232 .map(
233 /**
234 * Handles the callback logic for this hook.
235 * @param {string} line the line
236 * @param {number} i the index
237 * @param {string[]} _lines the lines
238 * @returns {string} the line with line number
239 */
240 (line, i, _lines) => {
241 const iStr = `${i + 1}`;
242 return `${" ".repeat(n - iStr.length)}${iStr} | ${line}`;
243 }
244 )
245 .join("\n")}`;
246};
247
248/**
249 * Defines the render context type used by this module.
250 * @typedef {object} RenderContext
251 * @property {Chunk} chunk the chunk
252 * @property {DependencyTemplates} dependencyTemplates the dependency templates
253 * @property {RuntimeTemplate} runtimeTemplate the runtime template
254 * @property {ModuleGraph} moduleGraph the module graph
255 * @property {ChunkGraph} chunkGraph the chunk graph
256 * @property {CodeGenerationResults} codeGenerationResults results of code generation
257 * @property {boolean | undefined} strictMode rendering in strict context
258 */
259
260/**
261 * Defines the main render context type used by this module.
262 * @typedef {object} MainRenderContext
263 * @property {Chunk} chunk the chunk
264 * @property {DependencyTemplates} dependencyTemplates the dependency templates
265 * @property {RuntimeTemplate} runtimeTemplate the runtime template
266 * @property {ModuleGraph} moduleGraph the module graph
267 * @property {ChunkGraph} chunkGraph the chunk graph
268 * @property {CodeGenerationResults} codeGenerationResults results of code generation
269 * @property {string} hash hash to be used for render call
270 * @property {boolean | undefined} strictMode rendering in strict context
271 */
272
273/**
274 * Defines the chunk render context type used by this module.
275 * @typedef {object} ChunkRenderContext
276 * @property {Chunk} chunk the chunk
277 * @property {DependencyTemplates} dependencyTemplates the dependency templates
278 * @property {RuntimeTemplate} runtimeTemplate the runtime template
279 * @property {ModuleGraph} moduleGraph the module graph
280 * @property {ChunkGraph} chunkGraph the chunk graph
281 * @property {CodeGenerationResults} codeGenerationResults results of code generation
282 * @property {InitFragment<ChunkRenderContext>[]} chunkInitFragments init fragments for the chunk
283 * @property {boolean | undefined} strictMode rendering in strict context
284 */
285
286/**
287 * Defines the render bootstrap context type used by this module.
288 * @typedef {object} RenderBootstrapContext
289 * @property {Chunk} chunk the chunk
290 * @property {CodeGenerationResults} codeGenerationResults results of code generation
291 * @property {RuntimeTemplate} runtimeTemplate the runtime template
292 * @property {ModuleGraph} moduleGraph the module graph
293 * @property {ChunkGraph} chunkGraph the chunk graph
294 * @property {string} hash hash to be used for render call
295 */
296
297/**
298 * Defines the startup render context type used by this module.
299 * @typedef {object} StartupRenderContext
300 * @property {Chunk} chunk the chunk
301 * @property {DependencyTemplates} dependencyTemplates the dependency templates
302 * @property {RuntimeTemplate} runtimeTemplate the runtime template
303 * @property {ModuleGraph} moduleGraph the module graph
304 * @property {ChunkGraph} chunkGraph the chunk graph
305 * @property {CodeGenerationResults} codeGenerationResults results of code generation
306 * @property {boolean | undefined} strictMode rendering in strict context
307 * @property {boolean=} inlined inlined
308 * @property {boolean=} inlinedInIIFE the inlined entry module is wrapped in an IIFE
309 * @property {boolean=} needExportsDeclaration whether the top-level exports declaration needs to be generated
310 */
311
312/**
313 * Defines the module render context type used by this module.
314 * @typedef {object} ModuleRenderContext
315 * @property {Chunk} chunk the chunk
316 * @property {DependencyTemplates} dependencyTemplates the dependency templates
317 * @property {RuntimeTemplate} runtimeTemplate the runtime template
318 * @property {ModuleGraph} moduleGraph the module graph
319 * @property {ChunkGraph} chunkGraph the chunk graph
320 * @property {CodeGenerationResults} codeGenerationResults results of code generation
321 * @property {InitFragment<ChunkRenderContext>[]} chunkInitFragments init fragments for the chunk
322 * @property {boolean | undefined} strictMode rendering in strict context
323 * @property {boolean} factory true: renders as factory method, false: pure module content
324 * @property {boolean=} inlinedInIIFE the inlined entry module is wrapped in an IIFE, existing only when `factory` is set to false
325 * @property {boolean=} renderInObject render module in object container
326 */
327
328/**
329 * Defines the compilation hooks type used by this module.
330 * @typedef {object} CompilationHooks
331 * @property {SyncWaterfallHook<[Source, Module, ModuleRenderContext]>} renderModuleContent
332 * @property {SyncWaterfallHook<[Source, Module, ModuleRenderContext]>} renderModuleContainer
333 * @property {SyncWaterfallHook<[Source, Module, ModuleRenderContext]>} renderModulePackage
334 * @property {SyncWaterfallHook<[Source, RenderContext]>} renderChunk
335 * @property {SyncWaterfallHook<[Source, RenderContext]>} renderMain
336 * @property {SyncWaterfallHook<[Source, RenderContext]>} renderContent
337 * @property {SyncWaterfallHook<[Source, RenderContext]>} render
338 * @property {SyncWaterfallHook<[Source, Module, StartupRenderContext]>} renderStartup
339 * @property {SyncWaterfallHook<[string, RenderBootstrapContext]>} renderRequire
340 * @property {SyncBailHook<[Module, Partial<RenderBootstrapContext>], string | void>} inlineInRuntimeBailout
341 * @property {SyncBailHook<[Module, RenderContext], string | void>} embedInRuntimeBailout
342 * @property {SyncBailHook<[RenderContext], string | void>} strictRuntimeBailout
343 * @property {SyncHook<[Chunk, Hash, ChunkHashContext]>} chunkHash
344 * @property {SyncBailHook<[Chunk, RenderContext], boolean | void>} useSourceMap
345 */
346
347/** @type {WeakMap<Compilation, CompilationHooks>} */
348const compilationHooksMap = new WeakMap();
349
350const PLUGIN_NAME = "JavascriptModulesPlugin";
351
352/** @typedef {{ header: string[], beforeStartup: string[], startup: string[], afterStartup: string[], allowInlineStartup: boolean }} Bootstrap */
353
354class JavascriptModulesPlugin {
355 /**
356 * Returns the attached hooks.
357 * @param {Compilation} compilation the compilation
358 * @returns {CompilationHooks} the attached hooks
359 */
360 static getCompilationHooks(compilation) {
361 if (!(compilation instanceof Compilation)) {
362 throw new TypeError(
363 "The 'compilation' argument must be an instance of Compilation"
364 );
365 }
366 let hooks = compilationHooksMap.get(compilation);
367 if (hooks === undefined) {
368 hooks = {
369 renderModuleContent: new SyncWaterfallHook([
370 "source",
371 "module",
372 "moduleRenderContext"
373 ]),
374 renderModuleContainer: new SyncWaterfallHook([
375 "source",
376 "module",
377 "moduleRenderContext"
378 ]),
379 renderModulePackage: new SyncWaterfallHook([
380 "source",
381 "module",
382 "moduleRenderContext"
383 ]),
384 render: new SyncWaterfallHook(["source", "renderContext"]),
385 renderContent: new SyncWaterfallHook(["source", "renderContext"]),
386 renderStartup: new SyncWaterfallHook([
387 "source",
388 "module",
389 "startupRenderContext"
390 ]),
391 renderChunk: new SyncWaterfallHook(["source", "renderContext"]),
392 renderMain: new SyncWaterfallHook(["source", "renderContext"]),
393 renderRequire: new SyncWaterfallHook(["code", "renderContext"]),
394 inlineInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
395 embedInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
396 strictRuntimeBailout: new SyncBailHook(["renderContext"]),
397 chunkHash: new SyncHook(["chunk", "hash", "context"]),
398 useSourceMap: new SyncBailHook(["chunk", "renderContext"])
399 };
400 compilationHooksMap.set(compilation, hooks);
401 }
402 return hooks;
403 }
404
405 constructor(options = {}) {
406 this.options = options;
407 /** @type {WeakMap<Source, { source: Source, needModule: boolean, needExports: boolean, needRequire: boolean, needThisAsExports: boolean, needStrict: boolean | undefined, renderShorthand: boolean }>} */
408 this._moduleFactoryCache = new WeakMap();
409 }
410
411 /**
412 * Applies the plugin by registering its hooks on the compiler.
413 * @param {Compiler} compiler the compiler instance
414 * @returns {void}
415 */
416 apply(compiler) {
417 compiler.hooks.compilation.tap(
418 PLUGIN_NAME,
419 (compilation, { normalModuleFactory }) => {
420 const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
421
422 for (const type of [
423 JAVASCRIPT_MODULE_TYPE_AUTO,
424 JAVASCRIPT_MODULE_TYPE_DYNAMIC,
425 JAVASCRIPT_MODULE_TYPE_ESM
426 ]) {
427 normalModuleFactory.hooks.createParser
428 .for(type)
429 .tap(PLUGIN_NAME, (options) => {
430 switch (type) {
431 case JAVASCRIPT_MODULE_TYPE_AUTO: {
432 return new JavascriptParser("auto", {
433 parse: options.parse,
434 typescript: options.typescript
435 });
436 }
437 case JAVASCRIPT_MODULE_TYPE_DYNAMIC: {
438 return new JavascriptParser("script", {
439 parse: options.parse,
440 typescript: options.typescript
441 });
442 }
443 case JAVASCRIPT_MODULE_TYPE_ESM: {
444 return new JavascriptParser("module", {
445 parse: options.parse,
446 typescript: options.typescript
447 });
448 }
449 }
450 });
451 normalModuleFactory.hooks.createGenerator
452 .for(type)
453 .tap(PLUGIN_NAME, () => new JavascriptGenerator());
454
455 NormalModule.getCompilationHooks(compilation).processResult.tap(
456 PLUGIN_NAME,
457 (result, module) => {
458 if (module.type === type) {
459 const [source, ...rest] = result;
460
461 return [removeBOM(source), ...rest];
462 }
463
464 return result;
465 }
466 );
467 }
468
469 compilation.hooks.renderManifest.tap(PLUGIN_NAME, (result, options) => {
470 const {
471 hash,
472 chunk,
473 chunkGraph,
474 moduleGraph,
475 runtimeTemplate,
476 dependencyTemplates,
477 outputOptions,
478 codeGenerationResults
479 } = options;
480
481 const hotUpdateChunk = chunk instanceof HotUpdateChunk ? chunk : null;
482 const filenameTemplate =
483 JavascriptModulesPlugin.getChunkFilenameTemplate(
484 chunk,
485 outputOptions
486 );
487
488 /** @type {() => Source} */
489 let render;
490
491 if (hotUpdateChunk) {
492 render = () =>
493 this.renderChunk(
494 {
495 chunk,
496 dependencyTemplates,
497 runtimeTemplate,
498 moduleGraph,
499 chunkGraph,
500 codeGenerationResults,
501 strictMode: runtimeTemplate.isModule()
502 },
503 hooks
504 );
505 } else if (chunk.hasRuntime()) {
506 if (!chunkHasRuntimeOrJs(chunk, chunkGraph)) {
507 return result;
508 }
509
510 render = () =>
511 this.renderMain(
512 {
513 hash,
514 chunk,
515 dependencyTemplates,
516 runtimeTemplate,
517 moduleGraph,
518 chunkGraph,
519 codeGenerationResults,
520 strictMode: runtimeTemplate.isModule()
521 },
522 hooks,
523 compilation
524 );
525 } else {
526 if (!chunkHasJs(chunk, chunkGraph)) {
527 return result;
528 }
529
530 render = () =>
531 this.renderChunk(
532 {
533 chunk,
534 dependencyTemplates,
535 runtimeTemplate,
536 moduleGraph,
537 chunkGraph,
538 codeGenerationResults,
539 strictMode: runtimeTemplate.isModule()
540 },
541 hooks
542 );
543 }
544
545 result.push({
546 render,
547 filenameTemplate,
548 pathOptions: {
549 hash,
550 runtime: chunk.runtime,
551 chunk,
552 contentHashType: "javascript"
553 },
554 info: {
555 javascriptModule: compilation.runtimeTemplate.isModule()
556 },
557 identifier: hotUpdateChunk
558 ? `hotupdatechunk${chunk.id}`
559 : `chunk${chunk.id}`,
560 hash: chunk.contentHash.javascript
561 });
562
563 return result;
564 });
565 compilation.hooks.chunkHash.tap(PLUGIN_NAME, (chunk, hash, context) => {
566 hooks.chunkHash.call(chunk, hash, context);
567 if (chunk.hasRuntime()) {
568 this.updateHashWithBootstrap(
569 hash,
570 {
571 hash: "0000",
572 chunk,
573 codeGenerationResults: context.codeGenerationResults,
574 chunkGraph: context.chunkGraph,
575 moduleGraph: context.moduleGraph,
576 runtimeTemplate: context.runtimeTemplate
577 },
578 hooks
579 );
580 }
581 });
582 compilation.hooks.contentHash.tap(PLUGIN_NAME, (chunk) => {
583 const {
584 chunkGraph,
585 moduleGraph,
586 runtimeTemplate,
587 outputOptions: {
588 hashSalt,
589 hashDigest,
590 hashDigestLength,
591 hashFunction
592 }
593 } = compilation;
594 const codeGenerationResults =
595 /** @type {CodeGenerationResults} */
596 (compilation.codeGenerationResults);
597 const hash = createHash(hashFunction);
598 if (hashSalt) hash.update(hashSalt);
599 if (chunk.hasRuntime()) {
600 this.updateHashWithBootstrap(
601 hash,
602 {
603 hash: "0000",
604 chunk,
605 codeGenerationResults,
606 chunkGraph: compilation.chunkGraph,
607 moduleGraph: compilation.moduleGraph,
608 runtimeTemplate: compilation.runtimeTemplate
609 },
610 hooks
611 );
612 } else {
613 hash.update(`${chunk.id} `);
614 hash.update(chunk.ids ? chunk.ids.join(",") : "");
615 }
616 hooks.chunkHash.call(chunk, hash, {
617 chunkGraph,
618 codeGenerationResults,
619 moduleGraph,
620 runtimeTemplate
621 });
622 const modules = chunkGraph.getChunkModulesIterableBySourceType(
623 chunk,
624 JAVASCRIPT_TYPE
625 );
626 if (modules) {
627 const xor = new StringXor();
628 for (const m of modules) {
629 xor.add(chunkGraph.getModuleHash(m, chunk.runtime));
630 }
631 xor.updateHash(hash);
632 }
633 const runtimeModules = chunkGraph.getChunkModulesIterableBySourceType(
634 chunk,
635 WEBPACK_MODULE_TYPE_RUNTIME
636 );
637 if (runtimeModules) {
638 const xor = new StringXor();
639 for (const m of runtimeModules) {
640 xor.add(chunkGraph.getModuleHash(m, chunk.runtime));
641 }
642 xor.updateHash(hash);
643 }
644 const digest = hash.digest(hashDigest);
645 chunk.contentHash.javascript = nonNumericOnlyHash(
646 digest,
647 hashDigestLength
648 );
649 });
650 compilation.hooks.additionalTreeRuntimeRequirements.tap(
651 PLUGIN_NAME,
652 (chunk, set, { chunkGraph }) => {
653 if (
654 !set.has(RuntimeGlobals.startupNoDefault) &&
655 chunkGraph.hasChunkEntryDependentChunks(chunk)
656 ) {
657 set.add(RuntimeGlobals.onChunksLoaded);
658 set.add(RuntimeGlobals.exports);
659 set.add(RuntimeGlobals.require);
660 }
661 }
662 );
663 compilation.hooks.executeModule.tap(PLUGIN_NAME, (options, context) => {
664 const source =
665 options.codeGenerationResult.sources.get(JAVASCRIPT_TYPE);
666 if (source === undefined) return;
667 const { module } = options;
668 const code = source.source();
669
670 /** @type {(this: ExecuteModuleObject["exports"], exports: ExecuteModuleObject["exports"], moduleObject: ExecuteModuleObject, webpackRequire: WebpackRequire) => void} */
671 const fn = vm.runInThisContext(
672 `(function(${module.moduleArgument}, ${module.exportsArgument}, ${RuntimeGlobals.require}) {\n${code}\n/**/})`,
673 {
674 filename: module.identifier(),
675 lineOffset: -1
676 }
677 );
678
679 const moduleObject =
680 /** @type {ExecuteModuleObject} */
681 (options.moduleObject);
682
683 try {
684 fn.call(
685 moduleObject.exports,
686 moduleObject,
687 moduleObject.exports,
688 /** @type {WebpackRequire} */
689 (context.__webpack_require__)
690 );
691 } catch (err) {
692 /** @type {Error} */
693 (err).stack += printGeneratedCodeForStack(
694 options.module,
695 /** @type {string} */ (code)
696 );
697 throw err;
698 }
699 });
700 compilation.hooks.executeModule.tap(PLUGIN_NAME, (options, context) => {
701 const source = options.codeGenerationResult.sources.get("runtime");
702 if (source === undefined) return;
703 let code = source.source();
704 if (typeof code !== "string") code = code.toString();
705
706 /** @type {(this: null, webpackRequire: WebpackRequire) => void} */
707 const fn = vm.runInThisContext(
708 `(function(${RuntimeGlobals.require}) {\n${code}\n/**/})`,
709 {
710 filename: options.module.identifier(),
711 lineOffset: -1
712 }
713 );
714 try {
715 // eslint-disable-next-line no-useless-call
716 fn.call(
717 null,
718 /** @type {WebpackRequire} */
719 (context.__webpack_require__)
720 );
721 } catch (err) {
722 /** @type {Error} */
723 (err).stack += printGeneratedCodeForStack(options.module, code);
724 throw err;
725 }
726 });
727 }
728 );
729 }
730
731 /**
732 * Gets chunk filename template.
733 * @param {Chunk} chunk chunk
734 * @param {OutputOptions} outputOptions output options
735 * @returns {ChunkFilenameTemplate} used filename template
736 */
737 static getChunkFilenameTemplate(chunk, outputOptions) {
738 if (chunk.filenameTemplate) {
739 return chunk.filenameTemplate;
740 } else if (chunk instanceof HotUpdateChunk) {
741 return outputOptions.hotUpdateChunkFilename;
742 } else if (chunk.canBeInitial()) {
743 return outputOptions.filename;
744 }
745 return outputOptions.chunkFilename;
746 }
747
748 /**
749 * Renders the newly generated source from rendering.
750 * @param {Module} module the rendered module
751 * @param {ModuleRenderContext} renderContext options object
752 * @param {CompilationHooks} hooks hooks
753 * @returns {Source | null} the newly generated source from rendering
754 */
755 renderModule(module, renderContext, hooks) {
756 const {
757 chunk,
758 chunkGraph,
759 runtimeTemplate,
760 codeGenerationResults,
761 strictMode,
762 factory,
763 renderInObject
764 } = renderContext;
765 try {
766 const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
767 const moduleSource = codeGenResult.sources.get(JAVASCRIPT_TYPE);
768 if (!moduleSource) return null;
769 if (codeGenResult.data !== undefined) {
770 const chunkInitFragments = codeGenResult.data.get("chunkInitFragments");
771 if (chunkInitFragments) {
772 for (const i of chunkInitFragments) {
773 renderContext.chunkInitFragments.push(i);
774 }
775 }
776 }
777 const moduleSourcePostContent = tryRunOrWebpackError(
778 () =>
779 hooks.renderModuleContent.call(moduleSource, module, renderContext),
780 "JavascriptModulesPlugin.getCompilationHooks().renderModuleContent"
781 );
782 /** @type {Source} */
783 let moduleSourcePostContainer;
784 if (factory) {
785 const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
786 module,
787 chunk.runtime
788 );
789 const needModule = runtimeRequirements.has(RuntimeGlobals.module);
790 const needExports = runtimeRequirements.has(RuntimeGlobals.exports);
791 const needRequire =
792 runtimeRequirements.has(RuntimeGlobals.require) ||
793 runtimeRequirements.has(RuntimeGlobals.requireScope);
794 const needThisAsExports = runtimeRequirements.has(
795 RuntimeGlobals.thisAsExports
796 );
797 const needStrict =
798 /** @type {BuildInfo} */
799 (module.buildInfo).strict && !strictMode;
800 const cacheEntry = this._moduleFactoryCache.get(
801 moduleSourcePostContent
802 );
803 const renderShorthand =
804 renderInObject === true && runtimeTemplate.supportsMethodShorthand();
805 /** @type {Source} */
806 let source;
807 if (
808 cacheEntry &&
809 cacheEntry.needModule === needModule &&
810 cacheEntry.needExports === needExports &&
811 cacheEntry.needRequire === needRequire &&
812 cacheEntry.needThisAsExports === needThisAsExports &&
813 cacheEntry.needStrict === needStrict &&
814 cacheEntry.renderShorthand === renderShorthand
815 ) {
816 source = cacheEntry.source;
817 } else {
818 const factorySource = new ConcatSource();
819 /** @type {string[]} */
820 const args = [];
821 if (needExports || needRequire || needModule) {
822 args.push(
823 needModule
824 ? module.moduleArgument
825 : `__unused_webpack_${module.moduleArgument}`
826 );
827 }
828 if (needExports || needRequire) {
829 args.push(
830 needExports
831 ? module.exportsArgument
832 : `__unused_webpack_${module.exportsArgument}`
833 );
834 }
835 if (needRequire) args.push(RuntimeGlobals.require);
836
837 if (renderShorthand) {
838 // we can optimize function to methodShorthand if render module factory in object
839 factorySource.add(`(${args.join(", ")}) {\n\n`);
840 } else if (
841 !needThisAsExports &&
842 runtimeTemplate.supportsArrowFunction()
843 ) {
844 factorySource.add(`/***/ ((${args.join(", ")}) => {\n\n`);
845 } else {
846 factorySource.add(`/***/ (function(${args.join(", ")}) {\n\n`);
847 }
848
849 if (needStrict) {
850 factorySource.add('"use strict";\n');
851 }
852 factorySource.add(moduleSourcePostContent);
853 factorySource.add(`\n\n/***/ }${renderShorthand ? "" : ")"}`);
854 source = new CachedSource(factorySource);
855 this._moduleFactoryCache.set(moduleSourcePostContent, {
856 source,
857 needModule,
858 needExports,
859 needRequire,
860 needThisAsExports,
861 needStrict,
862 renderShorthand
863 });
864 }
865 moduleSourcePostContainer = tryRunOrWebpackError(
866 () => hooks.renderModuleContainer.call(source, module, renderContext),
867 "JavascriptModulesPlugin.getCompilationHooks().renderModuleContainer"
868 );
869 } else {
870 moduleSourcePostContainer = moduleSourcePostContent;
871 }
872 return tryRunOrWebpackError(
873 () =>
874 hooks.renderModulePackage.call(
875 moduleSourcePostContainer,
876 module,
877 renderContext
878 ),
879 "JavascriptModulesPlugin.getCompilationHooks().renderModulePackage"
880 );
881 } catch (err) {
882 /** @type {WebpackError} */
883 (err).module = module;
884 throw err;
885 }
886 }
887
888 /**
889 * Renders the rendered source.
890 * @param {RenderContext} renderContext the render context
891 * @param {CompilationHooks} hooks hooks
892 * @returns {Source} the rendered source
893 */
894 renderChunk(renderContext, hooks) {
895 const { chunk, chunkGraph, runtimeTemplate } = renderContext;
896 const modules = chunkGraph.getOrderedChunkModulesIterableBySourceType(
897 chunk,
898 JAVASCRIPT_TYPE,
899 compareModulesByFullName(runtimeTemplate.compilation.compiler)
900 );
901 const allModules = modules ? [...modules] : [];
902 /** @type {undefined | string} */
903 let strictHeader;
904 let allStrict = renderContext.strictMode;
905 if (
906 !allStrict &&
907 allModules.every((m) => /** @type {BuildInfo} */ (m.buildInfo).strict)
908 ) {
909 const strictBailout = hooks.strictRuntimeBailout.call(renderContext);
910 strictHeader = strictBailout
911 ? `// runtime can't be in strict mode because ${strictBailout}.\n`
912 : '"use strict";\n';
913 if (!strictBailout) allStrict = true;
914 }
915 /** @type {ChunkRenderContext} */
916 const chunkRenderContext = {
917 ...renderContext,
918 chunkInitFragments: [],
919 strictMode: allStrict
920 };
921 const moduleSources =
922 Template.renderChunkModules(
923 chunkRenderContext,
924 allModules,
925 (module, renderInObject) =>
926 this.renderModule(
927 module,
928 { ...chunkRenderContext, factory: true, renderInObject },
929 hooks
930 )
931 ) || new RawSource("{}");
932 let source = tryRunOrWebpackError(
933 () => hooks.renderChunk.call(moduleSources, chunkRenderContext),
934 "JavascriptModulesPlugin.getCompilationHooks().renderChunk"
935 );
936 source = tryRunOrWebpackError(
937 () => hooks.renderContent.call(source, chunkRenderContext),
938 "JavascriptModulesPlugin.getCompilationHooks().renderContent"
939 );
940 if (!source) {
941 throw new Error(
942 "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderContent plugins should return something"
943 );
944 }
945 source = InitFragment.addToSource(
946 source,
947 chunkRenderContext.chunkInitFragments,
948 chunkRenderContext
949 );
950 source = tryRunOrWebpackError(
951 () => hooks.render.call(source, chunkRenderContext),
952 "JavascriptModulesPlugin.getCompilationHooks().render"
953 );
954 if (!source) {
955 throw new Error(
956 "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().render plugins should return something"
957 );
958 }
959 chunk.rendered = true;
960 return strictHeader
961 ? new ConcatSource(strictHeader, source, ";")
962 : renderContext.runtimeTemplate.isModule()
963 ? source
964 : new ConcatSource(source, ";");
965 }
966
967 /**
968 * Renders the newly generated source from rendering.
969 * @param {MainRenderContext} renderContext options object
970 * @param {CompilationHooks} hooks hooks
971 * @param {Compilation} compilation the compilation
972 * @returns {Source} the newly generated source from rendering
973 */
974 renderMain(renderContext, hooks, compilation) {
975 const { chunk, chunkGraph, runtimeTemplate } = renderContext;
976
977 const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
978 const iife = runtimeTemplate.isIIFE();
979
980 const bootstrap = this.renderBootstrap(renderContext, hooks);
981 const useSourceMap = hooks.useSourceMap.call(chunk, renderContext);
982
983 /** @type {Module[]} */
984 const allModules = [
985 ...(chunkGraph.getOrderedChunkModulesIterableBySourceType(
986 chunk,
987 JAVASCRIPT_TYPE,
988 compareModulesByFullName(runtimeTemplate.compilation.compiler)
989 ) || [])
990 ];
991
992 const hasEntryModules = chunkGraph.getNumberOfEntryModules(chunk) > 0;
993 /** @type {Set<Module> | undefined} */
994 let inlinedModules;
995 if (bootstrap.allowInlineStartup && hasEntryModules) {
996 inlinedModules = new Set(chunkGraph.getChunkEntryModulesIterable(chunk));
997 }
998
999 const source = new ConcatSource();
1000 /** @type {string} */
1001 let prefix;
1002 if (iife) {
1003 if (runtimeTemplate.supportsArrowFunction()) {
1004 source.add("/******/ (() => { // webpackBootstrap\n");
1005 } else {
1006 source.add("/******/ (function() { // webpackBootstrap\n");
1007 }
1008 prefix = "/******/ \t";
1009 } else {
1010 prefix = "/******/ ";
1011 }
1012 let allStrict = renderContext.strictMode;
1013 if (
1014 !allStrict &&
1015 allModules.every((m) => /** @type {BuildInfo} */ (m.buildInfo).strict)
1016 ) {
1017 const strictBailout = hooks.strictRuntimeBailout.call(renderContext);
1018 if (strictBailout) {
1019 source.add(
1020 `${
1021 prefix
1022 }// runtime can't be in strict mode because ${strictBailout}.\n`
1023 );
1024 } else {
1025 allStrict = true;
1026 source.add(`${prefix}"use strict";\n`);
1027 }
1028 }
1029
1030 /** @type {ChunkRenderContext} */
1031 const chunkRenderContext = {
1032 ...renderContext,
1033 chunkInitFragments: [],
1034 strictMode: allStrict
1035 };
1036
1037 const chunkModules = Template.renderChunkModules(
1038 chunkRenderContext,
1039 inlinedModules
1040 ? allModules.filter(
1041 (m) => !(/** @type {Set<Module>} */ (inlinedModules).has(m))
1042 )
1043 : allModules,
1044 (module, renderInObject) =>
1045 this.renderModule(
1046 module,
1047 { ...chunkRenderContext, factory: true, renderInObject },
1048 hooks
1049 ),
1050 prefix
1051 );
1052 if (
1053 chunkModules ||
1054 runtimeRequirements.has(RuntimeGlobals.moduleFactories) ||
1055 runtimeRequirements.has(RuntimeGlobals.moduleFactoriesAddOnly) ||
1056 runtimeRequirements.has(RuntimeGlobals.require)
1057 ) {
1058 source.add(`${prefix}var __webpack_modules__ = (`);
1059 source.add(chunkModules || "{}");
1060 source.add(");\n");
1061 source.add(
1062 "/************************************************************************/\n"
1063 );
1064 }
1065
1066 if (bootstrap.header.length > 0) {
1067 const header = `${Template.asString(bootstrap.header)}\n`;
1068 source.add(
1069 new PrefixSource(
1070 prefix,
1071 useSourceMap
1072 ? new OriginalSource(header, "webpack/bootstrap")
1073 : new RawSource(header)
1074 )
1075 );
1076 source.add(
1077 "/************************************************************************/\n"
1078 );
1079 }
1080
1081 const runtimeModules =
1082 renderContext.chunkGraph.getChunkRuntimeModulesInOrder(chunk);
1083
1084 if (runtimeModules.length > 0) {
1085 source.add(
1086 new PrefixSource(
1087 prefix,
1088 Template.renderRuntimeModules(runtimeModules, chunkRenderContext)
1089 )
1090 );
1091 source.add(
1092 "/************************************************************************/\n"
1093 );
1094 // runtimeRuntimeModules calls codeGeneration
1095 for (const module of runtimeModules) {
1096 compilation.codeGeneratedModules.add(module);
1097 }
1098 }
1099 if (inlinedModules) {
1100 if (bootstrap.beforeStartup.length > 0) {
1101 const beforeStartup = `${Template.asString(bootstrap.beforeStartup)}\n`;
1102 source.add(
1103 new PrefixSource(
1104 prefix,
1105 useSourceMap
1106 ? new OriginalSource(beforeStartup, "webpack/before-startup")
1107 : new RawSource(beforeStartup)
1108 )
1109 );
1110 }
1111 const lastInlinedModule = /** @type {Module} */ (last(inlinedModules));
1112 const startupSource = new ConcatSource();
1113
1114 const avoidEntryIife = compilation.options.optimization.avoidEntryIife;
1115 /** @type {Map<Module, Source> | false} */
1116 let renamedInlinedModule = false;
1117 let inlinedInIIFE = false;
1118
1119 if (avoidEntryIife) {
1120 renamedInlinedModule = this._getRenamedInlineModule(
1121 compilation,
1122 allModules,
1123 renderContext,
1124 inlinedModules,
1125 chunkRenderContext,
1126 hooks,
1127 allStrict,
1128 Boolean(chunkModules)
1129 );
1130 }
1131
1132 for (const m of inlinedModules) {
1133 const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
1134 m,
1135 chunk.runtime
1136 );
1137 const exports = runtimeRequirements.has(RuntimeGlobals.exports);
1138 const webpackExports =
1139 exports && m.exportsArgument === RuntimeGlobals.exports;
1140
1141 const innerStrict =
1142 !allStrict && /** @type {BuildInfo} */ (m.buildInfo).strict;
1143
1144 const iife = innerStrict
1145 ? "it needs to be in strict mode."
1146 : inlinedModules.size > 1
1147 ? // TODO check globals and top-level declarations of other entries and chunk modules
1148 // to make a better decision
1149 "it needs to be isolated against other entry modules."
1150 : chunkModules && !renamedInlinedModule
1151 ? "it needs to be isolated against other modules in the chunk."
1152 : exports && !webpackExports
1153 ? `it uses a non-standard name for the exports (${m.exportsArgument}).`
1154 : hooks.embedInRuntimeBailout.call(m, renderContext);
1155
1156 if (iife) {
1157 inlinedInIIFE = true;
1158 }
1159
1160 const renderedModule = renamedInlinedModule
1161 ? renamedInlinedModule.get(m)
1162 : this.renderModule(
1163 m,
1164 {
1165 ...chunkRenderContext,
1166 factory: false,
1167 inlinedInIIFE
1168 },
1169 hooks
1170 );
1171
1172 if (renderedModule) {
1173 /** @type {string} */
1174 let footer;
1175 if (iife !== undefined) {
1176 startupSource.add(
1177 `// This entry needs to be wrapped in an IIFE because ${iife}\n`
1178 );
1179 const arrow = runtimeTemplate.supportsArrowFunction();
1180 if (arrow) {
1181 startupSource.add("(() => {\n");
1182 footer = "\n})();\n\n";
1183 } else {
1184 startupSource.add("!function() {\n");
1185 footer = "\n}();\n";
1186 }
1187 if (innerStrict) startupSource.add('"use strict";\n');
1188 } else {
1189 footer = "\n";
1190 }
1191 if (exports) {
1192 if (m !== lastInlinedModule) {
1193 startupSource.add(`var ${m.exportsArgument} = {};\n`);
1194 } else if (m.exportsArgument !== RuntimeGlobals.exports) {
1195 startupSource.add(
1196 `var ${m.exportsArgument} = ${RuntimeGlobals.exports};\n`
1197 );
1198 }
1199 }
1200 startupSource.add(renderedModule);
1201 startupSource.add(footer);
1202 }
1203 }
1204 if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
1205 startupSource.add(
1206 `${RuntimeGlobals.exports} = ${RuntimeGlobals.onChunksLoaded}(${RuntimeGlobals.exports});\n`
1207 );
1208 }
1209 /** @type {StartupRenderContext} */
1210 const startupRenderContext = {
1211 ...renderContext,
1212 inlined: true,
1213 inlinedInIIFE,
1214 needExportsDeclaration: runtimeRequirements.has(RuntimeGlobals.exports)
1215 };
1216 let renderedStartup = hooks.renderStartup.call(
1217 startupSource,
1218 lastInlinedModule,
1219 startupRenderContext
1220 );
1221 const lastInlinedModuleRequirements =
1222 chunkGraph.getModuleRuntimeRequirements(
1223 lastInlinedModule,
1224 chunk.runtime
1225 );
1226 if (
1227 // `onChunksLoaded` reads and reassigns `__webpack_exports__`
1228 runtimeRequirements.has(RuntimeGlobals.onChunksLoaded) ||
1229 // Top-level `__webpack_exports__` will be returned
1230 runtimeRequirements.has(RuntimeGlobals.returnExportsFromRuntime) ||
1231 // Custom exports argument aliases from `__webpack_exports__`
1232 (lastInlinedModuleRequirements.has(RuntimeGlobals.exports) &&
1233 lastInlinedModule.exportsArgument !== RuntimeGlobals.exports)
1234 ) {
1235 startupRenderContext.needExportsDeclaration = true;
1236 }
1237 if (startupRenderContext.needExportsDeclaration) {
1238 renderedStartup = new ConcatSource(
1239 `var ${RuntimeGlobals.exports} = {};\n`,
1240 renderedStartup
1241 );
1242 }
1243 source.add(renderedStartup);
1244 if (bootstrap.afterStartup.length > 0) {
1245 const afterStartup = `${Template.asString(bootstrap.afterStartup)}\n`;
1246 source.add(
1247 new PrefixSource(
1248 prefix,
1249 useSourceMap
1250 ? new OriginalSource(afterStartup, "webpack/after-startup")
1251 : new RawSource(afterStartup)
1252 )
1253 );
1254 }
1255 } else {
1256 const lastEntryModule =
1257 /** @type {Module} */
1258 (last(chunkGraph.getChunkEntryModulesIterable(chunk)));
1259 /** @type {(content: string[], name: string) => Source} */
1260 const toSource = useSourceMap
1261 ? (content, name) =>
1262 new OriginalSource(Template.asString(content), name)
1263 : (content) => new RawSource(Template.asString(content));
1264 source.add(
1265 new PrefixSource(
1266 prefix,
1267 new ConcatSource(
1268 toSource(bootstrap.beforeStartup, "webpack/before-startup"),
1269 "\n",
1270 hooks.renderStartup.call(
1271 toSource([...bootstrap.startup, ""], "webpack/startup"),
1272 lastEntryModule,
1273 {
1274 ...renderContext,
1275 inlined: false,
1276 needExportsDeclaration: true
1277 }
1278 ),
1279 toSource(bootstrap.afterStartup, "webpack/after-startup"),
1280 "\n"
1281 )
1282 )
1283 );
1284 }
1285 if (
1286 hasEntryModules &&
1287 runtimeRequirements.has(RuntimeGlobals.returnExportsFromRuntime)
1288 ) {
1289 source.add(`${prefix}return ${RuntimeGlobals.exports};\n`);
1290 }
1291 if (iife) {
1292 source.add("/******/ })()\n");
1293 }
1294
1295 /** @type {Source} */
1296 let finalSource = tryRunOrWebpackError(
1297 () => hooks.renderMain.call(source, renderContext),
1298 "JavascriptModulesPlugin.getCompilationHooks().renderMain"
1299 );
1300 if (!finalSource) {
1301 throw new Error(
1302 "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderMain plugins should return something"
1303 );
1304 }
1305 finalSource = tryRunOrWebpackError(
1306 () => hooks.renderContent.call(finalSource, renderContext),
1307 "JavascriptModulesPlugin.getCompilationHooks().renderContent"
1308 );
1309 if (!finalSource) {
1310 throw new Error(
1311 "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderContent plugins should return something"
1312 );
1313 }
1314
1315 finalSource = InitFragment.addToSource(
1316 finalSource,
1317 chunkRenderContext.chunkInitFragments,
1318 chunkRenderContext
1319 );
1320 finalSource = tryRunOrWebpackError(
1321 () => hooks.render.call(finalSource, renderContext),
1322 "JavascriptModulesPlugin.getCompilationHooks().render"
1323 );
1324 if (!finalSource) {
1325 throw new Error(
1326 "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().render plugins should return something"
1327 );
1328 }
1329 chunk.rendered = true;
1330 return iife ? new ConcatSource(finalSource, ";") : finalSource;
1331 }
1332
1333 /**
1334 * Updates hash with bootstrap.
1335 * @param {Hash} hash the hash to be updated
1336 * @param {RenderBootstrapContext} renderContext options object
1337 * @param {CompilationHooks} hooks hooks
1338 */
1339 updateHashWithBootstrap(hash, renderContext, hooks) {
1340 const bootstrap = this.renderBootstrap(renderContext, hooks);
1341 for (const _k of Object.keys(bootstrap)) {
1342 const key = /** @type {keyof Bootstrap} */ (_k);
1343 hash.update(key);
1344 if (Array.isArray(bootstrap[key])) {
1345 for (const line of bootstrap[key]) {
1346 hash.update(line);
1347 }
1348 } else {
1349 hash.update(JSON.stringify(bootstrap[key]));
1350 }
1351 }
1352 }
1353
1354 /**
1355 * Renders the generated source of the bootstrap code.
1356 * @param {RenderBootstrapContext} renderContext options object
1357 * @param {CompilationHooks} hooks hooks
1358 * @returns {Bootstrap} the generated source of the bootstrap code
1359 */
1360 renderBootstrap(renderContext, hooks) {
1361 const {
1362 chunkGraph,
1363 codeGenerationResults,
1364 moduleGraph,
1365 chunk,
1366 runtimeTemplate
1367 } = renderContext;
1368
1369 const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
1370
1371 const requireFunction = runtimeRequirements.has(RuntimeGlobals.require);
1372 const moduleCache = runtimeRequirements.has(RuntimeGlobals.moduleCache);
1373 const moduleFactories = runtimeRequirements.has(
1374 RuntimeGlobals.moduleFactories
1375 );
1376 const moduleUsed = runtimeRequirements.has(RuntimeGlobals.module);
1377 const requireScopeUsed = runtimeRequirements.has(
1378 RuntimeGlobals.requireScope
1379 );
1380 const interceptModuleExecution = runtimeRequirements.has(
1381 RuntimeGlobals.interceptModuleExecution
1382 );
1383
1384 const useRequire =
1385 requireFunction || interceptModuleExecution || moduleUsed;
1386
1387 /**
1388 * @type {{ startup: string[], beforeStartup: string[], header: string[], afterStartup: string[], allowInlineStartup: boolean }}
1389 */
1390 const result = {
1391 header: [],
1392 beforeStartup: [],
1393 startup: [],
1394 afterStartup: [],
1395 allowInlineStartup: true
1396 };
1397
1398 const { header: buf, startup, beforeStartup, afterStartup } = result;
1399
1400 if (result.allowInlineStartup && moduleFactories) {
1401 startup.push(
1402 "// module factories are used so entry inlining is disabled"
1403 );
1404 result.allowInlineStartup = false;
1405 }
1406 if (result.allowInlineStartup && moduleCache) {
1407 startup.push("// module cache are used so entry inlining is disabled");
1408 result.allowInlineStartup = false;
1409 }
1410 if (result.allowInlineStartup && interceptModuleExecution) {
1411 startup.push(
1412 "// module execution is intercepted so entry inlining is disabled"
1413 );
1414 result.allowInlineStartup = false;
1415 }
1416
1417 if (useRequire || moduleCache) {
1418 buf.push("// The module cache");
1419 buf.push("var __webpack_module_cache__ = {};");
1420 buf.push("");
1421 }
1422
1423 if (runtimeRequirements.has(RuntimeGlobals.makeDeferredNamespaceObject)) {
1424 // in order to optimize of DeferredNamespaceObject, we remove all proxy handlers after the module initialize
1425 // (see MakeDeferredNamespaceObjectRuntimeModule)
1426 // This requires all deferred imports to a module can get the module export object before the module
1427 // is evaluated.
1428 buf.push("// The deferred module cache");
1429 buf.push("var __webpack_module_deferred_exports__ = {};");
1430 // Per the TC39 import-defer spec, every defer-import call site for
1431 // the same module must yield the same Deferred Module Namespace
1432 // Exotic Object (and a distinct one from any eager namespace).
1433 // Cache the deferred namespace proxy here so calls from different
1434 // files share identity.
1435 buf.push("// The deferred namespace cache");
1436 buf.push("var __webpack_module_deferred_namespace_cache__ = {};");
1437 buf.push("");
1438 }
1439
1440 if (useRequire) {
1441 buf.push("// The require function");
1442 buf.push(`function ${RuntimeGlobals.require}(moduleId) {`);
1443 buf.push(Template.indent(this.renderRequire(renderContext, hooks)));
1444 buf.push("}");
1445 buf.push("");
1446 } else if (runtimeRequirements.has(RuntimeGlobals.requireScope)) {
1447 buf.push("// The require scope");
1448 buf.push(`var ${RuntimeGlobals.require} = {};`);
1449 buf.push("");
1450 }
1451
1452 if (
1453 moduleFactories ||
1454 runtimeRequirements.has(RuntimeGlobals.moduleFactoriesAddOnly)
1455 ) {
1456 buf.push("// expose the modules object (__webpack_modules__)");
1457 buf.push(`${RuntimeGlobals.moduleFactories} = __webpack_modules__;`);
1458 buf.push("");
1459 }
1460
1461 if (moduleCache) {
1462 buf.push("// expose the module cache");
1463 buf.push(`${RuntimeGlobals.moduleCache} = __webpack_module_cache__;`);
1464 buf.push("");
1465 }
1466
1467 if (interceptModuleExecution) {
1468 buf.push("// expose the module execution interceptor");
1469 buf.push(`${RuntimeGlobals.interceptModuleExecution} = [];`);
1470 buf.push("");
1471 }
1472
1473 if (!runtimeRequirements.has(RuntimeGlobals.startupNoDefault)) {
1474 if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
1475 /** @type {string[]} */
1476 const buf2 = [];
1477 const runtimeRequirements =
1478 chunkGraph.getTreeRuntimeRequirements(chunk);
1479 buf2.push("// Load entry module and return exports");
1480
1481 /** @type {EntryModuleWithChunkGroup[]} */
1482 const jsEntries = [];
1483 for (const [
1484 entryModule,
1485 entrypoint
1486 ] of chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)) {
1487 if (
1488 chunkGraph.getModuleSourceTypes(entryModule).has(JAVASCRIPT_TYPE)
1489 ) {
1490 jsEntries.push([entryModule, entrypoint]);
1491 continue;
1492 }
1493 }
1494 let i = jsEntries.length;
1495 for (const [entryModule, entrypoint] of jsEntries) {
1496 const chunks =
1497 /** @type {Entrypoint} */
1498 (entrypoint).chunks.filter((c) => c !== chunk);
1499 if (result.allowInlineStartup && chunks.length > 0) {
1500 buf2.push(
1501 "// This entry module depends on other loaded chunks and execution need to be delayed"
1502 );
1503 result.allowInlineStartup = false;
1504 }
1505 if (
1506 result.allowInlineStartup &&
1507 someInIterable(
1508 moduleGraph.getIncomingConnectionsByOriginModule(entryModule),
1509 ([originModule, connections]) =>
1510 originModule &&
1511 connections.some((c) => c.isTargetActive(chunk.runtime)) &&
1512 someInIterable(
1513 chunkGraph.getModuleRuntimes(originModule),
1514 (runtime) =>
1515 intersectRuntime(runtime, chunk.runtime) !== undefined
1516 )
1517 )
1518 ) {
1519 buf2.push(
1520 "// This entry module is referenced by other modules so it can't be inlined"
1521 );
1522 result.allowInlineStartup = false;
1523 }
1524
1525 /** @type {undefined | CodeGenerationResultData} */
1526 let data;
1527 if (codeGenerationResults.has(entryModule, chunk.runtime)) {
1528 const result = codeGenerationResults.get(
1529 entryModule,
1530 chunk.runtime
1531 );
1532 data = result.data;
1533 }
1534 if (
1535 result.allowInlineStartup &&
1536 (!data || !data.get("topLevelDeclarations")) &&
1537 (!entryModule.buildInfo ||
1538 !entryModule.buildInfo.topLevelDeclarations)
1539 ) {
1540 buf2.push(
1541 "// This entry module doesn't tell about it's top-level declarations so it can't be inlined"
1542 );
1543 result.allowInlineStartup = false;
1544 }
1545 if (result.allowInlineStartup) {
1546 const bailout = hooks.inlineInRuntimeBailout.call(
1547 entryModule,
1548 renderContext
1549 );
1550 if (bailout !== undefined) {
1551 buf2.push(
1552 `// This entry module can't be inlined because ${bailout}`
1553 );
1554 result.allowInlineStartup = false;
1555 }
1556 }
1557 i--;
1558 const moduleId = chunkGraph.getModuleId(entryModule);
1559 const entryRuntimeRequirements =
1560 chunkGraph.getModuleRuntimeRequirements(entryModule, chunk.runtime);
1561 let moduleIdExpr = JSON.stringify(moduleId);
1562 if (runtimeRequirements.has(RuntimeGlobals.entryModuleId)) {
1563 moduleIdExpr = `${RuntimeGlobals.entryModuleId} = ${moduleIdExpr}`;
1564 }
1565 if (
1566 result.allowInlineStartup &&
1567 entryRuntimeRequirements.has(RuntimeGlobals.module)
1568 ) {
1569 result.allowInlineStartup = false;
1570 buf2.push(
1571 "// This entry module used 'module' so it can't be inlined"
1572 );
1573 }
1574 if (
1575 result.allowInlineStartup &&
1576 entryRuntimeRequirements.has(RuntimeGlobals.thisAsExports)
1577 ) {
1578 buf2.push(
1579 "// This entry module used `this` as exports so it can't be inlined"
1580 );
1581 result.allowInlineStartup = false;
1582 }
1583
1584 if (chunks.length > 0) {
1585 buf2.push(
1586 `${i === 0 ? `var ${RuntimeGlobals.exports} = ` : ""}${
1587 RuntimeGlobals.onChunksLoaded
1588 }(undefined, ${JSON.stringify(
1589 chunks.map((c) => c.id)
1590 )}, ${runtimeTemplate.returningFunction(
1591 `${RuntimeGlobals.require}(${moduleIdExpr})`
1592 )})`
1593 );
1594 } else if (useRequire) {
1595 buf2.push(
1596 `${i === 0 ? `var ${RuntimeGlobals.exports} = ` : ""}${
1597 RuntimeGlobals.require
1598 }(${moduleIdExpr});`
1599 );
1600 } else {
1601 if (i === 0) buf2.push(`var ${RuntimeGlobals.exports} = {};`);
1602 const needThisAsExports = entryRuntimeRequirements.has(
1603 RuntimeGlobals.thisAsExports
1604 );
1605
1606 /** @type {string[]} */
1607 const args = [];
1608 if (
1609 requireScopeUsed ||
1610 entryRuntimeRequirements.has(RuntimeGlobals.exports)
1611 ) {
1612 const exportsArg = i === 0 ? RuntimeGlobals.exports : "{}";
1613 args.push("0", exportsArg);
1614 if (requireScopeUsed) {
1615 args.push(RuntimeGlobals.require);
1616 }
1617 }
1618 buf2.push(
1619 Template.asString(
1620 (() => {
1621 if (needThisAsExports) {
1622 const comma = args.length ? "," : "";
1623 return `__webpack_modules__[${moduleIdExpr}].call(${RuntimeGlobals.exports}${comma}${args.join(",")});`;
1624 }
1625 return `__webpack_modules__[${moduleIdExpr}](${args.join(",")});`;
1626 })()
1627 )
1628 );
1629 }
1630 }
1631 if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
1632 buf2.push(
1633 `${RuntimeGlobals.exports} = ${RuntimeGlobals.onChunksLoaded}(${RuntimeGlobals.exports});`
1634 );
1635 }
1636 if (
1637 runtimeRequirements.has(RuntimeGlobals.startup) ||
1638 (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) &&
1639 runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter))
1640 ) {
1641 result.allowInlineStartup = false;
1642 buf.push("// the startup function");
1643 buf.push(
1644 `${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction("", [
1645 ...buf2,
1646 `return ${RuntimeGlobals.exports};`
1647 ])};`
1648 );
1649 buf.push("");
1650 startup.push("// run startup");
1651 startup.push(
1652 `var ${RuntimeGlobals.exports} = ${RuntimeGlobals.startup}();`
1653 );
1654 } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore)) {
1655 buf.push("// the startup function");
1656 buf.push(
1657 `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
1658 );
1659 beforeStartup.push("// run runtime startup");
1660 beforeStartup.push(`${RuntimeGlobals.startup}();`);
1661 startup.push("// startup");
1662 startup.push(Template.asString(buf2));
1663 } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)) {
1664 buf.push("// the startup function");
1665 buf.push(
1666 `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
1667 );
1668 startup.push("// startup");
1669 startup.push(Template.asString(buf2));
1670 afterStartup.push("// run runtime startup");
1671 afterStartup.push(`${RuntimeGlobals.startup}();`);
1672 } else {
1673 startup.push("// startup");
1674 startup.push(Template.asString(buf2));
1675 }
1676 } else if (
1677 runtimeRequirements.has(RuntimeGlobals.startup) ||
1678 runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) ||
1679 runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)
1680 ) {
1681 buf.push(
1682 "// the startup function",
1683 "// It's empty as no entry modules are in this chunk",
1684 `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`,
1685 ""
1686 );
1687 }
1688 } else if (
1689 runtimeRequirements.has(RuntimeGlobals.startup) ||
1690 runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) ||
1691 runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)
1692 ) {
1693 result.allowInlineStartup = false;
1694 buf.push(
1695 "// the startup function",
1696 "// It's empty as some runtime module handles the default behavior",
1697 `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
1698 );
1699 startup.push("// run startup");
1700 startup.push(
1701 `var ${RuntimeGlobals.exports} = ${RuntimeGlobals.startup}();`
1702 );
1703 }
1704 return result;
1705 }
1706
1707 /**
1708 * Renders the generated source of the require function.
1709 * @param {RenderBootstrapContext} renderContext options object
1710 * @param {CompilationHooks} hooks hooks
1711 * @returns {string} the generated source of the require function
1712 */
1713 renderRequire(renderContext, hooks) {
1714 const {
1715 chunk,
1716 chunkGraph,
1717 runtimeTemplate: { outputOptions }
1718 } = renderContext;
1719 const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
1720
1721 /**
1722 * Renders missing module error.
1723 * @param {string} condition guard expression
1724 * @returns {string[]} source
1725 */
1726 const renderMissingModuleError = (condition) =>
1727 outputOptions.pathinfo
1728 ? [
1729 `if (${condition}) {`,
1730 Template.indent([
1731 "delete __webpack_module_cache__[moduleId];",
1732 'var e = new Error("Cannot find module \'" + moduleId + "\'");',
1733 "e.code = 'MODULE_NOT_FOUND';",
1734 "throw e;"
1735 ]),
1736 "}"
1737 ]
1738 : [];
1739
1740 const moduleExecution = runtimeRequirements.has(
1741 RuntimeGlobals.interceptModuleExecution
1742 )
1743 ? Template.asString([
1744 `var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: ${RuntimeGlobals.require} };`,
1745 `${RuntimeGlobals.interceptModuleExecution}.forEach(function(handler) { handler(execOptions); });`,
1746 ...renderMissingModuleError("!execOptions.factory"),
1747 "module = execOptions.module;",
1748 "execOptions.factory.call(module.exports, module, module.exports, execOptions.require);"
1749 ])
1750 : runtimeRequirements.has(RuntimeGlobals.thisAsExports)
1751 ? Template.asString([
1752 ...renderMissingModuleError("!(moduleId in __webpack_modules__)"),
1753 `__webpack_modules__[moduleId].call(module.exports, module, module.exports, ${RuntimeGlobals.require});`
1754 ])
1755 : Template.asString([
1756 ...renderMissingModuleError("!(moduleId in __webpack_modules__)"),
1757 `__webpack_modules__[moduleId](module, module.exports, ${RuntimeGlobals.require});`
1758 ]);
1759 const needModuleId = runtimeRequirements.has(RuntimeGlobals.moduleId);
1760 const needModuleLoaded = runtimeRequirements.has(
1761 RuntimeGlobals.moduleLoaded
1762 );
1763 const needModuleDefer = runtimeRequirements.has(
1764 RuntimeGlobals.makeDeferredNamespaceObject
1765 );
1766 const content = Template.asString([
1767 "// Check if module is in cache",
1768 "var cachedModule = __webpack_module_cache__[moduleId];",
1769 "if (cachedModule !== undefined) {",
1770 outputOptions.strictModuleErrorHandling
1771 ? Template.indent([
1772 "if (cachedModule.error !== undefined) throw cachedModule.error;",
1773 "return cachedModule.exports;"
1774 ])
1775 : Template.indent("return cachedModule.exports;"),
1776 "}",
1777 "// Create a new module (and put it into the cache)",
1778 "var module = __webpack_module_cache__[moduleId] = {",
1779 Template.indent([
1780 needModuleId ? "id: moduleId," : "// no module.id needed",
1781 needModuleLoaded ? "loaded: false," : "// no module.loaded needed",
1782 needModuleDefer
1783 ? "exports: __webpack_module_deferred_exports__[moduleId] || {}"
1784 : "exports: {}"
1785 ]),
1786 "};",
1787 "",
1788 outputOptions.strictModuleExceptionHandling
1789 ? Template.asString([
1790 "// Execute the module function",
1791 "var threw = true;",
1792 "try {",
1793 Template.indent([
1794 moduleExecution,
1795 "threw = false;",
1796 ...(needModuleDefer
1797 ? ["delete __webpack_module_deferred_exports__[moduleId];"]
1798 : [])
1799 ]),
1800 "} finally {",
1801 Template.indent([
1802 "if(threw) delete __webpack_module_cache__[moduleId];"
1803 ]),
1804 "}"
1805 ])
1806 : outputOptions.strictModuleErrorHandling
1807 ? Template.asString([
1808 "// Execute the module function",
1809 "try {",
1810 Template.indent(
1811 needModuleDefer
1812 ? [
1813 moduleExecution,
1814 "delete __webpack_module_deferred_exports__[moduleId];"
1815 ]
1816 : moduleExecution
1817 ),
1818 "} catch(e) {",
1819 Template.indent(["module.error = e;", "throw e;"]),
1820 "}"
1821 ])
1822 : Template.asString([
1823 "// Execute the module function",
1824 moduleExecution,
1825 ...(needModuleDefer
1826 ? ["delete __webpack_module_deferred_exports__[moduleId];"]
1827 : [])
1828 ]),
1829 needModuleLoaded
1830 ? Template.asString([
1831 "",
1832 "// Flag the module as loaded",
1833 `${RuntimeGlobals.moduleLoaded} = true;`,
1834 ""
1835 ])
1836 : "",
1837 "// Return the exports of the module",
1838 "return module.exports;"
1839 ]);
1840 return tryRunOrWebpackError(
1841 () => hooks.renderRequire.call(content, renderContext),
1842 "JavascriptModulesPlugin.getCompilationHooks().renderRequire"
1843 );
1844 }
1845
1846 /**
1847 * Get renamed inline module.
1848 * @param {Compilation} compilation compilation
1849 * @param {Module[]} allModules allModules
1850 * @param {MainRenderContext} renderContext renderContext
1851 * @param {Set<Module>} inlinedModules inlinedModules
1852 * @param {ChunkRenderContext} chunkRenderContext chunkRenderContext
1853 * @param {CompilationHooks} hooks hooks
1854 * @param {boolean | undefined} allStrict allStrict
1855 * @param {boolean} hasChunkModules hasChunkModules
1856 * @returns {Map<Module, Source> | false} renamed inlined modules
1857 */
1858 _getRenamedInlineModule(
1859 compilation,
1860 allModules,
1861 renderContext,
1862 inlinedModules,
1863 chunkRenderContext,
1864 hooks,
1865 allStrict,
1866 hasChunkModules
1867 ) {
1868 const innerStrict =
1869 !allStrict &&
1870 allModules.every((m) => /** @type {BuildInfo} */ (m.buildInfo).strict);
1871 const isMultipleEntries = inlinedModules.size > 1;
1872 const singleEntryWithModules = inlinedModules.size === 1 && hasChunkModules;
1873 // TODO:
1874 // This step is before the IIFE reason calculation. Ideally, it should only be executed when this function can optimize the
1875 // IIFE reason. Otherwise, it should directly return false. There are four reasons now, we have skipped two already, the left
1876 // one is 'it uses a non-standard name for the exports'.
1877 if (isMultipleEntries || innerStrict || !singleEntryWithModules) {
1878 return false;
1879 }
1880
1881 /** @type {Map<Module, Source>} */
1882 const renamedInlinedModules = new Map();
1883 const { runtimeTemplate } = renderContext;
1884
1885 /** @typedef {{ source: Source, module: Module, ast: Program, variables: Set<Variable>, through: Set<Reference>, usedInNonInlined: Set<Variable>, moduleScope: Scope }} Info */
1886 /** @type {Map<Module, Info>} */
1887 const inlinedModulesToInfo = new Map();
1888 /** @type {Set<string>} */
1889 const nonInlinedModuleThroughIdentifiers = new Set();
1890
1891 for (const m of allModules) {
1892 const isInlinedModule = inlinedModules && inlinedModules.has(m);
1893 const moduleSource = this.renderModule(
1894 m,
1895 {
1896 ...chunkRenderContext,
1897 factory: !isInlinedModule,
1898 inlinedInIIFE: false
1899 },
1900 hooks
1901 );
1902
1903 if (!moduleSource) continue;
1904 const code = /** @type {string} */ (moduleSource.source());
1905
1906 const { ast } = JavascriptParser._parse(
1907 code,
1908 {
1909 sourceType: "auto",
1910 ranges: true
1911 },
1912 JavascriptParser._getModuleParseFunction(compilation, m)
1913 );
1914
1915 const scopeManager = eslintScope.analyze(ast, {
1916 ecmaVersion: 6,
1917 sourceType: "module",
1918 optimistic: true,
1919 ignoreEval: true
1920 });
1921
1922 const globalScope = /** @type {Scope} */ (scopeManager.acquire(ast));
1923 if (inlinedModules && inlinedModules.has(m)) {
1924 const moduleScope = globalScope.childScopes[0];
1925 inlinedModulesToInfo.set(m, {
1926 source: moduleSource,
1927 ast,
1928 module: m,
1929 variables: new Set(moduleScope.variables),
1930 through: new Set(moduleScope.through),
1931 usedInNonInlined: new Set(),
1932 moduleScope
1933 });
1934 } else {
1935 for (const ref of globalScope.through) {
1936 nonInlinedModuleThroughIdentifiers.add(ref.identifier.name);
1937 }
1938 }
1939 }
1940
1941 for (const [, { variables, usedInNonInlined }] of inlinedModulesToInfo) {
1942 for (const variable of variables) {
1943 if (
1944 nonInlinedModuleThroughIdentifiers.has(variable.name) ||
1945 RESERVED_NAMES.has(variable.name)
1946 ) {
1947 usedInNonInlined.add(variable);
1948 }
1949 }
1950 }
1951
1952 for (const [m, moduleInfo] of inlinedModulesToInfo) {
1953 const { ast, source: _source, usedInNonInlined } = moduleInfo;
1954 const source = new ReplaceSource(_source);
1955 if (usedInNonInlined.size === 0) {
1956 renamedInlinedModules.set(m, source);
1957 continue;
1958 }
1959
1960 const info = /** @type {Info} */ (inlinedModulesToInfo.get(m));
1961 const allUsedNames = new Set(
1962 Array.from(info.through, (v) => v.identifier.name)
1963 );
1964
1965 for (const variable of usedInNonInlined) {
1966 allUsedNames.add(variable.name);
1967 }
1968
1969 for (const variable of info.variables) {
1970 /** @type {UsedNamesInScopeInfo} */
1971 const usedNamesInScopeInfo = new Map();
1972 /** @type {ScopeSet} */
1973 const ignoredScopes = new Set();
1974
1975 const name = variable.name;
1976 const { usedNames, alreadyCheckedScopes } = getUsedNamesInScopeInfo(
1977 usedNamesInScopeInfo,
1978 info.module.identifier(),
1979 name
1980 );
1981
1982 if (allUsedNames.has(name) || usedNames.has(name)) {
1983 const references = getAllReferences(variable);
1984 const allIdentifiers = new Set([
1985 ...references.map((r) => r.identifier),
1986 ...variable.identifiers
1987 ]);
1988 for (const ref of references) {
1989 addScopeSymbols(
1990 ref.from,
1991 usedNames,
1992 alreadyCheckedScopes,
1993 ignoredScopes
1994 );
1995 }
1996
1997 const newName = findNewName(
1998 variable.name,
1999 allUsedNames,
2000 usedNames,
2001 m.readableIdentifier(runtimeTemplate.requestShortener)
2002 );
2003 allUsedNames.add(newName);
2004 for (const identifier of allIdentifiers) {
2005 const r = /** @type {Range} */ (identifier.range);
2006 const path = getPathInAst(ast, identifier);
2007 if (path && path.length > 1) {
2008 const maybeProperty =
2009 path[1].type === "AssignmentPattern" && path[1].left === path[0]
2010 ? path[2]
2011 : path[1];
2012 if (
2013 maybeProperty.type === "Property" &&
2014 maybeProperty.shorthand
2015 ) {
2016 source.insert(r[1], `: ${newName}`);
2017 continue;
2018 }
2019 }
2020 source.replace(r[0], r[1] - 1, newName);
2021 }
2022 }
2023 allUsedNames.add(name);
2024 }
2025
2026 renamedInlinedModules.set(m, source);
2027 }
2028
2029 return renamedInlinedModules;
2030 }
2031}
2032
2033module.exports = JavascriptModulesPlugin;
2034module.exports.chunkHasJs = chunkHasJs;
Note: See TracBrowser for help on using the repository browser.