code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const util = require("util");
const ChunkGraph = require("./ChunkGraph");
const DependenciesBlock = require("./DependenciesBlock");
const ModuleGraph = require("./ModuleGraph");
const RuntimeGlobals = require("./RuntimeGlobals");
const { first } = require("./util/SetHelpers");
const { compareChunksById } = require("./util/comparators");
const makeSerializable = require("./util/makeSerializable");

/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../declarations/WebpackOptions").ResolveOptions} ResolveOptions */
/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
/** @typedef {import("./Chunk")} Chunk */
/** @typedef {import("./ChunkGroup")} ChunkGroup */
/** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
/** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./Compilation").AssetInfo} AssetInfo */
/** @typedef {import("./ConcatenationScope")} ConcatenationScope */
/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
/** @typedef {import("./ExportsInfo").UsageStateType} UsageStateType */
/** @typedef {import("./FileSystemInfo")} FileSystemInfo */
/** @typedef {import("./FileSystemInfo").Snapshot} Snapshot */
/** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */
/** @typedef {import("./ModuleTypeConstants").ModuleTypes} ModuleTypes */
/** @typedef {import("./NormalModuleFactory")} NormalModuleFactory */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("./WebpackError")} WebpackError */
/** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
/** @typedef {import("./util/Hash")} Hash */
/** @template T @typedef {import("./util/LazySet")<T>} LazySet<T> */
/** @template T @typedef {import("./util/SortableSet")<T>} SortableSet<T> */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */

/**
 * @typedef {object} SourceContext
 * @property {DependencyTemplates} dependencyTemplates the dependency templates
 * @property {RuntimeTemplate} runtimeTemplate the runtime template
 * @property {ModuleGraph} moduleGraph the module graph
 * @property {ChunkGraph} chunkGraph the chunk graph
 * @property {RuntimeSpec} runtime the runtimes code should be generated for
 * @property {string=} type the type of source that should be generated
 */

// TODO webpack 6: compilation will be required in CodeGenerationContext
/**
 * @typedef {object} CodeGenerationContext
 * @property {DependencyTemplates} dependencyTemplates the dependency templates
 * @property {RuntimeTemplate} runtimeTemplate the runtime template
 * @property {ModuleGraph} moduleGraph the module graph
 * @property {ChunkGraph} chunkGraph the chunk graph
 * @property {RuntimeSpec} runtime the runtimes code should be generated for
 * @property {ConcatenationScope=} concatenationScope when in concatenated module, information about other concatenated modules
 * @property {CodeGenerationResults | undefined} codeGenerationResults code generation results of other modules (need to have a codeGenerationDependency to use that)
 * @property {Compilation=} compilation the compilation
 * @property {ReadonlySet<string>=} sourceTypes source types
 */

/**
 * @typedef {object} ConcatenationBailoutReasonContext
 * @property {ModuleGraph} moduleGraph the module graph
 * @property {ChunkGraph} chunkGraph the chunk graph
 */

/** @typedef {Set<string>} RuntimeRequirements */
/** @typedef {ReadonlySet<string>} ReadOnlyRuntimeRequirements */

/**
 * @typedef {object} CodeGenerationResult
 * @property {Map<string, Source>} sources the resulting sources for all source types
 * @property {Map<string, any>=} data the resulting data for all source types
 * @property {ReadOnlyRuntimeRequirements} runtimeRequirements the runtime requirements
 * @property {string=} hash a hash of the code generation result (will be automatically calculated from sources and runtimeRequirements if not provided)
 */

/**
 * @typedef {object} LibIdentOptions
 * @property {string} context absolute context path to which lib ident is relative to
 * @property {object=} associatedObjectForCache object for caching
 */

/**
 * @typedef {object} KnownBuildMeta
 * @property {string=} moduleArgument
 * @property {string=} exportsArgument
 * @property {boolean=} strict
 * @property {string=} moduleConcatenationBailout
 * @property {("default" | "namespace" | "flagged" | "dynamic")=} exportsType
 * @property {(false | "redirect" | "redirect-warn")=} defaultObject
 * @property {boolean=} strictHarmonyModule
 * @property {boolean=} async
 * @property {boolean=} sideEffectFree
 */

/**
 * @typedef {object} KnownBuildInfo
 * @property {boolean=} cacheable
 * @property {boolean=} parsed
 * @property {LazySet<string>=} fileDependencies
 * @property {LazySet<string>=} contextDependencies
 * @property {LazySet<string>=} missingDependencies
 * @property {LazySet<string>=} buildDependencies
 * @property {(Map<string, string | Set<string>>)=} valueDependencies
 * @property {TODO=} hash
 * @property {Record<string, Source>=} assets
 * @property {Map<string, AssetInfo | undefined>=} assetsInfo
 * @property {(Snapshot | null)=} snapshot
 */

/**
 * @typedef {object} NeedBuildContext
 * @property {Compilation} compilation
 * @property {FileSystemInfo} fileSystemInfo
 * @property {Map<string, string | Set<string>>} valueCacheVersions
 */

/** @typedef {KnownBuildMeta & Record<string, any>} BuildMeta */
/** @typedef {KnownBuildInfo & Record<string, any>} BuildInfo */

/**
 * @typedef {object} FactoryMeta
 * @property {boolean=} sideEffectFree
 */

/** @typedef {Set<string>} SourceTypes */

/** @typedef {{ factoryMeta: FactoryMeta | undefined, resolveOptions: ResolveOptions | undefined }} UnsafeCacheData */

const EMPTY_RESOLVE_OPTIONS = {};

let debugId = 1000;

const DEFAULT_TYPES_UNKNOWN = new Set(["unknown"]);
const DEFAULT_TYPES_JS = new Set(["javascript"]);

const deprecatedNeedRebuild = util.deprecate(
	/**
	 * @param {Module} module the module
	 * @param {NeedBuildContext} context context info
	 * @returns {boolean} true, when rebuild is needed
	 */
	(module, context) => {
		return module.needRebuild(
			context.fileSystemInfo.getDeprecatedFileTimestamps(),
			context.fileSystemInfo.getDeprecatedContextTimestamps()
		);
	},
	"Module.needRebuild is deprecated in favor of Module.needBuild",
	"DEP_WEBPACK_MODULE_NEED_REBUILD"
);

/** @typedef {(requestShortener: RequestShortener) => string} OptimizationBailoutFunction */

class Module extends DependenciesBlock {
	/**
	 * @param {ModuleTypes | ""} type the module type, when deserializing the type is not known and is an empty string
	 * @param {(string | null)=} context an optional context
	 * @param {(string | null)=} layer an optional layer in which the module is
	 */
	constructor(type, context = null, layer = null) {
		super();

		/** @type {ModuleTypes} */
		this.type = type;
		/** @type {string | null} */
		this.context = context;
		/** @type {string | null} */
		this.layer = layer;
		/** @type {boolean} */
		this.needId = true;

		// Unique Id
		/** @type {number} */
		this.debugId = debugId++;

		// Info from Factory
		/** @type {ResolveOptions | undefined} */
		this.resolveOptions = EMPTY_RESOLVE_OPTIONS;
		/** @type {FactoryMeta | undefined} */
		this.factoryMeta = undefined;
		// TODO refactor this -> options object filled from Factory
		// TODO webpack 6: use an enum
		/** @type {boolean} */
		this.useSourceMap = false;
		/** @type {boolean} */
		this.useSimpleSourceMap = false;

		// Info from Build
		/** @type {WebpackError[] | undefined} */
		this._warnings = undefined;
		/** @type {WebpackError[] | undefined} */
		this._errors = undefined;
		/** @type {BuildMeta | undefined} */
		this.buildMeta = undefined;
		/** @type {BuildInfo | undefined} */
		this.buildInfo = undefined;
		/** @type {Dependency[] | undefined} */
		this.presentationalDependencies = undefined;
		/** @type {Dependency[] | undefined} */
		this.codeGenerationDependencies = undefined;
	}

	// TODO remove in webpack 6
	// BACKWARD-COMPAT START
	get id() {
		return ChunkGraph.getChunkGraphForModule(
			this,
			"Module.id",
			"DEP_WEBPACK_MODULE_ID"
		).getModuleId(this);
	}

	set id(value) {
		if (value === "") {
			this.needId = false;
			return;
		}
		ChunkGraph.getChunkGraphForModule(
			this,
			"Module.id",
			"DEP_WEBPACK_MODULE_ID"
		).setModuleId(this, value);
	}

	/**
	 * @returns {string} the hash of the module
	 */
	get hash() {
		return ChunkGraph.getChunkGraphForModule(
			this,
			"Module.hash",
			"DEP_WEBPACK_MODULE_HASH"
		).getModuleHash(this, undefined);
	}

	/**
	 * @returns {string} the shortened hash of the module
	 */
	get renderedHash() {
		return ChunkGraph.getChunkGraphForModule(
			this,
			"Module.renderedHash",
			"DEP_WEBPACK_MODULE_RENDERED_HASH"
		).getRenderedModuleHash(this, undefined);
	}

	get profile() {
		return ModuleGraph.getModuleGraphForModule(
			this,
			"Module.profile",
			"DEP_WEBPACK_MODULE_PROFILE"
		).getProfile(this);
	}

	set profile(value) {
		ModuleGraph.getModuleGraphForModule(
			this,
			"Module.profile",
			"DEP_WEBPACK_MODULE_PROFILE"
		).setProfile(this, value);
	}

	/**
	 * @returns {number | null} the pre order index
	 */
	get index() {
		return ModuleGraph.getModuleGraphForModule(
			this,
			"Module.index",
			"DEP_WEBPACK_MODULE_INDEX"
		).getPreOrderIndex(this);
	}

	/**
	 * @param {number} value the pre order index
	 */
	set index(value) {
		ModuleGraph.getModuleGraphForModule(
			this,
			"Module.index",
			"DEP_WEBPACK_MODULE_INDEX"
		).setPreOrderIndex(this, value);
	}

	/**
	 * @returns {number | null} the post order index
	 */
	get index2() {
		return ModuleGraph.getModuleGraphForModule(
			this,
			"Module.index2",
			"DEP_WEBPACK_MODULE_INDEX2"
		).getPostOrderIndex(this);
	}

	/**
	 * @param {number} value the post order index
	 */
	set index2(value) {
		ModuleGraph.getModuleGraphForModule(
			this,
			"Module.index2",
			"DEP_WEBPACK_MODULE_INDEX2"
		).setPostOrderIndex(this, value);
	}

	/**
	 * @returns {number | null} the depth
	 */
	get depth() {
		return ModuleGraph.getModuleGraphForModule(
			this,
			"Module.depth",
			"DEP_WEBPACK_MODULE_DEPTH"
		).getDepth(this);
	}

	/**
	 * @param {number} value the depth
	 */
	set depth(value) {
		ModuleGraph.getModuleGraphForModule(
			this,
			"Module.depth",
			"DEP_WEBPACK_MODULE_DEPTH"
		).setDepth(this, value);
	}

	/**
	 * @returns {Module | null | undefined} issuer
	 */
	get issuer() {
		return ModuleGraph.getModuleGraphForModule(
			this,
			"Module.issuer",
			"DEP_WEBPACK_MODULE_ISSUER"
		).getIssuer(this);
	}

	/**
	 * @param {Module | null} value issuer
	 */
	set issuer(value) {
		ModuleGraph.getModuleGraphForModule(
			this,
			"Module.issuer",
			"DEP_WEBPACK_MODULE_ISSUER"
		).setIssuer(this, value);
	}

	get usedExports() {
		return ModuleGraph.getModuleGraphForModule(
			this,
			"Module.usedExports",
			"DEP_WEBPACK_MODULE_USED_EXPORTS"
		).getUsedExports(this, undefined);
	}

	/**
	 * @deprecated
	 * @returns {(string | OptimizationBailoutFunction)[]} list
	 */
	get optimizationBailout() {
		return ModuleGraph.getModuleGraphForModule(
			this,
			"Module.optimizationBailout",
			"DEP_WEBPACK_MODULE_OPTIMIZATION_BAILOUT"
		).getOptimizationBailout(this);
	}

