| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 | 
							- /*
 
- 	MIT License http://www.opensource.org/licenses/mit-license.php
 
- 	Author Tobias Koppers @sokra
 
- */
 
- "use strict";
 
- const NativeModule = require("module");
 
- const {
 
- 	CachedSource,
 
- 	LineToLineMappedSource,
 
- 	OriginalSource,
 
- 	RawSource,
 
- 	SourceMapSource
 
- } = require("webpack-sources");
 
- const { getContext, runLoaders } = require("loader-runner");
 
- const WebpackError = require("./WebpackError");
 
- const Module = require("./Module");
 
- const ModuleParseError = require("./ModuleParseError");
 
- const ModuleBuildError = require("./ModuleBuildError");
 
- const ModuleError = require("./ModuleError");
 
- const ModuleWarning = require("./ModuleWarning");
 
- const createHash = require("./util/createHash");
 
- const contextify = require("./util/identifier").contextify;
 
- /** @typedef {import("./util/createHash").Hash} Hash */
 
- const asString = buf => {
 
- 	if (Buffer.isBuffer(buf)) {
 
- 		return buf.toString("utf-8");
 
- 	}
 
- 	return buf;
 
- };
 
- const asBuffer = str => {
 
- 	if (!Buffer.isBuffer(str)) {
 
- 		return Buffer.from(str, "utf-8");
 
- 	}
 
- 	return str;
 
- };
 
- class NonErrorEmittedError extends WebpackError {
 
- 	constructor(error) {
 
- 		super();
 
- 		this.name = "NonErrorEmittedError";
 
- 		this.message = "(Emitted value instead of an instance of Error) " + error;
 
- 		Error.captureStackTrace(this, this.constructor);
 
- 	}
 
- }
 
- /**
 
-  * @typedef {Object} CachedSourceEntry
 
-  * @property {TODO} source the generated source
 
-  * @property {string} hash the hash value
 
-  */
 
