| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 | /*	MIT License http://www.opensource.org/licenses/mit-license.php	Author Tobias Koppers @sokra*/"use strict";const NormalModule = require("../NormalModule");const LazySet = require("../util/LazySet");const LoaderDependency = require("./LoaderDependency");const LoaderImportDependency = require("./LoaderImportDependency");/** @typedef {import("../../declarations/LoaderContext").LoaderPluginLoaderContext} LoaderPluginLoaderContext *//** @typedef {import("../Compilation").DepConstructor} DepConstructor *//** @typedef {import("../Compilation").ExecuteModuleExports} ExecuteModuleExports *//** @typedef {import("../Compilation").ExecuteModuleResult} ExecuteModuleResult *//** @typedef {import("../Compiler")} Compiler *//** @typedef {import("../Module")} Module *//** @typedef {import("../Module").BuildInfo} BuildInfo *//** * @callback ImportModuleCallback * @param {(Error | null)=} err error object * @param {ExecuteModuleExports=} exports exports of the evaluated module *//** * @typedef {object} ImportModuleOptions * @property {string=} layer the target layer * @property {string=} publicPath the target public path * @property {string=} baseUri target base uri */const PLUGIN_NAME = "LoaderPlugin";class LoaderPlugin {	/**	 * Apply the plugin	 * @param {Compiler} compiler the compiler instance	 * @returns {void}	 */	apply(compiler) {		compiler.hooks.compilation.tap(			PLUGIN_NAME,			(compilation, { normalModuleFactory }) => {				compilation.dependencyFactories.set(					LoaderDependency,					normalModuleFactory				);				compilation.dependencyFactories.set(					LoaderImportDependency,					normalModuleFactory				);			}		);		compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => {			const moduleGraph = compilation.moduleGraph;			NormalModule.getCompilationHooks(compilation).loader.tap(				PLUGIN_NAME,				loaderContext => {					loaderContext.loadModule = (request, callback) => {						const dep = new LoaderDependency(request);						dep.loc = {							name: request						};						const factory = compilation.dependencyFactories.get(							/** @type {DepConstructor} */ (dep.constructor)						);						if (factory === undefined) {							return callback(								new Error(									`No module factory available for dependency type: ${dep.constructor.name}`								)							);						}						const oldFactorizeQueueContext =							compilation.factorizeQueue.getContext();						compilation.factorizeQueue.setContext("load-module");						const oldAddModuleQueueContext =							compilation.addModuleQueue.getContext();						compilation.addModuleQueue.setContext("load-module");						compilation.buildQueue.increaseParallelism();						compilation.handleModuleCreation(							{								factory,								dependencies: [dep],								originModule:									/** @type {NormalModule} */									(loaderContext._module),								context: loaderContext.context,								recursive: false							},							err => {								compilation.factorizeQueue.setContext(oldFactorizeQueueContext);								compilation.addModuleQueue.setContext(oldAddModuleQueueContext);								compilation.buildQueue.decreaseParallelism();								if (err) {									return callback(err);								}								const referencedModule = moduleGraph.getModule(dep);								if (!referencedModule) {									return callback(new Error("Cannot load the module"));								}								if (referencedModule.getNumberOfErrors() > 0) {									return callback(										new Error("The loaded module contains errors")									);								}								const moduleSource = referencedModule.originalSource();								if (!moduleSource) {									return callback(										new Error(											"The module created for a LoaderDependency must have an original source"										)									);								}								let map;								let source;								if (moduleSource.sourceAndMap) {									const sourceAndMap = moduleSource.sourceAndMap();									map = sourceAndMap.map;									source = sourceAndMap.source;								} else {									map = moduleSource.map();									source = moduleSource.source();								}								const fileDependencies = new LazySet();								const contextDependencies = new LazySet();								const missingDependencies = new LazySet();								const buildDependencies = new LazySet();								referencedModule.addCacheDependencies(									fileDependencies,									contextDependencies,									missingDependencies,									buildDependencies								);								for (const d of fileDependencies) {									loaderContext.addDependency(d);								}								for (const d of contextDependencies) {									loaderContext.addContextDependency(d);								}								for (const d of missingDependencies) {									loaderContext.addMissingDependency(d);								}								for (const d of buildDependencies) {									loaderContext.addBuildDependency(d);								}								return callback(null, source, map, referencedModule);							}						);					};					/**					 * @param {string} request the request string to load the module from					 * @param {ImportModuleOptions} options options					 * @param {ImportModuleCallback} callback callback returning the exports					 * @returns {void}					 */					const importModule = (request, options, callback) => {						const dep = new LoaderImportDependency(request);						dep.loc = {							name: request						};						const factory = compilation.dependencyFactories.get(							/** @type {DepConstructor} */ (dep.constructor)						);						if (factory === undefined) {							return callback(								new Error(									`No module factory available for dependency type: ${dep.constructor.name}`								)							);						}						const oldFactorizeQueueContext =							compilation.factorizeQueue.getContext();						compilation.factorizeQueue.setContext("import-module");						const oldAddModuleQueueContext =							compilation.addModuleQueue.getContext();						compilation.addModuleQueue.setContext("import-module");						compilation.buildQueue.increaseParallelism();						compilation.handleModuleCreation(							{								factory,								dependencies: [dep],								originModule:									/** @type {NormalModule} */									(loaderContext._module),								contextInfo: {									issuerLayer: options.layer								},								context: loaderContext.context,								connectOrigin: false,								checkCycle: true							},							err => {								compilation.factorizeQueue.setContext(oldFactorizeQueueContext);								compilation.addModuleQueue.setContext(oldAddModuleQueueContext);								compilation.buildQueue.decreaseParallelism();								if (err) {									return callback(err);								}								const referencedModule = moduleGraph.getModule(dep);								if (!referencedModule) {									return callback(new Error("Cannot load the module"));								}								compilation.buildQueue.increaseParallelism();								compilation.executeModule(									referencedModule,									{										entryOptions: {											baseUri: options.baseUri,											publicPath: options.publicPath										}									},									(err, result) => {										compilation.buildQueue.decreaseParallelism();										if (err) return callback(err);										const {											fileDependencies,											contextDependencies,											missingDependencies,											buildDependencies,											cacheable,											assets,											exports										} = /** @type {ExecuteModuleResult} */ (result);										for (const d of fileDependencies) {											loaderContext.addDependency(d);										}										for (const d of contextDependencies) {											loaderContext.addContextDependency(d);										}										for (const d of missingDependencies) {											loaderContext.addMissingDependency(d);										}										for (const d of buildDependencies) {											loaderContext.addBuildDependency(d);										}										if (cacheable === false) loaderContext.cacheable(false);										for (const [name, { source, info }] of assets) {											const buildInfo =												/** @type {BuildInfo} */												(													/** @type {NormalModule} */ (loaderContext._module)														.buildInfo												);											if (!buildInfo.assets) {												buildInfo.assets = Object.create(null);												buildInfo.assetsInfo = new Map();											}											/** @type {NonNullable<BuildInfo["assets"]>} */											(buildInfo.assets)[name] = source;											/** @type {NonNullable<BuildInfo["assetsInfo"]>} */											(buildInfo.assetsInfo).set(name, info);										}										callback(null, exports);									}								);							}						);					};					// @ts-expect-error overloading doesn't work					loaderContext.importModule = (request, options, callback) => {						if (!callback) {							return new Promise((resolve, reject) => {								importModule(request, options || {}, (err, result) => {									if (err) reject(err);									else resolve(result);								});							});						}						return importModule(request, options || {}, callback);					};				}			);		});	}}module.exports = LoaderPlugin;
 |