	get optional() {
		return this.isOptional(
			ModuleGraph.getModuleGraphForModule(
				this,
				"Module.optional",
				"DEP_WEBPACK_MODULE_OPTIONAL"
			)
		);
	}

	/**
	 * @param {Chunk} chunk the chunk
	 * @returns {boolean} true, when the module was added
	 */
	addChunk(chunk) {
		const chunkGraph = ChunkGraph.getChunkGraphForModule(
			this,
			"Module.addChunk",
			"DEP_WEBPACK_MODULE_ADD_CHUNK"
		);
		if (chunkGraph.isModuleInChunk(this, chunk)) return false;
		chunkGraph.connectChunkAndModule(chunk, this);
		return true;
	}

	/**
	 * @param {Chunk} chunk the chunk
	 * @returns {void}
	 */
	removeChunk(chunk) {
		return ChunkGraph.getChunkGraphForModule(
			this,
			"Module.removeChunk",
			"DEP_WEBPACK_MODULE_REMOVE_CHUNK"
		).disconnectChunkAndModule(chunk, this);
	}

	/**
	 * @param {Chunk} chunk the chunk
	 * @returns {boolean} true, when the module is in the chunk
	 */
	isInChunk(chunk) {
		return ChunkGraph.getChunkGraphForModule(
			this,
			"Module.isInChunk",
			"DEP_WEBPACK_MODULE_IS_IN_CHUNK"
		).isModuleInChunk(this, chunk);
	}

	isEntryModule() {
		return ChunkGraph.getChunkGraphForModule(
			this,
			"Module.isEntryModule",
			"DEP_WEBPACK_MODULE_IS_ENTRY_MODULE"
		).isEntryModule(this);
	}

	getChunks() {
		return ChunkGraph.getChunkGraphForModule(
			this,
			"Module.getChunks",
			"DEP_WEBPACK_MODULE_GET_CHUNKS"
		).getModuleChunks(this);
	}

	getNumberOfChunks() {
		return ChunkGraph.getChunkGraphForModule(
			this,
			"Module.getNumberOfChunks",
			"DEP_WEBPACK_MODULE_GET_NUMBER_OF_CHUNKS"
		).getNumberOfModuleChunks(this);
	}

	get chunksIterable() {
		return ChunkGraph.getChunkGraphForModule(
			this,
			"Module.chunksIterable",
			"DEP_WEBPACK_MODULE_CHUNKS_ITERABLE"
		).getOrderedModuleChunksIterable(this, compareChunksById);
	}

	/**
	 * @param {string} exportName a name of an export
	 * @returns {boolean | null} true, if the export is provided why the module.
	 * null, if it's unknown.
	 * false, if it's not provided.
	 */
	isProvided(exportName) {
		return ModuleGraph.getModuleGraphForModule(
			this,
			"Module.usedExports",
			"DEP_WEBPACK_MODULE_USED_EXPORTS"
		).isExportProvided(this, exportName);
	}
	// BACKWARD-COMPAT END

	/**
	 * @returns {string} name of the exports argument
	 */
	get exportsArgument() {
		return (this.buildInfo && this.buildInfo.exportsArgument) || "exports";
	}

	/**
	 * @returns {string} name of the module argument
	 */
	get moduleArgument() {
		return (this.buildInfo && this.buildInfo.moduleArgument) || "module";
	}

	/**
	 * @param {ModuleGraph} moduleGraph the module graph
	 * @param {boolean | undefined} strict the importing module is strict
	 * @returns {"namespace" | "default-only" | "default-with-named" | "dynamic"} export type
	 * "namespace": Exports is already a namespace object. namespace = exports.
	 * "dynamic": Check at runtime if __esModule is set. When set: namespace = { ...exports, default: exports }. When not set: namespace = { default: exports }.
	 * "default-only": Provide a namespace object with only default export. namespace = { default: exports }
	 * "default-with-named": Provide a namespace object with named and default export. namespace = { ...exports, default: exports }
	 */
	getExportsType(moduleGraph, strict) {
		switch (this.buildMeta && this.buildMeta.exportsType) {
			case "flagged":
				return strict ? "default-with-named" : "namespace";
			case "namespace":
				return "namespace";
			case "default":
				switch (/** @type {BuildMeta} */ (this.buildMeta).defaultObject) {
					case "redirect":
						return "default-with-named";
					case "redirect-warn":
						return strict ? "default-only" : "default-with-named";
					default:
						return "default-only";
				}
			case "dynamic": {
				if (strict) return "default-with-named";
				// Try to figure out value of __esModule by following reexports
				const handleDefault = () => {
					switch (/** @type {BuildMeta} */ (this.buildMeta).defaultObject) {
						case "redirect":
						case "redirect-warn":
							return "default-with-named";
						default:
							return "default-only";
					}
				};
				const exportInfo = moduleGraph.getReadOnlyExportInfo(
					this,
					"__esModule"
				);
				if (exportInfo.provided === false) {
					return handleDefault();
				}
				const target = exportInfo.getTarget(moduleGraph);
				if (
					!target ||
					!target.export ||
					target.export.length !== 1 ||
					target.export[0] !== "__esModule"
				) {
					return "dynamic";
				}
				switch (
					target.module.buildMeta &&
					target.module.buildMeta.exportsType
				) {
					case "flagged":
					case "namespace":
						return "namespace";
					case "default":
						return handleDefault();
					default:
						return "dynamic";
				}
			}
			default:
				return strict ? "default-with-named" : "dynamic";
		}
	}

	/**
	 * @param {Dependency} presentationalDependency dependency being tied to module.
	 * This is a Dependency without edge in the module graph. It's only for presentation.
	 * @returns {void}
	 */
	addPresentationalDependency(presentationalDependency) {
		if (this.presentationalDependencies === undefined) {
			this.presentationalDependencies = [];
		}
		this.presentationalDependencies.push(presentationalDependency);
	}

	/**
	 * @param {Dependency} codeGenerationDependency dependency being tied to module.
	 * This is a Dependency where the code generation result of the referenced module is needed during code generation.
	 * The Dependency should also be added to normal dependencies via addDependency.
	 * @returns {void}
	 */
	addCodeGenerationDependency(codeGenerationDependency) {
		if (this.codeGenerationDependencies === undefined) {
			this.codeGenerationDependencies = [];
		}
		this.codeGenerationDependencies.push(codeGenerationDependency);
	}

	/**
	 * Removes all dependencies and blocks
	 * @returns {void}
	 */
	clearDependenciesAndBlocks() {
		if (this.presentationalDependencies !== undefined) {
			this.presentationalDependencies.length = 0;
		}
		if (this.codeGenerationDependencies !== undefined) {
			this.codeGenerationDependencies.length = 0;
		}
		super.clearDependenciesAndBlocks();
	}

	/**
	 * @param {WebpackError} warning the warning
	 * @returns {void}
	 */
	addWarning(warning) {
		if (this._warnings === undefined) {
			this._warnings = [];
		}
		this._warnings.push(warning);
	}

	/**
	 * @returns {Iterable<WebpackError> | undefined} list of warnings if any
	 */
	getWarnings() {
		return this._warnings;
	}

	/**
	 * @returns {number} number of warnings
	 */
	getNumberOfWarnings() {
		return this._warnings !== undefined ? this._warnings.length : 0;
	}

	/**
	 * @param {WebpackError} error the error
	 * @returns {void}
	 */
	addError(error) {
		if (this._errors === undefined) {
			this._errors = [];
		}
		this._errors.push(error);
	}

	/**
	 * @returns {Iterable<WebpackError> | undefined} list of errors if any
	 */
	getErrors() {
		return this._errors;
	}

	/**
	 * @returns {number} number of errors
	 */
	getNumberOfErrors() {
		return this._errors !== undefined ? this._errors.length : 0;
	}

	/**
	 * removes all warnings and errors
	 * @returns {void}
	 */
	clearWarningsAndErrors() {
		if (this._warnings !== undefined) {
			this._warnings.length = 0;
		}
		if (this._errors !== undefined) {
			this._errors.length = 0;
		}
	}

	/**
	 * @param {ModuleGraph} moduleGraph the module graph
	 * @returns {boolean} true, if the module is optional
	 */
	isOptional(moduleGraph) {
		let hasConnections = false;
		for (const r of moduleGraph.getIncomingConnections(this)) {
			if (
				!r.dependency ||
				!r.dependency.optional ||
				!r.isTargetActive(undefined)
			) {
				return false;
			}
			hasConnections = true;
		}
		return hasConnections;
	}

	/**
	 * @param {ChunkGraph} chunkGraph the chunk graph
	 * @param {Chunk} chunk a chunk
	 * @param {Chunk=} ignoreChunk chunk to be ignored
	 * @returns {boolean} true, if the module is accessible from "chunk" when ignoring "ignoreChunk"
	 */
	isAccessibleInChunk(chunkGraph, chunk, ignoreChunk) {
		// Check if module is accessible in ALL chunk groups
		for (const chunkGroup of chunk.groupsIterable) {
			if (!this.isAccessibleInChunkGroup(chunkGraph, chunkGroup)) return false;
		}
		return true;
	}

	/**
	 * @param {ChunkGraph} chunkGraph the chunk graph
	 * @param {ChunkGroup} chunkGroup a chunk group
	 * @param {Chunk=} ignoreChunk chunk to be ignored
	 * @returns {boolean} true, if the module is accessible from "chunkGroup" when ignoring "ignoreChunk"
	 */
	isAccessibleInChunkGroup(chunkGraph, chunkGroup, ignoreChunk) {
		const queue = new Set([chunkGroup]);

		// Check if module is accessible from all items of the queue
		queueFor: for (const cg of queue) {
			// 1. If module is in one of the chunks of the group we can continue checking the next items
			//    because it's accessible.
			for (const chunk of cg.chunks) {
				if (chunk !== ignoreChunk && chunkGraph.isModuleInChunk(this, chunk))
					continue queueFor;
			}
			// 2. If the chunk group is initial, we can break here because it's not accessible.
			if (chunkGroup.isInitial()) return false;
			// 3. Enqueue all parents because it must be accessible from ALL parents
			for (const parent of chunkGroup.parentsIterable) queue.add(parent);
		}
		// When we processed through the whole list and we didn't bailout, the module is accessible
		return true;
	}

	/**
	 * @param {Chunk} chunk a chunk
	 * @param {ModuleGraph} moduleGraph the module graph
	 * @param {ChunkGraph} chunkGraph the chunk graph
	 * @returns {boolean} true, if the module has any reason why "chunk" should be included
	 */
	hasReasonForChunk(chunk, moduleGraph, chunkGraph) {
		// check for each reason if we need the chunk
		for (const [
			fromModule,
			connections
		] of moduleGraph.getIncomingConnectionsByOriginModule(this)) {
			if (!connections.some(c => c.isTargetActive(chunk.runtime))) continue;
			for (const originChunk of chunkGraph.getModuleChunksIterable(
				/** @type {Module} */ (fromModule)
			)) {
				// return true if module this is not reachable from originChunk when ignoring chunk
				if (!this.isAccessibleInChunk(chunkGraph, originChunk, chunk))
					return true;
			}
		}
		return false;
	}

	/**
	 * @param {ModuleGraph} moduleGraph the module graph
	 * @param {RuntimeSpec} runtime the runtime
	 * @returns {boolean} true if at least one other module depends on this module
	 */
	hasReasons(moduleGraph, runtime) {
		for (const c of moduleGraph.getIncomingConnections(this)) {
			if (c.isTargetActive(runtime)) return true;
		}
		return false;
	}

	/**
	 * @returns {string} for debugging
	 */
	toString() {
		return `Module[${this.debugId}: ${this.identifier()}]`;
	}

	/**
	 * @param {NeedBuildContext} context context info
	 * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
	 * @returns {void}
	 */
	needBuild(context, callback) {
		callback(
			null,
			!this.buildMeta ||
				this.needRebuild === Module.prototype.needRebuild ||
				deprecatedNeedRebuild(this, context)
		);
	}

	/**
	 * @deprecated Use needBuild instead
	 * @param {Map<string, number|null>} fileTimestamps timestamps of files
	 * @param {Map<string, number|null>} contextTimestamps timestamps of directories
	 * @returns {boolean} true, if the module needs a rebuild
	 */
	needRebuild(fileTimestamps, contextTimestamps) {
		return true;
	}