- class NormalModule extends Module {
 
- 	constructor({
 
- 		type,
 
- 		request,
 
- 		userRequest,
 
- 		rawRequest,
 
- 		loaders,
 
- 		resource,
 
- 		matchResource,
 
- 		parser,
 
- 		generator,
 
- 		resolveOptions
 
- 	}) {
 
- 		super(type, getContext(resource));
 
- 		// Info from Factory
 
- 		this.request = request;
 
- 		this.userRequest = userRequest;
 
- 		this.rawRequest = rawRequest;
 
- 		this.binary = type.startsWith("webassembly");
 
- 		this.parser = parser;
 
- 		this.generator = generator;
 
- 		this.resource = resource;
 
- 		this.matchResource = matchResource;
 
- 		this.loaders = loaders;
 
- 		if (resolveOptions !== undefined) this.resolveOptions = resolveOptions;
 
- 		// Info from Build
 
- 		this.error = null;
 
- 		this._source = null;
 
- 		this._sourceSize = null;
 
- 		this._buildHash = "";
 
- 		this.buildTimestamp = undefined;
 
- 		/** @private @type {Map<string, CachedSourceEntry>} */
 
- 		this._cachedSources = new Map();
 
- 		// Options for the NormalModule set by plugins
 
- 		// TODO refactor this -> options object filled from Factory
 
- 		this.useSourceMap = false;
 
- 		this.lineToLine = false;
 
- 		// Cache
 
- 		this._lastSuccessfulBuildMeta = {};
 
- 	}
 
- 	identifier() {
 
- 		return this.request;
 
- 	}
 
- 	readableIdentifier(requestShortener) {
 
- 		return requestShortener.shorten(this.userRequest);
 
- 	}
 
- 	libIdent(options) {
 
- 		return contextify(options.context, this.userRequest);
 
- 	}
 
- 	nameForCondition() {
 
- 		const resource = this.matchResource || this.resource;
 
- 		const idx = resource.indexOf("?");
 
- 		if (idx >= 0) return resource.substr(0, idx);
 
- 		return resource;
 
- 	}
 
- 	updateCacheModule(module) {
 
- 		this.type = module.type;
 
- 		this.request = module.request;
 
- 		this.userRequest = module.userRequest;
 
- 		this.rawRequest = module.rawRequest;
 
- 		this.parser = module.parser;
 
- 		this.generator = module.generator;
 
- 		this.resource = module.resource;
 
- 		this.matchResource = module.matchResource;
 
- 		this.loaders = module.loaders;
 
- 		this.resolveOptions = module.resolveOptions;
 
- 	}
 
- 	createSourceForAsset(name, content, sourceMap) {
 
- 		if (!sourceMap) {
 
- 			return new RawSource(content);
 
- 		}
 
- 		if (typeof sourceMap === "string") {
 
- 			return new OriginalSource(content, sourceMap);
 
- 		}
 
- 		return new SourceMapSource(content, name, sourceMap);
 
- 	}
 
- 	createLoaderContext(resolver, options, compilation, fs) {
 
- 		const requestShortener = compilation.runtimeTemplate.requestShortener;
 
- 		const getCurrentLoaderName = () => {
 
- 			const currentLoader = this.getCurrentLoader(loaderContext);
 
- 			if (!currentLoader) return "(not in loader scope)";
 
- 			return requestShortener.shorten(currentLoader.loader);
 
- 		};
 
- 		const loaderContext = {
 
- 			version: 2,
 
- 			emitWarning: warning => {
 
- 				if (!(warning instanceof Error)) {
 
- 					warning = new NonErrorEmittedError(warning);
 
- 				}
 
- 				this.warnings.push(
 
- 					new ModuleWarning(this, warning, {
 
- 						from: getCurrentLoaderName()
 
- 					})
 
- 				);
 
- 			},
 
- 			emitError: error => {
 
- 				if (!(error instanceof Error)) {
 
- 					error = new NonErrorEmittedError(error);
 
- 				}
 
- 				this.errors.push(
 
- 					new ModuleError(this, error, {
 
- 						from: getCurrentLoaderName()
 
- 					})
 
- 				);
 
- 			},
 
- 			getLogger: name => {
 
- 				const currentLoader = this.getCurrentLoader(loaderContext);
 
- 				return compilation.getLogger(() =>
 
- 					[currentLoader && currentLoader.loader, name, this.identifier()]
 
- 						.filter(Boolean)
 
- 						.join("|")
 
- 				);
 
- 			},
 
- 			// TODO remove in webpack 5
 
- 			exec: (code, filename) => {
 
- 				// @ts-ignore Argument of type 'this' is not assignable to parameter of type 'Module'.
 
- 				const module = new NativeModule(filename, this);
 
- 				// @ts-ignore _nodeModulePaths is deprecated and undocumented Node.js API
 
- 				module.paths = NativeModule._nodeModulePaths(this.context);
 
- 				module.filename = filename;
 
- 				module._compile(code, filename);
 
- 				return module.exports;
 
- 			},
 
- 			resolve(context, request, callback) {
 
- 				resolver.resolve({}, context, request, {}, callback);
 
- 			},
 
- 			getResolve(options) {
 
- 				const child = options ? resolver.withOptions(options) : resolver;
 
- 				return (context, request, callback) => {
 
- 					if (callback) {
 
- 						child.resolve({}, context, request, {}, callback);
 
- 					} else {
 
- 						return new Promise((resolve, reject) => {
 
- 							child.resolve({}, context, request, {}, (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(
 
- 					name,
 
- 					content,
 
- 					sourceMap
 
- 				);
 
- 				this.buildInfo.assetsInfo.set(name, assetInfo);
 
- 			},
 
- 			rootContext: options.context,
 
- 			webpack: true,
 
- 			sourceMap: !!this.useSourceMap,
 
- 			mode: options.mode || "production",
 
- 			_module: this,
 
- 			_compilation: compilation,
 
- 			_compiler: compilation.compiler,
 
- 			fs: fs
 
- 		};
 
- 		compilation.hooks.normalModuleLoader.call(loaderContext, this);
 
- 		if (options.loader) {
 
- 			Object.assign(loaderContext, options.loader);
 
- 		}
 
- 		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;
 
- 	}
 
- 	createSource(source, resourceBuffer, sourceMap) {
 
- 		// if there is no identifier return raw source
 
- 		if (!this.identifier) {
 
- 			return new RawSource(source);
 
- 		}
 
- 		// from here on we assume we have an identifier
 
- 		const identifier = this.identifier();
 
- 		if (this.lineToLine && resourceBuffer) {
 
- 			return new LineToLineMappedSource(
 
- 				source,
 
- 				identifier,
 
- 				asString(resourceBuffer)
 
- 			);
 
- 		}
 
- 		if (this.useSourceMap && sourceMap) {
 
- 			return new SourceMapSource(source, identifier, sourceMap);
 
- 		}
 
- 		if (Buffer.isBuffer(source)) {
 
- 			// @ts-ignore
 
- 			// TODO We need to fix @types/webpack-sources to allow RawSource to take a Buffer | string
 
- 			return new RawSource(source);
 
- 		}
 
- 		return new OriginalSource(source, identifier);
 
- 	}
 
- 	doBuild(options, compilation, resolver, fs, callback) {
 
- 		const loaderContext = this.createLoaderContext(
 
- 			resolver,
 
- 			options,
 
- 			compilation,
 
- 			fs
 
- 		);
 
- 		runLoaders(
 
- 			{
 
- 				resource: this.resource,
 
- 				loaders: this.loaders,
 
- 				context: loaderContext,
 
- 				readResource: fs.readFile.bind(fs)
 
- 			},
 
- 			(err, result) => {
 
- 				if (result) {
 
- 					this.buildInfo.cacheable = result.cacheable;
 
- 					this.buildInfo.fileDependencies = new Set(result.fileDependencies);
 
- 					this.buildInfo.contextDependencies = new Set(
 
- 						result.contextDependencies
 
- 					);
 
- 				}
 
- 				if (err) {
 
- 					if (!(err instanceof Error)) {
 
- 						err = new NonErrorEmittedError(err);
 
- 					}
 
- 					const currentLoader = this.getCurrentLoader(loaderContext);
 
- 					const error = new ModuleBuildError(this, err, {
 
- 						from:
 
- 							currentLoader &&
 
- 							compilation.runtimeTemplate.requestShortener.shorten(
 
- 								currentLoader.loader
 
- 							)
 
- 					});
 
- 					return callback(error);
 
- 				}
 
- 				const resourceBuffer = result.resourceBuffer;
 
- 				const source = result.result[0];
 
- 				const sourceMap = result.result.length >= 1 ? result.result[1] : null;
 
- 				const extraInfo = result.result.length >= 2 ? result.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(this, err);
 
- 					return callback(error);
 
- 				}
 
- 				this._source = this.createSource(
 
- 					this.binary ? asBuffer(source) : asString(source),
 
- 					resourceBuffer,
 
- 					sourceMap
 
- 				);
 
- 				this._sourceSize = null;
 
- 				this._ast =
 
- 					typeof extraInfo === "object" &&
 
- 					extraInfo !== null &&
 
- 					extraInfo.webpackAST !== undefined
 
- 						? extraInfo.webpackAST
 
- 						: null;
 
- 				return callback();
 
- 			}
 
- 		);
 
- 	}
 
- 	markModuleAsErrored(error) {
 
- 		// Restore build meta from successful build to keep importing state
 
- 		this.buildMeta = Object.assign({}, this._lastSuccessfulBuildMeta);
 
- 		this.error = error;
 
- 		this.errors.push(this.error);
 
- 		this._source = new RawSource(
 
- 			"throw new Error(" + JSON.stringify(this.error.message) + ");"
 
- 		);
 
- 		this._sourceSize = null;
 
- 		this._ast = null;
 
- 	}
 
- 	applyNoParseRule(rule, content) {
 
- 		// must start with "rule" if rule is a string
 
- 		if (typeof rule === "string") {
 
- 			return content.indexOf(rule) === 0;
 
- 		}
 
- 		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._buildHash = /** @type {string} */ (hash.digest("hex"));
 
- 	}
 
- 	build(options, compilation, resolver, fs, callback) {
 
- 		this.buildTimestamp = Date.now();
 
- 		this.built = true;
 
- 		this._source = null;
 
- 		this._sourceSize = null;
 
- 		this._ast = null;
 
- 		this._buildHash = "";
 
- 		this.error = null;
 
- 		this.errors.length = 0;
 
- 		this.warnings.length = 0;
 
- 		this.buildMeta = {};
 
- 		this.buildInfo = {
 
- 			cacheable: false,
 
- 			fileDependencies: new Set(),
 
- 			contextDependencies: new Set(),
 
- 			assets: undefined,
 
- 			assetsInfo: undefined
 
- 		};
 
- 		return this.doBuild(options, compilation, resolver, fs, err => {
 
- 			this._cachedSources.clear();
 
- 			// if we have an error mark module as failed and exit
 
- 			if (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)) {
 
- 				this._initBuildHash(compilation);
 
- 				return callback();
 
- 			}
 
- 			const handleParseError = e => {
 
- 				const source = this._source.source();
 
- 				const loaders = this.loaders.map(item =>
 
- 					contextify(options.context, item.loader)
 
- 				);
 
- 				const error = new ModuleParseError(this, source, e, loaders);
 
- 				this.markModuleAsErrored(error);
 
- 				this._initBuildHash(compilation);
 
- 				return callback();
 
- 			};
 
- 			const handleParseResult = result => {
 
- 				this._lastSuccessfulBuildMeta = this.buildMeta;
 
- 				this._initBuildHash(compilation);
 
- 				return callback();
 
- 			};
 
- 			try {
 
- 				const result = this.parser.parse(
 
- 					this._ast || this._source.source(),
 
- 					{
 
- 						current: this,
 
- 						module: this,
 
- 						compilation: compilation,
 
- 						options: options
 
- 					},
 
- 					(err, result) => {
 
- 						if (err) {
 
- 							handleParseError(err);
 
- 						} else {
 
- 							handleParseResult(result);
 
- 						}
 
- 					}
 
- 				);
 
- 				if (result !== undefined) {
 
- 					// parse is sync
 
- 					handleParseResult(result);
 
- 				}
 
- 			} catch (e) {
 
- 				handleParseError(e);
 
- 			}
 
- 		});
 
- 	}
 
- 	getHashDigest(dependencyTemplates) {
 
- 		// TODO webpack 5 refactor
 
- 		let dtHash = dependencyTemplates.get("hash");
 
- 		return `${this.hash}-${dtHash}`;
 
- 	}
 
- 	source(dependencyTemplates, runtimeTemplate, type = "javascript") {
 
- 		const hashDigest = this.getHashDigest(dependencyTemplates);
 
- 		const cacheEntry = this._cachedSources.get(type);
 
- 		if (cacheEntry !== undefined && cacheEntry.hash === hashDigest) {
 
- 			// We can reuse the cached source
 
- 			return cacheEntry.source;
 
- 		}
 
- 		const source = this.generator.generate(
 
- 			this,
 
- 			dependencyTemplates,
 
- 			runtimeTemplate,
 
- 			type
 
- 		);
 
- 		const cachedSource = new CachedSource(source);
 
- 		this._cachedSources.set(type, {
 
- 			source: cachedSource,
 
- 			hash: hashDigest
 
- 		});
 
- 		return cachedSource;
 
- 	}
 
- 	originalSource() {
 
- 		return this._source;
 
- 	}
 
- 	needRebuild(fileTimestamps, contextTimestamps) {
 
- 		// always try to rebuild in case of an error
 
- 		if (this.error) return true;
 
- 		// always rebuild when module is not cacheable
 
- 		if (!this.buildInfo.cacheable) return true;
 
- 		// Check timestamps of all dependencies
 
- 		// Missing timestamp -> need rebuild
 
- 		// Timestamp bigger than buildTimestamp -> need rebuild
 
- 		for (const file of this.buildInfo.fileDependencies) {
 
- 			const timestamp = fileTimestamps.get(file);
 
- 			if (!timestamp) return true;
 
- 			if (timestamp >= this.buildTimestamp) return true;
 
- 		}
 
- 		for (const file of this.buildInfo.contextDependencies) {
 
- 			const timestamp = contextTimestamps.get(file);
 
- 			if (!timestamp) return true;
 
- 			if (timestamp >= this.buildTimestamp) return true;
 
- 		}
 
- 		// elsewise -> no rebuild needed
 
- 		return false;
 
- 	}
 
- 	size() {
 
- 		if (this._sourceSize === null) {
 
- 			this._sourceSize = this._source ? this._source.size() : -1;
 
- 		}
 
- 		return this._sourceSize;
 
- 	}
 
- 	/**
 
- 	 * @param {Hash} hash the hash used to track dependencies
 
- 	 * @returns {void}
 
- 	 */
 
- 	updateHash(hash) {
 
- 		hash.update(this._buildHash);
 
- 		super.updateHash(hash);
 
- 	}
 
- }
 
- module.exports = NormalModule;
 
 
  |