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.
		
		
		
		
		
			
		
			
	
	
		
			219 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			JavaScript
		
	
		
		
			
		
	
	
			219 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			JavaScript
		
	
| 
											9 months ago
										 | /* | ||
|  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | ||
|  | 	Author Tobias Koppers @sokra | ||
|  | */ | ||
|  | 
 | ||
|  | "use strict"; | ||
|  | 
 | ||
|  | const { SyncWaterfallHook } = require("tapable"); | ||
|  | const Compilation = require("../Compilation"); | ||
|  | const Generator = require("../Generator"); | ||
|  | const { tryRunOrWebpackError } = require("../HookWebpackError"); | ||
|  | const { WEBASSEMBLY_MODULE_TYPE_ASYNC } = require("../ModuleTypeConstants"); | ||
|  | const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency"); | ||
|  | const { compareModulesByIdentifier } = require("../util/comparators"); | ||
|  | const memoize = require("../util/memoize"); | ||
|  | 
 | ||
|  | /** @typedef {import("webpack-sources").Source} Source */ | ||
|  | /** @typedef {import("../../declarations/WebpackOptions").OutputNormalized} OutputOptions */ | ||
|  | /** @typedef {import("../Chunk")} Chunk */ | ||
|  | /** @typedef {import("../ChunkGraph")} ChunkGraph */ | ||
|  | /** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */ | ||
|  | /** @typedef {import("../Compiler")} Compiler */ | ||
|  | /** @typedef {import("../DependencyTemplates")} DependencyTemplates */ | ||
|  | /** @typedef {import("../Module")} Module */ | ||
|  | /** @typedef {import("../ModuleGraph")} ModuleGraph */ | ||
|  | /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */ | ||
|  | /** @typedef {import("../Template").RenderManifestEntry} RenderManifestEntry */ | ||
|  | /** @typedef {import("../Template").RenderManifestOptions} RenderManifestOptions */ | ||
|  | /** @typedef {import("../WebpackError")} WebpackError */ | ||
|  | 
 | ||
|  | const getAsyncWebAssemblyGenerator = memoize(() => | ||
|  | 	require("./AsyncWebAssemblyGenerator") | ||
|  | ); | ||
|  | const getAsyncWebAssemblyJavascriptGenerator = memoize(() => | ||
|  | 	require("./AsyncWebAssemblyJavascriptGenerator") | ||
|  | ); | ||
|  | const getAsyncWebAssemblyParser = memoize(() => | ||
|  | 	require("./AsyncWebAssemblyParser") | ||
|  | ); | ||
|  | 
 | ||
|  | /** | ||
|  |  * @typedef {Object} WebAssemblyRenderContext | ||
|  |  * @property {Chunk} chunk the chunk | ||
|  |  * @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 {CodeGenerationResults} codeGenerationResults results of code generation | ||
|  |  */ | ||
|  | 
 | ||
|  | /** | ||
|  |  * @typedef {Object} CompilationHooks | ||
|  |  * @property {SyncWaterfallHook<[Source, Module, WebAssemblyRenderContext]>} renderModuleContent | ||
|  |  */ | ||
|  | 
 | ||
|  | /** | ||
|  |  * @typedef {Object} AsyncWebAssemblyModulesPluginOptions | ||
|  |  * @property {boolean} [mangleImports] mangle imports | ||
|  |  */ | ||
|  | 
 | ||
|  | /** @type {WeakMap<Compilation, CompilationHooks>} */ | ||
|  | const compilationHooksMap = new WeakMap(); | ||
|  | 
 | ||
|  | const PLUGIN_NAME = "AsyncWebAssemblyModulesPlugin"; | ||
|  | 
 | ||