	/**
	 * @param {Hash} hash the hash used to track dependencies
	 * @param {UpdateHashContext} context context
	 * @returns {void}
	 */
	updateHash(
		hash,
		context = {
			chunkGraph: ChunkGraph.getChunkGraphForModule(
				this,
				"Module.updateHash",
				"DEP_WEBPACK_MODULE_UPDATE_HASH"
			),
			runtime: undefined
		}
	) {
		const { chunkGraph, runtime } = context;
		hash.update(chunkGraph.getModuleGraphHash(this, runtime));
		if (this.presentationalDependencies !== undefined) {
			for (const dep of this.presentationalDependencies) {
				dep.updateHash(hash, context);
			}
		}
		super.updateHash(hash, context);
	}

	/**
	 * @returns {void}
	 */
	invalidateBuild() {
		// should be overridden to support this feature
	}

	/* istanbul ignore next */
	/**
	 * @abstract
	 * @returns {string} a unique identifier of the module
	 */
	identifier() {
		const AbstractMethodError = require("./AbstractMethodError");
		throw new AbstractMethodError();
	}

	/* istanbul ignore next */
	/**
	 * @abstract
	 * @param {RequestShortener} requestShortener the request shortener
	 * @returns {string} a user readable identifier of the module
	 */
	readableIdentifier(requestShortener) {
		const AbstractMethodError = require("./AbstractMethodError");
		throw new AbstractMethodError();
	}

	/* istanbul ignore next */
	/**
	 * @abstract
	 * @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 AbstractMethodError = require("./AbstractMethodError");
		throw new AbstractMethodError();
	}

	/**
	 * @abstract
	 * @returns {SourceTypes} types available (do not mutate)
	 */
	getSourceTypes() {
		// Better override this method to return the correct types
		if (this.source === Module.prototype.source) {
			return DEFAULT_TYPES_UNKNOWN;
		} else {
			return DEFAULT_TYPES_JS;
		}
	}

	/**
	 * @abstract
	 * @deprecated Use codeGeneration() instead
	 * @param {DependencyTemplates} dependencyTemplates the dependency templates
	 * @param {RuntimeTemplate} runtimeTemplate the runtime template
	 * @param {string=} type the type of source that should be generated
	 * @returns {Source} generated source
	 */
	source(dependencyTemplates, runtimeTemplate, type = "javascript") {
		if (this.codeGeneration === Module.prototype.codeGeneration) {
			const AbstractMethodError = require("./AbstractMethodError");
			throw new AbstractMethodError();
		}
		const chunkGraph = ChunkGraph.getChunkGraphForModule(
			this,
			"Module.source() is deprecated. Use Compilation.codeGenerationResults.getSource(module, runtime, type) instead",
			"DEP_WEBPACK_MODULE_SOURCE"
		);
		/** @type {CodeGenerationContext} */
		const codeGenContext = {
			dependencyTemplates,
			runtimeTemplate,
			moduleGraph: chunkGraph.moduleGraph,
			chunkGraph,
			runtime: undefined,
			codeGenerationResults: undefined
		};
		const sources = this.codeGeneration(codeGenContext).sources;

		return type ? sources.get(type) : sources.get(first(this.getSourceTypes()));
	}

	/* istanbul ignore next */
	/**
	 * @abstract
	 * @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) {
		const AbstractMethodError = require("./AbstractMethodError");
		throw new AbstractMethodError();
	}

	/**
	 * @param {LibIdentOptions} options options
	 * @returns {string | null} an identifier for library inclusion
	 */
	libIdent(options) {
		return null;
	}

	/**
	 * @returns {string | null} absolute path which should be used for condition matching (usually the resource path)
	 */
	nameForCondition() {
		return null;
	}

	/**
	 * @param {ConcatenationBailoutReasonContext} context context
	 * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
	 */
	getConcatenationBailoutReason(context) {
		return `Module Concatenation is not implemented for ${this.constructor.name}`;
	}

	/**
	 * @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 true;
	}

	/**
	 * @param {CodeGenerationContext} context context for code generation
	 * @returns {CodeGenerationResult} result
	 */
	codeGeneration(context) {
		// Best override this method
		const sources = new Map();
		for (const type of this.getSourceTypes()) {
			if (type !== "unknown") {
				sources.set(
					type,
					this.source(
						context.dependencyTemplates,
						context.runtimeTemplate,
						type
					)
				);
			}
		}
		return {
			sources,
			runtimeRequirements: new Set([
				RuntimeGlobals.module,
				RuntimeGlobals.exports,
				RuntimeGlobals.require
			])
		};
	}

	/**
	 * @param {Chunk} chunk the chunk which condition should be checked
	 * @param {Compilation} compilation the compilation
	 * @returns {boolean} true, if the chunk is ok for the module
	 */
	chunkCondition(chunk, compilation) {
		return true;
	}

	hasChunkCondition() {
		return this.chunkCondition !== Module.prototype.chunkCondition;
	}

	/**
	 * 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) {
		this.type = module.type;
		this.layer = module.layer;
		this.context = module.context;
		this.factoryMeta = module.factoryMeta;
		this.resolveOptions = module.resolveOptions;
	}

	/**
	 * Module should be unsafe cached. Get data that's needed for that.
	 * This data will be passed to restoreFromUnsafeCache later.
	 * @returns {UnsafeCacheData} cached data
	 */
	getUnsafeCacheData() {
		return {
			factoryMeta: this.factoryMeta,
			resolveOptions: this.resolveOptions
		};
	}

	/**
	 * restore unsafe cache data
	 * @param {object} unsafeCacheData data from getUnsafeCacheData
	 * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching
	 */
	_restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {
		this.factoryMeta = unsafeCacheData.factoryMeta;
		this.resolveOptions = unsafeCacheData.resolveOptions;
	}

	/**
	 * Assuming this module is in the cache. Remove internal references to allow freeing some memory.
	 */
	cleanupForCache() {
		this.factoryMeta = undefined;
		this.resolveOptions = undefined;
	}

	/**
	 * @returns {Source | null} the original source for the module before webpack transformation
	 */
	originalSource() {
		return null;
	}

	/**
	 * @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
	) {}

	/**
	 * @param {ObjectSerializerContext} context context
	 */
	serialize(context) {
		const { write } = context;
		write(this.type);
		write(this.layer);
		write(this.context);
		write(this.resolveOptions);
		write(this.factoryMeta);
		write(this.useSourceMap);
		write(this.useSimpleSourceMap);
		write(
			this._warnings !== undefined && this._warnings.length === 0
				? undefined
				: this._warnings
		);
		write(
			this._errors !== undefined && this._errors.length === 0
				? undefined
				: this._errors
		);
		write(this.buildMeta);
		write(this.buildInfo);
		write(this.presentationalDependencies);
		write(this.codeGenerationDependencies);
		super.serialize(context);
	}

	/**
	 * @param {ObjectDeserializerContext} context context
	 */
	deserialize(context) {
		const { read } = context;
		this.type = read();
		this.layer = read();
		this.context = read();
		this.resolveOptions = read();
		this.factoryMeta = read();
		this.useSourceMap = read();
		this.useSimpleSourceMap = read();
		this._warnings = read();
		this._errors = read();
		this.buildMeta = read();
		this.buildInfo = read();
		this.presentationalDependencies = read();
		this.codeGenerationDependencies = read();
		super.deserialize(context);
	}
}

makeSerializable(Module, "webpack/lib/Module");

// TODO remove in webpack 6
Object.defineProperty(Module.prototype, "hasEqualsChunks", {
	get() {
		throw new Error(
			"Module.hasEqualsChunks was renamed (use hasEqualChunks instead)"
		);
	}
});

// TODO remove in webpack 6
Object.defineProperty(Module.prototype, "isUsed", {
	get() {
		throw new Error(
			"Module.isUsed was renamed (use getUsedName, isExportUsed or isModuleUsed instead)"
		);
	}
});

// TODO remove in webpack 6
Object.defineProperty(Module.prototype, "errors", {
	get: util.deprecate(
		/**
		 * @this {Module}
		 * @returns {WebpackError[]} array
		 */
		function () {
			if (this._errors === undefined) {
				this._errors = [];
			}
			return this._errors;
		},
		"Module.errors was removed (use getErrors instead)",
		"DEP_WEBPACK_MODULE_ERRORS"
	)
});

// TODO remove in webpack 6
Object.defineProperty(Module.prototype, "warnings", {
	get: util.deprecate(
		/**
		 * @this {Module}
		 * @returns {WebpackError[]} array
		 */
		function () {
			if (this._warnings === undefined) {
				this._warnings = [];
			}
			return this._warnings;
		},
		"Module.warnings was removed (use getWarnings instead)",
		"DEP_WEBPACK_MODULE_WARNINGS"
	)
});

// TODO remove in webpack 6
Object.defineProperty(Module.prototype, "used", {
	get() {
		throw new Error(
			"Module.used was refactored (use ModuleGraph.getUsedExports instead)"
		);
	},
	set(value) {
		throw new Error(
			"Module.used was refactored (use ModuleGraph.setUsedExports instead)"
		);
	}
});

module.exports = Module;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { cutOffLoaderExecution } = require("./ErrorHelpers");
const WebpackError = require("./WebpackError");
const makeSerializable = require("./util/makeSerializable");

/** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */

class ModuleBuildError extends WebpackError {
	/**
	 * @param {string | Error&any} err error thrown
	 * @param {{from?: string|null}} info additional info
	 */
	constructor(err, { from = null } = {}) {
		let message = "Module build failed";
		let details = undefined;

		if (from) {
			message += ` (from ${from}):\n`;
		} else {
			message += ": ";
		}

		if (err !== null && typeof err === "object") {
			if (typeof err.stack === "string" && err.stack) {
				const stack = cutOffLoaderExecution(err.stack);

				if (!err.hideStack) {
					message += stack;
				} else {
					details = stack;

					if (typeof err.message === "string" && err.message) {
						message += err.message;
					} else {
						message += err;
					}
				}
			} else if (typeof err.message === "string" && err.message) {
				message += err.message;
			} else {
				message += String(err);
			}
		} else {
			message += String(err);
		}

		super(message);

		this.name = "ModuleBuildError";
		this.details = details;
		this.error = err;
	}

	/**
	 * @param {ObjectSerializerContext} context context
	 */
	serialize(context) {
		const { write } = context;

		write(this.error);

		super.serialize(context);
	}

	/**
	 * @param {ObjectDeserializerContext} context context
	 */
	deserialize(context) {
		const { read } = context;

		this.error = read();

		super.deserialize(context);
	}
}

makeSerializable(ModuleBuildError, "webpack/lib/ModuleBuildError");

module.exports = ModuleBuildError;

license: mit


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const WebpackError = require("./WebpackError");

/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("./Module")} Module */

class ModuleDependencyError extends WebpackError {
	/**
	 * Creates an instance of ModuleDependencyError.
	 * @param {Module} module module tied to dependency
	 * @param {Error} err error thrown
	 * @param {DependencyLocation} loc location of dependency
	 */
	constructor(module, err, loc) {
		super(err.message);

		this.name = "ModuleDependencyError";
		this.details =
			err && !(/** @type {any} */ (err).hideStack)
				? /** @type {string} */ (err.stack).split("\n").slice(1).join("\n")
				: undefined;
		this.module = module;
		this.loc = loc;
		/** error is not (de)serialized, so it might be undefined after deserialization */
		this.error = err;

		if (err && /** @type {any} */ (err).hideStack) {
			this.stack =
				/** @type {string} */ (err.stack).split("\n").slice(1).join("\n") +
				"\n\n" +
				this.stack;
		}
	}
}

module.exports = ModuleDependencyError;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const WebpackError = require("./WebpackError");
const makeSerializable = require("./util/makeSerializable");

/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("./Module")} Module */

