You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			1425 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			JavaScript
		
	
		
		
			
		
	
	
			1425 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			JavaScript
		
	
| 
											9 months ago
										 | /* | ||
|  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | ||
|  | 	Author Tobias Koppers @sokra | ||
|  | */ | ||
|  | 
 | ||
|  | "use strict"; | ||
|  | 
 | ||
|  | const parseJson = require("json-parse-even-better-errors"); | ||
|  | const { getContext, runLoaders } = require("loader-runner"); | ||
|  | const querystring = require("querystring"); | ||
|  | const { HookMap, SyncHook, AsyncSeriesBailHook } = require("tapable"); | ||
|  | const { | ||
|  | 	CachedSource, | ||
|  | 	OriginalSource, | ||
|  | 	RawSource, | ||
|  | 	SourceMapSource | ||
|  | } = require("webpack-sources"); | ||
|  | const Compilation = require("./Compilation"); | ||
|  | const HookWebpackError = require("./HookWebpackError"); | ||
|  | const Module = require("./Module"); | ||
|  | const ModuleBuildError = require("./ModuleBuildError"); | ||
|  | const ModuleError = require("./ModuleError"); | ||
|  | const ModuleGraphConnection = require("./ModuleGraphConnection"); | ||
|  | const ModuleParseError = require("./ModuleParseError"); | ||
|  | const { JAVASCRIPT_MODULE_TYPE_AUTO } = require("./ModuleTypeConstants"); | ||
|  | const ModuleWarning = require("./ModuleWarning"); | ||
|  | const RuntimeGlobals = require("./RuntimeGlobals"); | ||
|  | const UnhandledSchemeError = require("./UnhandledSchemeError"); | ||
|  | const WebpackError = require("./WebpackError"); | ||
|  | const formatLocation = require("./formatLocation"); | ||
|  | const LazySet = require("./util/LazySet"); | ||
|  | const { isSubset } = require("./util/SetHelpers"); | ||
|  | const { getScheme } = require("./util/URLAbsoluteSpecifier"); | ||
|  | const { | ||
|  | 	compareLocations, | ||
|  | 	concatComparators, | ||
|  | 	compareSelect, | ||
|  | 	keepOriginalOrder | ||
|  | } = require("./util/comparators"); | ||
|  | const createHash = require("./util/createHash"); | ||
|  | const { createFakeHook } = require("./util/deprecation"); | ||
|  | const { join } = require("./util/fs"); | ||
|  | const { | ||
|  | 	contextify, | ||
|  | 	absolutify, | ||
|  | 	makePathsRelative | ||
|  | } = require("./util/identifier"); | ||
|  | const makeSerializable = require("./util/makeSerializable"); | ||
|  | const memoize = require("./util/memoize"); | ||
|  | 
 | ||
|  | /** @typedef {import("webpack-sources").Source} Source */ | ||
|  | /** @typedef {import("../declarations/LoaderContext").NormalModuleLoaderContext} NormalModuleLoaderContext */ | ||
|  | /** @typedef {import("../declarations/WebpackOptions").Mode} Mode */ | ||
|  | /** @typedef {import("../declarations/WebpackOptions").ResolveOptions} ResolveOptions */ | ||
|  | /** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */ | ||
|  | /** @typedef {import("./ChunkGraph")} ChunkGraph */ | ||
|  | /** @typedef {import("./Compiler")} Compiler */ | ||
|  | /** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */ | ||
|  | /** @typedef {import("./DependencyTemplates")} DependencyTemplates */ | ||
|  | /** @typedef {import("./Generator")} Generator */ | ||
|  | /** @typedef {import("./Module").CodeGenerationContext} CodeGenerationContext */ | ||
|  | /** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */ | ||
|  | /** @typedef {import("./Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */ | ||
|  | /** @typedef {import("./Module").LibIdentOptions} LibIdentOptions */ | ||
|  | /** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */ | ||
|  | /** @typedef {import("./ModuleGraph")} ModuleGraph */ | ||
|  | /** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */ | ||
|  | /** @typedef {import("./ModuleTypeConstants").JavaScriptModuleTypes} JavaScriptModuleTypes */ | ||
|  | /** @typedef {import("./NormalModuleFactory")} NormalModuleFactory */ | ||
|  | /** @typedef {import("./Parser")} Parser */ | ||
|  | /** @typedef {import("./RequestShortener")} RequestShortener */ | ||
|  | /** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */ | ||
|  | /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */ | ||
|  | /** @typedef {import("./logging/Logger").Logger} WebpackLogger */ | ||
|  | /** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */ | ||
|  | /** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */ | ||
|  | /** @typedef {import("./util/Hash")} Hash */ | ||
|  | /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */ | ||
|  | /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */ | ||
|  | 
 | ||
|  | /** | ||
|  |  * @typedef {Object} SourceMap | ||
|  |  * @property {number} version | ||
|  |  * @property {string[]} sources | ||
|  |  * @property {string} mappings | ||
|  |  * @property {string=} file | ||
|  |  * @property {string=} sourceRoot | ||
|  |  * @property {string[]=} sourcesContent | ||
|  |  * @property {string[]=} names | ||
|  |  */ | ||
|  | 
 | ||
|  | const getInvalidDependenciesModuleWarning = memoize(() => | ||
|  | 	require("./InvalidDependenciesModuleWarning") | ||
|  | ); | ||
|  | const getValidate = memoize(() => require("schema-utils").validate); | ||
|  | 
 | ||
|  | const ABSOLUTE_PATH_REGEX = /^([a-zA-Z]:\\|\\\\|\/)/; | ||
|  | 
 | ||
|  | /** | ||
|  |  * @typedef {Object} LoaderItem | ||
|  |  * @property {string} loader | ||
|  |  * @property {any} options | ||
|  |  * @property {string?} ident | ||
|  |  * @property {string?} type | ||
|  |  */ | ||
|  | 
 | ||