|  | class AsyncWebAssemblyModulesPlugin { | ||
|  | 	/** | ||
|  | 	 * @param {Compilation} compilation the compilation | ||
|  | 	 * @returns {CompilationHooks} 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 = { | ||
|  | 				renderModuleContent: new SyncWaterfallHook([ | ||
|  | 					"source", | ||
|  | 					"module", | ||
|  | 					"renderContext" | ||
|  | 				]) | ||
|  | 			}; | ||
|  | 			compilationHooksMap.set(compilation, hooks); | ||
|  | 		} | ||
|  | 		return hooks; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {AsyncWebAssemblyModulesPluginOptions} options options | ||
|  | 	 */ | ||
|  | 	constructor(options) { | ||
|  | 		this.options = options; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Apply the plugin | ||
|  | 	 * @param {Compiler} compiler the compiler instance | ||
|  | 	 * @returns {void} | ||
|  | 	 */ | ||
|  | 	apply(compiler) { | ||
|  | 		compiler.hooks.compilation.tap( | ||
|  | 			PLUGIN_NAME, | ||
|  | 			(compilation, { normalModuleFactory }) => { | ||
|  | 				const hooks = | ||
|  | 					AsyncWebAssemblyModulesPlugin.getCompilationHooks(compilation); | ||
|  | 				compilation.dependencyFactories.set( | ||
|  | 					WebAssemblyImportDependency, | ||
|  | 					normalModuleFactory | ||
|  | 				); | ||
|  | 
 | ||
|  | 				normalModuleFactory.hooks.createParser | ||
|  | 					.for(WEBASSEMBLY_MODULE_TYPE_ASYNC) | ||
|  | 					.tap(PLUGIN_NAME, () => { | ||
|  | 						const AsyncWebAssemblyParser = getAsyncWebAssemblyParser(); | ||
|  | 
 | ||
|  | 						return new AsyncWebAssemblyParser(); | ||
|  | 					}); | ||
|  | 				normalModuleFactory.hooks.createGenerator | ||
|  | 					.for(WEBASSEMBLY_MODULE_TYPE_ASYNC) | ||
|  | 					.tap(PLUGIN_NAME, () => { | ||
|  | 						const AsyncWebAssemblyJavascriptGenerator = | ||
|  | 							getAsyncWebAssemblyJavascriptGenerator(); | ||
|  | 						const AsyncWebAssemblyGenerator = getAsyncWebAssemblyGenerator(); | ||
|  | 
 | ||
|  | 						return Generator.byType({ | ||
|  | 							javascript: new AsyncWebAssemblyJavascriptGenerator( | ||
|  | 								compilation.outputOptions.webassemblyModuleFilename | ||
|  | 							), | ||
|  | 							webassembly: new AsyncWebAssemblyGenerator(this.options) | ||
|  | 						}); | ||
|  | 					}); | ||
|  | 
 | ||
|  | 				compilation.hooks.renderManifest.tap( | ||
|  | 					"WebAssemblyModulesPlugin", | ||
|  | 					(result, options) => { | ||
|  | 						const { moduleGraph, chunkGraph, runtimeTemplate } = compilation; | ||
|  | 						const { | ||
|  | 							chunk, | ||
|  | 							outputOptions, | ||
|  | 							dependencyTemplates, | ||
|  | 							codeGenerationResults | ||
|  | 						} = options; | ||
|  | 
 | ||
|  | 						for (const module of chunkGraph.getOrderedChunkModulesIterable( | ||
|  | 							chunk, | ||
|  | 							compareModulesByIdentifier | ||
|  | 						)) { | ||
|  | 							if (module.type === WEBASSEMBLY_MODULE_TYPE_ASYNC) { | ||
|  | 								const filenameTemplate = | ||
|  | 									/** @type {NonNullable<OutputOptions["webassemblyModuleFilename"]>} */ | ||
|  | 									(outputOptions.webassemblyModuleFilename); | ||
|  | 
 | ||
|  | 								result.push({ | ||
|  | 									render: () => | ||
|  | 										this.renderModule( | ||
|  | 											module, | ||
|  | 											{ | ||
|  | 												chunk, | ||
|  | 												dependencyTemplates, | ||
|  | 												runtimeTemplate, | ||
|  | 												moduleGraph, | ||
|  | 												chunkGraph, | ||
|  | 												codeGenerationResults | ||
|  | 											}, | ||
|  | 											hooks | ||
|  | 										), | ||
|  | 									filenameTemplate, | ||
|  | 									pathOptions: { | ||
|  | 										module, | ||
|  | 										runtime: chunk.runtime, | ||
|  | 										chunkGraph | ||
|  | 									}, | ||
|  | 									auxiliary: true, | ||
|  | 									identifier: `webassemblyAsyncModule${chunkGraph.getModuleId( | ||
|  | 										module | ||
|  | 									)}`,
 | ||
|  | 									hash: chunkGraph.getModuleHash(module, chunk.runtime) | ||
|  | 								}); | ||
|  | 							} | ||
|  | 						} | ||
|  | 
 | ||
|  | 						return result; | ||
|  | 					} | ||
|  | 				); | ||
|  | 			} | ||
|  | 		); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * @param {Module} module the rendered module | ||
|  | 	 * @param {WebAssemblyRenderContext} renderContext options object | ||
|  | 	 * @param {CompilationHooks} hooks hooks | ||
|  | 	 * @returns {Source} the newly generated source from rendering | ||
|  | 	 */ | ||
|  | 	renderModule(module, renderContext, hooks) { | ||
|  | 		const { codeGenerationResults, chunk } = renderContext; | ||
|  | 		try { | ||
|  | 			const moduleSource = codeGenerationResults.getSource( | ||
|  | 				module, | ||
|  | 				chunk.runtime, | ||
|  | 				"webassembly" | ||
|  | 			); | ||
|  | 			return tryRunOrWebpackError( | ||
|  | 				() => | ||
|  | 					hooks.renderModuleContent.call(moduleSource, module, renderContext), | ||
|  | 				"AsyncWebAssemblyModulesPlugin.getCompilationHooks().renderModuleContent" | ||
|  | 			); | ||
|  | 		} catch (e) { | ||
|  | 			/** @type {WebpackError} */ (e).module = module; | ||
|  | 			throw e; | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = AsyncWebAssemblyModulesPlugin; |