class ModuleDependencyWarning extends WebpackError {
	/**
	 * @param {Module} module module tied to dependency
	 * @param {Error} err error thrown
	 * @param {DependencyLocation} loc location of dependency
	 */
	constructor(module, err, loc) {
		super(err ? err.message : "");

		this.name = "ModuleDependencyWarning";
		this.details =
			err && !(/** @type {any} */ (err).hideStack)
				? /** @type {string} */ (err.stack).split("\n").slice(1).join("\n")
				: undefined;
		this.module = module;
		this.loc = loc;
		/** error is not (de)serialized, so it might be undefined after deserialization */
		this.error = err;

		if (err && /** @type {any} */ (err).hideStack) {
			this.stack =
				/** @type {string} */ (err.stack).split("\n").slice(1).join("\n") +
				"\n\n" +
				this.stack;
		}
	}
}

makeSerializable(
	ModuleDependencyWarning,
	"webpack/lib/ModuleDependencyWarning"
);

module.exports = ModuleDependencyWarning;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { cleanUp } = require("./ErrorHelpers");
const WebpackError = require("./WebpackError");
const makeSerializable = require("./util/makeSerializable");

/** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */

class ModuleError extends WebpackError {
	/**
	 * @param {Error} err error thrown
	 * @param {{from?: string|null}} info additional info
	 */
	constructor(err, { from = null } = {}) {
		let message = "Module Error";

		if (from) {
			message += ` (from ${from}):\n`;
		} else {
			message += ": ";
		}

		if (err && typeof err === "object" && err.message) {
			message += err.message;
		} else if (err) {
			message += err;
		}

		super(message);

		this.name = "ModuleError";
		this.error = err;
		this.details =
			err && typeof err === "object" && err.stack
				? cleanUp(err.stack, this.message)
				: undefined;
	}

	/**
	 * @param {ObjectSerializerContext} context context
	 */
	serialize(context) {
		const { write } = context;

		write(this.error);

		super.serialize(context);
	}

	/**
	 * @param {ObjectDeserializerContext} context context
	 */
	deserialize(context) {
		const { read } = context;

		this.error = read();

		super.deserialize(context);
	}
}

makeSerializable(ModuleError, "webpack/lib/ModuleError");

module.exports = ModuleError;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

/** @typedef {import("../declarations/WebpackOptions").ResolveOptions} ResolveOptions */
/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./Module")} Module */

/**
 * @typedef {object} ModuleFactoryResult
 * @property {Module=} module the created module or unset if no module was created
 * @property {Set<string>=} fileDependencies
 * @property {Set<string>=} contextDependencies
 * @property {Set<string>=} missingDependencies
 * @property {boolean=} cacheable allow to use the unsafe cache
 */

/**
 * @typedef {object} ModuleFactoryCreateDataContextInfo
 * @property {string} issuer
 * @property {string | null=} issuerLayer
 * @property {string} compiler
 */

/**
 * @typedef {object} ModuleFactoryCreateData
 * @property {ModuleFactoryCreateDataContextInfo} contextInfo
 * @property {ResolveOptions=} resolveOptions
 * @property {string} context
 * @property {Dependency[]} dependencies
 */

class ModuleFactory {
	/* istanbul ignore next */
	/**
	 * @abstract
	 * @param {ModuleFactoryCreateData} data data object
	 * @param {function((Error | null)=, ModuleFactoryResult=): void} callback callback
	 * @returns {void}
	 */
	create(data, callback) {
		const AbstractMethodError = require("./AbstractMethodError");
		throw new AbstractMethodError();
	}
}

module.exports = ModuleFactory;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const NormalModule = require("./NormalModule");
const createHash = require("./util/createHash");
const memoize = require("./util/memoize");

/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Module")} Module */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {typeof import("./util/Hash")} Hash */

/** @typedef {string | RegExp | (string | RegExp)[]} Matcher */
/** @typedef {{test?: Matcher, include?: Matcher, exclude?: Matcher }} MatchObject */

const ModuleFilenameHelpers = exports;

// TODO webpack 6: consider removing these
ModuleFilenameHelpers.ALL_LOADERS_RESOURCE = "[all-loaders][resource]";
ModuleFilenameHelpers.REGEXP_ALL_LOADERS_RESOURCE =
	/\[all-?loaders\]\[resource\]/gi;
ModuleFilenameHelpers.LOADERS_RESOURCE = "[loaders][resource]";
ModuleFilenameHelpers.REGEXP_LOADERS_RESOURCE = /\[loaders\]\[resource\]/gi;
ModuleFilenameHelpers.RESOURCE = "[resource]";
ModuleFilenameHelpers.REGEXP_RESOURCE = /\[resource\]/gi;
ModuleFilenameHelpers.ABSOLUTE_RESOURCE_PATH = "[absolute-resource-path]";
// cSpell:words olute
ModuleFilenameHelpers.REGEXP_ABSOLUTE_RESOURCE_PATH =
	/\[abs(olute)?-?resource-?path\]/gi;
ModuleFilenameHelpers.RESOURCE_PATH = "[resource-path]";
ModuleFilenameHelpers.REGEXP_RESOURCE_PATH = /\[resource-?path\]/gi;
ModuleFilenameHelpers.ALL_LOADERS = "[all-loaders]";
ModuleFilenameHelpers.REGEXP_ALL_LOADERS = /\[all-?loaders\]/gi;
ModuleFilenameHelpers.LOADERS = "[loaders]";
ModuleFilenameHelpers.REGEXP_LOADERS = /\[loaders\]/gi;
ModuleFilenameHelpers.QUERY = "[query]";
ModuleFilenameHelpers.REGEXP_QUERY = /\[query\]/gi;
ModuleFilenameHelpers.ID = "[id]";
ModuleFilenameHelpers.REGEXP_ID = /\[id\]/gi;
ModuleFilenameHelpers.HASH = "[hash]";
ModuleFilenameHelpers.REGEXP_HASH = /\[hash\]/gi;
ModuleFilenameHelpers.NAMESPACE = "[namespace]";
ModuleFilenameHelpers.REGEXP_NAMESPACE = /\[namespace\]/gi;

/** @typedef {() => string} ReturnStringCallback */

/**
 * Returns a function that returns the part of the string after the token
 * @param {ReturnStringCallback} strFn the function to get the string
 * @param {string} token the token to search for
 * @returns {ReturnStringCallback} a function that returns the part of the string after the token
 */
const getAfter = (strFn, token) => {
	return () => {
		const str = strFn();
		const idx = str.indexOf(token);
		return idx < 0 ? "" : str.slice(idx);
	};
};

/**
 * Returns a function that returns the part of the string before the token
 * @param {ReturnStringCallback} strFn the function to get the string
 * @param {string} token the token to search for
 * @returns {ReturnStringCallback} a function that returns the part of the string before the token
 */
const getBefore = (strFn, token) => {
	return () => {
		const str = strFn();
		const idx = str.lastIndexOf(token);
		return idx < 0 ? "" : str.slice(0, idx);
	};
};

/**
 * Returns a function that returns a hash of the string
 * @param {ReturnStringCallback} strFn the function to get the string
 * @param {string | Hash=} hashFunction the hash function to use
 * @returns {ReturnStringCallback} a function that returns the hash of the string
 */
const getHash = (strFn, hashFunction = "md4") => {
	return () => {
		const hash = createHash(hashFunction);
		hash.update(strFn());
		const digest = /** @type {string} */ (hash.digest("hex"));
		return digest.slice(0, 4);
	};
};

/**
 * Returns a function that returns the string with the token replaced with the replacement
 * @param {string|RegExp} test A regular expression string or Regular Expression object
 * @returns	{RegExp} A regular expression object
 * @example
 * ```js
 * const test = asRegExp("test");
 * test.test("test"); // true
 *
 * const test2 = asRegExp(/test/);
 * test2.test("test"); // true
 * ```
 */
