summaryrefslogtreecommitdiff
path: root/node_modules/webpack/lib/optimize/ConcatenatedModule.js
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2024-08-30 17:21:18 +0800
committerlittleblack111 <littleblack11111@gmail.com>2024-08-30 17:21:18 +0800
commitefbc2ffe6a1ee5ec38a4396305561d6515d0943e (patch)
tree2b4c94f18f2c792dfda813050755d5c0273fae22 /node_modules/webpack/lib/optimize/ConcatenatedModule.js
parent43acceb75957c880a5ba5a31aae221394a36d5f6 (diff)
node fixes, updates
Diffstat (limited to 'node_modules/webpack/lib/optimize/ConcatenatedModule.js')
-rw-r--r--node_modules/webpack/lib/optimize/ConcatenatedModule.js2008
1 files changed, 2008 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/optimize/ConcatenatedModule.js b/node_modules/webpack/lib/optimize/ConcatenatedModule.js
new file mode 100644
index 00000000..5321875c
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/ConcatenatedModule.js
@@ -0,0 +1,2008 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const eslintScope = require("eslint-scope");
+const Referencer = require("eslint-scope/lib/referencer");
+const { SyncBailHook } = require("tapable");
+const {
+ CachedSource,
+ ConcatSource,
+ ReplaceSource
+} = require("webpack-sources");
+const ConcatenationScope = require("../ConcatenationScope");
+const { UsageState } = require("../ExportsInfo");
+const Module = require("../Module");
+const { JAVASCRIPT_MODULE_TYPE_ESM } = require("../ModuleTypeConstants");
+const RuntimeGlobals = require("../RuntimeGlobals");
+const Template = require("../Template");
+const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
+const JavascriptParser = require("../javascript/JavascriptParser");
+const { equals } = require("../util/ArrayHelpers");
+const LazySet = require("../util/LazySet");
+const { concatComparators } = require("../util/comparators");
+const createHash = require("../util/createHash");
+const { makePathsRelative } = require("../util/identifier");
+const makeSerializable = require("../util/makeSerializable");
+const { getAllReferences, getPathInAst } = require("../util/mergeScope");
+const propertyAccess = require("../util/propertyAccess");
+const { propertyName } = require("../util/propertyName");
+const {
+ filterRuntime,
+ intersectRuntime,
+ mergeRuntimeCondition,
+ mergeRuntimeConditionNonFalse,
+ runtimeConditionToString,
+ subtractRuntimeCondition
+} = require("../util/runtime");
+
+/** @typedef {import("eslint-scope").Reference} Reference */
+/** @typedef {import("eslint-scope").Scope} Scope */
+/** @typedef {import("eslint-scope").Variable} Variable */
+/** @typedef {import("webpack-sources").Source} Source */
+/** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
+/** @typedef {import("../ChunkGraph")} ChunkGraph */
+/** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
+/** @typedef {import("../Compilation")} Compilation */
+/** @typedef {import("../Dependency")} Dependency */
+/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
+/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
+/** @typedef {import("../DependencyTemplates")} DependencyTemplates */
+/** @typedef {import("../ExportsInfo").ExportInfo} ExportInfo */
+/** @typedef {import("../Module").BuildInfo} BuildInfo */
+/** @typedef {import("../Module").BuildMeta} BuildMeta */
+/** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
+/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
+/** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
+/** @typedef {import("../Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
+/** @typedef {import("../Module").SourceTypes} SourceTypes */
+/** @typedef {import("../ModuleGraph")} ModuleGraph */
+/** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
+/** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
+/** @typedef {import("../ModuleParseError")} ModuleParseError */
+/** @typedef {import("../RequestShortener")} RequestShortener */
+/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
+/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
+/** @typedef {import("../WebpackError")} WebpackError */
+/** @typedef {import("../javascript/JavascriptModulesPlugin").ChunkRenderContext} ChunkRenderContext */
+/** @typedef {import("../javascript/JavascriptParser").Program} Program */
+/** @typedef {import("../javascript/JavascriptParser").Range} Range */
+/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
+/** @typedef {import("../util/Hash")} Hash */
+/** @typedef {typeof import("../util/Hash")} HashConstructor */
+/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
+/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
+
+/**
+ * @template T
+ * @typedef {import("../InitFragment")<T>} InitFragment
+ */
+
+/**
+ * @template T
+ * @typedef {import("../util/comparators").Comparator<T>} Comparator
+ */
+
+// fix eslint-scope to support class properties correctly
+// cspell:word Referencer
+const ReferencerClass = /** @type {any} */ (Referencer);
+if (!ReferencerClass.prototype.PropertyDefinition) {
+ ReferencerClass.prototype.PropertyDefinition =
+ ReferencerClass.prototype.Property;
+}
+
+/**
+ * @typedef {object} ReexportInfo
+ * @property {Module} module
+ * @property {string[]} export
+ */
+
+/** @typedef {RawBinding | SymbolBinding} Binding */
+
+/**
+ * @typedef {object} RawBinding
+ * @property {ModuleInfo} info
+ * @property {string} rawName
+ * @property {string=} comment
+ * @property {string[]} ids
+ * @property {string[]} exportName
+ */
+
+/**
+ * @typedef {object} SymbolBinding
+ * @property {ConcatenatedModuleInfo} info
+ * @property {string} name
+ * @property {string=} comment
+ * @property {string[]} ids
+ * @property {string[]} exportName
+ */
+
+/** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo } ModuleInfo */
+/** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo | ReferenceToModuleInfo } ModuleInfoOrReference */
+
+/**
+ * @typedef {object} ConcatenatedModuleInfo
+ * @property {"concatenated"} type
+ * @property {Module} module
+ * @property {number} index
+ * @property {Program | undefined} ast
+ * @property {Source | undefined} internalSource
+ * @property {ReplaceSource} source
+ * @property {InitFragment<ChunkRenderContext>[]=} chunkInitFragments
+ * @property {ReadOnlyRuntimeRequirements | undefined} runtimeRequirements
+ * @property {Scope | undefined} globalScope
+ * @property {Scope | undefined} moduleScope
+ * @property {Map<string, string>} internalNames
+ * @property {Map<string, string> | undefined} exportMap
+ * @property {Map<string, string> | undefined} rawExportMap
+ * @property {string=} namespaceExportSymbol
+ * @property {string | undefined} namespaceObjectName
+ * @property {boolean} interopNamespaceObjectUsed
+ * @property {string | undefined} interopNamespaceObjectName
+ * @property {boolean} interopNamespaceObject2Used
+ * @property {string | undefined} interopNamespaceObject2Name
+ * @property {boolean} interopDefaultAccessUsed
+ * @property {string | undefined} interopDefaultAccessName
+ */
+
+/**
+ * @typedef {object} ExternalModuleInfo
+ * @property {"external"} type
+ * @property {Module} module
+ * @property {RuntimeSpec | boolean} runtimeCondition
+ * @property {number} index
+ * @property {string | undefined} name
+ * @property {boolean} interopNamespaceObjectUsed
+ * @property {string | undefined} interopNamespaceObjectName
+ * @property {boolean} interopNamespaceObject2Used
+ * @property {string | undefined} interopNamespaceObject2Name
+ * @property {boolean} interopDefaultAccessUsed
+ * @property {string | undefined} interopDefaultAccessName
+ */
+
+/**
+ * @typedef {object} ReferenceToModuleInfo
+ * @property {"reference"} type
+ * @property {RuntimeSpec | boolean} runtimeCondition
+ * @property {ConcatenatedModuleInfo | ExternalModuleInfo} target
+ */
+
+/** @typedef {Set<string>} UsedNames */
+
+const RESERVED_NAMES = new Set(
+ [
+ // internal names (should always be renamed)
+ ConcatenationScope.DEFAULT_EXPORT,
+ ConcatenationScope.NAMESPACE_OBJECT_EXPORT,
+
+ // keywords
+ "abstract,arguments,async,await,boolean,break,byte,case,catch,char,class,const,continue",
+ "debugger,default,delete,do,double,else,enum,eval,export,extends,false,final,finally,float",
+ "for,function,goto,if,implements,import,in,instanceof,int,interface,let,long,native,new,null",
+ "package,private,protected,public,return,short,static,super,switch,synchronized,this,throw",
+ "throws,transient,true,try,typeof,var,void,volatile,while,with,yield",
+
+ // commonjs/amd
+ "module,__dirname,__filename,exports,require,define",
+
+ // js globals
+ "Array,Date,eval,function,hasOwnProperty,Infinity,isFinite,isNaN,isPrototypeOf,length,Math",
+ "NaN,name,Number,Object,prototype,String,toString,undefined,valueOf",
+
+ // browser globals
+ "alert,all,anchor,anchors,area,assign,blur,button,checkbox,clearInterval,clearTimeout",
+ "clientInformation,close,closed,confirm,constructor,crypto,decodeURI,decodeURIComponent",
+ "defaultStatus,document,element,elements,embed,embeds,encodeURI,encodeURIComponent,escape",
+ "event,fileUpload,focus,form,forms,frame,innerHeight,innerWidth,layer,layers,link,location",
+ "mimeTypes,navigate,navigator,frames,frameRate,hidden,history,image,images,offscreenBuffering",
+ "open,opener,option,outerHeight,outerWidth,packages,pageXOffset,pageYOffset,parent,parseFloat",
+ "parseInt,password,pkcs11,plugin,prompt,propertyIsEnum,radio,reset,screenX,screenY,scroll",
+ "secure,select,self,setInterval,setTimeout,status,submit,taint,text,textarea,top,unescape",
+ "untaint,window",
+
+ // window events
+ "onblur,onclick,onerror,onfocus,onkeydown,onkeypress,onkeyup,onmouseover,onload,onmouseup,onmousedown,onsubmit"
+ ]
+ .join(",")
+ .split(",")
+);
+
+/**
+ * @template T
+ * @param {string} property property
+ * @param {function(T[keyof T], T[keyof T]): 0 | 1 | -1} comparator comparator
+ * @returns {Comparator<T>} comparator
+ */
+const createComparator = (property, comparator) => (a, b) =>
+ comparator(
+ a[/** @type {keyof T} */ (property)],
+ b[/** @type {keyof T} */ (property)]
+ );
+
+/**
+ * @param {number} a a
+ * @param {number} b b
+ * @returns {0 | 1 | -1} result
+ */
+const compareNumbers = (a, b) => {
+ if (Number.isNaN(a)) {
+ if (!Number.isNaN(b)) {
+ return 1;
+ }
+ } else {
+ if (Number.isNaN(b)) {
+ return -1;
+ }
+ if (a !== b) {
+ return a < b ? -1 : 1;
+ }
+ }
+ return 0;
+};
+const bySourceOrder = createComparator("sourceOrder", compareNumbers);
+const byRangeStart = createComparator("rangeStart", compareNumbers);
+
+/**
+ * @param {Iterable<string>} iterable iterable object
+ * @returns {string} joined iterable object
+ */
+const joinIterableWithComma = iterable => {
+ // This is more performant than Array.from().join(", ")
+ // as it doesn't create an array
+ let str = "";
+ let first = true;
+ for (const item of iterable) {
+ if (first) {
+ first = false;
+ } else {
+ str += ", ";
+ }
+ str += item;
+ }
+ return str;
+};
+
+/**
+ * @typedef {object} ConcatenationEntry
+ * @property {"concatenated" | "external"} type
+ * @property {Module} module
+ * @property {RuntimeSpec | boolean} runtimeCondition
+ */
+
+/**
+ * @param {ModuleGraph} moduleGraph the module graph
+ * @param {ModuleInfo} info module info
+ * @param {string[]} exportName exportName
+ * @param {Map<Module, ModuleInfo>} moduleToInfoMap moduleToInfoMap
+ * @param {RuntimeSpec} runtime for which runtime
+ * @param {RequestShortener} requestShortener the request shortener
+ * @param {RuntimeTemplate} runtimeTemplate the runtime template
+ * @param {Set<ConcatenatedModuleInfo>} neededNamespaceObjects modules for which a namespace object should be generated
+ * @param {boolean} asCall asCall
+ * @param {boolean | undefined} strictHarmonyModule strictHarmonyModule
+ * @param {boolean | undefined} asiSafe asiSafe
+ * @param {Set<ExportInfo>} alreadyVisited alreadyVisited
+ * @returns {Binding} the final variable
+ */
+const getFinalBinding = (
+ moduleGraph,
+ info,
+ exportName,
+ moduleToInfoMap,
+ runtime,
+ requestShortener,
+ runtimeTemplate,
+ neededNamespaceObjects,
+ asCall,
+ strictHarmonyModule,
+ asiSafe,
+ alreadyVisited = new Set()
+) => {
+ const exportsType = info.module.getExportsType(
+ moduleGraph,
+ strictHarmonyModule
+ );
+ if (exportName.length === 0) {
+ switch (exportsType) {
+ case "default-only":
+ info.interopNamespaceObject2Used = true;
+ return {
+ info,
+ rawName: /** @type {string} */ (info.interopNamespaceObject2Name),
+ ids: exportName,
+ exportName
+ };
+ case "default-with-named":
+ info.interopNamespaceObjectUsed = true;
+ return {
+ info,
+ rawName: /** @type {string} */ (info.interopNamespaceObjectName),
+ ids: exportName,
+ exportName
+ };
+ case "namespace":
+ case "dynamic":
+ break;
+ default:
+ throw new Error(`Unexpected exportsType ${exportsType}`);
+ }
+ } else {
+ switch (exportsType) {
+ case "namespace":
+ break;
+ case "default-with-named":
+ switch (exportName[0]) {
+ case "default":
+ exportName = exportName.slice(1);
+ break;
+ case "__esModule":
+ return {
+ info,
+ rawName: "/* __esModule */true",
+ ids: exportName.slice(1),
+ exportName
+ };
+ }
+ break;
+ case "default-only": {
+ const exportId = exportName[0];
+ if (exportId === "__esModule") {
+ return {
+ info,
+ rawName: "/* __esModule */true",
+ ids: exportName.slice(1),
+ exportName
+ };
+ }
+ exportName = exportName.slice(1);
+ if (exportId !== "default") {
+ return {
+ info,
+ rawName:
+ "/* non-default import from default-exporting module */undefined",
+ ids: exportName,
+ exportName
+ };
+ }
+ break;
+ }
+ case "dynamic":
+ switch (exportName[0]) {
+ case "default": {
+ exportName = exportName.slice(1);
+ info.interopDefaultAccessUsed = true;
+ const defaultExport = asCall
+ ? `${info.interopDefaultAccessName}()`
+ : asiSafe
+ ? `(${info.interopDefaultAccessName}())`
+ : asiSafe === false
+ ? `;(${info.interopDefaultAccessName}())`
+ : `${info.interopDefaultAccessName}.a`;
+ return {
+ info,
+ rawName: defaultExport,
+ ids: exportName,
+ exportName
+ };
+ }
+ case "__esModule":
+ return {
+ info,
+ rawName: "/* __esModule */true",
+ ids: exportName.slice(1),
+ exportName
+ };
+ }
+ break;
+ default:
+ throw new Error(`Unexpected exportsType ${exportsType}`);
+ }
+ }
+ if (exportName.length === 0) {
+ switch (info.type) {
+ case "concatenated":
+ neededNamespaceObjects.add(info);
+ return {
+ info,
+ rawName:
+ /** @type {NonNullable<ConcatenatedModuleInfo["namespaceObjectName"]>} */
+ (info.namespaceObjectName),
+ ids: exportName,
+ exportName
+ };
+ case "external":
+ return {
+ info,
+ rawName:
+ /** @type {NonNullable<ExternalModuleInfo["name"]>} */
+ (info.name),
+ ids: exportName,
+ exportName
+ };
+ }
+ }
+ const exportsInfo = moduleGraph.getExportsInfo(info.module);
+ const exportInfo = exportsInfo.getExportInfo(exportName[0]);
+ if (alreadyVisited.has(exportInfo)) {
+ return {
+ info,
+ rawName: "/* circular reexport */ Object(function x() { x() }())",
+ ids: [],
+ exportName
+ };
+ }
+ alreadyVisited.add(exportInfo);
+ switch (info.type) {
+ case "concatenated": {
+ const exportId = exportName[0];
+ if (exportInfo.provided === false) {
+ // It's not provided, but it could be on the prototype
+ neededNamespaceObjects.add(info);
+ return {
+ info,
+ rawName: /** @type {string} */ (info.namespaceObjectName),
+ ids: exportName,
+ exportName
+ };
+ }
+ const directExport = info.exportMap && info.exportMap.get(exportId);
+ if (directExport) {
+ const usedName = /** @type {string[]} */ (
+ exportsInfo.getUsedName(exportName, runtime)
+ );
+ if (!usedName) {
+ return {
+ info,
+ rawName: "/* unused export */ undefined",
+ ids: exportName.slice(1),
+ exportName
+ };
+ }
+ return {
+ info,
+ name: directExport,
+ ids: usedName.slice(1),
+ exportName
+ };
+ }
+ const rawExport = info.rawExportMap && info.rawExportMap.get(exportId);
+ if (rawExport) {
+ return {
+ info,
+ rawName: rawExport,
+ ids: exportName.slice(1),
+ exportName
+ };
+ }
+ const reexport = exportInfo.findTarget(moduleGraph, module =>
+ moduleToInfoMap.has(module)
+ );
+ if (reexport === false) {
+ throw new Error(
+ `Target module of reexport from '${info.module.readableIdentifier(
+ requestShortener
+ )}' is not part of the concatenation (export '${exportId}')\nModules in the concatenation:\n${Array.from(
+ moduleToInfoMap,
+ ([m, info]) =>
+ ` * ${info.type} ${m.readableIdentifier(requestShortener)}`
+ ).join("\n")}`
+ );
+ }
+ if (reexport) {
+ const refInfo = moduleToInfoMap.get(reexport.module);
+ return getFinalBinding(
+ moduleGraph,
+ /** @type {ModuleInfo} */ (refInfo),
+ reexport.export
+ ? [...reexport.export, ...exportName.slice(1)]
+ : exportName.slice(1),
+ moduleToInfoMap,
+ runtime,
+ requestShortener,
+ runtimeTemplate,
+ neededNamespaceObjects,
+ asCall,
+ /** @type {BuildMeta} */
+ (info.module.buildMeta).strictHarmonyModule,
+ asiSafe,
+ alreadyVisited
+ );
+ }
+ if (info.namespaceExportSymbol) {
+ const usedName = /** @type {string[]} */ (
+ exportsInfo.getUsedName(exportName, runtime)
+ );
+ return {
+ info,
+ rawName: /** @type {string} */ (info.namespaceObjectName),
+ ids: usedName,
+ exportName
+ };
+ }
+ throw new Error(
+ `Cannot get final name for export '${exportName.join(
+ "."
+ )}' of ${info.module.readableIdentifier(requestShortener)}`
+ );
+ }
+
+ case "external": {
+ const used = /** @type {string[]} */ (
+ exportsInfo.getUsedName(exportName, runtime)
+ );
+ if (!used) {
+ return {
+ info,
+ rawName: "/* unused export */ undefined",
+ ids: exportName.slice(1),
+ exportName
+ };
+ }
+ const comment = equals(used, exportName)
+ ? ""
+ : Template.toNormalComment(`${exportName.join(".")}`);
+ return { info, rawName: info.name + comment, ids: used, exportName };
+ }
+ }
+};
+
+/**
+ * @param {ModuleGraph} moduleGraph the module graph
+ * @param {ModuleInfo} info module info
+ * @param {string[]} exportName exportName
+ * @param {Map<Module, ModuleInfo>} moduleToInfoMap moduleToInfoMap
+ * @param {RuntimeSpec} runtime for which runtime
+ * @param {RequestShortener} requestShortener the request shortener
+ * @param {RuntimeTemplate} runtimeTemplate the runtime template
+ * @param {Set<ConcatenatedModuleInfo>} neededNamespaceObjects modules for which a namespace object should be generated
+ * @param {boolean} asCall asCall
+ * @param {boolean | undefined} callContext callContext
+ * @param {boolean | undefined} strictHarmonyModule strictHarmonyModule
+ * @param {boolean | undefined} asiSafe asiSafe
+ * @returns {string} the final name
+ */
+const getFinalName = (
+ moduleGraph,
+ info,
+ exportName,
+ moduleToInfoMap,
+ runtime,
+ requestShortener,
+ runtimeTemplate,
+ neededNamespaceObjects,
+ asCall,
+ callContext,
+ strictHarmonyModule,
+ asiSafe
+) => {
+ const binding = getFinalBinding(
+ moduleGraph,
+ info,
+ exportName,
+ moduleToInfoMap,
+ runtime,
+ requestShortener,
+ runtimeTemplate,
+ neededNamespaceObjects,
+ asCall,
+ strictHarmonyModule,
+ asiSafe
+ );
+ {
+ const { ids, comment } = binding;
+ let reference;
+ let isPropertyAccess;
+ if ("rawName" in binding) {
+ reference = `${binding.rawName}${comment || ""}${propertyAccess(ids)}`;
+ isPropertyAccess = ids.length > 0;
+ } else {
+ const { info, name: exportId } = binding;
+ const name = info.internalNames.get(exportId);
+ if (!name) {
+ throw new Error(
+ `The export "${exportId}" in "${info.module.readableIdentifier(
+ requestShortener
+ )}" has no internal name (existing names: ${
+ Array.from(
+ info.internalNames,
+ ([name, symbol]) => `${name}: ${symbol}`
+ ).join(", ") || "none"
+ })`
+ );
+ }
+ reference = `${name}${comment || ""}${propertyAccess(ids)}`;
+ isPropertyAccess = ids.length > 1;
+ }
+ if (isPropertyAccess && asCall && callContext === false) {
+ return asiSafe
+ ? `(0,${reference})`
+ : asiSafe === false
+ ? `;(0,${reference})`
+ : `/*#__PURE__*/Object(${reference})`;
+ }
+ return reference;
+ }
+};
+
+/**
+ * @param {Scope | null} s scope
+ * @param {UsedNames} nameSet name set
+ * @param {TODO} scopeSet1 scope set 1
+ * @param {TODO} scopeSet2 scope set 2
+ */
+const addScopeSymbols = (s, nameSet, scopeSet1, scopeSet2) => {
+ let scope = s;
+ while (scope) {
+ if (scopeSet1.has(scope)) break;
+ if (scopeSet2.has(scope)) break;
+ scopeSet1.add(scope);
+ for (const variable of scope.variables) {
+ nameSet.add(variable.name);
+ }
+ scope = scope.upper;
+ }
+};
+
+const TYPES = new Set(["javascript"]);
+
+/**
+ * @typedef {object} ConcatenateModuleHooks
+ * @property {SyncBailHook<[Record<string, string>], boolean>} exportsDefinitions
+ */
+
+/** @type {WeakMap<Compilation, ConcatenateModuleHooks>} */
+const compilationHooksMap = new WeakMap();
+
+class ConcatenatedModule extends Module {
+ /**
+ * @param {Module} rootModule the root module of the concatenation
+ * @param {Set<Module>} modules all modules in the concatenation (including the root module)
+ * @param {RuntimeSpec} runtime the runtime
+ * @param {Compilation} compilation the compilation
+ * @param {object=} associatedObjectForCache object for caching
+ * @param {string | HashConstructor=} hashFunction hash function to use
+ * @returns {ConcatenatedModule} the module
+ */
+ static create(
+ rootModule,
+ modules,
+ runtime,
+ compilation,
+ associatedObjectForCache,
+ hashFunction = "md4"
+ ) {
+ const identifier = ConcatenatedModule._createIdentifier(
+ rootModule,
+ modules,
+ associatedObjectForCache,
+ hashFunction
+ );
+ return new ConcatenatedModule({
+ identifier,
+ rootModule,
+ modules,
+ runtime,
+ compilation
+ });
+ }
+
+ /**
+ * @param {Compilation} compilation the compilation
+ * @returns {ConcatenateModuleHooks} the attached hooks
+ */
+ static getCompilationHooks(compilation) {
+ let hooks = compilationHooksMap.get(compilation);
+ if (hooks === undefined) {
+ hooks = {
+ exportsDefinitions: new SyncBailHook(["definitions"])
+ };
+ compilationHooksMap.set(compilation, hooks);
+ }
+ return hooks;
+ }
+
+ /**
+ * @param {object} options options
+ * @param {string} options.identifier the identifier of the module
+ * @param {Module=} options.rootModule the root module of the concatenation
+ * @param {RuntimeSpec} options.runtime the selected runtime
+ * @param {Set<Module>=} options.modules all concatenated modules
+ * @param {Compilation} options.compilation the compilation
+ */
+ constructor({ identifier, rootModule, modules, runtime, compilation }) {
+ super(JAVASCRIPT_MODULE_TYPE_ESM, null, rootModule && rootModule.layer);
+
+ // Info from Factory
+ /** @type {string} */
+ this._identifier = identifier;
+ /** @type {Module} */
+ this.rootModule = rootModule;
+ /** @type {Set<Module>} */
+ this._modules = modules;
+ this._runtime = runtime;
+ this.factoryMeta = rootModule && rootModule.factoryMeta;
+ /** @type {Compilation | undefined} */
+ this.compilation = compilation;
+ }
+
+ /**
+ * Assuming this module is in the cache. Update the (cached) module with
+ * the fresh module from the factory. Usually updates internal references
+ * and properties.
+ * @param {Module} module fresh module
+ * @returns {void}
+ */
+ updateCacheModule(module) {
+ throw new Error("Must not be called");
+ }
+
+ /**
+ * @returns {SourceTypes} types available (do not mutate)
+ */
+ getSourceTypes() {
+ return TYPES;
+ }
+
+ get modules() {
+ return Array.from(this._modules);
+ }
+
+ /**
+ * @returns {string} a unique identifier of the module
+ */
+ identifier() {
+ return this._identifier;
+ }
+
+ /**
+ * @param {RequestShortener} requestShortener the request shortener
+ * @returns {string} a user readable identifier of the module
+ */
+ readableIdentifier(requestShortener) {
+ return `${this.rootModule.readableIdentifier(
+ requestShortener
+ )} + ${this._modules.size - 1} modules`;
+ }
+
+ /**
+ * @param {LibIdentOptions} options options
+ * @returns {string | null} an identifier for library inclusion
+ */
+ libIdent(options) {
+ return this.rootModule.libIdent(options);
+ }
+
+ /**
+ * @returns {string | null} absolute path which should be used for condition matching (usually the resource path)
+ */
+ nameForCondition() {
+ return this.rootModule.nameForCondition();
+ }
+
+ /**
+ * @param {ModuleGraph} moduleGraph the module graph
+ * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only
+ */
+ getSideEffectsConnectionState(moduleGraph) {
+ return this.rootModule.getSideEffectsConnectionState(moduleGraph);
+ }
+
+ /**
+ * @param {WebpackOptions} options webpack options
+ * @param {Compilation} compilation the compilation
+ * @param {ResolverWithOptions} resolver the resolver
+ * @param {InputFileSystem} fs the file system
+ * @param {function(WebpackError=): void} callback callback function
+ * @returns {void}
+ */
+ build(options, compilation, resolver, fs, callback) {
+ const { rootModule } = this;
+ const { moduleArgument, exportsArgument } =
+ /** @type {BuildInfo} */
+ (rootModule.buildInfo);
+ this.buildInfo = {
+ strict: true,
+ cacheable: true,
+ moduleArgument,
+ exportsArgument,
+ fileDependencies: new LazySet(),
+ contextDependencies: new LazySet(),
+ missingDependencies: new LazySet(),
+ topLevelDeclarations: new Set(),
+ assets: undefined
+ };
+ this.buildMeta = rootModule.buildMeta;
+ this.clearDependenciesAndBlocks();
+ this.clearWarningsAndErrors();
+
+ for (const m of this._modules) {
+ // populate cacheable
+ if (!(/** @type {BuildInfo} */ (m.buildInfo).cacheable)) {
+ this.buildInfo.cacheable = false;
+ }
+
+ // populate dependencies
+ for (const d of m.dependencies.filter(
+ dep =>
+ !(dep instanceof HarmonyImportDependency) ||
+ !this._modules.has(
+ /** @type {Module} */ (compilation.moduleGraph.getModule(dep))
+ )
+ )) {
+ this.dependencies.push(d);
+ }
+ // populate blocks
+ for (const d of m.blocks) {
+ this.blocks.push(d);
+ }
+
+ // populate warnings
+ const warnings = m.getWarnings();
+ if (warnings !== undefined) {
+ for (const warning of warnings) {
+ this.addWarning(warning);
+ }
+ }
+
+ // populate errors
+ const errors = m.getErrors();
+ if (errors !== undefined) {
+ for (const error of errors) {
+ this.addError(error);
+ }
+ }
+
+ const { assets, assetsInfo, topLevelDeclarations } =
+ /** @type {BuildInfo} */ (m.buildInfo);
+
+ // populate topLevelDeclarations
+ if (topLevelDeclarations) {
+ const topLevelDeclarations = this.buildInfo.topLevelDeclarations;
+ if (topLevelDeclarations !== undefined) {
+ for (const decl of topLevelDeclarations) {
+ topLevelDeclarations.add(decl);
+ }
+ }
+ } else {
+ this.buildInfo.topLevelDeclarations = undefined;
+ }
+
+ // populate assets
+ if (assets) {
+ if (this.buildInfo.assets === undefined) {
+ this.buildInfo.assets = Object.create(null);
+ }
+ Object.assign(
+ /** @type {NonNullable<BuildInfo["assets"]>} */
+ (
+ /** @type {BuildInfo} */
+ (this.buildInfo).assets
+ ),
+ assets
+ );
+ }
+ if (assetsInfo) {
+ if (this.buildInfo.assetsInfo === undefined) {
+ this.buildInfo.assetsInfo = new Map();
+ }
+ for (const [key, value] of assetsInfo) {
+ this.buildInfo.assetsInfo.set(key, value);
+ }
+ }
+ }
+ callback();
+ }
+
+ /**
+ * @param {string=} type the source type for which the size should be estimated
+ * @returns {number} the estimated size of the module (must be non-zero)
+ */
+ size(type) {
+ // Guess size from embedded modules
+ let size = 0;
+ for (const module of this._modules) {
+ size += module.size(type);
+ }
+ return size;
+ }
+
+ /**
+ * @private
+ * @param {Module} rootModule the root of the concatenation
+ * @param {Set<Module>} modulesSet a set of modules which should be concatenated
+ * @param {RuntimeSpec} runtime for this runtime
+ * @param {ModuleGraph} moduleGraph the module graph
+ * @returns {ConcatenationEntry[]} concatenation list
+ */
+ _createConcatenationList(rootModule, modulesSet, runtime, moduleGraph) {
+ /** @type {ConcatenationEntry[]} */
+ const list = [];
+ /** @type {Map<Module, RuntimeSpec | true>} */
+ const existingEntries = new Map();
+
+ /**
+ * @param {Module} module a module
+ * @returns {Iterable<{ connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true }>} imported modules in order
+ */
+ const getConcatenatedImports = module => {
+ const connections = Array.from(
+ moduleGraph.getOutgoingConnections(module)
+ );
+ if (module === rootModule) {
+ for (const c of moduleGraph.getOutgoingConnections(this))
+ connections.push(c);
+ }
+ /**
+ * @type {Array<{ connection: ModuleGraphConnection, sourceOrder: number, rangeStart: number }>}
+ */
+ const references = connections
+ .filter(connection => {
+ if (!(connection.dependency instanceof HarmonyImportDependency))
+ return false;
+ return (
+ connection &&
+ connection.resolvedOriginModule === module &&
+ connection.module &&
+ connection.isTargetActive(runtime)
+ );
+ })
+ .map(connection => {
+ const dep = /** @type {HarmonyImportDependency} */ (
+ connection.dependency
+ );
+ return {
+ connection,
+ sourceOrder: dep.sourceOrder,
+ rangeStart: dep.range && dep.range[0]
+ };
+ });
+ /**
+ * bySourceOrder
+ * @example
+ * import a from "a"; // sourceOrder=1
+ * import b from "b"; // sourceOrder=2
+ *
+ * byRangeStart
+ * @example
+ * import {a, b} from "a"; // sourceOrder=1
+ * a.a(); // first range
+ * b.b(); // second range
+ *
+ * If there is no reexport, we have the same source.
+ * If there is reexport, but module has side effects, this will lead to reexport module only.
+ * If there is side-effects-free reexport, we can get simple deterministic result with range start comparison.
+ */
+ references.sort(concatComparators(bySourceOrder, byRangeStart));
+ /** @type {Map<Module, { connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true }>} */
+ const referencesMap = new Map();
+ for (const { connection } of references) {
+ const runtimeCondition = filterRuntime(runtime, r =>
+ connection.isTargetActive(r)
+ );
+ if (runtimeCondition === false) continue;
+ const module = connection.module;
+ const entry = referencesMap.get(module);
+ if (entry === undefined) {
+ referencesMap.set(module, { connection, runtimeCondition });
+ continue;
+ }
+ entry.runtimeCondition = mergeRuntimeConditionNonFalse(
+ entry.runtimeCondition,
+ runtimeCondition,
+ runtime
+ );
+ }
+ return referencesMap.values();
+ };
+
+ /**
+ * @param {ModuleGraphConnection} connection graph connection
+ * @param {RuntimeSpec | true} runtimeCondition runtime condition
+ * @returns {void}
+ */
+ const enterModule = (connection, runtimeCondition) => {
+ const module = connection.module;
+ if (!module) return;
+ const existingEntry = existingEntries.get(module);
+ if (existingEntry === true) {
+ return;
+ }
+ if (modulesSet.has(module)) {
+ existingEntries.set(module, true);
+ if (runtimeCondition !== true) {
+ throw new Error(
+ `Cannot runtime-conditional concatenate a module (${module.identifier()} in ${this.rootModule.identifier()}, ${runtimeConditionToString(
+ runtimeCondition
+ )}). This should not happen.`
+ );
+ }
+ const imports = getConcatenatedImports(module);
+ for (const { connection, runtimeCondition } of imports)
+ enterModule(connection, runtimeCondition);
+ list.push({
+ type: "concatenated",
+ module: connection.module,
+ runtimeCondition
+ });
+ } else {
+ if (existingEntry !== undefined) {
+ const reducedRuntimeCondition = subtractRuntimeCondition(
+ runtimeCondition,
+ existingEntry,
+ runtime
+ );
+ if (reducedRuntimeCondition === false) return;
+ runtimeCondition = reducedRuntimeCondition;
+ existingEntries.set(
+ connection.module,
+ mergeRuntimeConditionNonFalse(
+ existingEntry,
+ runtimeCondition,
+ runtime
+ )
+ );
+ } else {
+ existingEntries.set(connection.module, runtimeCondition);
+ }
+ if (list.length > 0) {
+ const lastItem = list[list.length - 1];
+ if (
+ lastItem.type === "external" &&
+ lastItem.module === connection.module
+ ) {
+ lastItem.runtimeCondition = mergeRuntimeCondition(
+ lastItem.runtimeCondition,
+ runtimeCondition,
+ runtime
+ );
+ return;
+ }
+ }
+ list.push({
+ type: "external",
+ get module() {
+ // We need to use a getter here, because the module in the dependency
+ // could be replaced by some other process (i. e. also replaced with a
+ // concatenated module)
+ return connection.module;
+ },
+ runtimeCondition
+ });
+ }
+ };
+
+ existingEntries.set(rootModule, true);
+ const imports = getConcatenatedImports(rootModule);
+ for (const { connection, runtimeCondition } of imports)
+ enterModule(connection, runtimeCondition);
+ list.push({
+ type: "concatenated",
+ module: rootModule,
+ runtimeCondition: true
+ });
+
+ return list;
+ }
+
+ /**
+ * @param {Module} rootModule the root module of the concatenation
+ * @param {Set<Module>} modules all modules in the concatenation (including the root module)
+ * @param {object=} associatedObjectForCache object for caching
+ * @param {string | HashConstructor=} hashFunction hash function to use
+ * @returns {string} the identifier
+ */
+ static _createIdentifier(
+ rootModule,
+ modules,
+ associatedObjectForCache,
+ hashFunction = "md4"
+ ) {
+ const cachedMakePathsRelative = makePathsRelative.bindContextCache(
+ /** @type {string} */ (rootModule.context),
+ associatedObjectForCache
+ );
+ const identifiers = [];
+ for (const module of modules) {
+ identifiers.push(cachedMakePathsRelative(module.identifier()));
+ }
+ identifiers.sort();
+ const hash = createHash(hashFunction);
+ hash.update(identifiers.join(" "));
+ return `${rootModule.identifier()}|${hash.digest("hex")}`;
+ }
+
+ /**
+ * @param {LazySet<string>} fileDependencies set where file dependencies are added to
+ * @param {LazySet<string>} contextDependencies set where context dependencies are added to
+ * @param {LazySet<string>} missingDependencies set where missing dependencies are added to
+ * @param {LazySet<string>} buildDependencies set where build dependencies are added to
+ */
+ addCacheDependencies(
+ fileDependencies,
+ contextDependencies,
+ missingDependencies,
+ buildDependencies
+ ) {
+ for (const module of this._modules) {
+ module.addCacheDependencies(
+ fileDependencies,
+ contextDependencies,
+ missingDependencies,
+ buildDependencies
+ );
+ }
+ }
+
+ /**
+ * @param {CodeGenerationContext} context context for code generation
+ * @returns {CodeGenerationResult} result
+ */
+ codeGeneration({
+ dependencyTemplates,
+ runtimeTemplate,
+ moduleGraph,
+ chunkGraph,
+ runtime: generationRuntime,
+ codeGenerationResults
+ }) {
+ /** @type {Set<string>} */
+ const runtimeRequirements = new Set();
+ const runtime = intersectRuntime(generationRuntime, this._runtime);
+
+ const requestShortener = runtimeTemplate.requestShortener;
+ // Meta info for each module
+ const [modulesWithInfo, moduleToInfoMap] = this._getModulesWithInfo(
+ moduleGraph,
+ runtime
+ );
+
+ // Set with modules that need a generated namespace object
+ /** @type {Set<ConcatenatedModuleInfo>} */
+ const neededNamespaceObjects = new Set();
+
+ // Generate source code and analyse scopes
+ // Prepare a ReplaceSource for the final source
+ for (const info of moduleToInfoMap.values()) {
+ this._analyseModule(
+ moduleToInfoMap,
+ info,
+ dependencyTemplates,
+ runtimeTemplate,
+ moduleGraph,
+ chunkGraph,
+ runtime,
+ codeGenerationResults
+ );
+ }
+
+ // List of all used names to avoid conflicts
+ const allUsedNames = new Set(RESERVED_NAMES);
+ // Updated Top level declarations are created by renaming
+ const topLevelDeclarations = new Set();
+
+ // List of additional names in scope for module references
+ /** @type {Map<string, { usedNames: UsedNames, alreadyCheckedScopes: Set<TODO> }>} */
+ const usedNamesInScopeInfo = new Map();
+ /**
+ * @param {string} module module identifier
+ * @param {string} id export id
+ * @returns {{ usedNames: UsedNames, alreadyCheckedScopes: Set<TODO> }} info
+ */
+ const getUsedNamesInScopeInfo = (module, id) => {
+ const key = `${module}-${id}`;
+ let info = usedNamesInScopeInfo.get(key);
+ if (info === undefined) {
+ info = {
+ usedNames: new Set(),
+ alreadyCheckedScopes: new Set()
+ };
+ usedNamesInScopeInfo.set(key, info);
+ }
+ return info;
+ };
+
+ // Set of already checked scopes
+ const ignoredScopes = new Set();
+
+ // get all global names
+ for (const info of modulesWithInfo) {
+ if (info.type === "concatenated") {
+ // ignore symbols from moduleScope
+ if (info.moduleScope) {
+ ignoredScopes.add(info.moduleScope);
+ }
+
+ // The super class expression in class scopes behaves weird
+ // We get ranges of all super class expressions to make
+ // renaming to work correctly
+ const superClassCache = new WeakMap();
+ /**
+ * @param {Scope} scope scope
+ * @returns {TODO} result
+ */
+ const getSuperClassExpressions = scope => {
+ const cacheEntry = superClassCache.get(scope);
+ if (cacheEntry !== undefined) return cacheEntry;
+ const superClassExpressions = [];
+ for (const childScope of scope.childScopes) {
+ if (childScope.type !== "class") continue;
+ const block = childScope.block;
+ if (
+ (block.type === "ClassDeclaration" ||
+ block.type === "ClassExpression") &&
+ block.superClass
+ ) {
+ superClassExpressions.push({
+ range: block.superClass.range,
+ variables: childScope.variables
+ });
+ }
+ }
+ superClassCache.set(scope, superClassExpressions);
+ return superClassExpressions;
+ };
+
+ // add global symbols
+ if (info.globalScope) {
+ for (const reference of info.globalScope.through) {
+ const name = reference.identifier.name;
+ if (ConcatenationScope.isModuleReference(name)) {
+ const match = ConcatenationScope.matchModuleReference(name);
+ if (!match) continue;
+ const referencedInfo = modulesWithInfo[match.index];
+ if (referencedInfo.type === "reference")
+ throw new Error("Module reference can't point to a reference");
+ const binding = getFinalBinding(
+ moduleGraph,
+ referencedInfo,
+ match.ids,
+ moduleToInfoMap,
+ runtime,
+ requestShortener,
+ runtimeTemplate,
+ neededNamespaceObjects,
+ false,
+ /** @type {BuildMeta} */
+ (info.module.buildMeta).strictHarmonyModule,
+ true
+ );
+ if (!binding.ids) continue;
+ const { usedNames, alreadyCheckedScopes } =
+ getUsedNamesInScopeInfo(
+ binding.info.module.identifier(),
+ "name" in binding ? binding.name : ""
+ );
+ for (const expr of getSuperClassExpressions(reference.from)) {
+ if (
+ expr.range[0] <=
+ /** @type {Range} */ (reference.identifier.range)[0] &&
+ expr.range[1] >=
+ /** @type {Range} */ (reference.identifier.range)[1]
+ ) {
+ for (const variable of expr.variables) {
+ usedNames.add(variable.name);
+ }
+ }
+ }
+ addScopeSymbols(
+ reference.from,
+ usedNames,
+ alreadyCheckedScopes,
+ ignoredScopes
+ );
+ } else {
+ allUsedNames.add(name);
+ }
+ }
+ }
+ }
+ }
+
+ // generate names for symbols
+ for (const info of moduleToInfoMap.values()) {
+ const { usedNames: namespaceObjectUsedNames } = getUsedNamesInScopeInfo(
+ info.module.identifier(),
+ ""
+ );
+ switch (info.type) {
+ case "concatenated": {
+ for (const variable of info.moduleScope.variables) {
+ const name = variable.name;
+ const { usedNames, alreadyCheckedScopes } = getUsedNamesInScopeInfo(
+ info.module.identifier(),
+ name
+ );
+ if (allUsedNames.has(name) || usedNames.has(name)) {
+ const references = getAllReferences(variable);
+ for (const ref of references) {
+ addScopeSymbols(
+ ref.from,
+ usedNames,
+ alreadyCheckedScopes,
+ ignoredScopes
+ );
+ }
+ const newName = this.findNewName(
+ name,
+ allUsedNames,
+ usedNames,
+ info.module.readableIdentifier(requestShortener)
+ );
+ allUsedNames.add(newName);
+ info.internalNames.set(name, newName);
+ topLevelDeclarations.add(newName);
+ const source = info.source;
+ const allIdentifiers = new Set(
+ references.map(r => r.identifier).concat(variable.identifiers)
+ );
+ for (const identifier of allIdentifiers) {
+ const r = /** @type {Range} */ (identifier.range);
+ const path = getPathInAst(
+ /** @type {NonNullable<ConcatenatedModuleInfo["ast"]>} */
+ (info.ast),
+ identifier
+ );
+ if (path && path.length > 1) {
+ const maybeProperty =
+ path[1].type === "AssignmentPattern" &&
+ path[1].left === path[0]
+ ? path[2]
+ : path[1];
+ if (
+ maybeProperty.type === "Property" &&
+ maybeProperty.shorthand
+ ) {
+ source.insert(r[1], `: ${newName}`);
+ continue;
+ }
+ }
+ source.replace(r[0], r[1] - 1, newName);
+ }
+ } else {
+ allUsedNames.add(name);
+ info.internalNames.set(name, name);
+ topLevelDeclarations.add(name);
+ }
+ }
+ let namespaceObjectName;
+ if (info.namespaceExportSymbol) {
+ namespaceObjectName = info.internalNames.get(
+ info.namespaceExportSymbol
+ );
+ } else {
+ namespaceObjectName = this.findNewName(
+ "namespaceObject",
+ allUsedNames,
+ namespaceObjectUsedNames,
+ info.module.readableIdentifier(requestShortener)
+ );
+ allUsedNames.add(namespaceObjectName);
+ }
+ info.namespaceObjectName =
+ /** @type {string} */
+ (namespaceObjectName);
+ topLevelDeclarations.add(namespaceObjectName);
+ break;
+ }
+ case "external": {
+ const externalName = this.findNewName(
+ "",
+ allUsedNames,
+ namespaceObjectUsedNames,
+ info.module.readableIdentifier(requestShortener)
+ );
+ allUsedNames.add(externalName);
+ info.name = externalName;
+ topLevelDeclarations.add(externalName);
+ break;
+ }
+ }
+ const buildMeta = /** @type {BuildMeta} */ (info.module.buildMeta);
+ if (buildMeta.exportsType !== "namespace") {
+ const externalNameInterop = this.findNewName(
+ "namespaceObject",
+ allUsedNames,
+ namespaceObjectUsedNames,
+ info.module.readableIdentifier(requestShortener)
+ );
+ allUsedNames.add(externalNameInterop);
+ info.interopNamespaceObjectName = externalNameInterop;
+ topLevelDeclarations.add(externalNameInterop);
+ }
+ if (
+ buildMeta.exportsType === "default" &&
+ buildMeta.defaultObject !== "redirect"
+ ) {
+ const externalNameInterop = this.findNewName(
+ "namespaceObject2",
+ allUsedNames,
+ namespaceObjectUsedNames,
+ info.module.readableIdentifier(requestShortener)
+ );
+ allUsedNames.add(externalNameInterop);
+ info.interopNamespaceObject2Name = externalNameInterop;
+ topLevelDeclarations.add(externalNameInterop);
+ }
+ if (buildMeta.exportsType === "dynamic" || !buildMeta.exportsType) {
+ const externalNameInterop = this.findNewName(
+ "default",
+ allUsedNames,
+ namespaceObjectUsedNames,
+ info.module.readableIdentifier(requestShortener)
+ );
+ allUsedNames.add(externalNameInterop);
+ info.interopDefaultAccessName = externalNameInterop;
+ topLevelDeclarations.add(externalNameInterop);
+ }
+ }
+
+ // Find and replace references to modules
+ for (const info of moduleToInfoMap.values()) {
+ if (info.type === "concatenated") {
+ const globalScope = /** @type {Scope} */ (info.globalScope);
+ for (const reference of globalScope.through) {
+ const name = reference.identifier.name;
+ const match = ConcatenationScope.matchModuleReference(name);
+ if (match) {
+ const referencedInfo = modulesWithInfo[match.index];
+ if (referencedInfo.type === "reference")
+ throw new Error("Module reference can't point to a reference");
+ const finalName = getFinalName(
+ moduleGraph,
+ referencedInfo,
+ match.ids,
+ moduleToInfoMap,
+ runtime,
+ requestShortener,
+ runtimeTemplate,
+ neededNamespaceObjects,
+ match.call,
+ !match.directImport,
+ /** @type {BuildMeta} */
+ (info.module.buildMeta).strictHarmonyModule,
+ match.asiSafe
+ );
+ const r = /** @type {Range} */ (reference.identifier.range);
+ const source = info.source;
+ // range is extended by 2 chars to cover the appended "._"
+ source.replace(r[0], r[1] + 1, finalName);
+ }
+ }
+ }
+ }
+
+ // Map with all root exposed used exports
+ /** @type {Map<string, function(RequestShortener): string>} */
+ const exportsMap = new Map();
+
+ // Set with all root exposed unused exports
+ /** @type {Set<string>} */
+ const unusedExports = new Set();
+
+ const rootInfo = /** @type {ConcatenatedModuleInfo} */ (
+ moduleToInfoMap.get(this.rootModule)
+ );
+ const strictHarmonyModule =
+ /** @type {BuildMeta} */
+ (rootInfo.module.buildMeta).strictHarmonyModule;
+ const exportsInfo = moduleGraph.getExportsInfo(rootInfo.module);
+ /** @type {Record<string, string>} */
+ const exportsFinalName = {};
+ for (const exportInfo of exportsInfo.orderedExports) {
+ const name = exportInfo.name;
+ if (exportInfo.provided === false) continue;
+ const used = exportInfo.getUsedName(undefined, runtime);
+ if (!used) {
+ unusedExports.add(name);
+ continue;
+ }
+ exportsMap.set(used, requestShortener => {
+ try {
+ const finalName = getFinalName(
+ moduleGraph,
+ rootInfo,
+ [name],
+ moduleToInfoMap,
+ runtime,
+ requestShortener,
+ runtimeTemplate,
+ neededNamespaceObjects,
+ false,
+ false,
+ strictHarmonyModule,
+ true
+ );
+ exportsFinalName[used] = finalName;
+ return `/* ${
+ exportInfo.isReexport() ? "reexport" : "binding"
+ } */ ${finalName}`;
+ } catch (err) {
+ /** @type {Error} */
+ (err).message +=
+ `\nwhile generating the root export '${name}' (used name: '${used}')`;
+ throw err;
+ }
+ });
+ }
+
+ const result = new ConcatSource();
+
+ // add harmony compatibility flag (must be first because of possible circular dependencies)
+ let shouldAddHarmonyFlag = false;
+ if (
+ moduleGraph.getExportsInfo(this).otherExportsInfo.getUsed(runtime) !==
+ UsageState.Unused
+ ) {
+ shouldAddHarmonyFlag = true;
+ }
+
+ // define exports
+ if (exportsMap.size > 0) {
+ const { exportsDefinitions } = ConcatenatedModule.getCompilationHooks(
+ /** @type {Compilation} */ (this.compilation)
+ );
+
+ const definitions = [];
+ for (const [key, value] of exportsMap) {
+ definitions.push(
+ `\n ${propertyName(key)}: ${runtimeTemplate.returningFunction(
+ value(requestShortener)
+ )}`
+ );
+ }
+ const shouldSkipRenderDefinitions =
+ exportsDefinitions.call(exportsFinalName);
+
+ if (!shouldSkipRenderDefinitions) {
+ runtimeRequirements.add(RuntimeGlobals.exports);
+ runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
+
+ if (shouldAddHarmonyFlag) {
+ result.add("// ESM COMPAT FLAG\n");
+ result.add(
+ runtimeTemplate.defineEsModuleFlagStatement({
+ exportsArgument: this.exportsArgument,
+ runtimeRequirements
+ })
+ );
+ }
+
+ result.add("\n// EXPORTS\n");
+ result.add(
+ `${RuntimeGlobals.definePropertyGetters}(${
+ this.exportsArgument
+ }, {${definitions.join(",")}\n});\n`
+ );
+ } else {
+ /** @type {BuildMeta} */
+ (this.buildMeta).exportsFinalName = exportsFinalName;
+ }
+ }
+
+ // list unused exports
+ if (unusedExports.size > 0) {
+ result.add(
+ `\n// UNUSED EXPORTS: ${joinIterableWithComma(unusedExports)}\n`
+ );
+ }
+
+ // generate namespace objects
+ const namespaceObjectSources = new Map();
+ for (const info of neededNamespaceObjects) {
+ if (info.namespaceExportSymbol) continue;
+ const nsObj = [];
+ const exportsInfo = moduleGraph.getExportsInfo(info.module);
+ for (const exportInfo of exportsInfo.orderedExports) {
+ if (exportInfo.provided === false) continue;
+ const usedName = exportInfo.getUsedName(undefined, runtime);
+ if (usedName) {
+ const finalName = getFinalName(
+ moduleGraph,
+ info,
+ [exportInfo.name],
+ moduleToInfoMap,
+ runtime,
+ requestShortener,
+ runtimeTemplate,
+ neededNamespaceObjects,
+ false,
+ undefined,
+ /** @type {BuildMeta} */
+ (info.module.buildMeta).strictHarmonyModule,
+ true
+ );
+ nsObj.push(
+ `\n ${propertyName(usedName)}: ${runtimeTemplate.returningFunction(
+ finalName
+ )}`
+ );
+ }
+ }
+ const name = info.namespaceObjectName;
+ const defineGetters =
+ nsObj.length > 0
+ ? `${RuntimeGlobals.definePropertyGetters}(${name}, {${nsObj.join(
+ ","
+ )}\n});\n`
+ : "";
+ if (nsObj.length > 0)
+ runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
+ namespaceObjectSources.set(
+ info,
+ `
+// NAMESPACE OBJECT: ${info.module.readableIdentifier(requestShortener)}
+var ${name} = {};
+${RuntimeGlobals.makeNamespaceObject}(${name});
+${defineGetters}`
+ );
+ runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject);
+ }
+
+ // define required namespace objects (must be before evaluation modules)
+ for (const info of modulesWithInfo) {
+ if (info.type === "concatenated") {
+ const source = namespaceObjectSources.get(info);
+ if (!source) continue;
+ result.add(source);
+ }
+ }
+
+ const chunkInitFragments = [];
+
+ // evaluate modules in order
+ for (const rawInfo of modulesWithInfo) {
+ let name;
+ let isConditional = false;
+ const info = rawInfo.type === "reference" ? rawInfo.target : rawInfo;
+ switch (info.type) {
+ case "concatenated": {
+ result.add(
+ `\n;// CONCATENATED MODULE: ${info.module.readableIdentifier(
+ requestShortener
+ )}\n`
+ );
+ result.add(info.source);
+ if (info.chunkInitFragments) {
+ for (const f of info.chunkInitFragments) chunkInitFragments.push(f);
+ }
+ if (info.runtimeRequirements) {
+ for (const r of info.runtimeRequirements) {
+ runtimeRequirements.add(r);
+ }
+ }
+ name = info.namespaceObjectName;
+ break;
+ }
+ case "external": {
+ result.add(
+ `\n// EXTERNAL MODULE: ${info.module.readableIdentifier(
+ requestShortener
+ )}\n`
+ );
+ runtimeRequirements.add(RuntimeGlobals.require);
+ const { runtimeCondition } =
+ /** @type {ExternalModuleInfo | ReferenceToModuleInfo} */ (rawInfo);
+ const condition = runtimeTemplate.runtimeConditionExpression({
+ chunkGraph,
+ runtimeCondition,
+ runtime,
+ runtimeRequirements
+ });
+ if (condition !== "true") {
+ isConditional = true;
+ result.add(`if (${condition}) {\n`);
+ }
+ result.add(
+ `var ${info.name} = ${RuntimeGlobals.require}(${JSON.stringify(
+ chunkGraph.getModuleId(info.module)
+ )});`
+ );
+ name = info.name;
+ break;
+ }
+ default:
+ // @ts-expect-error never is expected here
+ throw new Error(`Unsupported concatenation entry type ${info.type}`);
+ }
+ if (info.interopNamespaceObjectUsed) {
+ runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
+ result.add(
+ `\nvar ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name}, 2);`
+ );
+ }
+ if (info.interopNamespaceObject2Used) {
+ runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
+ result.add(
+ `\nvar ${info.interopNamespaceObject2Name} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name});`
+ );
+ }
+ if (info.interopDefaultAccessUsed) {
+ runtimeRequirements.add(RuntimeGlobals.compatGetDefaultExport);
+ result.add(
+ `\nvar ${info.interopDefaultAccessName} = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${name});`
+ );
+ }
+ if (isConditional) {
+ result.add("\n}");
+ }
+ }
+
+ const data = new Map();
+ if (chunkInitFragments.length > 0)
+ data.set("chunkInitFragments", chunkInitFragments);
+ data.set("topLevelDeclarations", topLevelDeclarations);
+
+ /** @type {CodeGenerationResult} */
+ const resultEntry = {
+ sources: new Map([["javascript", new CachedSource(result)]]),
+ data,
+ runtimeRequirements
+ };
+
+ return resultEntry;
+ }
+
+ /**
+ * @param {Map<Module, ModuleInfo>} modulesMap modulesMap
+ * @param {ModuleInfo} info info
+ * @param {DependencyTemplates} dependencyTemplates dependencyTemplates
+ * @param {RuntimeTemplate} runtimeTemplate runtimeTemplate
+ * @param {ModuleGraph} moduleGraph moduleGraph
+ * @param {ChunkGraph} chunkGraph chunkGraph
+ * @param {RuntimeSpec} runtime runtime
+ * @param {CodeGenerationResults} codeGenerationResults codeGenerationResults
+ */
+ _analyseModule(
+ modulesMap,
+ info,
+ dependencyTemplates,
+ runtimeTemplate,
+ moduleGraph,
+ chunkGraph,
+ runtime,
+ codeGenerationResults
+ ) {
+ if (info.type === "concatenated") {
+ const m = info.module;
+ try {
+ // Create a concatenation scope to track and capture information
+ const concatenationScope = new ConcatenationScope(modulesMap, info);
+
+ // TODO cache codeGeneration results
+ const codeGenResult = m.codeGeneration({
+ dependencyTemplates,
+ runtimeTemplate,
+ moduleGraph,
+ chunkGraph,
+ runtime,
+ concatenationScope,
+ codeGenerationResults,
+ sourceTypes: TYPES
+ });
+ const source = /** @type {Source} */ (
+ codeGenResult.sources.get("javascript")
+ );
+ const data = codeGenResult.data;
+ const chunkInitFragments = data && data.get("chunkInitFragments");
+ const code = source.source().toString();
+ let ast;
+ try {
+ ast = JavascriptParser._parse(code, {
+ sourceType: "module"
+ });
+ } catch (_err) {
+ const err = /** @type {TODO} */ (_err);
+ if (
+ err.loc &&
+ typeof err.loc === "object" &&
+ typeof err.loc.line === "number"
+ ) {
+ const lineNumber = err.loc.line;
+ const lines = code.split("\n");
+ err.message += `\n| ${lines
+ .slice(Math.max(0, lineNumber - 3), lineNumber + 2)
+ .join("\n| ")}`;
+ }
+ throw err;
+ }
+ const scopeManager = eslintScope.analyze(ast, {
+ ecmaVersion: 6,
+ sourceType: "module",
+ optimistic: true,
+ ignoreEval: true,
+ impliedStrict: true
+ });
+ const globalScope = /** @type {Scope} */ (scopeManager.acquire(ast));
+ const moduleScope = globalScope.childScopes[0];
+ const resultSource = new ReplaceSource(source);
+ info.runtimeRequirements = codeGenResult.runtimeRequirements;
+ info.ast = ast;
+ info.internalSource = source;
+ info.source = resultSource;
+ info.chunkInitFragments = chunkInitFragments;
+ info.globalScope = globalScope;
+ info.moduleScope = moduleScope;
+ } catch (err) {
+ /** @type {Error} */
+ (err).message +=
+ `\nwhile analyzing module ${m.identifier()} for concatenation`;
+ throw err;
+ }
+ }
+ }
+
+ /**
+ * @param {ModuleGraph} moduleGraph the module graph
+ * @param {RuntimeSpec} runtime the runtime
+ * @returns {[ModuleInfoOrReference[], Map<Module, ModuleInfo>]} module info items
+ */
+ _getModulesWithInfo(moduleGraph, runtime) {
+ const orderedConcatenationList = this._createConcatenationList(
+ this.rootModule,
+ this._modules,
+ runtime,
+ moduleGraph
+ );
+ /** @type {Map<Module, ModuleInfo>} */
+ const map = new Map();
+ const list = orderedConcatenationList.map((info, index) => {
+ let item = map.get(info.module);
+ if (item === undefined) {
+ switch (info.type) {
+ case "concatenated":
+ item = {
+ type: "concatenated",
+ module: info.module,
+ index,
+ ast: undefined,
+ internalSource: undefined,
+ runtimeRequirements: undefined,
+ source: undefined,
+ globalScope: undefined,
+ moduleScope: undefined,
+ internalNames: new Map(),
+ exportMap: undefined,
+ rawExportMap: undefined,
+ namespaceExportSymbol: undefined,
+ namespaceObjectName: undefined,
+ interopNamespaceObjectUsed: false,
+ interopNamespaceObjectName: undefined,
+ interopNamespaceObject2Used: false,
+ interopNamespaceObject2Name: undefined,
+ interopDefaultAccessUsed: false,
+ interopDefaultAccessName: undefined
+ };
+ break;
+ case "external":
+ item = {
+ type: "external",
+ module: info.module,
+ runtimeCondition: info.runtimeCondition,
+ index,
+ name: undefined,
+ interopNamespaceObjectUsed: false,
+ interopNamespaceObjectName: undefined,
+ interopNamespaceObject2Used: false,
+ interopNamespaceObject2Name: undefined,
+ interopDefaultAccessUsed: false,
+ interopDefaultAccessName: undefined
+ };
+ break;
+ default:
+ throw new Error(
+ `Unsupported concatenation entry type ${info.type}`
+ );
+ }
+ map.set(
+ /** @type {ModuleInfo} */ (item).module,
+ /** @type {ModuleInfo} */ (item)
+ );
+ return /** @type {ModuleInfo} */ (item);
+ }
+ /** @type {ReferenceToModuleInfo} */
+ const ref = {
+ type: "reference",
+ runtimeCondition: info.runtimeCondition,
+ target: item
+ };
+ return ref;
+ });
+ return [list, map];
+ }
+
+ /**
+ * @param {string} oldName old name
+ * @param {UsedNames} usedNamed1 used named 1
+ * @param {UsedNames} usedNamed2 used named 2
+ * @param {string} extraInfo extra info
+ * @returns {string} found new name
+ */
+ findNewName(oldName, usedNamed1, usedNamed2, extraInfo) {
+ let name = oldName;
+
+ if (name === ConcatenationScope.DEFAULT_EXPORT) {
+ name = "";
+ }
+ if (name === ConcatenationScope.NAMESPACE_OBJECT_EXPORT) {
+ name = "namespaceObject";
+ }
+
+ // Remove uncool stuff
+ extraInfo = extraInfo.replace(
+ /\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g,
+ ""
+ );
+
+ const splittedInfo = extraInfo.split("/");
+ while (splittedInfo.length) {
+ name = splittedInfo.pop() + (name ? `_${name}` : "");
+ const nameIdent = Template.toIdentifier(name);
+ if (
+ !usedNamed1.has(nameIdent) &&
+ (!usedNamed2 || !usedNamed2.has(nameIdent))
+ )
+ return nameIdent;
+ }
+
+ let i = 0;
+ let nameWithNumber = Template.toIdentifier(`${name}_${i}`);
+ while (
+ usedNamed1.has(nameWithNumber) ||
+ // eslint-disable-next-line no-unmodified-loop-condition
+ (usedNamed2 && usedNamed2.has(nameWithNumber))
+ ) {
+ i++;
+ nameWithNumber = Template.toIdentifier(`${name}_${i}`);
+ }
+ return nameWithNumber;
+ }
+
+ /**
+ * @param {Hash} hash the hash used to track dependencies
+ * @param {UpdateHashContext} context context
+ * @returns {void}
+ */
+ updateHash(hash, context) {
+ const { chunkGraph, runtime } = context;
+ for (const info of this._createConcatenationList(
+ this.rootModule,
+ this._modules,
+ intersectRuntime(runtime, this._runtime),
+ chunkGraph.moduleGraph
+ )) {
+ switch (info.type) {
+ case "concatenated":
+ info.module.updateHash(hash, context);
+ break;
+ case "external":
+ hash.update(`${chunkGraph.getModuleId(info.module)}`);
+ // TODO runtimeCondition
+ break;
+ }
+ }
+ super.updateHash(hash, context);
+ }
+
+ /**
+ * @param {ObjectDeserializerContext} context context
+ * @returns {ConcatenatedModule} ConcatenatedModule
+ */
+ static deserialize(context) {
+ const obj = new ConcatenatedModule({
+ identifier: undefined,
+ rootModule: undefined,
+ modules: undefined,
+ runtime: undefined,
+ compilation: undefined
+ });
+ obj.deserialize(context);
+ return obj;
+ }
+}
+
+makeSerializable(ConcatenatedModule, "webpack/lib/optimize/ConcatenatedModule");
+
+module.exports = ConcatenatedModule;