source: frontend/node_modules/webpack/lib/optimize/ConcatenatedModule.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: 69.7 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 eslintScope = require("eslint-scope");
9const Referencer = require("eslint-scope/lib/referencer");
10const { SyncBailHook } = require("tapable");
11const {
12 CachedSource,
13 ConcatSource,
14 ReplaceSource
15} = require("webpack-sources");
16const ConcatenationScope = require("../ConcatenationScope");
17const Dependency = require("../Dependency");
18const { UsageState } = require("../ExportsInfo");
19const Module = require("../Module");
20const {
21 JAVASCRIPT_TYPE,
22 JAVASCRIPT_TYPES
23} = require("../ModuleSourceTypeConstants");
24const { JAVASCRIPT_MODULE_TYPE_ESM } = require("../ModuleTypeConstants");
25const RuntimeGlobals = require("../RuntimeGlobals");
26const Template = require("../Template");
27const { DEFAULTS } = require("../config/defaults");
28const { ImportPhaseUtils } = require("../dependencies/ImportPhase");
29const JavascriptParser = require("../javascript/JavascriptParser");
30const {
31 getMakeDeferredNamespaceModeFromExportsType,
32 getOptimizedDeferredModule
33} = require("../runtime/MakeDeferredNamespaceObjectRuntime");
34const { equals } = require("../util/ArrayHelpers");
35const LazySet = require("../util/LazySet");
36const { concatComparators } = require("../util/comparators");
37const {
38 RESERVED_NAMES,
39 addScopeSymbols,
40 findNewName,
41 getAllReferences,
42 getPathInAst,
43 getUsedNamesInScopeInfo
44} = require("../util/concatenate");
45const createHash = require("../util/createHash");
46const { makePathsRelative } = require("../util/identifier");
47const makeSerializable = require("../util/makeSerializable");
48const { propertyAccess, propertyName } = require("../util/property");
49const {
50 filterRuntime,
51 intersectRuntime,
52 mergeRuntimeCondition,
53 mergeRuntimeConditionNonFalse,
54 runtimeConditionToString,
55 subtractRuntimeCondition
56} = require("../util/runtime");
57
58/** @typedef {import("webpack-sources").Source} Source */
59/** @typedef {import("../config/defaults").WebpackOptionsNormalizedWithDefaults} WebpackOptions */
60/** @typedef {import("../ChunkGraph")} ChunkGraph */
61/** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
62/** @typedef {import("../Compilation")} Compilation */
63/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
64/** @typedef {import("../dependencies/ModuleDependency")} ModuleDependency */
65/** @typedef {import("../dependencies/HarmonyImportDependency")} HarmonyImportDependency */
66/** @typedef {import("../DependencyTemplates")} DependencyTemplates */
67/** @typedef {import("../ExportsInfo").ExportInfo} ExportInfo */
68/** @typedef {import("../Module").BuildCallback} BuildCallback */
69/** @typedef {import("../Module").BuildInfo} BuildInfo */
70/** @typedef {import("../Module").FileSystemDependencies} FileSystemDependencies */
71/** @typedef {import("../Module").BuildMeta} BuildMeta */
72/** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
73/** @typedef {import("../Module").CodeGenerationResultData} CodeGenerationResultData */
74/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
75/** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
76/** @typedef {import("../Module").LibIdent} LibIdent */
77/** @typedef {import("../Module").NameForCondition} NameForCondition */
78/** @typedef {import("../Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
79/** @typedef {import("../Module").RuntimeRequirements} RuntimeRequirements */
80/** @typedef {import("../Module").SourceTypes} SourceTypes */
81/** @typedef {import("../ModuleGraph")} ModuleGraph */
82/** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
83/** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
84/** @typedef {import("../RequestShortener")} RequestShortener */
85/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
86/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
87/** @typedef {import("../javascript/JavascriptModulesPlugin").ChunkRenderContext} ChunkRenderContext */
88/** @typedef {import("../javascript/JavascriptModulesPlugin").Scope} Scope */
89/** @typedef {import("../javascript/JavascriptModulesPlugin").Reference} Reference */
90/** @typedef {import("../javascript/JavascriptModulesPlugin").Variable} Variable */
91/** @typedef {import("../javascript/JavascriptParser").Program} Program */
92/** @typedef {import("../javascript/JavascriptParser").Range} Range */
93/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
94/** @typedef {import("../util/Hash")} Hash */
95/** @typedef {import("../util/Hash").HashFunction} HashFunction */
96/** @typedef {import("../util/concatenate").UsedNames} UsedNames */
97/** @typedef {import("../util/concatenate").ScopeInfo} ScopeInfo */
98/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
99/** @typedef {import("../util/identifier").AssociatedObjectForCache} AssociatedObjectForCache */
100/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
101/**
102 * @template T
103 * @typedef {import("../InitFragment")<T>} InitFragment
104 */
105
106/**
107 * @template T
108 * @typedef {import("../util/comparators").Comparator<T>} Comparator
109 */
110
111// fix eslint-scope to support class properties correctly
112// cspell:word Referencer
113const ReferencerClass = Referencer;
114if (!ReferencerClass.prototype.PropertyDefinition) {
115 ReferencerClass.prototype.PropertyDefinition =
116 ReferencerClass.prototype.Property;
117}
118
119/** @typedef {RawBinding | SymbolBinding} Binding */
120
121/** @typedef {string[]} ExportName */
122
123/**
124 * @typedef {object} RawBinding
125 * @property {ModuleInfo} info
126 * @property {string} rawName
127 * @property {string=} comment
128 * @property {ExportName} ids
129 * @property {ExportName} exportName
130 */
131
132/**
133 * @typedef {object} SymbolBinding
134 * @property {ConcatenatedModuleInfo} info
135 * @property {string} name
136 * @property {string=} comment
137 * @property {ExportName} ids
138 * @property {ExportName} exportName
139 */
140
141/** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo} ModuleInfo */
142/** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo | ReferenceToModuleInfo} ModuleInfoOrReference */
143
144/** @typedef {Map<string, string>} ExportMap */
145
146/**
147 * @typedef {object} ConcatenatedModuleInfo
148 * @property {"concatenated"} type
149 * @property {Module} module
150 * @property {number} index
151 * @property {Program | undefined} ast
152 * @property {Source | undefined} internalSource
153 * @property {ReplaceSource | undefined} source
154 * @property {InitFragment<ChunkRenderContext>[]=} chunkInitFragments
155 * @property {ReadOnlyRuntimeRequirements | undefined} runtimeRequirements
156 * @property {Scope | undefined} globalScope
157 * @property {Scope | undefined} moduleScope
158 * @property {Map<string, string>} internalNames
159 * @property {ExportMap | undefined} exportMap
160 * @property {ExportMap | undefined} rawExportMap
161 * @property {string=} namespaceExportSymbol
162 * @property {string | undefined} namespaceObjectName
163 * @property {ConcatenationScope | undefined} concatenationScope
164 * @property {boolean} interopNamespaceObjectUsed "default-with-named" namespace
165 * @property {string | undefined} interopNamespaceObjectName "default-with-named" namespace
166 * @property {boolean} interopNamespaceObject2Used "default-only" namespace
167 * @property {string | undefined} interopNamespaceObject2Name "default-only" namespace
168 * @property {boolean} interopDefaultAccessUsed runtime namespace object that detects "__esModule"
169 * @property {string | undefined} interopDefaultAccessName runtime namespace object that detects "__esModule"
170 */
171
172/**
173 * @typedef {object} ExternalModuleInfo
174 * @property {"external"} type
175 * @property {Module} module
176 * @property {RuntimeSpec | boolean} runtimeCondition
177 * @property {NonDeferAccess} nonDeferAccess
178 * @property {number} index
179 * @property {string | undefined} name module.exports / harmony namespace object
180 * @property {string | undefined} deferredName deferred module.exports / harmony namespace object
181 * @property {boolean} deferred the module is deferred at least once
182 * @property {boolean} deferredNamespaceObjectUsed deferred namespace object that being used in a not-analyzable way so it must be materialized
183 * @property {string | undefined} deferredNamespaceObjectName deferred namespace object that being used in a not-analyzable way so it must be materialized
184 * @property {boolean} interopNamespaceObjectUsed "default-with-named" namespace
185 * @property {string | undefined} interopNamespaceObjectName "default-with-named" namespace
186 * @property {boolean} interopNamespaceObject2Used "default-only" namespace
187 * @property {string | undefined} interopNamespaceObject2Name "default-only" namespace
188 * @property {boolean} interopDefaultAccessUsed runtime namespace object that detects "__esModule"
189 * @property {string | undefined} interopDefaultAccessName runtime namespace object that detects "__esModule"
190 */
191
192/**
193 * @typedef {object} ReferenceToModuleInfo
194 * @property {"reference"} type
195 * @property {RuntimeSpec | boolean} runtimeCondition
196 * @property {NonDeferAccess} nonDeferAccess
197 * @property {ModuleInfo} target
198 */
199
200/**
201 * @template T
202 * @param {string} property property
203 * @param {(a: T[keyof T], b: T[keyof T]) => 0 | 1 | -1} comparator comparator
204 * @returns {Comparator<T>} comparator
205 */
206
207const createComparator = (property, comparator) => (a, b) =>
208 comparator(
209 a[/** @type {keyof T} */ (property)],
210 b[/** @type {keyof T} */ (property)]
211 );
212
213/**
214 * @param {number} a a
215 * @param {number} b b
216 * @returns {0 | 1 | -1} result
217 */
218const compareNumbers = (a, b) => {
219 if (Number.isNaN(a)) {
220 if (!Number.isNaN(b)) {
221 return 1;
222 }
223 } else {
224 if (Number.isNaN(b)) {
225 return -1;
226 }
227 if (a !== b) {
228 return a < b ? -1 : 1;
229 }
230 }
231 return 0;
232};
233
234const bySourceOrder = createComparator("sourceOrder", compareNumbers);
235const byRangeStart = createComparator("rangeStart", compareNumbers);
236
237/**
238 * @param {Iterable<string>} iterable iterable object
239 * @returns {string} joined iterable object
240 */
241const joinIterableWithComma = (iterable) => {
242 // This is more performant than Array.from().join(", ")
243 // as it doesn't create an array
244 let str = "";
245 let first = true;
246 for (const item of iterable) {
247 if (first) {
248 first = false;
249 } else {
250 str += ", ";
251 }
252 str += item;
253 }
254 return str;
255};
256
257/** @typedef {boolean} NonDeferAccess */
258
259/**
260 * @param {NonDeferAccess} a a
261 * @param {NonDeferAccess} b b
262 * @returns {NonDeferAccess} merged
263 */
264const mergeNonDeferAccess = (a, b) => a || b;
265
266/**
267 * @param {NonDeferAccess} a first
268 * @param {NonDeferAccess} b second
269 * @returns {NonDeferAccess} first - second
270 */
271const subtractNonDeferAccess = (a, b) => a && !b;
272
273/**
274 * @typedef {object} ConcatenationEntry
275 * @property {"concatenated" | "external"} type
276 * @property {Module} module
277 * @property {RuntimeSpec | boolean} runtimeCondition
278 * @property {NonDeferAccess} nonDeferAccess
279 */
280
281/** @typedef {Set<ConcatenatedModuleInfo>} NeededNamespaceObjects */
282
283/** @typedef {Map<Module, ModuleInfo>} ModuleToInfoMap */
284
285/**
286 * @param {ModuleGraph} moduleGraph the module graph
287 * @param {ModuleInfo} info module info
288 * @param {ExportName} exportName exportName
289 * @param {ModuleToInfoMap} moduleToInfoMap moduleToInfoMap
290 * @param {RuntimeSpec} runtime for which runtime
291 * @param {RequestShortener} requestShortener the request shortener
292 * @param {RuntimeTemplate} runtimeTemplate the runtime template
293 * @param {NeededNamespaceObjects} neededNamespaceObjects modules for which a namespace object should be generated
294 * @param {boolean} asCall asCall
295 * @param {boolean} depDeferred the dependency is deferred
296 * @param {boolean | undefined} strictHarmonyModule strictHarmonyModule
297 * @param {boolean | undefined} asiSafe asiSafe
298 * @param {Set<ExportInfo>} alreadyVisited alreadyVisited
299 * @returns {Binding} the final variable
300 */
301const getFinalBinding = (
302 moduleGraph,
303 info,
304 exportName,
305 moduleToInfoMap,
306 runtime,
307 requestShortener,
308 runtimeTemplate,
309 neededNamespaceObjects,
310 asCall,
311 depDeferred,
312 strictHarmonyModule,
313 asiSafe,
314 alreadyVisited = new Set()
315) => {
316 const exportsType = info.module.getExportsType(
317 moduleGraph,
318 strictHarmonyModule
319 );
320 const moduleDeferred =
321 info.type === "external" &&
322 info.deferred &&
323 !(/** @type {BuildMeta} */ (info.module.buildMeta).async);
324 const deferred = depDeferred && moduleDeferred;
325 if (exportName.length === 0) {
326 switch (exportsType) {
327 case "default-only":
328 if (deferred) info.deferredNamespaceObjectUsed = true;
329 else info.interopNamespaceObject2Used = true;
330 return {
331 info,
332 rawName: /** @type {string} */ (
333 deferred
334 ? info.deferredNamespaceObjectName
335 : info.interopNamespaceObject2Name
336 ),
337 ids: exportName,
338 exportName
339 };
340 case "default-with-named":
341 if (deferred) info.deferredNamespaceObjectUsed = true;
342 else info.interopNamespaceObjectUsed = true;
343 return {
344 info,
345 rawName: /** @type {string} */ (
346 deferred
347 ? info.deferredNamespaceObjectName
348 : info.interopNamespaceObjectName
349 ),
350 ids: exportName,
351 exportName
352 };
353 case "namespace":
354 case "dynamic":
355 break;
356 default:
357 throw new Error(`Unexpected exportsType ${exportsType}`);
358 }
359 } else {
360 switch (exportsType) {
361 case "namespace":
362 break;
363 case "default-with-named":
364 switch (exportName[0]) {
365 case "default":
366 exportName = exportName.slice(1);
367 if (deferred) {
368 // `ns.default` for a deferred default-with-named external
369 // module must read through the optimized `.a` getter
370 // (which lazily evaluates the module and returns its
371 // exports), not the proxy namespace itself — otherwise
372 // `typeof ns.default` / `ns.default instanceof X`
373 // observe the proxy instead of the actual default.
374 return {
375 info,
376 rawName: `${info.deferredName}.a`,
377 ids: exportName,
378 exportName
379 };
380 }
381 break;
382 case "__esModule":
383 return {
384 info,
385 rawName: "/* __esModule */true",
386 ids: exportName.slice(1),
387 exportName
388 };
389 }
390 break;
391 case "default-only": {
392 const exportId = exportName[0];
393 if (exportId === "__esModule") {
394 return {
395 info,
396 rawName: "/* __esModule */true",
397 ids: exportName.slice(1),
398 exportName
399 };
400 }
401 exportName = exportName.slice(1);
402 if (exportId !== "default") {
403 return {
404 info,
405 rawName:
406 "/* non-default import from default-exporting module */undefined",
407 ids: exportName,
408 exportName
409 };
410 }
411 if (deferred) {
412 // As with default-with-named above, `ns.default` for a
413 // deferred default-only external must read through the
414 // optimized `.a` getter so that `typeof` / `instanceof`
415 // observe the actual default value rather than the proxy.
416 return {
417 info,
418 rawName: `${info.deferredName}.a`,
419 ids: exportName,
420 exportName
421 };
422 }
423 break;
424 }
425 case "dynamic":
426 switch (exportName[0]) {
427 case "default": {
428 exportName = exportName.slice(1);
429 if (deferred) {
430 return {
431 info,
432 rawName: `${info.deferredName}.a`,
433 ids: exportName,
434 exportName
435 };
436 }
437 if (moduleDeferred) {
438 return {
439 info,
440 rawName: /** @type {string} */ (info.name),
441 ids: exportName,
442 exportName
443 };
444 }
445 info.interopDefaultAccessUsed = true;
446 const defaultExport = asCall
447 ? `${info.interopDefaultAccessName}()`
448 : asiSafe
449 ? `(${info.interopDefaultAccessName}())`
450 : asiSafe === false
451 ? `;(${info.interopDefaultAccessName}())`
452 : `${info.interopDefaultAccessName}.a`;
453 return {
454 info,
455 rawName: defaultExport,
456 ids: exportName,
457 exportName
458 };
459 }
460 case "__esModule":
461 return {
462 info,
463 rawName: "/* __esModule */true",
464 ids: exportName.slice(1),
465 exportName
466 };
467 }
468 break;
469 default:
470 throw new Error(`Unexpected exportsType ${exportsType}`);
471 }
472 }
473 if (exportName.length === 0) {
474 switch (info.type) {
475 case "concatenated":
476 neededNamespaceObjects.add(info);
477 return {
478 info,
479 rawName:
480 /** @type {NonNullable<ConcatenatedModuleInfo["namespaceObjectName"]>} */
481 (info.namespaceObjectName),
482 ids: exportName,
483 exportName
484 };
485 case "external":
486 if (deferred) {
487 info.deferredNamespaceObjectUsed = true;
488 return {
489 info,
490 rawName: /** @type {string} */ (info.deferredNamespaceObjectName),
491 ids: exportName,
492 exportName
493 };
494 }
495 return {
496 info,
497 rawName:
498 /** @type {NonNullable<ExternalModuleInfo["name"]>} */
499 (info.name),
500 ids: exportName,
501 exportName
502 };
503 }
504 }
505 const exportsInfo = moduleGraph.getExportsInfo(info.module);
506 const exportInfo = exportsInfo.getExportInfo(exportName[0]);
507 if (alreadyVisited.has(exportInfo)) {
508 return {
509 info,
510 rawName: "/* circular reexport */ Object(function x() { x() }())",
511 ids: [],
512 exportName
513 };
514 }
515 alreadyVisited.add(exportInfo);
516 switch (info.type) {
517 case "concatenated": {
518 const exportId = exportName[0];
519 if (exportInfo.provided === false) {
520 // It's not provided, but it could be on the prototype
521 neededNamespaceObjects.add(info);
522 return {
523 info,
524 rawName: /** @type {string} */ (info.namespaceObjectName),
525 ids: exportName,
526 exportName
527 };
528 }
529 const directExport = info.exportMap && info.exportMap.get(exportId);
530 if (directExport) {
531 const usedName = /** @type {ExportName} */ (
532 exportsInfo.getUsedName(exportName, runtime)
533 );
534 if (!usedName) {
535 return {
536 info,
537 rawName: "/* unused export */ undefined",
538 ids: exportName.slice(1),
539 exportName
540 };
541 }
542 return {
543 info,
544 name: directExport,
545 ids: usedName.slice(1),
546 exportName
547 };
548 }
549 const rawExport = info.rawExportMap && info.rawExportMap.get(exportId);
550 if (rawExport) {
551 return {
552 info,
553 rawName: rawExport,
554 ids: exportName.slice(1),
555 exportName
556 };
557 }
558 const reexport = exportInfo.findTarget(moduleGraph, (module) =>
559 moduleToInfoMap.has(module)
560 );
561 if (reexport === false) {
562 throw new Error(
563 `Target module of reexport from '${info.module.readableIdentifier(
564 requestShortener
565 )}' is not part of the concatenation (export '${exportId}')\nModules in the concatenation:\n${Array.from(
566 moduleToInfoMap,
567 ([m, info]) =>
568 ` * ${info.type} ${m.readableIdentifier(requestShortener)}`
569 ).join("\n")}`
570 );
571 }
572 if (reexport) {
573 const refInfo = moduleToInfoMap.get(reexport.module);
574 return getFinalBinding(
575 moduleGraph,
576 /** @type {ModuleInfo} */ (refInfo),
577 reexport.export
578 ? [...reexport.export, ...exportName.slice(1)]
579 : exportName.slice(1),
580 moduleToInfoMap,
581 runtime,
582 requestShortener,
583 runtimeTemplate,
584 neededNamespaceObjects,
585 asCall,
586 reexport.deferred,
587 /** @type {BuildMeta} */
588 (info.module.buildMeta).strictHarmonyModule,
589 asiSafe,
590 alreadyVisited
591 );
592 }
593 if (info.namespaceExportSymbol) {
594 const usedName = /** @type {ExportName} */ (
595 exportsInfo.getUsedName(exportName, runtime)
596 );
597 return {
598 info,
599 rawName: /** @type {string} */ (info.namespaceObjectName),
600 ids: usedName,
601 exportName
602 };
603 }
604 throw new Error(
605 `Cannot get final name for export '${exportName.join(
606 "."
607 )}' of ${info.module.readableIdentifier(requestShortener)}`
608 );
609 }
610
611 case "external": {
612 const used = /** @type {ExportName} */ (
613 exportsInfo.getUsedName(exportName, runtime)
614 );
615 if (!used) {
616 return {
617 info,
618 rawName: "/* unused export */ undefined",
619 ids: exportName.slice(1),
620 exportName
621 };
622 }
623 const comment = equals(used, exportName)
624 ? ""
625 : Template.toNormalComment(`${exportName.join(".")}`);
626 return {
627 info,
628 rawName:
629 (deferred ? info.deferredName : info.name) +
630 (deferred ? ".a" : "") +
631 comment,
632 ids: used,
633 exportName
634 };
635 }
636 }
637};
638
639/**
640 * @param {ModuleGraph} moduleGraph the module graph
641 * @param {ModuleInfo} info module info
642 * @param {ExportName} exportName exportName
643 * @param {ModuleToInfoMap} moduleToInfoMap moduleToInfoMap
644 * @param {RuntimeSpec} runtime for which runtime
645 * @param {RequestShortener} requestShortener the request shortener
646 * @param {RuntimeTemplate} runtimeTemplate the runtime template
647 * @param {NeededNamespaceObjects} neededNamespaceObjects modules for which a namespace object should be generated
648 * @param {boolean} asCall asCall
649 * @param {boolean} depDeferred the dependency is deferred
650 * @param {boolean | undefined} callContext callContext
651 * @param {boolean | undefined} strictHarmonyModule strictHarmonyModule
652 * @param {boolean | undefined} asiSafe asiSafe
653 * @returns {string} the final name
654 */
655const getFinalName = (
656 moduleGraph,
657 info,
658 exportName,
659 moduleToInfoMap,
660 runtime,
661 requestShortener,
662 runtimeTemplate,
663 neededNamespaceObjects,
664 asCall,
665 depDeferred,
666 callContext,
667 strictHarmonyModule,
668 asiSafe
669) => {
670 const binding = getFinalBinding(
671 moduleGraph,
672 info,
673 exportName,
674 moduleToInfoMap,
675 runtime,
676 requestShortener,
677 runtimeTemplate,
678 neededNamespaceObjects,
679 asCall,
680 depDeferred,
681 strictHarmonyModule,
682 asiSafe
683 );
684 {
685 const { ids, comment } = binding;
686 /** @type {string} */
687 let reference;
688 /** @type {boolean} */
689 let isPropertyAccess;
690 if ("rawName" in binding) {
691 reference = `${binding.rawName}${comment || ""}${propertyAccess(ids)}`;
692 isPropertyAccess = ids.length > 0;
693 } else {
694 const { info, name: exportId } = binding;
695 const name = info.internalNames.get(exportId);
696 if (!name) {
697 throw new Error(
698 `The export "${exportId}" in "${info.module.readableIdentifier(
699 requestShortener
700 )}" has no internal name (existing names: ${
701 Array.from(
702 info.internalNames,
703 ([name, symbol]) => `${name}: ${symbol}`
704 ).join(", ") || "none"
705 })`
706 );
707 }
708 reference = `${name}${comment || ""}${propertyAccess(ids)}`;
709 isPropertyAccess = ids.length > 1;
710 }
711 if (isPropertyAccess && asCall && callContext === false) {
712 return asiSafe
713 ? `(0,${reference})`
714 : asiSafe === false
715 ? `;(0,${reference})`
716 : `/*#__PURE__*/Object(${reference})`;
717 }
718 return reference;
719 }
720};
721
722/**
723 * @typedef {object} ConcatenateModuleHooks
724 * @property {SyncBailHook<[ConcatenatedModule, RuntimeSpec[], string, Record<string, string>], boolean>} onDemandExportsGeneration
725 * @property {SyncBailHook<[Partial<ConcatenatedModuleInfo>, ConcatenatedModuleInfo], boolean | void>} concatenatedModuleInfo
726 */
727
728/** @typedef {BuildInfo["topLevelDeclarations"]} TopLevelDeclarations */
729
730/** @type {WeakMap<Compilation, ConcatenateModuleHooks>} */
731const compilationHooksMap = new WeakMap();
732
733class ConcatenatedModule extends Module {
734 /**
735 * @param {Module} rootModule the root module of the concatenation
736 * @param {Set<Module>} modules all modules in the concatenation (including the root module)
737 * @param {RuntimeSpec} runtime the runtime
738 * @param {Compilation} compilation the compilation
739 * @param {AssociatedObjectForCache=} associatedObjectForCache object for caching
740 * @param {HashFunction=} hashFunction hash function to use
741 * @returns {ConcatenatedModule} the module
742 */
743 static create(
744 rootModule,
745 modules,
746 runtime,
747 compilation,
748 associatedObjectForCache,
749 hashFunction = DEFAULTS.HASH_FUNCTION
750 ) {
751 const identifier = ConcatenatedModule._createIdentifier(
752 rootModule,
753 modules,
754 associatedObjectForCache,
755 hashFunction
756 );
757 return new ConcatenatedModule({
758 identifier,
759 rootModule,
760 modules,
761 runtime,
762 compilation
763 });
764 }
765
766 /**
767 * @param {Compilation} compilation the compilation
768 * @returns {ConcatenateModuleHooks} the attached hooks
769 */
770 static getCompilationHooks(compilation) {
771 let hooks = compilationHooksMap.get(compilation);
772 if (hooks === undefined) {
773 hooks = {
774 onDemandExportsGeneration: new SyncBailHook([
775 "module",
776 "runtimes",
777 "exportsFinalName",
778 "exportsSource"
779 ]),
780 concatenatedModuleInfo: new SyncBailHook([
781 "updatedInfo",
782 "concatenatedModuleInfo"
783 ])
784 };
785 compilationHooksMap.set(compilation, hooks);
786 }
787 return hooks;
788 }
789
790 /**
791 * @param {object} options options
792 * @param {string} options.identifier the identifier of the module
793 * @param {Module} options.rootModule the root module of the concatenation
794 * @param {RuntimeSpec} options.runtime the selected runtime
795 * @param {Set<Module>} options.modules all concatenated modules
796 * @param {Compilation} options.compilation the compilation
797 */
798 constructor({ identifier, rootModule, modules, runtime, compilation }) {
799 super(JAVASCRIPT_MODULE_TYPE_ESM, null, rootModule && rootModule.layer);
800
801 // Info from Factory
802 /** @type {string} */
803 this._identifier = identifier;
804 /** @type {Module} */
805 this.rootModule = rootModule;
806 /** @type {Set<Module>} */
807 this._modules = modules;
808 this._runtime = runtime;
809 this.factoryMeta = rootModule && rootModule.factoryMeta;
810 /** @type {Compilation} */
811 this.compilation = compilation;
812 }
813
814 /**
815 * Assuming this module is in the cache. Update the (cached) module with
816 * the fresh module from the factory. Usually updates internal references
817 * and properties.
818 * @param {Module} module fresh module
819 * @returns {void}
820 */
821 updateCacheModule(module) {
822 throw new Error("Must not be called");
823 }
824
825 /**
826 * Returns the source types this module can generate.
827 * @returns {SourceTypes} types available (do not mutate)
828 */
829 getSourceTypes() {
830 return JAVASCRIPT_TYPES;
831 }
832
833 get modules() {
834 return [...this._modules];
835 }
836
837 /**
838 * Returns the unique identifier used to reference this module.
839 * @returns {string} a unique identifier of the module
840 */
841 identifier() {
842 return this._identifier;
843 }
844
845 /**
846 * Returns a human-readable identifier for this module.
847 * @param {RequestShortener} requestShortener the request shortener
848 * @returns {string} a user readable identifier of the module
849 */
850 readableIdentifier(requestShortener) {
851 return `${this.rootModule.readableIdentifier(
852 requestShortener
853 )} + ${this._modules.size - 1} modules`;
854 }
855
856 /**
857 * Gets the library identifier.
858 * @param {LibIdentOptions} options options
859 * @returns {LibIdent | null} an identifier for library inclusion
860 */
861 libIdent(options) {
862 return this.rootModule.libIdent(options);
863 }
864
865 /**
866 * Returns the path used when matching this module against rule conditions.
867 * @returns {NameForCondition | null} absolute path which should be used for condition matching (usually the resource path)
868 */
869 nameForCondition() {
870 return this.rootModule.nameForCondition();
871 }
872
873 /**
874 * Gets side effects connection state.
875 * @param {ModuleGraph} moduleGraph the module graph
876 * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only
877 */
878 getSideEffectsConnectionState(moduleGraph) {
879 return this.rootModule.getSideEffectsConnectionState(moduleGraph);
880 }
881
882 /**
883 * Builds the module using the provided compilation context.
884 * @param {WebpackOptions} options webpack options
885 * @param {Compilation} compilation the compilation
886 * @param {ResolverWithOptions} resolver the resolver
887 * @param {InputFileSystem} fs the file system
888 * @param {BuildCallback} callback callback function
889 * @returns {void}
890 */
891 build(options, compilation, resolver, fs, callback) {
892 const { rootModule } = this;
893 const { moduleArgument, exportsArgument } =
894 /** @type {BuildInfo} */
895 (rootModule.buildInfo);
896 /** @type {BuildInfo} */
897 this.buildInfo = {
898 strict: true,
899 cacheable: true,
900 moduleArgument,
901 exportsArgument,
902 fileDependencies: new LazySet(),
903 contextDependencies: new LazySet(),
904 missingDependencies: new LazySet(),
905 topLevelDeclarations: new Set(),
906 assets: undefined
907 };
908 this.buildMeta = rootModule.buildMeta;
909 this.clearDependenciesAndBlocks();
910 this.clearWarningsAndErrors();
911
912 for (const m of this._modules) {
913 // populate cacheable
914 if (!(/** @type {BuildInfo} */ (m.buildInfo).cacheable)) {
915 this.buildInfo.cacheable = false;
916 }
917
918 // populate dependencies
919 for (const d of m.dependencies.filter(
920 (dep) =>
921 !Dependency.canConcatenate(dep) ||
922 !this._modules.has(
923 /** @type {Module} */
924 (compilation.moduleGraph.getModule(dep))
925 )
926 )) {
927 this.dependencies.push(d);
928 }
929 // populate codeGenerationDependencies — the inner modules'
930 // templates are applied during ConcatenatedModule.codeGeneration,
931 // so the referenced modules must have been code-generated by then.
932 // Skip references that point back into the concat set itself.
933 if (m.codeGenerationDependencies !== undefined) {
934 for (const d of m.codeGenerationDependencies) {
935 const referenced =
936 /** @type {Module} */
937 (compilation.moduleGraph.getModule(d));
938 if (!this._modules.has(referenced)) {
939 this.addCodeGenerationDependency(d);
940 }
941 }
942 }
943 // populate blocks
944 for (const d of m.blocks) {
945 this.blocks.push(d);
946 }
947
948 // populate warnings
949 const warnings = m.getWarnings();
950 if (warnings !== undefined) {
951 for (const warning of warnings) {
952 this.addWarning(warning);
953 }
954 }
955
956 // populate errors
957 const errors = m.getErrors();
958 if (errors !== undefined) {
959 for (const error of errors) {
960 this.addError(error);
961 }
962 }
963
964 const { assets, assetsInfo, topLevelDeclarations, needCreateRequire } =
965 /** @type {BuildInfo} */ (m.buildInfo);
966
967 const buildInfo = this.buildInfo;
968
969 // populate topLevelDeclarations
970 if (topLevelDeclarations) {
971 const topLevelDeclarations = buildInfo.topLevelDeclarations;
972 if (topLevelDeclarations !== undefined) {
973 for (const decl of topLevelDeclarations) {
974 topLevelDeclarations.add(decl);
975 }
976 }
977 } else {
978 buildInfo.topLevelDeclarations = undefined;
979 }
980
981 // populate needCreateRequire
982 if (needCreateRequire) {
983 this.buildInfo.needCreateRequire = true;
984 }
985
986 // populate assets
987 if (assets) {
988 if (buildInfo.assets === undefined) {
989 buildInfo.assets = Object.create(null);
990 }
991 Object.assign(
992 /** @type {NonNullable<BuildInfo["assets"]>} */
993 (buildInfo.assets),
994 assets
995 );
996 }
997 if (assetsInfo) {
998 if (buildInfo.assetsInfo === undefined) {
999 buildInfo.assetsInfo = new Map();
1000 }
1001 for (const [key, value] of assetsInfo) {
1002 buildInfo.assetsInfo.set(key, value);
1003 }
1004 }
1005 }
1006 callback();
1007 }
1008
1009 /**
1010 * Returns the estimated size for the requested source type.
1011 * @param {string=} type the source type for which the size should be estimated
1012 * @returns {number} the estimated size of the module (must be non-zero)
1013 */
1014 size(type) {
1015 // Guess size from embedded modules
1016 let size = 0;
1017 for (const module of this._modules) {
1018 size += module.size(type);
1019 }
1020 return size;
1021 }
1022
1023 /**
1024 * @private
1025 * @param {Module} rootModule the root of the concatenation
1026 * @param {Set<Module>} modulesSet a set of modules which should be concatenated
1027 * @param {RuntimeSpec} runtime for this runtime
1028 * @param {ModuleGraph} moduleGraph the module graph
1029 * @returns {ConcatenationEntry[]} concatenation list
1030 */
1031 _createConcatenationList(rootModule, modulesSet, runtime, moduleGraph) {
1032 /** @type {ConcatenationEntry[]} */
1033 const list = [];
1034 /** @type {Map<Module, { runtimeCondition: RuntimeSpec | true, nonDeferAccess: NonDeferAccess }>} */
1035 const existingEntries = new Map();
1036
1037 /**
1038 * @param {Module} module a module
1039 * @returns {Iterable<{ connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true, nonDeferAccess: NonDeferAccess }>} imported modules in order
1040 */
1041 const getConcatenatedImports = (module) => {
1042 const connections = [...moduleGraph.getOutgoingConnections(module)];
1043 if (module === rootModule) {
1044 for (const c of moduleGraph.getOutgoingConnections(this)) {
1045 connections.push(c);
1046 }
1047 }
1048 /**
1049 * @type {{ connection: ModuleGraphConnection, sourceOrder: number, rangeStart: number | undefined, defer?: boolean }[]}
1050 */
1051 const references = connections
1052 .filter((connection) => {
1053 if (
1054 !connection.dependency ||
1055 !Dependency.canConcatenate(connection.dependency)
1056 ) {
1057 return false;
1058 }
1059 if (
1060 !Module.getSourceBasicTypes(connection.module).has(JAVASCRIPT_TYPE)
1061 ) {
1062 return false;
1063 }
1064 return (
1065 connection &&
1066 connection.resolvedOriginModule === module &&
1067 connection.module &&
1068 connection.isTargetActive(runtime)
1069 );
1070 })
1071 .map((connection) => {
1072 const dep =
1073 /** @type {HarmonyImportDependency} */
1074 (connection.dependency);
1075 return {
1076 connection,
1077 sourceOrder: /** @type {number} */ (dep.sourceOrder),
1078 rangeStart: dep.range && dep.range[0],
1079 defer: ImportPhaseUtils.isDefer(dep.phase)
1080 };
1081 });
1082 /**
1083 * bySourceOrder
1084 * @example
1085 * import a from "a"; // sourceOrder=1
1086 * import b from "b"; // sourceOrder=2
1087 *
1088 * byRangeStart
1089 * @example
1090 * import {a, b} from "a"; // sourceOrder=1
1091 * a.a(); // first range
1092 * b.b(); // second range
1093 *
1094 * If there is no reexport, we have the same source.
1095 * If there is reexport, but module has side effects, this will lead to reexport module only.
1096 * If there is side-effects-free reexport, we can get simple deterministic result with range start comparison.
1097 */
1098 references.sort(concatComparators(bySourceOrder, byRangeStart));
1099 /** @type {Map<Module, { connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true, nonDeferAccess: NonDeferAccess }>} */
1100 const referencesMap = new Map();
1101 for (const { connection, defer } of references) {
1102 const runtimeCondition = filterRuntime(runtime, (r) =>
1103 connection.isTargetActive(r)
1104 );
1105 if (runtimeCondition === false) continue;
1106 const nonDeferAccess = !defer;
1107 const module = connection.module;
1108 const entry = referencesMap.get(module);
1109 if (entry === undefined) {
1110 referencesMap.set(module, {
1111 connection,
1112 runtimeCondition,
1113 nonDeferAccess
1114 });
1115 continue;
1116 }
1117 entry.runtimeCondition = mergeRuntimeConditionNonFalse(
1118 entry.runtimeCondition,
1119 runtimeCondition,
1120 runtime
1121 );
1122 entry.nonDeferAccess = mergeNonDeferAccess(
1123 entry.nonDeferAccess,
1124 nonDeferAccess
1125 );
1126 }
1127 return referencesMap.values();
1128 };
1129
1130 /**
1131 * @param {ModuleGraphConnection} connection graph connection
1132 * @param {RuntimeSpec | true} runtimeCondition runtime condition
1133 * @param {NonDeferAccess} nonDeferAccess non-defer access
1134 * @returns {void}
1135 */
1136 const enterModule = (connection, runtimeCondition, nonDeferAccess) => {
1137 const module = connection.module;
1138 if (!module) return;
1139 const existingEntry = existingEntries.get(module);
1140 if (
1141 existingEntry &&
1142 existingEntry.runtimeCondition === true &&
1143 existingEntry.nonDeferAccess === true
1144 ) {
1145 return;
1146 }
1147 if (modulesSet.has(module)) {
1148 existingEntries.set(module, {
1149 runtimeCondition: true,
1150 nonDeferAccess: true
1151 });
1152 if (runtimeCondition !== true) {
1153 throw new Error(
1154 `Cannot runtime-conditional concatenate a module (${module.identifier()} in ${this.rootModule.identifier()}, ${runtimeConditionToString(
1155 runtimeCondition
1156 )}). This should not happen.`
1157 );
1158 }
1159 if (nonDeferAccess !== true) {
1160 throw new Error(
1161 `Cannot deferred concatenate a module (${module.identifier()} in ${this.rootModule.identifier()}. This should not happen.`
1162 );
1163 }
1164 const imports = getConcatenatedImports(module);
1165 for (const {
1166 connection,
1167 runtimeCondition,
1168 nonDeferAccess
1169 } of imports) {
1170 enterModule(connection, runtimeCondition, nonDeferAccess);
1171 }
1172 list.push({
1173 type: "concatenated",
1174 module: connection.module,
1175 runtimeCondition,
1176 nonDeferAccess
1177 });
1178 } else {
1179 /** @type {RuntimeSpec | boolean} */
1180 let reducedRuntimeCondition;
1181 /** @type {NonDeferAccess} */
1182 let reducedNonDeferAccess;
1183 if (existingEntry !== undefined) {
1184 reducedRuntimeCondition = subtractRuntimeCondition(
1185 runtimeCondition,
1186 existingEntry.runtimeCondition,
1187 runtime
1188 );
1189 reducedNonDeferAccess = subtractNonDeferAccess(
1190 nonDeferAccess,
1191 existingEntry.nonDeferAccess
1192 );
1193 if (
1194 reducedRuntimeCondition === false &&
1195 reducedNonDeferAccess === false
1196 ) {
1197 return;
1198 }
1199 if (reducedRuntimeCondition !== false) {
1200 existingEntry.runtimeCondition = mergeRuntimeConditionNonFalse(
1201 existingEntry.runtimeCondition,
1202 reducedRuntimeCondition,
1203 runtime
1204 );
1205 }
1206 if (reducedNonDeferAccess !== false) {
1207 existingEntry.nonDeferAccess = mergeNonDeferAccess(
1208 existingEntry.nonDeferAccess,
1209 reducedNonDeferAccess
1210 );
1211 }
1212 } else {
1213 reducedRuntimeCondition = runtimeCondition;
1214 reducedNonDeferAccess = nonDeferAccess;
1215 existingEntries.set(connection.module, {
1216 runtimeCondition,
1217 nonDeferAccess
1218 });
1219 }
1220 if (list.length > 0) {
1221 const lastItem = list[list.length - 1];
1222 if (
1223 lastItem.type === "external" &&
1224 lastItem.module === connection.module
1225 ) {
1226 lastItem.runtimeCondition = mergeRuntimeCondition(
1227 lastItem.runtimeCondition,
1228 reducedRuntimeCondition,
1229 runtime
1230 );
1231 lastItem.nonDeferAccess = mergeNonDeferAccess(
1232 lastItem.nonDeferAccess,
1233 reducedNonDeferAccess
1234 );
1235 return;
1236 }
1237 }
1238 list.push({
1239 type: "external",
1240 get module() {
1241 // We need to use a getter here, because the module in the dependency
1242 // could be replaced by some other process (i. e. also replaced with a
1243 // concatenated module)
1244 return connection.module;
1245 },
1246 runtimeCondition: reducedRuntimeCondition,
1247 nonDeferAccess: reducedNonDeferAccess
1248 });
1249 }
1250 };
1251
1252 existingEntries.set(rootModule, {
1253 runtimeCondition: true,
1254 nonDeferAccess: true
1255 });
1256 const imports = getConcatenatedImports(rootModule);
1257 for (const { connection, runtimeCondition, nonDeferAccess } of imports) {
1258 enterModule(connection, runtimeCondition, nonDeferAccess);
1259 }
1260 list.push({
1261 type: "concatenated",
1262 module: rootModule,
1263 runtimeCondition: true,
1264 nonDeferAccess: true
1265 });
1266
1267 return list;
1268 }
1269
1270 /**
1271 * @param {Module} rootModule the root module of the concatenation
1272 * @param {Set<Module>} modules all modules in the concatenation (including the root module)
1273 * @param {AssociatedObjectForCache=} associatedObjectForCache object for caching
1274 * @param {HashFunction=} hashFunction hash function to use
1275 * @returns {string} the identifier
1276 */
1277 static _createIdentifier(
1278 rootModule,
1279 modules,
1280 associatedObjectForCache,
1281 hashFunction = DEFAULTS.HASH_FUNCTION
1282 ) {
1283 const cachedMakePathsRelative = makePathsRelative.bindContextCache(
1284 /** @type {string} */ (rootModule.context),
1285 associatedObjectForCache
1286 );
1287 /** @type {string[]} */
1288 const identifiers = [];
1289 for (const module of modules) {
1290 identifiers.push(cachedMakePathsRelative(module.identifier()));
1291 }
1292 identifiers.sort();
1293 const hash = createHash(hashFunction);
1294 hash.update(identifiers.join(" "));
1295 return `${rootModule.identifier()}|${hash.digest("hex")}`;
1296 }
1297
1298 /**
1299 * Adds the provided file dependencies to the module.
1300 * @param {FileSystemDependencies} fileDependencies set where file dependencies are added to
1301 * @param {FileSystemDependencies} contextDependencies set where context dependencies are added to
1302 * @param {FileSystemDependencies} missingDependencies set where missing dependencies are added to
1303 * @param {FileSystemDependencies} buildDependencies set where build dependencies are added to
1304 */
1305 addCacheDependencies(
1306 fileDependencies,
1307 contextDependencies,
1308 missingDependencies,
1309 buildDependencies
1310 ) {
1311 for (const module of this._modules) {
1312 module.addCacheDependencies(
1313 fileDependencies,
1314 contextDependencies,
1315 missingDependencies,
1316 buildDependencies
1317 );
1318 }
1319 }
1320
1321 /**
1322 * Generates code and runtime requirements for this module.
1323 * @param {CodeGenerationContext} context context for code generation
1324 * @returns {CodeGenerationResult} result
1325 */
1326 codeGeneration({
1327 dependencyTemplates,
1328 runtimeTemplate,
1329 moduleGraph,
1330 chunkGraph,
1331 runtime: generationRuntime,
1332 runtimes,
1333 codeGenerationResults
1334 }) {
1335 const { concatenatedModuleInfo } = ConcatenatedModule.getCompilationHooks(
1336 this.compilation
1337 );
1338
1339 /** @type {RuntimeRequirements} */
1340 const runtimeRequirements = new Set();
1341 const runtime = intersectRuntime(generationRuntime, this._runtime);
1342
1343 const requestShortener = runtimeTemplate.requestShortener;
1344 // Meta info for each module
1345 const [modulesWithInfo, moduleToInfoMap] = this._getModulesWithInfo(
1346 moduleGraph,
1347 runtime
1348 );
1349
1350 // Set with modules that need a generated namespace object
1351 /** @type {NeededNamespaceObjects} */
1352 const neededNamespaceObjects = new Set();
1353
1354 // List of all used names to avoid conflicts
1355 const allUsedNames = new Set(RESERVED_NAMES);
1356
1357 // Generate source code and analyse scopes
1358 // Prepare a ReplaceSource for the final source
1359 for (const info of moduleToInfoMap.values()) {
1360 this._analyseModule(
1361 moduleToInfoMap,
1362 info,
1363 dependencyTemplates,
1364 runtimeTemplate,
1365 moduleGraph,
1366 chunkGraph,
1367 runtime,
1368 runtimes,
1369 /** @type {CodeGenerationResults} */
1370 (codeGenerationResults),
1371 allUsedNames
1372 );
1373 }
1374
1375 // Updated Top level declarations are created by renaming
1376 /** @type {TopLevelDeclarations} */
1377 const topLevelDeclarations = new Set();
1378
1379 // List of additional names in scope for module references
1380 /** @type {Map<string, ScopeInfo>} */
1381 const usedNamesInScopeInfo = new Map();
1382
1383 // Set of already checked scopes
1384 /** @type {Set<Scope>} */
1385 const ignoredScopes = new Set();
1386
1387 // get all global names
1388 for (const info of modulesWithInfo) {
1389 if (info.type === "concatenated") {
1390 // ignore symbols from moduleScope
1391 if (info.moduleScope) {
1392 ignoredScopes.add(info.moduleScope);
1393 }
1394
1395 // The super class expression in class scopes behaves weird
1396 // We get ranges of all super class expressions to make
1397 // renaming to work correctly
1398 /** @typedef {{ range: Range, variables: Variable[] }} ClassInfo */
1399 /** @type {WeakMap<Scope, ClassInfo[]>} */
1400 const superClassCache = new WeakMap();
1401 /**
1402 * @param {Scope} scope scope
1403 * @returns {ClassInfo[]} result
1404 */
1405 const getSuperClassExpressions = (scope) => {
1406 const cacheEntry = superClassCache.get(scope);
1407 if (cacheEntry !== undefined) return cacheEntry;
1408 /** @type {ClassInfo[]} */
1409 const superClassExpressions = [];
1410 for (const childScope of scope.childScopes) {
1411 if (childScope.type !== "class") continue;
1412 const block = childScope.block;
1413 if (
1414 (block.type === "ClassDeclaration" ||
1415 block.type === "ClassExpression") &&
1416 block.superClass
1417 ) {
1418 superClassExpressions.push({
1419 range: /** @type {Range} */ (block.superClass.range),
1420 variables: childScope.variables
1421 });
1422 }
1423 }
1424 superClassCache.set(scope, superClassExpressions);
1425 return superClassExpressions;
1426 };
1427
1428 // add global symbols
1429 if (info.globalScope) {
1430 for (const reference of info.globalScope.through) {
1431 const name = reference.identifier.name;
1432 if (ConcatenationScope.isModuleReference(name)) {
1433 const match = ConcatenationScope.matchModuleReference(name);
1434 if (!match) continue;
1435 const referencedInfo = modulesWithInfo[match.index];
1436 if (referencedInfo.type === "reference") {
1437 throw new Error("Module reference can't point to a reference");
1438 }
1439 const binding = getFinalBinding(
1440 moduleGraph,
1441 referencedInfo,
1442 match.ids,
1443 moduleToInfoMap,
1444 runtime,
1445 requestShortener,
1446 runtimeTemplate,
1447 neededNamespaceObjects,
1448 false,
1449 match.deferredImport,
1450 /** @type {BuildMeta} */
1451 (info.module.buildMeta).strictHarmonyModule,
1452 true
1453 );
1454 if (!binding.ids) continue;
1455 const { usedNames, alreadyCheckedScopes } =
1456 getUsedNamesInScopeInfo(
1457 usedNamesInScopeInfo,
1458 binding.info.module.identifier(),
1459 "name" in binding ? binding.name : ""
1460 );
1461 for (const expr of getSuperClassExpressions(reference.from)) {
1462 if (
1463 expr.range[0] <=
1464 /** @type {Range} */ (reference.identifier.range)[0] &&
1465 expr.range[1] >=
1466 /** @type {Range} */ (reference.identifier.range)[1]
1467 ) {
1468 for (const variable of expr.variables) {
1469 usedNames.add(variable.name);
1470 }
1471 }
1472 }
1473 addScopeSymbols(
1474 reference.from,
1475 usedNames,
1476 alreadyCheckedScopes,
1477 ignoredScopes
1478 );
1479 } else {
1480 allUsedNames.add(name);
1481 }
1482 }
1483 }
1484 }
1485 }
1486
1487 /**
1488 * @param {string} name the name to find a new name for
1489 * @param {ConcatenatedModuleInfo} info the info of the module
1490 * @param {Reference[]} references the references to the name
1491 * @returns {string | undefined} the new name or undefined if the name is not found
1492 */
1493 const _findNewName = (name, info, references) => {
1494 const { usedNames, alreadyCheckedScopes } = getUsedNamesInScopeInfo(
1495 usedNamesInScopeInfo,
1496 info.module.identifier(),
1497 name
1498 );
1499 if (allUsedNames.has(name) || usedNames.has(name)) {
1500 for (const ref of references) {
1501 addScopeSymbols(
1502 ref.from,
1503 usedNames,
1504 alreadyCheckedScopes,
1505 ignoredScopes
1506 );
1507 }
1508 const newName = findNewName(
1509 name,
1510 allUsedNames,
1511 usedNames,
1512 info.module.readableIdentifier(requestShortener)
1513 );
1514 allUsedNames.add(newName);
1515 info.internalNames.set(name, newName);
1516 topLevelDeclarations.add(newName);
1517 return newName;
1518 }
1519 };
1520
1521 /**
1522 * @param {string} name the name to find a new name for
1523 * @param {ConcatenatedModuleInfo} info the info of the module
1524 * @param {Reference[]} references the references to the name
1525 * @returns {string | undefined} the new name or undefined if the name is not found
1526 */
1527 const _findNewNameForSpecifier = (name, info, references) => {
1528 const { usedNames: moduleUsedNames, alreadyCheckedScopes } =
1529 getUsedNamesInScopeInfo(
1530 usedNamesInScopeInfo,
1531 info.module.identifier(),
1532 name
1533 );
1534 /** @type {UsedNames} */
1535 const referencesUsedNames = new Set();
1536 for (const ref of references) {
1537 addScopeSymbols(
1538 ref.from,
1539 referencesUsedNames,
1540 alreadyCheckedScopes,
1541 ignoredScopes
1542 );
1543 }
1544 if (moduleUsedNames.has(name) || referencesUsedNames.has(name)) {
1545 const newName = findNewName(
1546 name,
1547 allUsedNames,
1548 new Set([...moduleUsedNames, ...referencesUsedNames]),
1549 info.module.readableIdentifier(requestShortener)
1550 );
1551 allUsedNames.add(newName);
1552 topLevelDeclarations.add(newName);
1553 return newName;
1554 }
1555 };
1556
1557 // generate names for symbols
1558 for (const info of moduleToInfoMap.values()) {
1559 const { usedNames: namespaceObjectUsedNames } = getUsedNamesInScopeInfo(
1560 usedNamesInScopeInfo,
1561 info.module.identifier(),
1562 ""
1563 );
1564 switch (info.type) {
1565 case "concatenated": {
1566 const variables = /** @type {Scope} */ (info.moduleScope).variables;
1567 for (const variable of variables) {
1568 const name = variable.name;
1569 const references = getAllReferences(variable);
1570 const newName = _findNewName(name, info, references);
1571 if (newName) {
1572 const source = /** @type {ReplaceSource} */ (info.source);
1573 const allIdentifiers = new Set([
1574 ...references.map((r) => r.identifier),
1575 ...variable.identifiers
1576 ]);
1577 for (const identifier of allIdentifiers) {
1578 const r = /** @type {Range} */ (identifier.range);
1579 const path = getPathInAst(
1580 /** @type {NonNullable<ConcatenatedModuleInfo["ast"]>} */
1581 (info.ast),
1582 identifier
1583 );
1584 if (path && path.length > 1) {
1585 const maybeProperty =
1586 path[1].type === "AssignmentPattern" &&
1587 path[1].left === path[0]
1588 ? path[2]
1589 : path[1];
1590 if (
1591 maybeProperty.type === "Property" &&
1592 maybeProperty.shorthand
1593 ) {
1594 source.insert(r[1], `: ${newName}`);
1595 continue;
1596 }
1597 }
1598 source.replace(r[0], r[1] - 1, newName);
1599 }
1600 } else {
1601 allUsedNames.add(name);
1602 info.internalNames.set(name, name);
1603 topLevelDeclarations.add(name);
1604 }
1605 }
1606 /** @type {string} */
1607 let namespaceObjectName;
1608 if (info.namespaceExportSymbol) {
1609 namespaceObjectName =
1610 /** @type {string} */
1611 (info.internalNames.get(info.namespaceExportSymbol));
1612 } else {
1613 namespaceObjectName = findNewName(
1614 "namespaceObject",
1615 allUsedNames,
1616 namespaceObjectUsedNames,
1617 info.module.readableIdentifier(requestShortener)
1618 );
1619 allUsedNames.add(namespaceObjectName);
1620 }
1621 info.namespaceObjectName = namespaceObjectName;
1622 topLevelDeclarations.add(namespaceObjectName);
1623 break;
1624 }
1625 case "external": {
1626 const externalName = findNewName(
1627 "",
1628 allUsedNames,
1629 namespaceObjectUsedNames,
1630 info.module.readableIdentifier(requestShortener)
1631 );
1632 allUsedNames.add(externalName);
1633 info.name = externalName;
1634 topLevelDeclarations.add(externalName);
1635
1636 if (info.deferred) {
1637 const externalName = findNewName(
1638 "deferred",
1639 allUsedNames,
1640 namespaceObjectUsedNames,
1641 info.module.readableIdentifier(requestShortener)
1642 );
1643 allUsedNames.add(externalName);
1644 info.deferredName = externalName;
1645 topLevelDeclarations.add(externalName);
1646
1647 const externalNameInterop = findNewName(
1648 "deferredNamespaceObject",
1649 allUsedNames,
1650 namespaceObjectUsedNames,
1651 info.module.readableIdentifier(requestShortener)
1652 );
1653 allUsedNames.add(externalNameInterop);
1654 info.deferredNamespaceObjectName = externalNameInterop;
1655 topLevelDeclarations.add(externalNameInterop);
1656 }
1657 break;
1658 }
1659 }
1660 const buildMeta = /** @type {BuildMeta} */ (info.module.buildMeta);
1661 if (buildMeta.exportsType !== "namespace") {
1662 const externalNameInterop = findNewName(
1663 "namespaceObject",
1664 allUsedNames,
1665 namespaceObjectUsedNames,
1666 info.module.readableIdentifier(requestShortener)
1667 );
1668 allUsedNames.add(externalNameInterop);
1669 info.interopNamespaceObjectName = externalNameInterop;
1670 topLevelDeclarations.add(externalNameInterop);
1671 }
1672 if (
1673 buildMeta.exportsType === "default" &&
1674 buildMeta.defaultObject !== "redirect" &&
1675 info.interopNamespaceObject2Used
1676 ) {
1677 const externalNameInterop = findNewName(
1678 "namespaceObject2",
1679 allUsedNames,
1680 namespaceObjectUsedNames,
1681 info.module.readableIdentifier(requestShortener)
1682 );
1683 allUsedNames.add(externalNameInterop);
1684 info.interopNamespaceObject2Name = externalNameInterop;
1685 topLevelDeclarations.add(externalNameInterop);
1686 }
1687 if (buildMeta.exportsType === "dynamic" || !buildMeta.exportsType) {
1688 const externalNameInterop = findNewName(
1689 "default",
1690 allUsedNames,
1691 namespaceObjectUsedNames,
1692 info.module.readableIdentifier(requestShortener)
1693 );
1694 allUsedNames.add(externalNameInterop);
1695 info.interopDefaultAccessName = externalNameInterop;
1696 topLevelDeclarations.add(externalNameInterop);
1697 }
1698 }
1699
1700 // Find and replace references to modules
1701 for (const info of moduleToInfoMap.values()) {
1702 if (info.type === "concatenated") {
1703 const globalScope = /** @type {Scope} */ (info.globalScope);
1704 // group references by name
1705 /** @type {Map<string, Reference[]>} */
1706 const referencesByName = new Map();
1707 for (const reference of globalScope.through) {
1708 const name = reference.identifier.name;
1709 if (!referencesByName.has(name)) {
1710 referencesByName.set(name, []);
1711 }
1712 /** @type {Reference[]} */
1713 (referencesByName.get(name)).push(reference);
1714 }
1715 for (const [name, references] of referencesByName) {
1716 const match = ConcatenationScope.matchModuleReference(name);
1717 if (match) {
1718 const referencedInfo = modulesWithInfo[match.index];
1719 if (referencedInfo.type === "reference") {
1720 throw new Error("Module reference can't point to a reference");
1721 }
1722 const concatenationScope = /** @type {ConcatenatedModuleInfo} */ (
1723 referencedInfo
1724 ).concatenationScope;
1725 const exportId = match.ids[0];
1726 const specifier =
1727 concatenationScope && concatenationScope.getRawExport(exportId);
1728 if (specifier) {
1729 const newName = _findNewNameForSpecifier(
1730 specifier,
1731 info,
1732 references
1733 );
1734 const initFragmentChanged =
1735 newName &&
1736 concatenatedModuleInfo.call(
1737 {
1738 rawExportMap: new Map([
1739 [exportId, /** @type {string} */ (newName)]
1740 ])
1741 },
1742 /** @type {ConcatenatedModuleInfo} */ (referencedInfo)
1743 );
1744 if (initFragmentChanged) {
1745 concatenationScope.setRawExportMap(exportId, newName);
1746 }
1747 }
1748 const finalName = getFinalName(
1749 moduleGraph,
1750 referencedInfo,
1751 match.ids,
1752 moduleToInfoMap,
1753 runtime,
1754 requestShortener,
1755 runtimeTemplate,
1756 neededNamespaceObjects,
1757 match.call,
1758 match.deferredImport,
1759 !match.directImport,
1760 /** @type {BuildMeta} */
1761 (info.module.buildMeta).strictHarmonyModule,
1762 match.asiSafe
1763 );
1764
1765 for (const reference of references) {
1766 const r = /** @type {Range} */ (reference.identifier.range);
1767 const source = /** @type {ReplaceSource} */ (info.source);
1768 // range is extended by 2 chars to cover the appended "._"
1769 source.replace(r[0], r[1] + 1, finalName);
1770 }
1771 }
1772 }
1773 }
1774 }
1775
1776 // Map with all root exposed used exports
1777 /** @type {Map<string, (requestShortener: RequestShortener) => string>} */
1778 const exportsMap = new Map();
1779
1780 // Set with all root exposed unused exports
1781 /** @type {Set<string>} */
1782 const unusedExports = new Set();
1783
1784 const rootInfo =
1785 /** @type {ConcatenatedModuleInfo} */
1786 (moduleToInfoMap.get(this.rootModule));
1787 const strictHarmonyModule =
1788 /** @type {BuildMeta} */
1789 (rootInfo.module.buildMeta).strictHarmonyModule;
1790 const exportsInfo = moduleGraph.getExportsInfo(rootInfo.module);
1791 /** @type {Record<string, string>} */
1792 const exportsFinalName = {};
1793 for (const exportInfo of exportsInfo.orderedExports) {
1794 const name = exportInfo.name;
1795 if (exportInfo.provided === false) continue;
1796 const used = exportInfo.getUsedName(undefined, runtime);
1797 if (!used) {
1798 unusedExports.add(name);
1799 continue;
1800 }
1801 exportsMap.set(used, (requestShortener) => {
1802 try {
1803 const finalName = getFinalName(
1804 moduleGraph,
1805 rootInfo,
1806 [name],
1807 moduleToInfoMap,
1808 runtime,
1809 requestShortener,
1810 runtimeTemplate,
1811 neededNamespaceObjects,
1812 false,
1813 false,
1814 false,
1815 strictHarmonyModule,
1816 true
1817 );
1818 exportsFinalName[used] = finalName;
1819 return `/* ${
1820 exportInfo.isReexport() ? "reexport" : "binding"
1821 } */ ${finalName}`;
1822 } catch (err) {
1823 /** @type {Error} */
1824 (err).message +=
1825 `\nwhile generating the root export '${name}' (used name: '${used}')`;
1826 throw err;
1827 }
1828 });
1829 }
1830
1831 const result = new ConcatSource();
1832
1833 // add harmony compatibility flag (must be first because of possible circular dependencies)
1834 let shouldAddHarmonyFlag = false;
1835 const rootExportsInfo = moduleGraph.getExportsInfo(this);
1836 if (
1837 rootExportsInfo.otherExportsInfo.getUsed(runtime) !== UsageState.Unused ||
1838 rootExportsInfo.getReadOnlyExportInfo("__esModule").getUsed(runtime) !==
1839 UsageState.Unused
1840 ) {
1841 shouldAddHarmonyFlag = true;
1842 }
1843
1844 // define exports
1845 if (exportsMap.size > 0) {
1846 /** @type {string[]} */
1847 const definitions = [];
1848 for (const [key, value] of exportsMap) {
1849 definitions.push(
1850 `\n ${propertyName(key)}: ${runtimeTemplate.returningFunction(
1851 value(requestShortener)
1852 )}`
1853 );
1854 }
1855
1856 runtimeRequirements.add(RuntimeGlobals.exports);
1857 runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
1858
1859 if (shouldAddHarmonyFlag) {
1860 result.add("// ESM COMPAT FLAG\n");
1861 result.add(
1862 runtimeTemplate.defineEsModuleFlagStatement({
1863 exportsArgument: this.exportsArgument,
1864 runtimeRequirements
1865 })
1866 );
1867 }
1868
1869 const exportsSource =
1870 "\n// EXPORTS\n" +
1871 `${RuntimeGlobals.definePropertyGetters}(${this.exportsArgument}, {${definitions.join(
1872 ","
1873 )}\n});\n`;
1874
1875 const { onDemandExportsGeneration } =
1876 ConcatenatedModule.getCompilationHooks(this.compilation);
1877
1878 if (
1879 !onDemandExportsGeneration.call(
1880 this,
1881 runtimes,
1882 exportsSource,
1883 exportsFinalName
1884 )
1885 ) {
1886 result.add(exportsSource);
1887 }
1888 }
1889
1890 // list unused exports
1891 if (unusedExports.size > 0) {
1892 result.add(
1893 `\n// UNUSED EXPORTS: ${joinIterableWithComma(unusedExports)}\n`
1894 );
1895 }
1896
1897 // generate namespace objects
1898 /** @type {Map<ConcatenatedModuleInfo, string>} */
1899 const namespaceObjectSources = new Map();
1900 for (const info of neededNamespaceObjects) {
1901 if (info.namespaceExportSymbol) continue;
1902 /** @type {string[]} */
1903 const nsObj = [];
1904 const exportsInfo = moduleGraph.getExportsInfo(info.module);
1905 for (const exportInfo of exportsInfo.orderedExports) {
1906 if (exportInfo.provided === false) continue;
1907 const usedName = exportInfo.getUsedName(undefined, runtime);
1908 if (usedName) {
1909 const finalName = getFinalName(
1910 moduleGraph,
1911 info,
1912 [exportInfo.name],
1913 moduleToInfoMap,
1914 runtime,
1915 requestShortener,
1916 runtimeTemplate,
1917 neededNamespaceObjects,
1918 false,
1919 false,
1920 undefined,
1921 /** @type {BuildMeta} */
1922 (info.module.buildMeta).strictHarmonyModule,
1923 true
1924 );
1925 nsObj.push(
1926 `\n ${propertyName(usedName)}: ${runtimeTemplate.returningFunction(
1927 finalName
1928 )}`
1929 );
1930 }
1931 }
1932 const name = info.namespaceObjectName;
1933 const defineGetters =
1934 nsObj.length > 0
1935 ? `${RuntimeGlobals.definePropertyGetters}(${name}, {${nsObj.join(
1936 ","
1937 )}\n});\n`
1938 : "";
1939 if (nsObj.length > 0) {
1940 runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
1941 }
1942 namespaceObjectSources.set(
1943 info,
1944 `
1945// NAMESPACE OBJECT: ${info.module.readableIdentifier(requestShortener)}
1946var ${name} = {};
1947${RuntimeGlobals.makeNamespaceObject}(${name});
1948${defineGetters}`
1949 );
1950 runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject);
1951 }
1952
1953 // define required namespace objects (must be before evaluation modules)
1954 for (const info of modulesWithInfo) {
1955 if (info.type === "concatenated") {
1956 const source = namespaceObjectSources.get(info);
1957 if (!source) continue;
1958 result.add(source);
1959 }
1960
1961 if (info.type === "external" && info.deferred) {
1962 const moduleId = JSON.stringify(chunkGraph.getModuleId(info.module));
1963 const loader = getOptimizedDeferredModule(
1964 moduleId,
1965 info.module.getExportsType(
1966 moduleGraph,
1967 /** @type {BuildMeta} */
1968 (this.rootModule.buildMeta).strictHarmonyModule
1969 ),
1970 // an async module will opt-out of the concat module optimization.
1971 [],
1972 runtimeRequirements
1973 );
1974 runtimeRequirements.add(RuntimeGlobals.require);
1975 result.add(
1976 `\n// DEFERRED EXTERNAL MODULE: ${info.module.readableIdentifier(requestShortener)}\nvar ${info.deferredName} = ${loader};`
1977 );
1978 if (info.deferredNamespaceObjectUsed) {
1979 runtimeRequirements.add(RuntimeGlobals.makeDeferredNamespaceObject);
1980 result.add(
1981 `\nvar ${info.deferredNamespaceObjectName} = /*#__PURE__*/${
1982 RuntimeGlobals.makeDeferredNamespaceObject
1983 }(${JSON.stringify(
1984 chunkGraph.getModuleId(info.module)
1985 )}, ${getMakeDeferredNamespaceModeFromExportsType(
1986 info.module.getExportsType(moduleGraph, strictHarmonyModule)
1987 )});`
1988 );
1989 }
1990 }
1991 }
1992
1993 /** @type {InitFragment<ChunkRenderContext>[]} */
1994 const chunkInitFragments = [];
1995
1996 // evaluate modules in order
1997 for (const rawInfo of modulesWithInfo) {
1998 /** @type {undefined | string} */
1999 let name;
2000 let isConditional = false;
2001 const info = rawInfo.type === "reference" ? rawInfo.target : rawInfo;
2002 switch (info.type) {
2003 case "concatenated": {
2004 result.add(
2005 `\n;// ${info.module.readableIdentifier(requestShortener)}\n`
2006 );
2007 result.add(/** @type {ReplaceSource} */ (info.source));
2008 if (info.chunkInitFragments) {
2009 for (const f of info.chunkInitFragments) chunkInitFragments.push(f);
2010 }
2011 if (info.runtimeRequirements) {
2012 for (const r of info.runtimeRequirements) {
2013 runtimeRequirements.add(r);
2014 }
2015 }
2016 name = info.namespaceObjectName;
2017 break;
2018 }
2019 case "external": {
2020 // deferred case is handled in the "const info of modulesWithInfo" loop above
2021 if (!info.deferred) {
2022 result.add(
2023 `\n// EXTERNAL MODULE: ${info.module.readableIdentifier(
2024 requestShortener
2025 )}\n`
2026 );
2027 runtimeRequirements.add(RuntimeGlobals.require);
2028 const { runtimeCondition } =
2029 /** @type {ExternalModuleInfo | ReferenceToModuleInfo} */
2030 (rawInfo);
2031 const condition = runtimeTemplate.runtimeConditionExpression({
2032 chunkGraph,
2033 runtimeCondition,
2034 runtime,
2035 runtimeRequirements
2036 });
2037 if (condition !== "true") {
2038 isConditional = true;
2039 result.add(`if (${condition}) {\n`);
2040 }
2041 const moduleId = JSON.stringify(
2042 chunkGraph.getModuleId(info.module)
2043 );
2044 result.add(`var ${info.name} = __webpack_require__(${moduleId});`);
2045 name = info.name;
2046 }
2047 // If a module is deferred in other places, but used as non-deferred here,
2048 // the module itself will be emitted as mod_deferred (in the case "external"),
2049 // we need to emit an extra import declaration to evaluate it in order.
2050 const { nonDeferAccess } =
2051 /** @type {ExternalModuleInfo | ReferenceToModuleInfo} */
2052 (rawInfo);
2053 if (info.deferred && nonDeferAccess) {
2054 result.add(
2055 `\n// non-deferred import to a deferred module (${info.module.readableIdentifier(requestShortener)})\nvar ${info.name} = ${info.deferredName}.a;`
2056 );
2057 }
2058 break;
2059 }
2060 default:
2061 // @ts-expect-error never is expected here
2062 throw new Error(`Unsupported concatenation entry type ${info.type}`);
2063 }
2064 if (info.interopNamespaceObjectUsed) {
2065 runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
2066 result.add(
2067 `\nvar ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name}, 2);`
2068 );
2069 }
2070 if (info.interopNamespaceObject2Used) {
2071 runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
2072 result.add(
2073 `\nvar ${info.interopNamespaceObject2Name} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name});`
2074 );
2075 }
2076 if (info.interopDefaultAccessUsed) {
2077 runtimeRequirements.add(RuntimeGlobals.compatGetDefaultExport);
2078 result.add(
2079 `\nvar ${info.interopDefaultAccessName} = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${name});`
2080 );
2081 }
2082 if (isConditional) {
2083 result.add("\n}");
2084 }
2085 }
2086
2087 /** @type {CodeGenerationResultData} */
2088 const data = new Map();
2089 if (chunkInitFragments.length > 0) {
2090 data.set("chunkInitFragments", chunkInitFragments);
2091 }
2092 data.set("topLevelDeclarations", topLevelDeclarations);
2093
2094 /** @type {CodeGenerationResult} */
2095 const resultEntry = {
2096 sources: new Map([[JAVASCRIPT_TYPE, new CachedSource(result)]]),
2097 data,
2098 runtimeRequirements
2099 };
2100
2101 return resultEntry;
2102 }
2103
2104 /**
2105 * @param {ModuleToInfoMap} modulesMap modulesMap
2106 * @param {ModuleInfo} info info
2107 * @param {DependencyTemplates} dependencyTemplates dependencyTemplates
2108 * @param {RuntimeTemplate} runtimeTemplate runtimeTemplate
2109 * @param {ModuleGraph} moduleGraph moduleGraph
2110 * @param {ChunkGraph} chunkGraph chunkGraph
2111 * @param {RuntimeSpec} runtime runtime
2112 * @param {RuntimeSpec[]} runtimes runtimes
2113 * @param {CodeGenerationResults} codeGenerationResults codeGenerationResults
2114 * @param {UsedNames} usedNames used names
2115 */
2116 _analyseModule(
2117 modulesMap,
2118 info,
2119 dependencyTemplates,
2120 runtimeTemplate,
2121 moduleGraph,
2122 chunkGraph,
2123 runtime,
2124 runtimes,
2125 codeGenerationResults,
2126 usedNames
2127 ) {
2128 if (info.type === "concatenated") {
2129 const m = info.module;
2130 try {
2131 // Create a concatenation scope to track and capture information
2132 const concatenationScope = new ConcatenationScope(
2133 modulesMap,
2134 info,
2135 usedNames
2136 );
2137
2138 // TODO cache codeGeneration results
2139 const codeGenResult = m.codeGeneration({
2140 dependencyTemplates,
2141 runtimeTemplate,
2142 moduleGraph,
2143 chunkGraph,
2144 runtime,
2145 runtimes,
2146 concatenationScope,
2147 codeGenerationResults,
2148 sourceTypes: JAVASCRIPT_TYPES
2149 });
2150 const source =
2151 /** @type {Source} */
2152 (codeGenResult.sources.get(JAVASCRIPT_TYPE));
2153 const data = codeGenResult.data;
2154 const chunkInitFragments = data && data.get("chunkInitFragments");
2155 const code = source.source().toString();
2156
2157 /** @type {Program} */
2158 let ast;
2159
2160 try {
2161 ({ ast } = JavascriptParser._parse(
2162 code,
2163 {
2164 sourceType: "module",
2165 ranges: true
2166 },
2167 JavascriptParser._getModuleParseFunction(this.compilation, m)
2168 ));
2169 } catch (_err) {
2170 const err =
2171 /** @type {Error & { loc?: { line: number, column: number } }} */
2172 (_err);
2173 if (
2174 err.loc &&
2175 typeof err.loc === "object" &&
2176 typeof err.loc.line === "number"
2177 ) {
2178 const lineNumber = err.loc.line;
2179 const lines = code.split("\n");
2180 err.message += `\n| ${lines
2181 .slice(Math.max(0, lineNumber - 3), lineNumber + 2)
2182 .join("\n| ")}`;
2183 }
2184 throw err;
2185 }
2186 const scopeManager = eslintScope.analyze(ast, {
2187 ecmaVersion: 6,
2188 sourceType: "module",
2189 optimistic: true,
2190 ignoreEval: true,
2191 impliedStrict: true
2192 });
2193 const globalScope = /** @type {Scope} */ (scopeManager.acquire(ast));
2194 const moduleScope = globalScope.childScopes[0];
2195 const resultSource = new ReplaceSource(source);
2196 info.runtimeRequirements =
2197 /** @type {ReadOnlyRuntimeRequirements} */
2198 (codeGenResult.runtimeRequirements);
2199 info.ast = ast;
2200 info.internalSource = source;
2201 info.source = resultSource;
2202 info.chunkInitFragments = chunkInitFragments;
2203 info.globalScope = globalScope;
2204 info.moduleScope = moduleScope;
2205 info.concatenationScope = concatenationScope;
2206 } catch (err) {
2207 /** @type {Error} */
2208 (err).message +=
2209 `\nwhile analyzing module ${m.identifier()} for concatenation`;
2210 throw err;
2211 }
2212 }
2213 }
2214
2215 /**
2216 * @param {ModuleGraph} moduleGraph the module graph
2217 * @param {RuntimeSpec} runtime the runtime
2218 * @returns {[ModuleInfoOrReference[], ModuleToInfoMap]} module info items
2219 */
2220 _getModulesWithInfo(moduleGraph, runtime) {
2221 const orderedConcatenationList = this._createConcatenationList(
2222 this.rootModule,
2223 this._modules,
2224 runtime,
2225 moduleGraph
2226 );
2227 /** @type {ModuleToInfoMap} */
2228 const map = new Map();
2229 const list = orderedConcatenationList.map((info, index) => {
2230 let item = map.get(info.module);
2231 if (item === undefined) {
2232 switch (info.type) {
2233 case "concatenated":
2234 item = {
2235 type: "concatenated",
2236 module: info.module,
2237 index,
2238 ast: undefined,
2239 internalSource: undefined,
2240 runtimeRequirements: undefined,
2241 source: undefined,
2242 globalScope: undefined,
2243 moduleScope: undefined,
2244 internalNames: new Map(),
2245 exportMap: undefined,
2246 rawExportMap: undefined,
2247 namespaceExportSymbol: undefined,
2248 namespaceObjectName: undefined,
2249 interopNamespaceObjectUsed: false,
2250 interopNamespaceObjectName: undefined,
2251 interopNamespaceObject2Used: false,
2252 interopNamespaceObject2Name: undefined,
2253 interopDefaultAccessUsed: false,
2254 interopDefaultAccessName: undefined,
2255 concatenationScope: undefined
2256 };
2257 break;
2258 case "external":
2259 item = {
2260 type: "external",
2261 module: info.module,
2262 runtimeCondition: info.runtimeCondition,
2263 nonDeferAccess: info.nonDeferAccess,
2264 index,
2265 name: undefined,
2266 deferredName: undefined,
2267 interopNamespaceObjectUsed: false,
2268 interopNamespaceObjectName: undefined,
2269 interopNamespaceObject2Used: false,
2270 interopNamespaceObject2Name: undefined,
2271 interopDefaultAccessUsed: false,
2272 interopDefaultAccessName: undefined,
2273 deferred: moduleGraph.isDeferred(info.module),
2274 deferredNamespaceObjectName: undefined,
2275 deferredNamespaceObjectUsed: false
2276 };
2277 break;
2278 default:
2279 throw new Error(
2280 `Unsupported concatenation entry type ${info.type}`
2281 );
2282 }
2283 map.set(
2284 /** @type {ModuleInfo} */ (item).module,
2285 /** @type {ModuleInfo} */ (item)
2286 );
2287 return /** @type {ModuleInfo} */ (item);
2288 }
2289 /** @type {ReferenceToModuleInfo} */
2290 const ref = {
2291 type: "reference",
2292 runtimeCondition: info.runtimeCondition,
2293 nonDeferAccess: info.nonDeferAccess,
2294 target: item
2295 };
2296 return ref;
2297 });
2298 return [list, map];
2299 }
2300
2301 /**
2302 * Updates the hash with the data contributed by this instance.
2303 * @param {Hash} hash the hash used to track dependencies
2304 * @param {UpdateHashContext} context context
2305 * @returns {void}
2306 */
2307 updateHash(hash, context) {
2308 const { chunkGraph, runtime } = context;
2309 for (const info of this._createConcatenationList(
2310 this.rootModule,
2311 this._modules,
2312 intersectRuntime(runtime, this._runtime),
2313 chunkGraph.moduleGraph
2314 )) {
2315 switch (info.type) {
2316 case "concatenated":
2317 info.module.updateHash(hash, context);
2318 break;
2319 case "external":
2320 hash.update(`${chunkGraph.getModuleId(info.module)}`);
2321 // TODO runtimeCondition
2322 break;
2323 }
2324 }
2325 super.updateHash(hash, context);
2326 }
2327
2328 /**
2329 * @param {ObjectDeserializerContext} context context
2330 * @returns {ConcatenatedModule} ConcatenatedModule
2331 */
2332 static deserialize(context) {
2333 const obj = new ConcatenatedModule({
2334 identifier: /** @type {EXPECTED_ANY} */ (undefined),
2335 rootModule: /** @type {EXPECTED_ANY} */ (undefined),
2336 modules: /** @type {EXPECTED_ANY} */ (undefined),
2337 runtime: undefined,
2338 compilation: /** @type {EXPECTED_ANY} */ (undefined)
2339 });
2340 obj.deserialize(context);
2341 return obj;
2342 }
2343}
2344
2345makeSerializable(ConcatenatedModule, "webpack/lib/optimize/ConcatenatedModule");
2346
2347module.exports = ConcatenatedModule;
Note: See TracBrowser for help on using the repository browser.