const asRegExp = test => {
	if (typeof test === "string") {
		// Escape special characters in the string to prevent them from being interpreted as special characters in a regular expression. Do this by
		// adding a backslash before each special character
		test = new RegExp("^" + test.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"));
	}
	return test;
};

/**
 * @template T
 * Returns a lazy object. The object is lazy in the sense that the properties are
 * only evaluated when they are accessed. This is only obtained by setting a function as the value for each key.
 * @param {Record<string, () => T>} obj the object to convert to a lazy access object
 * @returns {object} the lazy access object
 */
const lazyObject = obj => {
	const newObj = {};
	for (const key of Object.keys(obj)) {
		const fn = obj[key];
		Object.defineProperty(newObj, key, {
			get: () => fn(),
			set: v => {
				Object.defineProperty(newObj, key, {
					value: v,
					enumerable: true,
					writable: true
				});
			},
			enumerable: true,
			configurable: true
		});
	}
	return newObj;
};

const SQUARE_BRACKET_TAG_REGEXP = /\[\\*([\w-]+)\\*\]/gi;

/**
 *
 * @param {Module | string} module the module
 * @param {TODO} options options
 * @param {object} contextInfo context info
 * @param {RequestShortener} contextInfo.requestShortener requestShortener
 * @param {ChunkGraph} contextInfo.chunkGraph chunk graph
 * @param {string | Hash=} contextInfo.hashFunction the hash function to use
 * @returns {string} the filename
 */
ModuleFilenameHelpers.createFilename = (
	module = "",
	options,
	{ requestShortener, chunkGraph, hashFunction = "md4" }
) => {
	const opts = {
		namespace: "",
		moduleFilenameTemplate: "",
		...(typeof options === "object"
			? options
			: {
					moduleFilenameTemplate: options
				})
	};

	let absoluteResourcePath;
	let hash;
	/** @type {ReturnStringCallback} */
	let identifier;
	/** @type {ReturnStringCallback} */
	let moduleId;
	/** @type {ReturnStringCallback} */
	let shortIdentifier;
	if (typeof module === "string") {
		shortIdentifier =
			/** @type {ReturnStringCallback} */
			(memoize(() => requestShortener.shorten(module)));
		identifier = shortIdentifier;
		moduleId = () => "";
		absoluteResourcePath = () => module.split("!").pop();
		hash = getHash(identifier, hashFunction);
	} else {
		shortIdentifier = memoize(() =>
			module.readableIdentifier(requestShortener)
		);
		identifier =
			/** @type {ReturnStringCallback} */
			(memoize(() => requestShortener.shorten(module.identifier())));
		moduleId =
			/** @type {ReturnStringCallback} */
			(() => chunkGraph.getModuleId(module));
		absoluteResourcePath = () =>
			module instanceof NormalModule
				? module.resource
				: module.identifier().split("!").pop();
		hash = getHash(identifier, hashFunction);
	}
	const resource =
		/** @type {ReturnStringCallback} */
		(memoize(() => shortIdentifier().split("!").pop()));

	const loaders = getBefore(shortIdentifier, "!");
	const allLoaders = getBefore(identifier, "!");
	const query = getAfter(resource, "?");
	const resourcePath = () => {
		const q = query().length;
		return q === 0 ? resource() : resource().slice(0, -q);
	};
	if (typeof opts.moduleFilenameTemplate === "function") {
		return opts.moduleFilenameTemplate(
			lazyObject({
				identifier: identifier,
				shortIdentifier: shortIdentifier,
				resource: resource,
				resourcePath: memoize(resourcePath),
				absoluteResourcePath: memoize(absoluteResourcePath),
				loaders: memoize(loaders),
				allLoaders: memoize(allLoaders),
				query: memoize(query),
				moduleId: memoize(moduleId),
				hash: memoize(hash),
				namespace: () => opts.namespace
			})
		);
	}

	// TODO webpack 6: consider removing alternatives without dashes
	/** @type {Map<string, function(): string>} */
	const replacements = new Map([
		["identifier", identifier],
		["short-identifier", shortIdentifier],
		["resource", resource],
		["resource-path", resourcePath],
		// cSpell:words resourcepath
		["resourcepath", resourcePath],
		["absolute-resource-path", absoluteResourcePath],
		["abs-resource-path", absoluteResourcePath],
		// cSpell:words absoluteresource
		["absoluteresource-path", absoluteResourcePath],
		// cSpell:words absresource
		["absresource-path", absoluteResourcePath],
		// cSpell:words resourcepath
		["absolute-resourcepath", absoluteResourcePath],
		// cSpell:words resourcepath
		["abs-resourcepath", absoluteResourcePath],
		// cSpell:words absoluteresourcepath
		["absoluteresourcepath", absoluteResourcePath],
		// cSpell:words absresourcepath
		["absresourcepath", absoluteResourcePath],
		["all-loaders", allLoaders],
		// cSpell:words allloaders
		["allloaders", allLoaders],
		["loaders", loaders],
		["query", query],
		["id", moduleId],
		["hash", hash],
		["namespace", () => opts.namespace]
	]);

	// TODO webpack 6: consider removing weird double placeholders
	return /** @type {string} */ (opts.moduleFilenameTemplate)
		.replace(ModuleFilenameHelpers.REGEXP_ALL_LOADERS_RESOURCE, "[identifier]")
		.replace(
			ModuleFilenameHelpers.REGEXP_LOADERS_RESOURCE,
			"[short-identifier]"
		)
		.replace(SQUARE_BRACKET_TAG_REGEXP, (match, content) => {
			if (content.length + 2 === match.length) {
				const replacement = replacements.get(content.toLowerCase());
				if (replacement !== undefined) {
					return replacement();
				}
			} else if (match.startsWith("[\\") && match.endsWith("\\]")) {
				return `[${match.slice(2, -2)}]`;
			}
			return match;
		});
};

/**
 * Replaces duplicate items in an array with new values generated by a callback function.
 * The callback function is called with the duplicate item, the index of the duplicate item, and the number of times the item has been replaced.
 * The callback function should return the new value for the duplicate item.
 *
 * @template T
 * @param {T[]} array the array with duplicates to be replaced
 * @param {(duplicateItem: T, duplicateItemIndex: number, numberOfTimesReplaced: number) => T} fn callback function to generate new values for the duplicate items
 * @param {(firstElement:T, nextElement:T) => -1 | 0 | 1} [comparator] optional comparator function to sort the duplicate items
 * @returns {T[]} the array with duplicates replaced
 *
 * @example
 * ```js
 * const array = ["a", "b", "c", "a", "b", "a"];
 * const result = ModuleFilenameHelpers.replaceDuplicates(array, (item, index, count) => `${item}-${count}`);
 * // result: ["a-1", "b-1", "c", "a-2", "b-2", "a-3"]
 * ```
 */
ModuleFilenameHelpers.replaceDuplicates = (array, fn, comparator) => {
	const countMap = Object.create(null);
	const posMap = Object.create(null);

	array.forEach((item, idx) => {
		countMap[item] = countMap[item] || [];
		countMap[item].push(idx);
		posMap[item] = 0;
	});
	if (comparator) {
		Object.keys(countMap).forEach(item => {
			countMap[item].sort(comparator);
		});
	}
	return array.map((item, i) => {
		if (countMap[item].length > 1) {
			if (comparator && countMap[item][0] === i) return item;
			return fn(item, i, posMap[item]++);
		} else {
			return item;
		}
	});
};

/**
 * Tests if a string matches a RegExp or an array of RegExp.
 *
 * @param {string} str string to test
 * @param {Matcher} test value which will be used to match against the string
 * @returns {boolean} true, when the RegExp matches
 *
 * @example
 * ```js
 * ModuleFilenameHelpers.matchPart("foo.js", "foo"); // true
 * ModuleFilenameHelpers.matchPart("foo.js", "foo.js"); // true
 * ModuleFilenameHelpers.matchPart("foo.js", "foo."); // false
 * ModuleFilenameHelpers.matchPart("foo.js", "foo*"); // false
 * ModuleFilenameHelpers.matchPart("foo.js", "foo.*"); // true
 * ModuleFilenameHelpers.matchPart("foo.js", /^foo/); // true
 * ModuleFilenameHelpers.matchPart("foo.js", [/^foo/, "bar"]); // true
 * ModuleFilenameHelpers.matchPart("foo.js", [/^foo/, "bar"]); // true
 * ModuleFilenameHelpers.matchPart("foo.js", [/^foo/, /^bar/]); // true
 * ModuleFilenameHelpers.matchPart("foo.js", [/^baz/, /^bar/]); // false
 * ```
 */
ModuleFilenameHelpers.matchPart = (str, test) => {
	if (!test) return true;

	if (Array.isArray(test)) {
		return test.map(asRegExp).some(regExp => regExp.test(str));
	} else {
		return asRegExp(test).test(str);
	}
};

/**
 * Tests if a string matches a match object. The match object can have the following properties:
 * - `test`: a RegExp or an array of RegExp
 * - `include`: a RegExp or an array of RegExp
 * - `exclude`: a RegExp or an array of RegExp
 *
 * The `test` property is tested first, then `include` and then `exclude`.
 *
 * @param {MatchObject} obj a match object to test against the string
 * @param {string} str string to test against the matching object
 * @returns {boolean} true, when the object matches
 * @example
 * ```js
 * ModuleFilenameHelpers.matchObject({ test: "foo.js" }, "foo.js"); // true
 * ModuleFilenameHelpers.matchObject({ test: /^foo/ }, "foo.js"); // true
 * ModuleFilenameHelpers.matchObject({ test: [/^foo/, "bar"] }, "foo.js"); // true
 * ModuleFilenameHelpers.matchObject({ test: [/^foo/, "bar"] }, "baz.js"); // false
 * ModuleFilenameHelpers.matchObject({ include: "foo.js" }, "foo.js"); // true
 * ModuleFilenameHelpers.matchObject({ include: "foo.js" }, "bar.js"); // false
 * ModuleFilenameHelpers.matchObject({ include: /^foo/ }, "foo.js"); // true
 * ModuleFilenameHelpers.matchObject({ include: [/^foo/, "bar"] }, "foo.js"); // true
 * ModuleFilenameHelpers.matchObject({ include: [/^foo/, "bar"] }, "baz.js"); // false
 * ModuleFilenameHelpers.matchObject({ exclude: "foo.js" }, "foo.js"); // false
 * ModuleFilenameHelpers.matchObject({ exclude: [/^foo/, "bar"] }, "foo.js"); // false
 * ```
 */
ModuleFilenameHelpers.matchObject = (obj, str) => {
	if (obj.test) {
		if (!ModuleFilenameHelpers.matchPart(str, obj.test)) {
			return false;
		}
	}
	if (obj.include) {
		if (!ModuleFilenameHelpers.matchPart(str, obj.include)) {
			return false;
		}
	}
	if (obj.exclude) {
		if (ModuleFilenameHelpers.matchPart(str, obj.exclude)) {
			return false;
		}
	}
	return true;
};


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const util = require("util");
const ExportsInfo = require("./ExportsInfo");
const ModuleGraphConnection = require("./ModuleGraphConnection");
const SortableSet = require("./util/SortableSet");
const WeakTupleMap = require("./util/WeakTupleMap");

/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./ExportsInfo").ExportInfo} ExportInfo */
/** @typedef {import("./Module")} Module */
/** @typedef {import("./ModuleProfile")} ModuleProfile */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */

/**
 * @callback OptimizationBailoutFunction
 * @param {RequestShortener} requestShortener
 * @returns {string}
 */

const EMPTY_SET = new Set();

/**
 * @param {SortableSet<ModuleGraphConnection>} set input
 * @returns {readonly Map<Module | undefined, readonly ModuleGraphConnection[]>} mapped by origin module
 */
const getConnectionsByOriginModule = set => {
	const map = new Map();
	/** @type {Module | 0} */
	let lastModule = 0;
	/** @type {ModuleGraphConnection[] | undefined} */
	let lastList = undefined;
	for (const connection of set) {
		const { originModule } = connection;
		if (lastModule === originModule) {
			/** @type {ModuleGraphConnection[]} */
			(lastList).push(connection);
		} else {
			lastModule = /** @type {Module} */ (originModule);
			const list = map.get(originModule);
			if (list !== undefined) {
				lastList = list;
				list.push(connection);
			} else {
				const list = [connection];
				lastList = list;
				map.set(originModule, list);
			}
		}
	}
	return map;
};

/**
 * @param {SortableSet<ModuleGraphConnection>} set input
 * @returns {readonly Map<Module | undefined, readonly ModuleGraphConnection[]>} mapped by module
 */
const getConnectionsByModule = set => {
	const map = new Map();
	/** @type {Module | 0} */
	let lastModule = 0;
	/** @type {ModuleGraphConnection[] | undefined} */
	let lastList = undefined;
	for (const connection of set) {
		const { module } = connection;
		if (lastModule === module) {
			/** @type {ModuleGraphConnection[]} */
			(lastList).push(connection);
		} else {
			lastModule = module;
			const list = map.get(module);
			if (list !== undefined) {
				lastList = list;
				list.push(connection);
			} else {
				const list = [connection];
				lastList = list;
				map.set(module, list);
			}
		}
	}
	return map;
};

/** @typedef {SortableSet<ModuleGraphConnection>} IncomingConnections */
/** @typedef {SortableSet<ModuleGraphConnection>} OutgoingConnections */

class ModuleGraphModule {
	constructor() {
		/** @type {IncomingConnections} */
		this.incomingConnections = new SortableSet();
		/** @type {OutgoingConnections | undefined} */
		this.outgoingConnections = undefined;
		/** @type {Module | null | undefined} */
		this.issuer = undefined;
		/** @type {(string | OptimizationBailoutFunction)[]} */
		this.optimizationBailout = [];
		/** @type {ExportsInfo} */
		this.exports = new ExportsInfo();
		/** @type {number | null} */
		this.preOrderIndex = null;
		/** @type {number | null} */
		this.postOrderIndex = null;
		/** @type {number | null} */
		this.depth = null;
		/** @type {ModuleProfile | undefined} */
		this.profile = undefined;
		/** @type {boolean} */
		this.async = false;
		/** @type {ModuleGraphConnection[] | undefined} */
		this._unassignedConnections = undefined;
	}
}

class ModuleGraph {
	constructor() {
		/**
		 * @type {WeakMap<Dependency, ModuleGraphConnection | null>}
		 * @private
		 */
		this._dependencyMap = new WeakMap();
		/**
		 * @type {Map<Module, ModuleGraphModule>}
		 * @private
		 */
		this._moduleMap = new Map();
		/**
		 * @type {WeakMap<any, object>}
		 * @private
		 */
		this._metaMap = new WeakMap();
		/**
		 * @type {WeakTupleMap<any[], any> | undefined}
		 * @private
		 */
		this._cache = undefined;
		/**
		 * @type {Map<Module, WeakTupleMap<any, any>> | undefined}
		 * @private
		 */
		this._moduleMemCaches = undefined;

		/**
		 * @type {string | undefined}
		 * @private
		 */
		this._cacheStage = undefined;
	}

	/**
	 * @param {Module} module the module
	 * @returns {ModuleGraphModule} the internal module
	 */
	_getModuleGraphModule(module) {
		let mgm = this._moduleMap.get(module);
		if (mgm === undefined) {
			mgm = new ModuleGraphModule();
			this._moduleMap.set(module, mgm);
		}
		return mgm;
	}

	/**
	 * @param {Dependency} dependency the dependency
	 * @param {DependenciesBlock} block parent block
	 * @param {Module} module parent module
	 * @param {number=} indexInBlock position in block
	 * @returns {void}
	 */
	setParents(dependency, block, module, indexInBlock = -1) {
		dependency._parentDependenciesBlockIndex = indexInBlock;
		dependency._parentDependenciesBlock = block;
		dependency._parentModule = module;
	}

	/**
	 * @param {Dependency} dependency the dependency
	 * @returns {Module | undefined} parent module
	 */
	getParentModule(dependency) {
		return dependency._parentModule;
	}

	/**
	 * @param {Dependency} dependency the dependency
	 * @returns {DependenciesBlock | undefined} parent block
	 */
	getParentBlock(dependency) {
		return dependency._parentDependenciesBlock;
	}

	/**
	 * @param {Dependency} dependency the dependency
	 * @returns {number} index
	 */
	getParentBlockIndex(dependency) {
		return dependency._parentDependenciesBlockIndex;
	}

	/**
	 * @param {Module | null} originModule the referencing module
	 * @param {Dependency} dependency the referencing dependency
	 * @param {Module} module the referenced module
	 * @returns {void}
	 */
	setResolvedModule(originModule, dependency, module) {
		const connection = new ModuleGraphConnection(
			originModule,
			dependency,
			module,
			undefined,
			dependency.weak,
			dependency.getCondition(this)
		);
		const connections = this._getModuleGraphModule(module).incomingConnections;
		connections.add(connection);
		if (originModule) {
			const mgm = this._getModuleGraphModule(originModule);
			if (mgm._unassignedConnections === undefined) {
				mgm._unassignedConnections = [];
			}
			mgm._unassignedConnections.push(connection);
			if (mgm.outgoingConnections === undefined) {
				mgm.outgoingConnections = new SortableSet();
			}
			mgm.outgoingConnections.add(connection);
		} else {
			this._dependencyMap.set(dependency, connection);
		}
	}

	/**
	 * @param {Dependency} dependency the referencing dependency
	 * @param {Module} module the referenced module
	 * @returns {void}
	 */
	updateModule(dependency, module) {
		const connection =
			/** @type {ModuleGraphConnection} */
			(this.getConnection(dependency));
		if (connection.module === module) return;
		const newConnection = connection.clone();
		newConnection.module = module;
		this._dependencyMap.set(dependency, newConnection);
		connection.setActive(false);
		const originMgm = this._getModuleGraphModule(
			/** @type {Module} */ (connection.originModule)
		);
		/** @type {OutgoingConnections} */
		(originMgm.outgoingConnections).add(newConnection);
		const targetMgm = this._getModuleGraphModule(module);
		targetMgm.incomingConnections.add(newConnection);
	}

	/**
	 * @param {Dependency} dependency the referencing dependency
	 * @returns {void}
	 */
	removeConnection(dependency) {
		const connection =
			/** @type {ModuleGraphConnection} */
			(this.getConnection(dependency));
		const targetMgm = this._getModuleGraphModule(connection.module);
		targetMgm.incomingConnections.delete(connection);
		const originMgm = this._getModuleGraphModule(
			/** @type {Module} */ (connection.originModule)
		);
		/** @type {OutgoingConnections} */
		(originMgm.outgoingConnections).delete(connection);
		this._dependencyMap.set(dependency, null);
	}

	/**
	 * @param {Dependency} dependency the referencing dependency
	 * @param {string} explanation an explanation
	 * @returns {void}
	 */
	addExplanation(dependency, explanation) {
		const connection =
			/** @type {ModuleGraphConnection} */
			(this.getConnection(dependency));
		connection.addExplanation(explanation);
	}

	/**
	 * @param {Module} sourceModule the source module
	 * @param {Module} targetModule the target module
	 * @returns {void}
	 */
	cloneModuleAttributes(sourceModule, targetModule) {
		const oldMgm = this._getModuleGraphModule(sourceModule);
		const newMgm = this._getModuleGraphModule(targetModule);
		newMgm.postOrderIndex = oldMgm.postOrderIndex;
		newMgm.preOrderIndex = oldMgm.preOrderIndex;
		newMgm.depth = oldMgm.depth;
		newMgm.exports = oldMgm.exports;
		newMgm.async = oldMgm.async;
	}

	/**
	 * @param {Module} module the module
	 * @returns {void}
	 */
	removeModuleAttributes(module) {
		const mgm = this._getModuleGraphModule(module);
		mgm.postOrderIndex = null;
		mgm.preOrderIndex = null;
		mgm.depth = null;
		mgm.async = false;
	}

	/**
	 * @returns {void}
	 */
	removeAllModuleAttributes() {
		for (const mgm of this._moduleMap.values()) {
			mgm.postOrderIndex = null;
			mgm.preOrderIndex = null;
			mgm.depth = null;
			mgm.async = false;
		}
	}

	/**
	 * @param {Module} oldModule the old referencing module
	 * @param {Module} newModule the new referencing module
	 * @param {function(ModuleGraphConnection): boolean} filterConnection filter predicate for replacement
	 * @returns {void}
	 */
	moveModuleConnections(oldModule, newModule, filterConnection) {
		if (oldModule === newModule) return;
		const oldMgm = this._getModuleGraphModule(oldModule);
		const newMgm = this._getModuleGraphModule(newModule);
		// Outgoing connections
		const oldConnections = oldMgm.outgoingConnections;
		if (oldConnections !== undefined) {
			if (newMgm.outgoingConnections === undefined) {
				newMgm.outgoingConnections = new SortableSet();
			}
			const newConnections = newMgm.outgoingConnections;
			for (const connection of oldConnections) {
				if (filterConnection(connection)) {
					connection.originModule = newModule;
					newConnections.add(connection);
					oldConnections.delete(connection);
				}
			}
		}
		// Incoming connections
		const oldConnections2 = oldMgm.incomingConnections;
		const newConnections2 = newMgm.incomingConnections;
		for (const connection of oldConnections2) {
			if (filterConnection(connection)) {
				connection.module = newModule;
				newConnections2.add(connection);
				oldConnections2.delete(connection);
			}
		}
	}

	/**
	 * @param {Module} oldModule the old referencing module
	 * @param {Module} newModule the new referencing module
	 * @param {function(ModuleGraphConnection): boolean} filterConnection filter predicate for replacement
	 * @returns {void}
	 */
	copyOutgoingModuleConnections(oldModule, newModule, filterConnection) {
		if (oldModule === newModule) return;
		const oldMgm = this._getModuleGraphModule(oldModule);
		const newMgm = this._getModuleGraphModule(newModule);
		// Outgoing connections
		const oldConnections = oldMgm.outgoingConnections;
		if (oldConnections !== undefined) {
			if (newMgm.outgoingConnections === undefined) {
				newMgm.outgoingConnections = new SortableSet();
			}
			const newConnections = newMgm.outgoingConnections;
			for (const connection of oldConnections) {
				if (filterConnection(connection)) {
					const newConnection = connection.clone();
					newConnection.originModule = newModule;
					newConnections.add(newConnection);
					if (newConnection.module !== undefined) {
						const otherMgm = this._getModuleGraphModule(newConnection.module);
						otherMgm.incomingConnections.add(newConnection);
					}
				}
			}
		}
	}

	/**
	 * @param {Module} module the referenced module
	 * @param {string} explanation an explanation why it's referenced
	 * @returns {void}
	 */
	addExtraReason(module, explanation) {
		const connections = this._getModuleGraphModule(module).incomingConnections;
		connections.add(new ModuleGraphConnection(null, null, module, explanation));
	}

	/**
	 * @param {Dependency} dependency the dependency to look for a referenced module
	 * @returns {Module | null} the referenced module
	 */
	getResolvedModule(dependency) {
		const connection = this.getConnection(dependency);
		return connection !== undefined ? connection.resolvedModule : null;
	}

	/**
	 * @param {Dependency} dependency the dependency to look for a referenced module
	 * @returns {ModuleGraphConnection | undefined} the connection
	 */
	getConnection(dependency) {
		const connection = this._dependencyMap.get(dependency);
		if (connection === undefined) {
			const module = this.getParentModule(dependency);
			if (module !== undefined) {
				const mgm = this._getModuleGraphModule(module);
				if (
					mgm._unassignedConnections &&
					mgm._unassignedConnections.length !== 0
				) {
					let foundConnection;
					for (const connection of mgm._unassignedConnections) {
						this._dependencyMap.set(
							/** @type {Dependency} */ (connection.dependency),
							connection
						);
						if (connection.dependency === dependency)
							foundConnection = connection;
					}
					mgm._unassignedConnections.length = 0;
					if (foundConnection !== undefined) {
						return foundConnection;
					}
				}
			}
			this._dependencyMap.set(dependency, null);
			return undefined;
		}
		return connection === null ? undefined : connection;
	}

	/**
	 * @param {Dependency} dependency the dependency to look for a referenced module
	 * @returns {Module | null} the referenced module
	 */
	getModule(dependency) {
		const connection = this.getConnection(dependency);
		return connection !== undefined ? connection.module : null;
	}

	/**
	 * @param {Dependency} dependency the dependency to look for a referencing module
	 * @returns {Module | null} the referencing module
	 */
	getOrigin(dependency) {
		const connection = this.getConnection(dependency);
		return connection !== undefined ? connection.originModule : null;
	}

	/**
	 * @param {Dependency} dependency the dependency to look for a referencing module
	 * @returns {Module | null} the original referencing module
	 */
	getResolvedOrigin(dependency) {
		const connection = this.getConnection(dependency);
		return connection !== undefined ? connection.resolvedOriginModule : null;
	}

	/**
	 * @param {Module} module the module
	 * @returns {Iterable<ModuleGraphConnection>} reasons why a module is included
	 */
	getIncomingConnections(module) {
		const connections = this._getModuleGraphModule(module).incomingConnections;
		return connections;
	}

	/**
	 * @param {Module} module the module
	 * @returns {Iterable<ModuleGraphConnection>} list of outgoing connections
	 */
	getOutgoingConnections(module) {
		const connections = this._getModuleGraphModule(module).outgoingConnections;
		return connections === undefined ? EMPTY_SET : connections;
	}

	/**
	 * @param {Module} module the module
	 * @returns {readonly Map<Module | undefined | null, readonly ModuleGraphConnection[]>} reasons why a module is included, in a map by source module
	 */
	getIncomingConnectionsByOriginModule(module) {
		const connections = this._getModuleGraphModule(module).incomingConnections;
		return connections.getFromUnorderedCache(getConnectionsByOriginModule);
	}

	/**
	 * @param {Module} module the module
	 * @returns {readonly Map<Module | undefined, readonly ModuleGraphConnection[]> | undefined} connections to modules, in a map by module
	 */
	getOutgoingConnectionsByModule(module) {
		const connections = this._getModuleGraphModule(module).outgoingConnections;
		return connections === undefined
			? undefined
			: connections.getFromUnorderedCache(getConnectionsByModule);
	}

	/**
	 * @param {Module} module the module
	 * @returns {ModuleProfile | undefined} the module profile
	 */
	getProfile(module) {
		const mgm = this._getModuleGraphModule(module);
		return mgm.profile;
	}

	/**
	 * @param {Module} module the module
	 * @param {ModuleProfile | undefined} profile the module profile
	 * @returns {void}
	 */
	setProfile(module, profile) {
		const mgm = this._getModuleGraphModule(module);
		mgm.profile = profile;
	}

	/**
	 * @param {Module} module the module
	 * @returns {Module | null | undefined} the issuer module
	 */
	getIssuer(module) {
		const mgm = this._getModuleGraphModule(module);
		return mgm.issuer;
	}

	/**
	 * @param {Module} module the module
	 * @param {Module | null} issuer the issuer module
	 * @returns {void}
	 */
	setIssuer(module, issuer) {
		const mgm = this._getModuleGraphModule(module);
		mgm.issuer = issuer;
	}

	/**
	 * @param {Module} module the module
	 * @param {Module | null} issuer the issuer module
	 * @returns {void}
	 */
	setIssuerIfUnset(module, issuer) {
		const mgm = this._getModuleGraphModule(module);
		if (mgm.issuer === undefined) mgm.issuer = issuer;
	}

	/**
	 * @param {Module} module the module
	 * @returns {(string | OptimizationBailoutFunction)[]} optimization bailouts
	 */
	getOptimizationBailout(module) {
		const mgm = this._getModuleGraphModule(module);
		return mgm.optimizationBailout;
	}

	/**
	 * @param {Module} module the module
	 * @returns {true | string[] | null} the provided exports
	 */
	getProvidedExports(module) {
		const mgm = this._getModuleGraphModule(module);
		return mgm.exports.getProvidedExports();
	}

	/**
	 * @param {Module} module the module
	 * @param {string | string[]} exportName a name of an export
	 * @returns {boolean | null} true, if the export is provided by the module.
	 * null, if it's unknown.
	 * false, if it's not provided.
	 */
	isExportProvided(module, exportName) {
		const mgm = this._getModuleGraphModule(module);
		const result = mgm.exports.isExportProvided(exportName);
		return result === undefined ? null : result;
	}

	/**
	 * @param {Module} module the module
	 * @returns {ExportsInfo} info about the exports
	 */
	getExportsInfo(module) {
		const mgm = this._getModuleGraphModule(module);
		return mgm.exports;
	}

	/**
	 * @param {Module} module the module
	 * @param {string} exportName the export
	 * @returns {ExportInfo} info about the export
	 */
	getExportInfo(module, exportName) {
		const mgm = this._getModuleGraphModule(module);
		return mgm.exports.getExportInfo(exportName);
	}

	/**
	 * @param {Module} module the module
	 * @param {string} exportName the export
	 * @returns {ExportInfo} info about the export (do not modify)
	 */
	getReadOnlyExportInfo(module, exportName) {
		const mgm = this._getModuleGraphModule(module);
		return mgm.exports.getReadOnlyExportInfo(exportName);
	}

	/**
	 * @param {Module} module the module
	 * @param {RuntimeSpec} runtime the runtime
	 * @returns {false | true | SortableSet<string> | null} the used exports
	 * false: module is not used at all.
	 * true: the module namespace/object export is used.
	 * SortableSet<string>: these export names are used.
	 * empty SortableSet<string>: module is used but no export.
	 * null: unknown, worst case should be assumed.
	 */
	getUsedExports(module, runtime) {
		const mgm = this._getModuleGraphModule(module);
		return mgm.exports.getUsedExports(runtime);
	}

	/**
	 * @param {Module} module the module
	 * @returns {number | null} the index of the module
	 */
	getPreOrderIndex(module) {
		const mgm = this._getModuleGraphModule(module);
		return mgm.preOrderIndex;
	}

	/**
	 * @param {Module} module the module
	 * @returns {number | null} the index of the module
	 */
	getPostOrderIndex(module) {
		const mgm = this._getModuleGraphModule(module);
		return mgm.postOrderIndex;
	}

	/**
	 * @param {Module} module the module
	 * @param {number} index the index of the module
	 * @returns {void}
	 */
	setPreOrderIndex(module, index) {
		const mgm = this._getModuleGraphModule(module);
		mgm.preOrderIndex = index;
	}

	/**
	 * @param {Module} module the module
	 * @param {number} index the index of the module
	 * @returns {boolean} true, if the index was set
	 */
	setPreOrderIndexIfUnset(module, index) {
		const mgm = this._getModuleGraphModule(module);
		if (mgm.preOrderIndex === null) {
			mgm.preOrderIndex = index;
			return true;
		}
		return false;
	}

	/**
	 * @param {Module} module the module
	 * @param {number} index the index of the module
	 * @returns {void}
	 */
	setPostOrderIndex(module, index) {
		const mgm = this._getModuleGraphModule(module);
		mgm.postOrderIndex = index;
	}

	/**
	 * @param {Module} module the module
	 * @param {number} index the index of the module
	 * @returns {boolean} true, if the index was set
	 */
	setPostOrderIndexIfUnset(module, index) {
		const mgm = this._getModuleGraphModule(module);
		if (mgm.postOrderIndex === null) {
			mgm.postOrderIndex = index;
			return true;
		}
		return false;
	}

	/**
	 * @param {Module} module the module
	 * @returns {number | null} the depth of the module
	 */
	getDepth(module) {
		const mgm = this._getModuleGraphModule(module);
		return mgm.depth;
	}

	/**
	 * @param {Module} module the module
	 * @param {number} depth the depth of the module
	 * @returns {void}
	 */
	setDepth(module, depth) {
		const mgm = this._getModuleGraphModule(module);
		mgm.depth = depth;
	}

	/**
	 * @param {Module} module the module
	 * @param {number} depth the depth of the module
	 * @returns {boolean} true, if the depth was set
	 */
	setDepthIfLower(module, depth) {
		const mgm = this._getModuleGraphModule(module);
		if (mgm.depth === null || mgm.depth > depth) {
			mgm.depth = depth;
			return true;
		}
		return false;
	}

	/**
	 * @param {Module} module the module
	 * @returns {boolean} true, if the module is async
	 */
	isAsync(module) {
		const mgm = this._getModuleGraphModule(module);
		return mgm.async;
	}

	/**
	 * @param {Module} module the module
	 * @returns {void}
	 */
	setAsync(module) {
		const mgm = this._getModuleGraphModule(module);
		mgm.async = true;
	}

	/**
	 * @param {any} thing any thing
	 * @returns {object} metadata
	 */
	getMeta(thing) {
		let meta = this._metaMap.get(thing);
		if (meta === undefined) {
			meta = Object.create(null);
			this._metaMap.set(thing, /** @type {object} */ (meta));
		}
		return /** @type {object} */ (meta);
	}

	/**
	 * @param {any} thing any thing
	 * @returns {object | undefined} metadata
	 */
	getMetaIfExisting(thing) {
		return this._metaMap.get(thing);
	}

	/**
	 * @param {string=} cacheStage a persistent stage name for caching
	 */
	freeze(cacheStage) {
		this._cache = new WeakTupleMap();
		this._cacheStage = cacheStage;
	}

	unfreeze() {
		this._cache = undefined;
		this._cacheStage = undefined;
	}

	/**
	 * @template {any[]} T
	 * @template V
	 * @param {(moduleGraph: ModuleGraph, ...args: T) => V} fn computer
	 * @param {T} args arguments
	 * @returns {V} computed value or cached
	 */
	cached(fn, ...args) {
		if (this._cache === undefined) return fn(this, ...args);
		return this._cache.provide(fn, ...args, () => fn(this, ...args));
	}

	/**
	 * @param {Map<Module, WeakTupleMap<any, any>>} moduleMemCaches mem caches for modules for better caching
	 */
	setModuleMemCaches(moduleMemCaches) {
		this._moduleMemCaches = moduleMemCaches;
	}

	/**
	 * @param {Dependency} dependency dependency
	 * @param {...any} args arguments, last argument is a function called with moduleGraph, dependency, ...args
	 * @returns {any} computed value or cached
	 */
	dependencyCacheProvide(dependency, ...args) {
		/** @type {(moduleGraph: ModuleGraph, dependency: Dependency, ...args: any[]) => any} */
		const fn = args.pop();
		if (this._moduleMemCaches && this._cacheStage) {
			const memCache = this._moduleMemCaches.get(
				/** @type {Module} */ (this.getParentModule(dependency))
			);
			if (memCache !== undefined) {
				return memCache.provide(dependency, this._cacheStage, ...args, () =>
					fn(this, dependency, ...args)
				);
			}
		}
		if (this._cache === undefined) return fn(this, dependency, ...args);
		return this._cache.provide(dependency, ...args, () =>
			fn(this, dependency, ...args)
		);
	}

	// TODO remove in webpack 6
	/**
	 * @param {Module} module the module
	 * @param {string} deprecateMessage message for the deprecation message
	 * @param {string} deprecationCode code for the deprecation
	 * @returns {ModuleGraph} the module graph
	 */
	static getModuleGraphForModule(module, deprecateMessage, deprecationCode) {
		const fn = deprecateMap.get(deprecateMessage);
		if (fn) return fn(module);
		const newFn = util.deprecate(
			/**
			 * @param {Module} module the module
			 * @returns {ModuleGraph} the module graph
			 */
			module => {
				const moduleGraph = moduleGraphForModuleMap.get(module);
				if (!moduleGraph)
					throw new Error(
						deprecateMessage +
							"There was no ModuleGraph assigned to the Module for backward-compat (Use the new API)"
					);
				return moduleGraph;
			},
			deprecateMessage + ": Use new ModuleGraph API",
			deprecationCode
		);
		deprecateMap.set(deprecateMessage, newFn);
		return newFn(module);
	}

	// TODO remove in webpack 6
	/**
	 * @param {Module} module the module
	 * @param {ModuleGraph} moduleGraph the module graph
	 * @returns {void}
	 */
	static setModuleGraphForModule(module, moduleGraph) {
		moduleGraphForModuleMap.set(module, moduleGraph);
	}

	// TODO remove in webpack 6
	/**
	 * @param {Module} module the module
	 * @returns {void}
	 */
	static clearModuleGraphForModule(module) {
		moduleGraphForModuleMap.delete(module);
	}
}

// TODO remove in webpack 6
/** @type {WeakMap<Module, ModuleGraph>} */
const moduleGraphForModuleMap = new WeakMap();

// TODO remove in webpack 6
/** @type {Map<string, (module: Module) => ModuleGraph>} */
const deprecateMap = new Map();

module.exports = ModuleGraph;
module.exports.ModuleGraphConnection = ModuleGraphConnection;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./Dependency").GetConditionFn} GetConditionFn */
/** @typedef {import("./Module")} Module */
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */

/**
 * Module itself is not connected, but transitive modules are connected transitively.
 */
const TRANSITIVE_ONLY = Symbol("transitive only");

/**
 * While determining the active state, this flag is used to signal a circular connection.
 */
const CIRCULAR_CONNECTION = Symbol("circular connection");

/** @typedef {boolean | typeof TRANSITIVE_ONLY | typeof CIRCULAR_CONNECTION} ConnectionState */

/**
 * @param {ConnectionState} a first
 * @param {ConnectionState} b second
 * @returns {ConnectionState} merged
 */
const addConnectionStates = (a, b) => {
	if (a === true || b === true) return true;
	if (a === false) return b;
	if (b === false) return a;
	if (a === TRANSITIVE_ONLY) return b;
	if (b === TRANSITIVE_ONLY) return a;
	return a;
};

/**
 * @param {ConnectionState} a first
 * @param {ConnectionState} b second
 * @returns {ConnectionState} intersected
 */
const intersectConnectionStates = (a, b) => {
	if (a === false || b === false) return false;
	if (a === true) return b;
	if (b === true) return a;
	if (a === CIRCULAR_CONNECTION) return b;
	if (b === CIRCULAR_CONNECTION) return a;
	return a;
};

class ModuleGraphConnection {
	/**
	 * @param {Module|null} originModule the referencing module
	 * @param {Dependency|null} dependency the referencing dependency
	 * @param {Module} module the referenced module
	 * @param {string=} explanation some extra detail
	 * @param {boolean=} weak the reference is weak
	 * @param {false | null | GetConditionFn | undefined} condition condition for the connection
	 */
	constructor(
		originModule,
		dependency,
		module,
		explanation,
		weak = false,
		condition = undefined
	) {
		this.originModule = originModule;
		this.resolvedOriginModule = originModule;
		this.dependency = dependency;
		this.resolvedModule = module;
		this.module = module;
		this.weak = weak;
		this.conditional = !!condition;
		this._active = condition !== false;
		/** @type {(function(ModuleGraphConnection, RuntimeSpec): ConnectionState) | undefined} */
		this.condition = condition || undefined;
		/** @type {Set<string> | undefined} */
		this.explanations = undefined;
		if (explanation) {
			this.explanations = new Set();
			this.explanations.add(explanation);
		}
	}

	clone() {
		const clone = new ModuleGraphConnection(
			this.resolvedOriginModule,
			this.dependency,
			this.resolvedModule,
			undefined,
			this.weak,
			this.condition
		);
		clone.originModule = this.originModule;
		clone.module = this.module;
		clone.conditional = this.conditional;
		clone._active = this._active;
		if (this.explanations) clone.explanations = new Set(this.explanations);
		return clone;
	}

	/**
	 * @param {function(ModuleGraphConnection, RuntimeSpec): ConnectionState} condition condition for the connection
	 * @returns {void}
	 */
	addCondition(condition) {
		if (this.conditional) {
			const old =
				/** @type {(function(ModuleGraphConnection, RuntimeSpec): ConnectionState)} */
				(this.condition);
			this.condition = (c, r) =>
				intersectConnectionStates(old(c, r), condition(c, r));
		} else if (this._active) {
			this.conditional = true;
			this.condition = condition;
		}
	}

	/**
	 * @param {string} explanation the explanation to add
	 * @returns {void}
	 */
	addExplanation(explanation) {
		if (this.explanations === undefined) {
			this.explanations = new Set();
		}
		this.explanations.add(explanation);
	}

	get explanation() {
		if (this.explanations === undefined) return "";
		return Array.from(this.explanations).join(" ");
	}

	// TODO webpack 5 remove
	get active() {
		throw new Error("Use getActiveState instead");
	}

	/**
	 * @param {RuntimeSpec} runtime the runtime
	 * @returns {boolean} true, if the connection is active
	 */
	isActive(runtime) {
		if (!this.conditional) return this._active;

		return (
			/** @type {(function(ModuleGraphConnection, RuntimeSpec): ConnectionState)} */ (
				this.condition
			)(this, runtime) !== false
		);
	}

	/**
	 * @param {RuntimeSpec} runtime the runtime
	 * @returns {boolean} true, if the connection is active
	 */
	isTargetActive(runtime) {
		if (!this.conditional) return this._active;
		return (
			/** @type {(function(ModuleGraphConnection, RuntimeSpec): ConnectionState)} */ (
				this.condition
			)(this, runtime) === true
		);
	}

	/**
	 * @param {RuntimeSpec} runtime the runtime
	 * @returns {ConnectionState} true: fully active, false: inactive, TRANSITIVE: direct module inactive, but transitive connection maybe active
	 */
	getActiveState(runtime) {
		if (!this.conditional) return this._active;
		return /** @type {(function(ModuleGraphConnection, RuntimeSpec): ConnectionState)} */ (
			this.condition
		)(this, runtime);
	}

	/**
	 * @param {boolean} value active or not
	 * @returns {void}
	 */
	setActive(value) {
		this.conditional = false;
		this._active = value;
	}

	set active(value) {
		throw new Error("Use setActive instead");
	}
}

/** @typedef {typeof TRANSITIVE_ONLY} TRANSITIVE_ONLY */
/** @typedef {typeof CIRCULAR_CONNECTION} CIRCULAR_CONNECTION */

module.exports = ModuleGraphConnection;
module.exports.addConnectionStates = addConnectionStates;
module.exports.TRANSITIVE_ONLY = /** @type {typeof TRANSITIVE_ONLY} */ (
	TRANSITIVE_ONLY
);
module.exports.CIRCULAR_CONNECTION = /** @type {typeof CIRCULAR_CONNECTION} */ (
	CIRCULAR_CONNECTION
);


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const WebpackError = require("./WebpackError");

/** @typedef {import("./Module")} Module */

class ModuleHashingError extends WebpackError {
	/**
	 * Create a new ModuleHashingError
	 * @param {Module} module related module
	 * @param {Error} error Original error
	 */
	constructor(module, error) {
		super();

		this.name = "ModuleHashingError";
		this.error = error;
		this.message = error.message;
		this.details = error.stack;
		this.module = module;
	}
}

module.exports = ModuleHashingError;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { ConcatSource, RawSource, CachedSource } = require("webpack-sources");
const { UsageState } = require("./ExportsInfo");
const Template = require("./Template");
const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");

/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("./Compiler")} Compiler */
/** @typedef {import("./ExportsInfo")} ExportsInfo */
/** @typedef {import("./ExportsInfo").ExportInfo} ExportInfo */
/** @typedef {import("./Module")} Module */
/** @typedef {import("./Module").BuildMeta} BuildMeta */
/** @typedef {import("./ModuleGraph")} ModuleGraph */
/** @typedef {import("./ModuleTemplate")} ModuleTemplate */
/** @typedef {import("./RequestShortener")} RequestShortener */