|  | /** | ||
|  |  * @param {string} context absolute context path | ||
|  |  * @param {string} source a source path | ||
|  |  * @param {Object=} associatedObjectForCache an object to which the cache will be attached | ||
|  |  * @returns {string} new source path | ||
|  |  */ | ||
|  | const contextifySourceUrl = (context, source, associatedObjectForCache) => { | ||
|  | 	if (source.startsWith("webpack://")) return source; | ||
|  | 	return `webpack://${makePathsRelative( | ||
|  | 		context, | ||
|  | 		source, | ||
|  | 		associatedObjectForCache | ||
|  | 	)}`;
 | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * @param {string} context absolute context path | ||
|  |  * @param {SourceMap} sourceMap a source map | ||
|  |  * @param {Object=} associatedObjectForCache an object to which the cache will be attached | ||
|  |  * @returns {SourceMap} new source map | ||
|  |  */ | ||
|  | const contextifySourceMap = (context, sourceMap, associatedObjectForCache) => { | ||
|  | 	if (!Array.isArray(sourceMap.sources)) return sourceMap; | ||
|  | 	const { sourceRoot } = sourceMap; | ||
|  | 	/** @type {function(string): string} */ | ||
|  | 	const mapper = !sourceRoot | ||
|  | 		? source => source | ||
|  | 		: sourceRoot.endsWith("/") | ||
|  | 		? source => | ||
|  | 				source.startsWith("/") | ||
|  | 					? `${sourceRoot.slice(0, -1)}${source}` | ||
|  | 					: `${sourceRoot}${source}` | ||
|  | 		: source => | ||
|  | 				source.startsWith("/") | ||
|  | 					? `${sourceRoot}${source}` | ||
|  | 					: `${sourceRoot}/${source}`; | ||
|  | 	const newSources = sourceMap.sources.map(source => | ||
|  | 		contextifySourceUrl(context, mapper(source), associatedObjectForCache) | ||
|  | 	); | ||
|  | 	return { | ||
|  | 		...sourceMap, | ||
|  | 		file: "x", | ||
|  | 		sourceRoot: undefined, | ||
|  | 		sources: newSources | ||
|  | 	}; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * @param {string | Buffer} input the input | ||
|  |  * @returns {string} the converted string | ||
|  |  */ | ||
|  | const asString = input => { | ||
|  | 	if (Buffer.isBuffer(input)) { | ||
|  | 		return input.toString("utf-8"); | ||
|  | 	} | ||
|  | 	return input; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * @param {string | Buffer} input the input | ||
|  |  * @returns {Buffer} the converted buffer | ||
|  |  */ | ||
|  | const asBuffer = input => { | ||
|  | 	if (!Buffer.isBuffer(input)) { | ||
|  | 		return Buffer.from(input, "utf-8"); | ||
|  | 	} | ||
|  | 	return input; | ||
|  | }; | ||
|  | 
 | ||
|  | class NonErrorEmittedError extends WebpackError { | ||
|  | 	constructor(error) { | ||
|  | 		super(); | ||
|  | 
 | ||
|  | 		this.name = "NonErrorEmittedError"; | ||
|  | 		this.message = "(Emitted value instead of an instance of Error) " + error; | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | makeSerializable( | ||
|  | 	NonErrorEmittedError, | ||
|  | 	"webpack/lib/NormalModule", | ||
|  | 	"NonErrorEmittedError" | ||
|  | ); | ||
|  | 
 | ||
|  | /** | ||
|  |  * @typedef {Object} NormalModuleCompilationHooks | ||
|  |  * @property {SyncHook<[object, NormalModule]>} loader | ||
|  |  * @property {SyncHook<[LoaderItem[], NormalModule, object]>} beforeLoaders | ||
|  |  * @property {SyncHook<[NormalModule]>} beforeParse | ||
|  |  * @property {SyncHook<[NormalModule]>} beforeSnapshot | ||
|  |  * @property {HookMap<AsyncSeriesBailHook<[string, NormalModule], string | Buffer>>} readResourceForScheme | ||
|  |  * @property {HookMap<AsyncSeriesBailHook<[object], string | Buffer>>} readResource | ||
|  |  * @property {AsyncSeriesBailHook<[NormalModule, NeedBuildContext], boolean>} needBuild | ||
|  |  */ | ||
|  | 
 | ||
|  | /** | ||
|  |  * @typedef {Object} NormalModuleCreateData | ||
|  |  * @property {string=} layer an optional layer in which the module is | ||
|  |  * @property {JavaScriptModuleTypes | ""} type module type. When deserializing, this is set to an empty string "". | ||
|  |  * @property {string} request request string | ||
|  |  * @property {string} userRequest request intended by user (without loaders from config) | ||
|  |  * @property {string} rawRequest request without resolving | ||
|  |  * @property {LoaderItem[]} loaders list of loaders | ||
|  |  * @property {string} resource path + query of the real resource | ||
|  |  * @property {Record<string, any>=} resourceResolveData resource resolve data | ||
|  |  * @property {string} context context directory for resolving | ||
|  |  * @property {string=} matchResource path + query of the matched resource (virtual) | ||
|  |  * @property {Parser} parser the parser used | ||
|  |  * @property {Record<string, any>=} parserOptions the options of the parser used | ||
|  |  * @property {Generator} generator the generator used | ||
|  |  * @property {Record<string, any>=} generatorOptions the options of the generator used | ||
|  |  * @property {ResolveOptions=} resolveOptions options used for resolving requests from this module | ||
|  |  */ | ||
|  | 
 | ||
|  | /** @type {WeakMap<Compilation, NormalModuleCompilationHooks>} */ | ||
|  | const compilationHooksMap = new WeakMap(); | ||
|  | 
 | ||
|  | class NormalModule extends Module { | ||
|  | 	/** | ||
|  | 	 * @param {Compilation} compilation the compilation | ||
|  | 	 * @returns {NormalModuleCompilationHooks} the attached hooks | ||
|  | 	 */ | ||
|  | 	static getCompilationHooks(compilation) { | ||
|  | 		if (!(compilation instanceof Compilation)) { | ||
|  | 			throw new TypeError( | ||
|  | 				"The 'compilation' argument must be an instance of Compilation" | ||
|  | 			); | ||
|  | 		} | ||
|  | 		let hooks = compilationHooksMap.get(compilation); | ||
|  | 		if (hooks === undefined) { | ||
|  | 			hooks = { | ||
|  | 				loader: new SyncHook(["loaderContext", "module"]), | ||
|  | 				beforeLoaders: new SyncHook(["loaders", "module", "loaderContext"]), | ||
|  | 				beforeParse: new SyncHook(["module"]), | ||
|  | 				beforeSnapshot: new SyncHook(["module"]), | ||
|  | 				// TODO webpack 6 deprecate
 | ||
|  | 				readResourceForScheme: new HookMap(scheme => { | ||
|  | 					const hook = hooks.readResource.for(scheme); | ||
|  | 					return createFakeHook( | ||
|  | 						/** @type {AsyncSeriesBailHook<[string, NormalModule], string | Buffer>} */ ({ | ||
|  | 							tap: (options, fn) => | ||
|  | 								hook.tap(options, loaderContext => | ||
|  | 									fn(loaderContext.resource, loaderContext._module) | ||
|  | 								), | ||
|  | 							tapAsync: (options, fn) => | ||
|  | 								hook.tapAsync(options, (loaderContext, callback) => | ||
|  | 									fn(loaderContext.resource, loaderContext._module, callback) | ||
|  | 								), | ||
|  | 							tapPromise: (options, fn) => | ||
|  | 								hook.tapPromise(options, loaderContext => | ||
|  | 									fn(loaderContext.resource, loaderContext._module) | ||
|  | 								) | ||
|  | 						}) | ||
|  | 					); | ||
|  | 				}), | ||
|  | 				readResource: new HookMap( | ||
|  | 					() => new AsyncSeriesBailHook(["loaderContext"]) | ||
|  | 				), | ||
|  | 				needBuild: new AsyncSeriesBailHook(["module", "context"]) | ||
|  | 			}; | ||
|  | 			compilationHooksMap.set(compilation, hooks); | ||
|  | 		} | ||
|  | 		return hooks; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {NormalModuleCreateData} options options object | ||
|  | 	 */ | ||
|  | 	constructor({ | ||
|  | 		layer, | ||
|  | 		type, | ||
|  | 		request, | ||
|  | 		userRequest, | ||
|  | 		rawRequest, | ||
|  | 		loaders, | ||
|  | 		resource, | ||
|  | 		resourceResolveData, | ||
|  | 		context, | ||
|  | 		matchResource, | ||
|  | 		parser, | ||
|  | 		parserOptions, | ||
|  | 		generator, | ||
|  | 		generatorOptions, | ||
|  | 		resolveOptions | ||
|  | 	}) { | ||
|  | 		super(type, context || getContext(resource), layer); | ||
|  | 
 | ||
|  | 		// Info from Factory
 | ||
|  | 		/** @type {string} */ | ||
|  | 		this.request = request; | ||
|  | 		/** @type {string} */ | ||
|  | 		this.userRequest = userRequest; | ||
|  | 		/** @type {string} */ | ||
|  | 		this.rawRequest = rawRequest; | ||
|  | 		/** @type {boolean} */ | ||
|  | 		this.binary = /^(asset|webassembly)\b/.test(type); | ||
|  | 		/** @type {Parser} */ | ||
|  | 		this.parser = parser; | ||
|  | 		this.parserOptions = parserOptions; | ||
|  | 		/** @type {Generator} */ | ||
|  | 		this.generator = generator; | ||
|  | 		this.generatorOptions = generatorOptions; | ||
|  | 		/** @type {string} */ | ||
|  | 		this.resource = resource; | ||
|  | 		this.resourceResolveData = resourceResolveData; | ||
|  | 		/** @type {string | undefined} */ | ||
|  | 		this.matchResource = matchResource; | ||
|  | 		/** @type {LoaderItem[]} */ | ||
|  | 		this.loaders = loaders; | ||
|  | 		if (resolveOptions !== undefined) { | ||
|  | 			// already declared in super class
 | ||
|  | 			this.resolveOptions = resolveOptions; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Info from Build
 | ||
|  | 		/** @type {(WebpackError | null)=} */ | ||
|  | 		this.error = null; | ||
|  | 		/** @private @type {Source=} */ | ||
|  | 		this._source = null; | ||
|  | 		/** @private @type {Map<string, number> | undefined} **/ | ||
|  | 		this._sourceSizes = undefined; | ||
|  | 		/** @private @type {Set<string>} */ | ||
|  | 		this._sourceTypes = undefined; | ||
|  | 
 | ||
|  | 		// Cache
 | ||
|  | 		this._lastSuccessfulBuildMeta = {}; | ||
|  | 		this._forceBuild = true; | ||
|  | 		this._isEvaluatingSideEffects = false; | ||
|  | 		/** @type {WeakSet<ModuleGraph> | undefined} */ | ||
|  | 		this._addedSideEffectsBailout = undefined; | ||
|  | 		/** @type {Map<string, any>} */ | ||
|  | 		this._codeGeneratorData = new Map(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @returns {string} a unique identifier of the module | ||
|  | 	 */ | ||
|  | 	identifier() { | ||
|  | 		if (this.layer === null) { | ||
|  | 			if (this.type === JAVASCRIPT_MODULE_TYPE_AUTO) { | ||
|  | 				return this.request; | ||
|  | 			} else { | ||
|  | 				return `${this.type}|${this.request}`; | ||
|  | 			} | ||
|  | 		} else { | ||
|  | 			return `${this.type}|${this.request}|${this.layer}`; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {RequestShortener} requestShortener the request shortener | ||
|  | 	 * @returns {string} a user readable identifier of the module | ||
|  | 	 */ | ||
|  | 	readableIdentifier(requestShortener) { | ||
|  | 		return requestShortener.shorten(this.userRequest); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {LibIdentOptions} options options | ||
|  | 	 * @returns {string | null} an identifier for library inclusion | ||
|  | 	 */ | ||
|  | 	libIdent(options) { | ||
|  | 		let ident = contextify( | ||
|  | 			options.context, | ||
|  | 			this.userRequest, | ||
|  | 			options.associatedObjectForCache | ||
|  | 		); | ||
|  | 		if (this.layer) ident = `(${this.layer})/${ident}`; | ||
|  | 		return ident; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @returns {string | null} absolute path which should be used for condition matching (usually the resource path) | ||
|  | 	 */ | ||
|  | 	nameForCondition() { | ||
|  | 		const resource = this.matchResource || this.resource; | ||
|  | 		const idx = resource.indexOf("?"); | ||
|  | 		if (idx >= 0) return resource.slice(0, idx); | ||
|  | 		return resource; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * 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) { | ||
|  | 		super.updateCacheModule(module); | ||
|  | 		const m = /** @type {NormalModule} */ (module); | ||
|  | 		this.binary = m.binary; | ||
|  | 		this.request = m.request; | ||
|  | 		this.userRequest = m.userRequest; | ||
|  | 		this.rawRequest = m.rawRequest; | ||
|  | 		this.parser = m.parser; | ||
|  | 		this.parserOptions = m.parserOptions; | ||
|  | 		this.generator = m.generator; | ||
|  | 		this.generatorOptions = m.generatorOptions; | ||
|  | 		this.resource = m.resource; | ||
|  | 		this.resourceResolveData = m.resourceResolveData; | ||
|  | 		this.context = m.context; | ||
|  | 		this.matchResource = m.matchResource; | ||
|  | 		this.loaders = m.loaders; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Assuming this module is in the cache. Remove internal references to allow freeing some memory. | ||
|  | 	 */ | ||
|  | 	cleanupForCache() { | ||
|  | 		// Make sure to cache types and sizes before cleanup when this module has been built
 | ||
|  | 		// They are accessed by the stats and we don't want them to crash after cleanup
 | ||
|  | 		// TODO reconsider this for webpack 6
 | ||
|  | 		if (this.buildInfo) { | ||
|  | 			if (this._sourceTypes === undefined) this.getSourceTypes(); | ||
|  | 			for (const type of this._sourceTypes) { | ||
|  | 				this.size(type); | ||
|  | 			} | ||
|  | 		} | ||
|  | 		super.cleanupForCache(); | ||
|  | 		this.parser = undefined; | ||
|  | 		this.parserOptions = undefined; | ||
|  | 		this.generator = undefined; | ||
|  | 		this.generatorOptions = undefined; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Module should be unsafe cached. Get data that's needed for that. | ||
|  | 	 * This data will be passed to restoreFromUnsafeCache later. | ||
|  | 	 * @returns {object} cached data | ||
|  | 	 */ | ||
|  | 	getUnsafeCacheData() { | ||
|  | 		const data = super.getUnsafeCacheData(); | ||
|  | 		data.parserOptions = this.parserOptions; | ||
|  | 		data.generatorOptions = this.generatorOptions; | ||
|  | 		return data; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) { | ||
|  | 		this._restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * restore unsafe cache data | ||
|  | 	 * @param {object} unsafeCacheData data from getUnsafeCacheData | ||
|  | 	 * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching | ||
|  | 	 */ | ||
|  | 	_restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) { | ||
|  | 		super._restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory); | ||
|  | 		this.parserOptions = unsafeCacheData.parserOptions; | ||
|  | 		this.parser = normalModuleFactory.getParser(this.type, this.parserOptions); | ||
|  | 		this.generatorOptions = unsafeCacheData.generatorOptions; | ||
|  | 		this.generator = normalModuleFactory.getGenerator( | ||
|  | 			this.type, | ||
|  | 			this.generatorOptions | ||
|  | 		); | ||
|  | 		// we assume the generator behaves identically and keep cached sourceTypes/Sizes
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {string} context the compilation context | ||
|  | 	 * @param {string} name the asset name | ||
|  | 	 * @param {string} content the content | ||
|  | 	 * @param {string | TODO} sourceMap an optional source map | ||
|  | 	 * @param {Object=} associatedObjectForCache object for caching | ||
|  | 	 * @returns {Source} the created source | ||
|  | 	 */ | ||
|  | 	createSourceForAsset( | ||
|  | 		context, | ||
|  | 		name, | ||
|  | 		content, | ||
|  | 		sourceMap, | ||
|  | 		associatedObjectForCache | ||
|  | 	) { | ||
|  | 		if (sourceMap) { | ||
|  | 			if ( | ||
|  | 				typeof sourceMap === "string" && | ||
|  | 				(this.useSourceMap || this.useSimpleSourceMap) | ||
|  | 			) { | ||
|  | 				return new OriginalSource( | ||
|  | 					content, | ||
|  | 					contextifySourceUrl(context, sourceMap, associatedObjectForCache) | ||
|  | 				); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			if (this.useSourceMap) { | ||
|  | 				return new SourceMapSource( | ||
|  | 					content, | ||
|  | 					name, | ||
|  | 					contextifySourceMap(context, sourceMap, associatedObjectForCache) | ||
|  | 				); | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return new RawSource(content); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {ResolverWithOptions} resolver a resolver | ||
|  | 	 * @param {WebpackOptions} options webpack options | ||
|  | 	 * @param {Compilation} compilation the compilation | ||
|  | 	 * @param {InputFileSystem} fs file system from reading | ||
|  | 	 * @param {NormalModuleCompilationHooks} hooks the hooks | ||
|  | 	 * @returns {NormalModuleLoaderContext} loader context | ||
|  | 	 */ | ||
|  | 	_createLoaderContext(resolver, options, compilation, fs, hooks) { | ||
|  | 		const { requestShortener } = compilation.runtimeTemplate; | ||
|  | 		const getCurrentLoaderName = () => { | ||
|  | 			const currentLoader = this.getCurrentLoader(loaderContext); | ||
|  | 			if (!currentLoader) return "(not in loader scope)"; | ||
|  | 			return requestShortener.shorten(currentLoader.loader); | ||
|  | 		}; | ||
|  | 		const getResolveContext = () => { | ||
|  | 			return { | ||
|  | 				fileDependencies: { | ||
|  | 					add: d => loaderContext.addDependency(d) | ||
|  | 				}, | ||
|  | 				contextDependencies: { | ||
|  | 					add: d => loaderContext.addContextDependency(d) | ||
|  | 				}, | ||
|  | 				missingDependencies: { | ||
|  | 					add: d => loaderContext.addMissingDependency(d) | ||
|  | 				} | ||
|  | 			}; | ||
|  | 		}; | ||
|  | 		const getAbsolutify = memoize(() => | ||
|  | 			absolutify.bindCache(compilation.compiler.root) | ||
|  | 		); | ||
|  | 		const getAbsolutifyInContext = memoize(() => | ||
|  | 			absolutify.bindContextCache(this.context, compilation.compiler.root) | ||
|  | 		); | ||
|  | 		const getContextify = memoize(() => | ||
|  | 			contextify.bindCache(compilation.compiler.root) | ||
|  | 		); | ||
|  | 		const getContextifyInContext = memoize(() => | ||
|  | 			contextify.bindContextCache(this.context, compilation.compiler.root) | ||
|  | 		); | ||
|  | 		const utils = { | ||
|  | 			absolutify: (context, request) => { | ||
|  | 				return context === this.context | ||
|  | 					? getAbsolutifyInContext()(request) | ||
|  | 					: getAbsolutify()(context, request); | ||
|  | 			}, | ||
|  | 			contextify: (context, request) => { | ||
|  | 				return context === this.context | ||
|  | 					? getContextifyInContext()(request) | ||
|  | 					: getContextify()(context, request); | ||
|  | 			}, | ||
|  | 			createHash: type => { | ||
|  | 				return createHash(type || compilation.outputOptions.hashFunction); | ||
|  | 			} | ||
|  | 		}; | ||
|  | 		const loaderContext = { | ||
|  | 			version: 2, | ||
|  | 			getOptions: schema => { | ||
|  | 				const loader = this.getCurrentLoader(loaderContext); | ||
|  | 
 | ||
|  | 				let { options } = loader; | ||
|  | 
 | ||
|  | 				if (typeof options === "string") { | ||
|  | 					if (options.startsWith("{") && options.endsWith("}")) { | ||
|  | 						try { | ||
|  | 							options = parseJson(options); | ||
|  | 						} catch (e) { | ||
|  | 							throw new Error(`Cannot parse string options: ${e.message}`); | ||
|  | 						} | ||
|  | 					} else { | ||
|  | 						options = querystring.parse(options, "&", "=", { | ||
|  | 							maxKeys: 0 | ||
|  | 						}); | ||
|  | 					} | ||
|  | 				} | ||
|  | 
 | ||
|  | 				if (options === null || options === undefined) { | ||
|  | 					options = {}; | ||
|  | 				} | ||
|  | 
 | ||
|  | 				if (schema) { | ||
|  | 					let name = "Loader"; | ||
|  | 					let baseDataPath = "options"; | ||
|  | 					let match; | ||
|  | 					if (schema.title && (match = /^(.+) (.+)$/.exec(schema.title))) { | ||
|  | 						[, name, baseDataPath] = match; | ||
|  | 					} | ||
|  | 					getValidate()(schema, options, { | ||
|  | 						name, | ||
|  | 						baseDataPath | ||
|  | 					}); | ||
|  | 				} | ||
|  | 
 | ||
|  | 				return options; | ||
|  | 			}, | ||
|  | 			emitWarning: warning => { | ||
|  | 				if (!(warning instanceof Error)) { | ||
|  | 					warning = new NonErrorEmittedError(warning); | ||
|  | 				} | ||
|  | 				this.addWarning( | ||
|  | 					new ModuleWarning(warning, { | ||
|  | 						from: getCurrentLoaderName() | ||
|  | 					}) | ||
|  | 				); | ||
|  | 			}, | ||
|  | 			emitError: error => { | ||
|  | 				if (!(error instanceof Error)) { | ||
|  | 					error = new NonErrorEmittedError(error); | ||
|  | 				} | ||
|  | 				this.addError( | ||
|  | 					new ModuleError(error, { | ||
|  | 						from: getCurrentLoaderName() | ||
|  | 					}) | ||
|  | 				); | ||
|  | 			}, | ||
|  | 			getLogger: name => { | ||
|  | 				const currentLoader = this.getCurrentLoader(loaderContext); | ||
|  | 				return compilation.getLogger(() => | ||
|  | 					[currentLoader && currentLoader.loader, name, this.identifier()] | ||
|  | 						.filter(Boolean) | ||
|  | 						.join("|") | ||
|  | 				); | ||
|  | 			}, | ||
|  | 			resolve(context, request, callback) { | ||
|  | 				resolver.resolve({}, context, request, getResolveContext(), callback); | ||
|  | 			}, | ||
|  | 			getResolve(options) { | ||
|  | 				const child = options ? resolver.withOptions(options) : resolver; | ||
|  | 				return (context, request, callback) => { | ||
|  | 					if (callback) { | ||
|  | 						child.resolve({}, context, request, getResolveContext(), callback); | ||
|  | 					} else { | ||
|  | 						return new Promise((resolve, reject) => { | ||
|  | 							child.resolve( | ||
|  | 								{}, | ||
|  | 								context, | ||
|  | 								request, | ||
|  | 								getResolveContext(), | ||
|  | 								(err, result) => { | ||
|  | 									if (err) reject(err); | ||
|  | 									else resolve(result); | ||
|  | 								} | ||
|  | 							); | ||
|  | 						}); | ||
|  | 					} | ||
|  | 				}; | ||
|  | 			}, | ||
|  | 			emitFile: (name, content, sourceMap, assetInfo) => { | ||
|  | 				if (!this.buildInfo.assets) { | ||
|  | 					this.buildInfo.assets = Object.create(null); | ||
|  | 					this.buildInfo.assetsInfo = new Map(); | ||
|  | 				} | ||
|  | 				this.buildInfo.assets[name] = this.createSourceForAsset( | ||
|  | 					options.context, | ||
|  | 					name, | ||
|  | 					content, | ||
|  | 					sourceMap, | ||
|  | 					compilation.compiler.root | ||
|  | 				); | ||
|  | 				this.buildInfo.assetsInfo.set(name, assetInfo); | ||
|  | 			}, | ||
|  | 			addBuildDependency: dep => { | ||
|  | 				if (this.buildInfo.buildDependencies === undefined) { | ||
|  | 					this.buildInfo.buildDependencies = new LazySet(); | ||
|  | 				} | ||
|  | 				this.buildInfo.buildDependencies.add(dep); | ||
|  | 			}, | ||
|  | 			utils, | ||
|  | 			rootContext: options.context, | ||
|  | 			webpack: true, | ||
|  | 			sourceMap: !!this.useSourceMap, | ||
|  | 			mode: options.mode || "production", | ||
|  | 			_module: this, | ||
|  | 			_compilation: compilation, | ||
|  | 			_compiler: compilation.compiler, | ||
|  | 			fs: fs | ||
|  | 		}; | ||
|  | 
 | ||
|  | 		Object.assign(loaderContext, options.loader); | ||
|  | 
 | ||
|  | 		hooks.loader.call(loaderContext, this); | ||
|  | 
 | ||
|  | 		return loaderContext; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	getCurrentLoader(loaderContext, index = loaderContext.loaderIndex) { | ||
|  | 		if ( | ||
|  | 			this.loaders && | ||
|  | 			this.loaders.length && | ||
|  | 			index < this.loaders.length && | ||
|  | 			index >= 0 && | ||
|  | 			this.loaders[index] | ||
|  | 		) { | ||
|  | 			return this.loaders[index]; | ||
|  | 		} | ||
|  | 		return null; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {string} context the compilation context | ||
|  | 	 * @param {string | Buffer} content the content | ||
|  | 	 * @param {string | TODO} sourceMap an optional source map | ||
|  | 	 * @param {Object=} associatedObjectForCache object for caching | ||
|  | 	 * @returns {Source} the created source | ||
|  | 	 */ | ||
|  | 	createSource(context, content, sourceMap, associatedObjectForCache) { | ||
|  | 		if (Buffer.isBuffer(content)) { | ||
|  | 			return new RawSource(content); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// if there is no identifier return raw source
 | ||
|  | 		if (!this.identifier) { | ||
|  | 			return new RawSource(content); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// from here on we assume we have an identifier
 | ||
|  | 		const identifier = this.identifier(); | ||
|  | 
 | ||
|  | 		if (this.useSourceMap && sourceMap) { | ||
|  | 			return new SourceMapSource( | ||
|  | 				content, | ||
|  | 				contextifySourceUrl(context, identifier, associatedObjectForCache), | ||
|  | 				contextifySourceMap(context, sourceMap, associatedObjectForCache) | ||
|  | 			); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if (this.useSourceMap || this.useSimpleSourceMap) { | ||
|  | 			return new OriginalSource( | ||
|  | 				content, | ||
|  | 				contextifySourceUrl(context, identifier, associatedObjectForCache) | ||
|  | 			); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return new RawSource(content); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {WebpackOptions} options webpack options | ||
|  | 	 * @param {Compilation} compilation the compilation | ||
|  | 	 * @param {ResolverWithOptions} resolver the resolver | ||
|  | 	 * @param {InputFileSystem} fs the file system | ||
|  | 	 * @param {NormalModuleCompilationHooks} hooks the hooks | ||
|  | 	 * @param {function((WebpackError | null)=): void} callback callback function | ||
|  | 	 * @returns {void} | ||
|  | 	 */ | ||
|  | 	_doBuild(options, compilation, resolver, fs, hooks, callback) { | ||
|  | 		const loaderContext = this._createLoaderContext( | ||
|  | 			resolver, | ||
|  | 			options, | ||
|  | 			compilation, | ||
|  | 			fs, | ||
|  | 			hooks | ||
|  | 		); | ||
|  | 
 | ||
|  | 		const processResult = (err, result) => { | ||
|  | 			if (err) { | ||
|  | 				if (!(err instanceof Error)) { | ||
|  | 					err = new NonErrorEmittedError(err); | ||
|  | 				} | ||
|  | 				const currentLoader = this.getCurrentLoader(loaderContext); | ||
|  | 				const error = new ModuleBuildError(err, { | ||
|  | 					from: | ||
|  | 						currentLoader && | ||
|  | 						compilation.runtimeTemplate.requestShortener.shorten( | ||
|  | 							currentLoader.loader | ||
|  | 						) | ||
|  | 				}); | ||
|  | 				return callback(error); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			const source = result[0]; | ||
|  | 			const sourceMap = result.length >= 1 ? result[1] : null; | ||
|  | 			const extraInfo = result.length >= 2 ? result[2] : null; | ||
|  | 
 | ||
|  | 			if (!Buffer.isBuffer(source) && typeof source !== "string") { | ||
|  | 				const currentLoader = this.getCurrentLoader(loaderContext, 0); | ||
|  | 				const err = new Error( | ||
|  | 					`Final loader (${ | ||
|  | 						currentLoader | ||
|  | 							? compilation.runtimeTemplate.requestShortener.shorten( | ||
|  | 									currentLoader.loader | ||
|  | 							  ) | ||
|  | 							: "unknown" | ||
|  | 					}) didn't return a Buffer or String`
 | ||
|  | 				); | ||
|  | 				const error = new ModuleBuildError(err); | ||
|  | 				return callback(error); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			this._source = this.createSource( | ||
|  | 				options.context, | ||
|  | 				this.binary ? asBuffer(source) : asString(source), | ||
|  | 				sourceMap, | ||
|  | 				compilation.compiler.root | ||
|  | 			); | ||
|  | 			if (this._sourceSizes !== undefined) this._sourceSizes.clear(); | ||
|  | 			this._ast = | ||
|  | 				typeof extraInfo === "object" && | ||
|  | 				extraInfo !== null && | ||
|  | 				extraInfo.webpackAST !== undefined | ||
|  | 					? extraInfo.webpackAST | ||
|  | 					: null; | ||
|  | 			return callback(); | ||
|  | 		}; | ||
|  | 
 | ||
|  | 		this.buildInfo.fileDependencies = new LazySet(); | ||
|  | 		this.buildInfo.contextDependencies = new LazySet(); | ||
|  | 		this.buildInfo.missingDependencies = new LazySet(); | ||
|  | 		this.buildInfo.cacheable = true; | ||
|  | 
 | ||
|  | 		try { | ||
|  | 			hooks.beforeLoaders.call(this.loaders, this, loaderContext); | ||
|  | 		} catch (err) { | ||
|  | 			processResult(err); | ||
|  | 			return; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if (this.loaders.length > 0) { | ||
|  | 			this.buildInfo.buildDependencies = new LazySet(); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		runLoaders( | ||
|  | 			{ | ||
|  | 				resource: this.resource, | ||
|  | 				loaders: this.loaders, | ||
|  | 				context: loaderContext, | ||
|  | 				processResource: (loaderContext, resourcePath, callback) => { | ||
|  | 					const resource = loaderContext.resource; | ||
|  | 					const scheme = getScheme(resource); | ||
|  | 					hooks.readResource | ||
|  | 						.for(scheme) | ||
|  | 						.callAsync(loaderContext, (err, result) => { | ||
|  | 							if (err) return callback(err); | ||
|  | 							if (typeof result !== "string" && !result) { | ||
|  | 								return callback(new UnhandledSchemeError(scheme, resource)); | ||
|  | 							} | ||
|  | 							return callback(null, result); | ||
|  | 						}); | ||
|  | 				} | ||
|  | 			}, | ||
|  | 			(err, result) => { | ||
|  | 				// Cleanup loaderContext to avoid leaking memory in ICs
 | ||
|  | 				loaderContext._compilation = | ||
|  | 					loaderContext._compiler = | ||
|  | 					loaderContext._module = | ||
|  | 					loaderContext.fs = | ||
|  | 						undefined; | ||
|  | 
 | ||
|  | 				if (!result) { | ||
|  | 					this.buildInfo.cacheable = false; | ||
|  | 					return processResult( | ||
|  | 						err || new Error("No result from loader-runner processing"), | ||
|  | 						null | ||
|  | 					); | ||
|  | 				} | ||
|  | 				this.buildInfo.fileDependencies.addAll(result.fileDependencies); | ||
|  | 				this.buildInfo.contextDependencies.addAll(result.contextDependencies); | ||
|  | 				this.buildInfo.missingDependencies.addAll(result.missingDependencies); | ||
|  | 				for (const loader of this.loaders) { | ||
|  | 					this.buildInfo.buildDependencies.add(loader.loader); | ||
|  | 				} | ||
|  | 				this.buildInfo.cacheable = this.buildInfo.cacheable && result.cacheable; | ||
|  | 				processResult(err, result.result); | ||
|  | 			} | ||
|  | 		); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {WebpackError} error the error | ||
|  | 	 * @returns {void} | ||
|  | 	 */ | ||
|  | 	markModuleAsErrored(error) { | ||
|  | 		// Restore build meta from successful build to keep importing state
 | ||
|  | 		this.buildMeta = { ...this._lastSuccessfulBuildMeta }; | ||
|  | 		this.error = error; | ||
|  | 		this.addError(error); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	applyNoParseRule(rule, content) { | ||
|  | 		// must start with "rule" if rule is a string
 | ||
|  | 		if (typeof rule === "string") { | ||
|  | 			return content.startsWith(rule); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if (typeof rule === "function") { | ||
|  | 			return rule(content); | ||
|  | 		} | ||
|  | 		// we assume rule is a regexp
 | ||
|  | 		return rule.test(content); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// check if module should not be parsed
 | ||
|  | 	// returns "true" if the module should !not! be parsed
 | ||
|  | 	// returns "false" if the module !must! be parsed
 | ||
|  | 	shouldPreventParsing(noParseRule, request) { | ||
|  | 		// if no noParseRule exists, return false
 | ||
|  | 		// the module !must! be parsed.
 | ||
|  | 		if (!noParseRule) { | ||
|  | 			return false; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// we only have one rule to check
 | ||
|  | 		if (!Array.isArray(noParseRule)) { | ||
|  | 			// returns "true" if the module is !not! to be parsed
 | ||
|  | 			return this.applyNoParseRule(noParseRule, request); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		for (let i = 0; i < noParseRule.length; i++) { | ||
|  | 			const rule = noParseRule[i]; | ||
|  | 			// early exit on first truthy match
 | ||
|  | 			// this module is !not! to be parsed
 | ||
|  | 			if (this.applyNoParseRule(rule, request)) { | ||
|  | 				return true; | ||
|  | 			} | ||
|  | 		} | ||
|  | 		// no match found, so this module !should! be parsed
 | ||
|  | 		return false; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	_initBuildHash(compilation) { | ||
|  | 		const hash = createHash(compilation.outputOptions.hashFunction); | ||
|  | 		if (this._source) { | ||
|  | 			hash.update("source"); | ||
|  | 			this._source.updateHash(hash); | ||
|  | 		} | ||
|  | 		hash.update("meta"); | ||
|  | 		hash.update(JSON.stringify(this.buildMeta)); | ||
|  | 		this.buildInfo.hash = /** @type {string} */ (hash.digest("hex")); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @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) { | ||
|  | 		this._forceBuild = false; | ||
|  | 		this._source = null; | ||
|  | 		if (this._sourceSizes !== undefined) this._sourceSizes.clear(); | ||
|  | 		this._sourceTypes = undefined; | ||
|  | 		this._ast = null; | ||
|  | 		this.error = null; | ||
|  | 		this.clearWarningsAndErrors(); | ||
|  | 		this.clearDependenciesAndBlocks(); | ||
|  | 		this.buildMeta = {}; | ||
|  | 		this.buildInfo = { | ||
|  | 			cacheable: false, | ||
|  | 			parsed: true, | ||
|  | 			fileDependencies: undefined, | ||
|  | 			contextDependencies: undefined, | ||
|  | 			missingDependencies: undefined, | ||
|  | 			buildDependencies: undefined, | ||
|  | 			valueDependencies: undefined, | ||
|  | 			hash: undefined, | ||
|  | 			assets: undefined, | ||
|  | 			assetsInfo: undefined | ||
|  | 		}; | ||
|  | 
 | ||
|  | 		const startTime = compilation.compiler.fsStartTime || Date.now(); | ||
|  | 
 | ||
|  | 		const hooks = NormalModule.getCompilationHooks(compilation); | ||
|  | 
 | ||
|  | 		return this._doBuild(options, compilation, resolver, fs, hooks, err => { | ||
|  | 			// if we have an error mark module as failed and exit
 | ||
|  | 			if (err) { | ||
|  | 				this.markModuleAsErrored(err); | ||
|  | 				this._initBuildHash(compilation); | ||
|  | 				return callback(); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			const handleParseError = e => { | ||
|  | 				const source = this._source.source(); | ||
|  | 				const loaders = this.loaders.map(item => | ||
|  | 					contextify(options.context, item.loader, compilation.compiler.root) | ||
|  | 				); | ||
|  | 				const error = new ModuleParseError(source, e, loaders, this.type); | ||
|  | 				this.markModuleAsErrored(error); | ||
|  | 				this._initBuildHash(compilation); | ||
|  | 				return callback(); | ||
|  | 			}; | ||
|  | 
 | ||
|  | 			const handleParseResult = result => { | ||
|  | 				this.dependencies.sort( | ||
|  | 					concatComparators( | ||
|  | 						compareSelect(a => a.loc, compareLocations), | ||
|  | 						keepOriginalOrder(this.dependencies) | ||
|  | 					) | ||
|  | 				); | ||
|  | 				this._initBuildHash(compilation); | ||
|  | 				this._lastSuccessfulBuildMeta = this.buildMeta; | ||
|  | 				return handleBuildDone(); | ||
|  | 			}; | ||
|  | 
 | ||
|  | 			const handleBuildDone = () => { | ||
|  | 				try { | ||
|  | 					hooks.beforeSnapshot.call(this); | ||
|  | 				} catch (err) { | ||
|  | 					this.markModuleAsErrored(err); | ||
|  | 					return callback(); | ||
|  | 				} | ||
|  | 
 | ||
|  | 				const snapshotOptions = compilation.options.snapshot.module; | ||
|  | 				if (!this.buildInfo.cacheable || !snapshotOptions) { | ||
|  | 					return callback(); | ||
|  | 				} | ||
|  | 				// add warning for all non-absolute paths in fileDependencies, etc
 | ||
|  | 				// This makes it easier to find problems with watching and/or caching
 | ||
|  | 				let nonAbsoluteDependencies = undefined; | ||
|  | 				const checkDependencies = deps => { | ||
|  | 					for (const dep of deps) { | ||
|  | 						if (!ABSOLUTE_PATH_REGEX.test(dep)) { | ||
|  | 							if (nonAbsoluteDependencies === undefined) | ||
|  | 								nonAbsoluteDependencies = new Set(); | ||
|  | 							nonAbsoluteDependencies.add(dep); | ||
|  | 							deps.delete(dep); | ||
|  | 							try { | ||
|  | 								const depWithoutGlob = dep.replace(/[\\/]?\*.*$/, ""); | ||
|  | 								const absolute = join( | ||
|  | 									compilation.fileSystemInfo.fs, | ||
|  | 									this.context, | ||
|  | 									depWithoutGlob | ||
|  | 								); | ||
|  | 								if (absolute !== dep && ABSOLUTE_PATH_REGEX.test(absolute)) { | ||
|  | 									(depWithoutGlob !== dep | ||
|  | 										? this.buildInfo.contextDependencies | ||
|  | 										: deps | ||
|  | 									).add(absolute); | ||
|  | 								} | ||
|  | 							} catch (e) { | ||
|  | 								// ignore
 | ||
|  | 							} | ||
|  | 						} | ||
|  | 					} | ||
|  | 				}; | ||
|  | 				checkDependencies(this.buildInfo.fileDependencies); | ||
|  | 				checkDependencies(this.buildInfo.missingDependencies); | ||
|  | 				checkDependencies(this.buildInfo.contextDependencies); | ||
|  | 				if (nonAbsoluteDependencies !== undefined) { | ||
|  | 					const InvalidDependenciesModuleWarning = | ||
|  | 						getInvalidDependenciesModuleWarning(); | ||
|  | 					this.addWarning( | ||
|  | 						new InvalidDependenciesModuleWarning(this, nonAbsoluteDependencies) | ||
|  | 					); | ||
|  | 				} | ||
|  | 				// convert file/context/missingDependencies into filesystem snapshot
 | ||
|  | 				compilation.fileSystemInfo.createSnapshot( | ||
|  | 					startTime, | ||
|  | 					this.buildInfo.fileDependencies, | ||
|  | 					this.buildInfo.contextDependencies, | ||
|  | 					this.buildInfo.missingDependencies, | ||
|  | 					snapshotOptions, | ||
|  | 					(err, snapshot) => { | ||
|  | 						if (err) { | ||
|  | 							this.markModuleAsErrored(err); | ||
|  | 							return; | ||
|  | 						} | ||
|  | 						this.buildInfo.fileDependencies = undefined; | ||
|  | 						this.buildInfo.contextDependencies = undefined; | ||
|  | 						this.buildInfo.missingDependencies = undefined; | ||
|  | 						this.buildInfo.snapshot = snapshot; | ||
|  | 						return callback(); | ||
|  | 					} | ||
|  | 				); | ||
|  | 			}; | ||
|  | 
 | ||
|  | 			try { | ||
|  | 				hooks.beforeParse.call(this); | ||
|  | 			} catch (err) { | ||
|  | 				this.markModuleAsErrored(err); | ||
|  | 				this._initBuildHash(compilation); | ||
|  | 				return callback(); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			// check if this module should !not! be parsed.
 | ||
|  | 			// if so, exit here;
 | ||
|  | 			const noParseRule = options.module && options.module.noParse; | ||
|  | 			if (this.shouldPreventParsing(noParseRule, this.request)) { | ||
|  | 				// We assume that we need module and exports
 | ||
|  | 				this.buildInfo.parsed = false; | ||
|  | 				this._initBuildHash(compilation); | ||
|  | 				return handleBuildDone(); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			let result; | ||
|  | 			try { | ||
|  | 				const source = this._source.source(); | ||
|  | 				result = this.parser.parse(this._ast || source, { | ||
|  | 					source, | ||
|  | 					current: this, | ||
|  | 					module: this, | ||
|  | 					compilation: compilation, | ||
|  | 					options: options | ||
|  | 				}); | ||
|  | 			} catch (e) { | ||
|  | 				handleParseError(e); | ||
|  | 				return; | ||
|  | 			} | ||
|  | 			handleParseResult(result); | ||
|  | 		}); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {ConcatenationBailoutReasonContext} context context | ||
|  | 	 * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated | ||
|  | 	 */ | ||
|  | 	getConcatenationBailoutReason(context) { | ||
|  | 		return this.generator.getConcatenationBailoutReason(this, context); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @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) { | ||
|  | 		if (this.factoryMeta !== undefined) { | ||
|  | 			if (this.factoryMeta.sideEffectFree) return false; | ||
|  | 			if (this.factoryMeta.sideEffectFree === false) return true; | ||
|  | 		} | ||
|  | 		if (this.buildMeta !== undefined && this.buildMeta.sideEffectFree) { | ||
|  | 			if (this._isEvaluatingSideEffects) | ||
|  | 				return ModuleGraphConnection.CIRCULAR_CONNECTION; | ||
|  | 			this._isEvaluatingSideEffects = true; | ||
|  | 			/** @type {ConnectionState} */ | ||
|  | 			let current = false; | ||
|  | 			for (const dep of this.dependencies) { | ||
|  | 				const state = dep.getModuleEvaluationSideEffectsState(moduleGraph); | ||
|  | 				if (state === true) { | ||
|  | 					if ( | ||
|  | 						this._addedSideEffectsBailout === undefined | ||
|  | 							? ((this._addedSideEffectsBailout = new WeakSet()), true) | ||
|  | 							: !this._addedSideEffectsBailout.has(moduleGraph) | ||
|  | 					) { | ||
|  | 						this._addedSideEffectsBailout.add(moduleGraph); | ||
|  | 						moduleGraph | ||
|  | 							.getOptimizationBailout(this) | ||
|  | 							.push( | ||
|  | 								() => | ||
|  | 									`Dependency (${ | ||
|  | 										dep.type | ||
|  | 									}) with side effects at ${formatLocation(dep.loc)}`
 | ||
|  | 							); | ||
|  | 					} | ||
|  | 					this._isEvaluatingSideEffects = false; | ||
|  | 					return true; | ||
|  | 				} else if (state !== ModuleGraphConnection.CIRCULAR_CONNECTION) { | ||
|  | 					current = ModuleGraphConnection.addConnectionStates(current, state); | ||
|  | 				} | ||
|  | 			} | ||
|  | 			this._isEvaluatingSideEffects = false; | ||
|  | 			// When caching is implemented here, make sure to not cache when
 | ||
|  | 			// at least one circular connection was in the loop above
 | ||
|  | 			return current; | ||
|  | 		} else { | ||
|  | 			return true; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @returns {Set<string>} types available (do not mutate) | ||
|  | 	 */ | ||
|  | 	getSourceTypes() { | ||
|  | 		if (this._sourceTypes === undefined) { | ||
|  | 			this._sourceTypes = this.generator.getTypes(this); | ||
|  | 		} | ||
|  | 		return this._sourceTypes; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {CodeGenerationContext} context context for code generation | ||
|  | 	 * @returns {CodeGenerationResult} result | ||
|  | 	 */ | ||
|  | 	codeGeneration({ | ||
|  | 		dependencyTemplates, | ||
|  | 		runtimeTemplate, | ||
|  | 		moduleGraph, | ||
|  | 		chunkGraph, | ||
|  | 		runtime, | ||
|  | 		concatenationScope, | ||
|  | 		codeGenerationResults, | ||
|  | 		sourceTypes | ||
|  | 	}) { | ||
|  | 		/** @type {Set<string>} */ | ||
|  | 		const runtimeRequirements = new Set(); | ||
|  | 
 | ||
|  | 		if (!this.buildInfo.parsed) { | ||
|  | 			runtimeRequirements.add(RuntimeGlobals.module); | ||
|  | 			runtimeRequirements.add(RuntimeGlobals.exports); | ||
|  | 			runtimeRequirements.add(RuntimeGlobals.thisAsExports); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/** @type {function(): Map<string, any>} */ | ||
|  | 		const getData = () => { | ||
|  | 			return this._codeGeneratorData; | ||
|  | 		}; | ||
|  | 
 | ||
|  | 		const sources = new Map(); | ||
|  | 		for (const type of sourceTypes || chunkGraph.getModuleSourceTypes(this)) { | ||
|  | 			const source = this.error | ||
|  | 				? new RawSource( | ||
|  | 						"throw new Error(" + JSON.stringify(this.error.message) + ");" | ||
|  | 				  ) | ||
|  | 				: this.generator.generate(this, { | ||
|  | 						dependencyTemplates, | ||
|  | 						runtimeTemplate, | ||
|  | 						moduleGraph, | ||
|  | 						chunkGraph, | ||
|  | 						runtimeRequirements, | ||
|  | 						runtime, | ||
|  | 						concatenationScope, | ||
|  | 						codeGenerationResults, | ||
|  | 						getData, | ||
|  | 						type | ||
|  | 				  }); | ||
|  | 
 | ||
|  | 			if (source) { | ||
|  | 				sources.set(type, new CachedSource(source)); | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/** @type {CodeGenerationResult} */ | ||
|  | 		const resultEntry = { | ||
|  | 			sources, | ||
|  | 			runtimeRequirements, | ||
|  | 			data: this._codeGeneratorData | ||
|  | 		}; | ||
|  | 		return resultEntry; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @returns {Source | null} the original source for the module before webpack transformation | ||
|  | 	 */ | ||
|  | 	originalSource() { | ||
|  | 		return this._source; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @returns {void} | ||
|  | 	 */ | ||
|  | 	invalidateBuild() { | ||
|  | 		this._forceBuild = true; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @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) { | ||
|  | 		const { fileSystemInfo, compilation, valueCacheVersions } = context; | ||
|  | 		// build if enforced
 | ||
|  | 		if (this._forceBuild) return callback(null, true); | ||
|  | 
 | ||
|  | 		// always try to build in case of an error
 | ||
|  | 		if (this.error) return callback(null, true); | ||
|  | 
 | ||
|  | 		// always build when module is not cacheable
 | ||
|  | 		if (!this.buildInfo.cacheable) return callback(null, true); | ||
|  | 
 | ||
|  | 		// build when there is no snapshot to check
 | ||
|  | 		if (!this.buildInfo.snapshot) return callback(null, true); | ||
|  | 
 | ||
|  | 		// build when valueDependencies have changed
 | ||
|  | 		/** @type {Map<string, string | Set<string>>} */ | ||
|  | 		const valueDependencies = this.buildInfo.valueDependencies; | ||
|  | 		if (valueDependencies) { | ||
|  | 			if (!valueCacheVersions) return callback(null, true); | ||
|  | 			for (const [key, value] of valueDependencies) { | ||
|  | 				if (value === undefined) return callback(null, true); | ||
|  | 				const current = valueCacheVersions.get(key); | ||
|  | 				if ( | ||
|  | 					value !== current && | ||
|  | 					(typeof value === "string" || | ||
|  | 						typeof current === "string" || | ||
|  | 						current === undefined || | ||
|  | 						!isSubset(value, current)) | ||
|  | 				) { | ||
|  | 					return callback(null, true); | ||
|  | 				} | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// check snapshot for validity
 | ||
|  | 		fileSystemInfo.checkSnapshotValid(this.buildInfo.snapshot, (err, valid) => { | ||
|  | 			if (err) return callback(err); | ||
|  | 			if (!valid) return callback(null, true); | ||
|  | 			const hooks = NormalModule.getCompilationHooks(compilation); | ||
|  | 			hooks.needBuild.callAsync(this, context, (err, needBuild) => { | ||
|  | 				if (err) { | ||
|  | 					return callback( | ||
|  | 						HookWebpackError.makeWebpackError( | ||
|  | 							err, | ||
|  | 							"NormalModule.getCompilationHooks().needBuild" | ||
|  | 						) | ||
|  | 					); | ||
|  | 				} | ||
|  | 				callback(null, !!needBuild); | ||
|  | 			}); | ||
|  | 		}); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @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 cachedSize = | ||
|  | 			this._sourceSizes === undefined ? undefined : this._sourceSizes.get(type); | ||
|  | 		if (cachedSize !== undefined) { | ||
|  | 			return cachedSize; | ||
|  | 		} | ||
|  | 		const size = Math.max(1, this.generator.getSize(this, type)); | ||
|  | 		if (this._sourceSizes === undefined) { | ||
|  | 			this._sourceSizes = new Map(); | ||
|  | 		} | ||
|  | 		this._sourceSizes.set(type, size); | ||
|  | 		return size; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @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 | ||
|  | 	) { | ||
|  | 		const { snapshot, buildDependencies: buildDeps } = this.buildInfo; | ||
|  | 		if (snapshot) { | ||
|  | 			fileDependencies.addAll(snapshot.getFileIterable()); | ||
|  | 			contextDependencies.addAll(snapshot.getContextIterable()); | ||
|  | 			missingDependencies.addAll(snapshot.getMissingIterable()); | ||
|  | 		} else { | ||
|  | 			const { | ||
|  | 				fileDependencies: fileDeps, | ||
|  | 				contextDependencies: contextDeps, | ||
|  | 				missingDependencies: missingDeps | ||
|  | 			} = this.buildInfo; | ||
|  | 			if (fileDeps !== undefined) fileDependencies.addAll(fileDeps); | ||
|  | 			if (contextDeps !== undefined) contextDependencies.addAll(contextDeps); | ||
|  | 			if (missingDeps !== undefined) missingDependencies.addAll(missingDeps); | ||
|  | 		} | ||
|  | 		if (buildDeps !== undefined) { | ||
|  | 			buildDependencies.addAll(buildDeps); | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {Hash} hash the hash used to track dependencies | ||
|  | 	 * @param {UpdateHashContext} context context | ||
|  | 	 * @returns {void} | ||
|  | 	 */ | ||
|  | 	updateHash(hash, context) { | ||
|  | 		hash.update(this.buildInfo.hash); | ||
|  | 		this.generator.updateHash(hash, { | ||
|  | 			module: this, | ||
|  | 			...context | ||
|  | 		}); | ||
|  | 		super.updateHash(hash, context); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {ObjectSerializerContext} context context | ||
|  | 	 */ | ||
|  | 	serialize(context) { | ||
|  | 		const { write } = context; | ||
|  | 		// deserialize
 | ||
|  | 		write(this._source); | ||
|  | 		write(this.error); | ||
|  | 		write(this._lastSuccessfulBuildMeta); | ||
|  | 		write(this._forceBuild); | ||
|  | 		write(this._codeGeneratorData); | ||
|  | 		super.serialize(context); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	static deserialize(context) { | ||
|  | 		const obj = new NormalModule({ | ||
|  | 			// will be deserialized by Module
 | ||
|  | 			layer: null, | ||
|  | 			type: "", | ||
|  | 			// will be filled by updateCacheModule
 | ||
|  | 			resource: "", | ||
|  | 			context: "", | ||
|  | 			request: null, | ||
|  | 			userRequest: null, | ||
|  | 			rawRequest: null, | ||
|  | 			loaders: null, | ||
|  | 			matchResource: null, | ||
|  | 			parser: null, | ||
|  | 			parserOptions: null, | ||
|  | 			generator: null, | ||
|  | 			generatorOptions: null, | ||
|  | 			resolveOptions: null | ||
|  | 		}); | ||
|  | 		obj.deserialize(context); | ||
|  | 		return obj; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {ObjectDeserializerContext} context context | ||
|  | 	 */ | ||
|  | 	deserialize(context) { | ||
|  | 		const { read } = context; | ||
|  | 		this._source = read(); | ||
|  | 		this.error = read(); | ||
|  | 		this._lastSuccessfulBuildMeta = read(); | ||
|  | 		this._forceBuild = read(); | ||
|  | 		this._codeGeneratorData = read(); | ||
|  | 		super.deserialize(context); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | makeSerializable(NormalModule, "webpack/lib/NormalModule"); | ||
|  | 
 | ||
|  | module.exports = NormalModule; |