/**
 * @template T
 * @param {Iterable<T>} iterable iterable
 * @returns {string} joined with comma
 */
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;
};

/**
 * @param {ConcatSource} source output
 * @param {string} indent spacing
 * @param {ExportsInfo} exportsInfo data
 * @param {ModuleGraph} moduleGraph moduleGraph
 * @param {RequestShortener} requestShortener requestShortener
 * @param {Set<ExportInfo>} alreadyPrinted deduplication set
 * @returns {void}
 */
const printExportsInfoToSource = (
	source,
	indent,
	exportsInfo,
	moduleGraph,
	requestShortener,
	alreadyPrinted = new Set()
) => {
	const otherExportsInfo = exportsInfo.otherExportsInfo;

	let alreadyPrintedExports = 0;

	// determine exports to print
	const printedExports = [];
	for (const exportInfo of exportsInfo.orderedExports) {
		if (!alreadyPrinted.has(exportInfo)) {
			alreadyPrinted.add(exportInfo);
			printedExports.push(exportInfo);
		} else {
			alreadyPrintedExports++;
		}
	}
	let showOtherExports = false;
	if (!alreadyPrinted.has(otherExportsInfo)) {
		alreadyPrinted.add(otherExportsInfo);
		showOtherExports = true;
	} else {
		alreadyPrintedExports++;
	}

	// print the exports
	for (const exportInfo of printedExports) {
		const target = exportInfo.getTarget(moduleGraph);
		source.add(
			Template.toComment(
				`${indent}export ${JSON.stringify(exportInfo.name).slice(
					1,
					-1
				)} [${exportInfo.getProvidedInfo()}] [${exportInfo.getUsedInfo()}] [${exportInfo.getRenameInfo()}]${
					target
						? ` -> ${target.module.readableIdentifier(requestShortener)}${
								target.export
									? ` .${target.export
											.map(e => JSON.stringify(e).slice(1, -1))
											.join(".")}`
									: ""
							}`
						: ""
				}`
			) + "\n"
		);
		if (exportInfo.exportsInfo) {
			printExportsInfoToSource(
				source,
				indent + "  ",
				exportInfo.exportsInfo,
				moduleGraph,
				requestShortener,
				alreadyPrinted
			);
		}
	}

	if (alreadyPrintedExports) {
		source.add(
			Template.toComment(
				`${indent}... (${alreadyPrintedExports} already listed exports)`
			) + "\n"
		);
	}

	if (showOtherExports) {
		const target = otherExportsInfo.getTarget(moduleGraph);
		if (
			target ||
			otherExportsInfo.provided !== false ||
			otherExportsInfo.getUsed(undefined) !== UsageState.Unused
		) {
			const title =
				printedExports.length > 0 || alreadyPrintedExports > 0
					? "other exports"
					: "exports";
			source.add(
				Template.toComment(
					`${indent}${title} [${otherExportsInfo.getProvidedInfo()}] [${otherExportsInfo.getUsedInfo()}]${
						target
							? ` -> ${target.module.readableIdentifier(requestShortener)}`
							: ""
					}`
				) + "\n"
			);
		}
	}
};

/** @type {WeakMap<RequestShortener, WeakMap<Module, { header: RawSource | undefined, full: WeakMap<Source, CachedSource> }>>} */
const caches = new WeakMap();

class ModuleInfoHeaderPlugin {
	/**
	 * @param {boolean=} verbose add more information like exports, runtime requirements and bailouts
	 */
	constructor(verbose = true) {
		this._verbose = verbose;
	}
	/**
	 * @param {Compiler} compiler the compiler
	 * @returns {void}
	 */
	apply(compiler) {
		const { _verbose: verbose } = this;
		compiler.hooks.compilation.tap("ModuleInfoHeaderPlugin", compilation => {
			const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
			hooks.renderModulePackage.tap(
				"ModuleInfoHeaderPlugin",
				(
					moduleSource,
					module,
					{ chunk, chunkGraph, moduleGraph, runtimeTemplate }
				) => {
					const { requestShortener } = runtimeTemplate;
					let cacheEntry;
					let cache = caches.get(requestShortener);
					if (cache === undefined) {
						caches.set(requestShortener, (cache = new WeakMap()));
						cache.set(
							module,
							(cacheEntry = { header: undefined, full: new WeakMap() })
						);
					} else {
						cacheEntry = cache.get(module);
						if (cacheEntry === undefined) {
							cache.set(
								module,
								(cacheEntry = { header: undefined, full: new WeakMap() })
							);
						} else if (!verbose) {
							const cachedSource = cacheEntry.full.get(moduleSource);
							if (cachedSource !== undefined) return cachedSource;
						}
					}
					const source = new ConcatSource();
					let header = cacheEntry.header;
					if (header === undefined) {
						const req = module.readableIdentifier(requestShortener);
						const reqStr = req.replace(/\*\//g, "*_/");
						const reqStrStar = "*".repeat(reqStr.length);
						const headerStr = `/*!****${reqStrStar}****!*\\\n  !*** ${reqStr} ***!\n  \\****${reqStrStar}****/\n`;
						header = new RawSource(headerStr);
						cacheEntry.header = header;
					}
					source.add(header);
					if (verbose) {
						const exportsType = /** @type {BuildMeta} */ (module.buildMeta)
							.exportsType;
						source.add(
							Template.toComment(
								exportsType
									? `${exportsType} exports`
									: "unknown exports (runtime-defined)"
							) + "\n"
						);
						if (exportsType) {
							const exportsInfo = moduleGraph.getExportsInfo(module);
							printExportsInfoToSource(
								source,
								"",
								exportsInfo,
								moduleGraph,
								requestShortener
							);
						}
						source.add(
							Template.toComment(
								`runtime requirements: ${joinIterableWithComma(
									chunkGraph.getModuleRuntimeRequirements(module, chunk.runtime)
								)}`
							) + "\n"
						);
						const optimizationBailout =
							moduleGraph.getOptimizationBailout(module);
						if (optimizationBailout) {
							for (const text of optimizationBailout) {
								let code;
								if (typeof text === "function") {
									code = text(requestShortener);
								} else {
									code = text;
								}
								source.add(Template.toComment(`${code}`) + "\n");
							}
						}
						source.add(moduleSource);
						return source;
					} else {
						source.add(moduleSource);
						const cachedSource = new CachedSource(source);
						cacheEntry.full.set(moduleSource, cachedSource);
						return cachedSource;
					}
				}
			);
			hooks.chunkHash.tap("ModuleInfoHeaderPlugin", (chunk, hash) => {
				hash.update("ModuleInfoHeaderPlugin");
				hash.update("1");
			});
		});
	}
}
module.exports = ModuleInfoHeaderPlugin;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const WebpackError = require("./WebpackError");

/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("./Module")} Module */

const previouslyPolyfilledBuiltinModules = {
	assert: "assert/",
	buffer: "buffer/",
	console: "console-browserify",
	constants: "constants-browserify",
	crypto: "crypto-browserify",
	domain: "domain-browser",
	events: "events/",
	http: "stream-http",
	https: "https-browserify",
	os: "os-browserify/browser",
	path: "path-browserify",
	punycode: "punycode/",
	process: "process/browser",
	querystring: "querystring-es3",
	stream: "stream-browserify",
	_stream_duplex: "readable-stream/duplex",
	_stream_passthrough: "readable-stream/passthrough",
	_stream_readable: "readable-stream/readable",
	_stream_transform: "readable-stream/transform",
	_stream_writable: "readable-stream/writable",
	string_decoder: "string_decoder/",
	sys: "util/",
	timers: "timers-browserify",
	tty: "tty-browserify",
	url: "url/",
	util: "util/",
	vm: "vm-browserify",
	zlib: "browserify-zlib"
};

class ModuleNotFoundError extends WebpackError {
	/**
	 * @param {Module | null} module module tied to dependency
	 * @param {Error&any} err error thrown
	 * @param {DependencyLocation} loc location of dependency
	 */
	constructor(module, err, loc) {
		let message = `Module not found: ${err.toString()}`;

		// TODO remove in webpack 6
		const match = err.message.match(/Can't resolve '([^']+)'/);
		if (match) {
			const request = match[1];
			const alias =
				previouslyPolyfilledBuiltinModules[
					/** @type {keyof previouslyPolyfilledBuiltinModules} */ (request)
				];
			if (alias) {
				const pathIndex = alias.indexOf("/");
				const dependency = pathIndex > 0 ? alias.slice(0, pathIndex) : alias;
				message +=
					"\n\n" +
					"BREAKING CHANGE: " +
					"webpack < 5 used to include polyfills for node.js core modules by default.\n" +
					"This is no longer the case. Verify if you need this module and configure a polyfill for it.\n\n";
				message +=
					"If you want to include a polyfill, you need to:\n" +
					`\t- add a fallback 'resolve.fallback: { "${request}": require.resolve("${alias}") }'\n` +
					`\t- install '${dependency}'\n`;
				message +=
					"If you don't want to include a polyfill, you can use an empty module like this:\n" +
					`\tresolve.fallback: { "${request}": false }`;
			}
		}

		super(message);

		this.name = "ModuleNotFoundError";
		this.details = err.details;
		this.module = module;
		this.error = err;
		this.loc = loc;
	}
}

module.exports = ModuleNotFoundError;