| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-28 01:02:02 +08:00
										 |  |  | const Template = require("../Template"); | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | const { compareModulesById } = require("../util/comparators"); | 
					
						
							| 
									
										
										
										
											2018-05-11 20:24:40 +08:00
										 |  |  | const WebAssemblyUtils = require("./WebAssemblyUtils"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | /** @typedef {import("../ChunkGraph")} ChunkGraph */ | 
					
						
							|  |  |  | /** @typedef {import("../Compilation")} Compilation */ | 
					
						
							| 
									
										
										
										
											2018-07-02 22:18:49 +08:00
										 |  |  | /** @typedef {import("../MainTemplate")} MainTemplate */ | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | /** @typedef {import("../Module")} Module */ | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | /** @typedef {import("../ModuleGraph")} ModuleGraph */ | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Get all wasm modules
 | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | const getAllWasmModules = (chunkGraph, chunk) => { | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 	const wasmModules = chunk.getAllAsyncChunks(); | 
					
						
							|  |  |  | 	const array = []; | 
					
						
							|  |  |  | 	for (const chunk of wasmModules) { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 		for (const m of chunkGraph.getOrderedChunkModulesIterable( | 
					
						
							|  |  |  | 			chunk, | 
					
						
							|  |  |  | 			compareModulesById | 
					
						
							|  |  |  | 		)) { | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 			if (m.type.startsWith("webassembly")) { | 
					
						
							|  |  |  | 				array.push(m); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return array; | 
					
						
							| 
									
										
										
										
											2018-06-27 19:48:13 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-11 20:24:40 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * generates the import object function for a module | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  |  * @param {ModuleGraph} moduleGraph the module graph | 
					
						
							| 
									
										
										
										
											2018-05-11 20:24:40 +08:00
										 |  |  |  * @param {Module} module the module | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  |  * @param {boolean} mangle mangle imports | 
					
						
							| 
									
										
										
										
											2018-05-11 20:24:40 +08:00
										 |  |  |  * @returns {string} source code | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | const generateImportObject = (moduleGraph, module, mangle) => { | 
					
						
							| 
									
										
										
										
											2018-05-11 00:08:29 +08:00
										 |  |  | 	const waitForInstances = new Map(); | 
					
						
							| 
									
										
										
										
											2018-05-10 17:34:09 +08:00
										 |  |  | 	const properties = []; | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 	const usedWasmDependencies = WebAssemblyUtils.getUsedDependencies( | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 		moduleGraph, | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 		module, | 
					
						
							|  |  |  | 		mangle | 
					
						
							|  |  |  | 	); | 
					
						
							| 
									
										
										
										
											2018-05-11 20:24:40 +08:00
										 |  |  | 	for (const usedDep of usedWasmDependencies) { | 
					
						
							|  |  |  | 		const dep = usedDep.dependency; | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 		const importedModule = moduleGraph.getModule(dep); | 
					
						
							| 
									
										
										
										
											2018-05-11 20:24:40 +08:00
										 |  |  | 		const exportName = dep.name; | 
					
						
							| 
									
										
										
										
											2018-08-07 01:39:43 +08:00
										 |  |  | 		const usedName = | 
					
						
							| 
									
										
										
										
											2018-08-07 03:01:24 +08:00
										 |  |  | 			importedModule && importedModule.getUsedName(moduleGraph, exportName); | 
					
						
							| 
									
										
										
										
											2018-05-11 20:24:40 +08:00
										 |  |  | 		const description = dep.description; | 
					
						
							|  |  |  | 		const direct = dep.onlyDirectImport; | 
					
						
							| 
									
										
										
										
											2018-05-05 00:52:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 		const module = usedDep.module; | 
					
						
							|  |  |  | 		const name = usedDep.name; | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-11 20:24:40 +08:00
										 |  |  | 		if (direct) { | 
					
						
							|  |  |  | 			const instanceVar = `m${waitForInstances.size}`; | 
					
						
							|  |  |  | 			waitForInstances.set(instanceVar, importedModule.id); | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 			properties.push({ | 
					
						
							|  |  |  | 				module, | 
					
						
							|  |  |  | 				name, | 
					
						
							|  |  |  | 				value: `${instanceVar}[${JSON.stringify(usedName)}]` | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2018-05-11 20:24:40 +08:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			const params = description.signature.params.map( | 
					
						
							|  |  |  | 				(param, k) => "p" + k + param.valtype | 
					
						
							|  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2018-03-28 20:58:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-11 20:24:40 +08:00
										 |  |  | 			const mod = `installedModules[${JSON.stringify(importedModule.id)}]`; | 
					
						
							|  |  |  | 			const func = `${mod}.exports[${JSON.stringify(usedName)}]`; | 
					
						
							| 
									
										
										
										
											2018-05-10 17:34:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 			properties.push({ | 
					
						
							|  |  |  | 				module, | 
					
						
							|  |  |  | 				name, | 
					
						
							|  |  |  | 				value: Template.asString([ | 
					
						
							|  |  |  | 					(importedModule.type.startsWith("webassembly") | 
					
						
							|  |  |  | 						? `${mod} ? ${func} : ` | 
					
						
							|  |  |  | 						: "") + `function(${params}) {`, | 
					
						
							| 
									
										
										
										
											2018-05-11 20:24:40 +08:00
										 |  |  | 					Template.indent([`return ${func}(${params});`]), | 
					
						
							|  |  |  | 					"}" | 
					
						
							|  |  |  | 				]) | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 	let importObject; | 
					
						
							|  |  |  | 	if (mangle) { | 
					
						
							|  |  |  | 		importObject = [ | 
					
						
							|  |  |  | 			"return {", | 
					
						
							|  |  |  | 			Template.indent([ | 
					
						
							|  |  |  | 				properties.map(p => `${JSON.stringify(p.name)}: ${p.value}`).join(",\n") | 
					
						
							|  |  |  | 			]), | 
					
						
							|  |  |  | 			"};" | 
					
						
							|  |  |  | 		]; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		const propertiesByModule = new Map(); | 
					
						
							|  |  |  | 		for (const p of properties) { | 
					
						
							|  |  |  | 			let list = propertiesByModule.get(p.module); | 
					
						
							|  |  |  | 			if (list === undefined) { | 
					
						
							|  |  |  | 				propertiesByModule.set(p.module, (list = [])); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			list.push(p); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		importObject = [ | 
					
						
							|  |  |  | 			"return {", | 
					
						
							|  |  |  | 			Template.indent([ | 
					
						
							|  |  |  | 				Array.from(propertiesByModule, ([module, list]) => { | 
					
						
							|  |  |  | 					return Template.asString([ | 
					
						
							|  |  |  | 						`${JSON.stringify(module)}: {`, | 
					
						
							|  |  |  | 						Template.indent([ | 
					
						
							|  |  |  | 							list.map(p => `${JSON.stringify(p.name)}: ${p.value}`).join(",\n") | 
					
						
							|  |  |  | 						]), | 
					
						
							|  |  |  | 						"}" | 
					
						
							|  |  |  | 					]); | 
					
						
							|  |  |  | 				}).join(",\n") | 
					
						
							|  |  |  | 			]), | 
					
						
							|  |  |  | 			"};" | 
					
						
							|  |  |  | 		]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-11 00:08:29 +08:00
										 |  |  | 	if (waitForInstances.size === 1) { | 
					
						
							|  |  |  | 		const moduleId = Array.from(waitForInstances.values())[0]; | 
					
						
							|  |  |  | 		const promise = `installedWasmModules[${JSON.stringify(moduleId)}]`; | 
					
						
							|  |  |  | 		const variable = Array.from(waitForInstances.keys())[0]; | 
					
						
							|  |  |  | 		return Template.asString([ | 
					
						
							|  |  |  | 			`${JSON.stringify(module.id)}: function() {`, | 
					
						
							|  |  |  | 			Template.indent([ | 
					
						
							|  |  |  | 				`return promiseResolve().then(function() { return ${promise}; }).then(function(${variable}) {`, | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 				Template.indent(importObject), | 
					
						
							| 
									
										
										
										
											2018-05-11 00:08:29 +08:00
										 |  |  | 				"});" | 
					
						
							|  |  |  | 			]), | 
					
						
							|  |  |  | 			"}," | 
					
						
							|  |  |  | 		]); | 
					
						
							|  |  |  | 	} else if (waitForInstances.size > 0) { | 
					
						
							|  |  |  | 		const promises = Array.from( | 
					
						
							|  |  |  | 			waitForInstances.values(), | 
					
						
							|  |  |  | 			id => `installedWasmModules[${JSON.stringify(id)}]` | 
					
						
							|  |  |  | 		).join(", "); | 
					
						
							| 
									
										
										
										
											2018-04-28 17:09:13 +08:00
										 |  |  | 		const variables = Array.from( | 
					
						
							| 
									
										
										
										
											2018-05-11 00:08:29 +08:00
										 |  |  | 			waitForInstances.keys(), | 
					
						
							| 
									
										
										
										
											2018-05-29 05:35:29 +08:00
										 |  |  | 			(name, i) => `${name} = array[${i}]` | 
					
						
							| 
									
										
										
										
											2018-05-11 00:08:29 +08:00
										 |  |  | 		).join(", "); | 
					
						
							| 
									
										
										
										
											2018-04-28 17:09:13 +08:00
										 |  |  | 		return Template.asString([ | 
					
						
							|  |  |  | 			`${JSON.stringify(module.id)}: function() {`, | 
					
						
							|  |  |  | 			Template.indent([ | 
					
						
							| 
									
										
										
										
											2018-05-11 00:08:29 +08:00
										 |  |  | 				`return promiseResolve().then(function() { return Promise.all([${promises}]); }).then(function(array) {`, | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 				Template.indent([`var ${variables};`, ...importObject]), | 
					
						
							| 
									
										
										
										
											2018-04-28 17:09:13 +08:00
										 |  |  | 				"});" | 
					
						
							|  |  |  | 			]), | 
					
						
							|  |  |  | 			"}," | 
					
						
							|  |  |  | 		]); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return Template.asString([ | 
					
						
							|  |  |  | 			`${JSON.stringify(module.id)}: function() {`, | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 			Template.indent(importObject), | 
					
						
							| 
									
										
										
										
											2018-04-28 17:09:13 +08:00
										 |  |  | 			"}," | 
					
						
							|  |  |  | 		]); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-27 19:48:13 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-28 01:02:02 +08:00
										 |  |  | class WasmMainTemplatePlugin { | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 	 * @param {Compilation} compilation the compilation | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 	 * @param {Object} options options | 
					
						
							|  |  |  | 	 * @param {function(string): string} options.generateLoadBinaryCode function to generate the load code | 
					
						
							|  |  |  | 	 * @param {boolean=} options.supportsStreaming whether the generateLoadBinaryCode function supports streaming compilation | 
					
						
							|  |  |  | 	 * @param {boolean=} options.mangleImports whether imports should be mangled | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	constructor( | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 		compilation, | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 		{ generateLoadBinaryCode, supportsStreaming, mangleImports } | 
					
						
							|  |  |  | 	) { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 		this.compilation = compilation; | 
					
						
							| 
									
										
										
										
											2018-04-28 01:02:02 +08:00
										 |  |  | 		this.generateLoadBinaryCode = generateLoadBinaryCode; | 
					
						
							| 
									
										
										
										
											2018-04-30 14:35:06 +08:00
										 |  |  | 		this.supportsStreaming = supportsStreaming; | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 		this.mangleImports = mangleImports; | 
					
						
							| 
									
										
										
										
											2018-04-28 01:02:02 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-02 22:18:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {MainTemplate} mainTemplate main template | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2018-04-28 01:02:02 +08:00
										 |  |  | 	apply(mainTemplate) { | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 		mainTemplate.hooks.localVars.tap( | 
					
						
							| 
									
										
										
										
											2018-04-28 01:02:02 +08:00
										 |  |  | 			"WasmMainTemplatePlugin", | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 			(source, chunk) => { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 				const wasmModules = getAllWasmModules( | 
					
						
							|  |  |  | 					this.compilation.chunkGraph, | 
					
						
							|  |  |  | 					chunk | 
					
						
							|  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2018-04-28 15:57:21 +08:00
										 |  |  | 				if (wasmModules.length === 0) return source; | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 				const importObjects = wasmModules.map(module => { | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 					return generateImportObject( | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 						this.compilation.moduleGraph, | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 						module, | 
					
						
							|  |  |  | 						this.mangleImports | 
					
						
							|  |  |  | 					); | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 				return Template.asString([ | 
					
						
							|  |  |  | 					source, | 
					
						
							|  |  |  | 					"", | 
					
						
							|  |  |  | 					"// object to store loaded and loading wasm modules", | 
					
						
							| 
									
										
										
										
											2018-04-28 15:57:21 +08:00
										 |  |  | 					"var installedWasmModules = {};", | 
					
						
							|  |  |  | 					"", | 
					
						
							| 
									
										
										
										
											2018-05-12 16:25:17 +08:00
										 |  |  | 					// This function is used to delay reading the installed wasm module promises
 | 
					
						
							|  |  |  | 					// by a microtask. Sorting them doesn't help because there are egdecases where
 | 
					
						
							|  |  |  | 					// sorting is not possible (modules splitted into different chunks).
 | 
					
						
							|  |  |  | 					// So we not even trying and solve this by a microtask delay.
 | 
					
						
							| 
									
										
										
										
											2018-05-11 00:08:29 +08:00
										 |  |  | 					"function promiseResolve() { return Promise.resolve(); }", | 
					
						
							|  |  |  | 					"", | 
					
						
							| 
									
										
										
										
											2018-04-28 15:57:21 +08:00
										 |  |  | 					"var wasmImportObjects = {", | 
					
						
							| 
									
										
										
										
											2018-05-07 17:19:13 +08:00
										 |  |  | 					Template.indent(importObjects), | 
					
						
							| 
									
										
										
										
											2018-04-28 15:57:21 +08:00
										 |  |  | 					"};" | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 				]); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		mainTemplate.hooks.requireEnsure.tap( | 
					
						
							| 
									
										
										
										
											2018-04-28 01:02:02 +08:00
										 |  |  | 			"WasmMainTemplatePlugin", | 
					
						
							| 
									
										
										
										
											2018-08-14 22:40:37 +08:00
										 |  |  | 			(source, chunkIdExpression, { chunk, hash }) => { | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 				const webassemblyModuleFilename = | 
					
						
							|  |  |  | 					mainTemplate.outputOptions.webassemblyModuleFilename; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 				const chunkModuleMaps = this.compilation.chunkGraph.getChunkModuleMaps( | 
					
						
							|  |  |  | 					chunk, | 
					
						
							|  |  |  | 					m => m.type.startsWith("webassembly") | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 				); | 
					
						
							|  |  |  | 				if (Object.keys(chunkModuleMaps.id).length === 0) return source; | 
					
						
							|  |  |  | 				const wasmModuleSrcPath = mainTemplate.getAssetPath( | 
					
						
							|  |  |  | 					JSON.stringify(webassemblyModuleFilename), | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, | 
					
						
							|  |  |  | 						hashWithLength: length => | 
					
						
							|  |  |  | 							`" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, | 
					
						
							|  |  |  | 						module: { | 
					
						
							|  |  |  | 							id: '" + wasmModuleId + "', | 
					
						
							|  |  |  | 							hash: `" + ${JSON.stringify( | 
					
						
							|  |  |  | 								chunkModuleMaps.hash | 
					
						
							|  |  |  | 							)}[wasmModuleId] + "`,
 | 
					
						
							|  |  |  | 							hashWithLength(length) { | 
					
						
							|  |  |  | 								const shortChunkHashMap = Object.create(null); | 
					
						
							|  |  |  | 								for (const wasmModuleId of Object.keys(chunkModuleMaps.hash)) { | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 									if (typeof chunkModuleMaps.hash[wasmModuleId] === "string") { | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 										shortChunkHashMap[wasmModuleId] = chunkModuleMaps.hash[ | 
					
						
							|  |  |  | 											wasmModuleId | 
					
						
							|  |  |  | 										].substr(0, length); | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 									} | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 								} | 
					
						
							|  |  |  | 								return `" + ${JSON.stringify( | 
					
						
							|  |  |  | 									shortChunkHashMap | 
					
						
							|  |  |  | 								)}[wasmModuleId] + "`;
 | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 				const createImportObject = content => | 
					
						
							|  |  |  | 					this.mangleImports | 
					
						
							|  |  |  | 						? `{ ${JSON.stringify( | 
					
						
							|  |  |  | 								WebAssemblyUtils.MANGLED_MODULE | 
					
						
							|  |  |  | 						  )}: ${content} }`
 | 
					
						
							|  |  |  | 						: content; | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 				return Template.asString([ | 
					
						
							|  |  |  | 					source, | 
					
						
							|  |  |  | 					"", | 
					
						
							|  |  |  | 					"// Fetch + compile chunk loading for webassembly", | 
					
						
							|  |  |  | 					"", | 
					
						
							|  |  |  | 					`var wasmModules = ${JSON.stringify( | 
					
						
							|  |  |  | 						chunkModuleMaps.id | 
					
						
							| 
									
										
										
										
											2018-08-14 22:40:37 +08:00
										 |  |  | 					)}[${chunkIdExpression}] || [];`,
 | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 					"", | 
					
						
							|  |  |  | 					"wasmModules.forEach(function(wasmModuleId) {", | 
					
						
							|  |  |  | 					Template.indent([ | 
					
						
							|  |  |  | 						"var installedWasmModuleData = installedWasmModules[wasmModuleId];", | 
					
						
							|  |  |  | 						"", | 
					
						
							|  |  |  | 						'// a Promise means "currently loading" or "already loaded".', | 
					
						
							| 
									
										
										
										
											2018-04-28 17:09:13 +08:00
										 |  |  | 						"if(installedWasmModuleData)", | 
					
						
							|  |  |  | 						Template.indent(["promises.push(installedWasmModuleData);"]), | 
					
						
							|  |  |  | 						"else {", | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 						Template.indent([ | 
					
						
							| 
									
										
										
										
											2018-04-30 14:35:06 +08:00
										 |  |  | 							`var importObject = wasmImportObjects[wasmModuleId]();`, | 
					
						
							| 
									
										
										
										
											2018-04-28 17:09:13 +08:00
										 |  |  | 							`var req = ${this.generateLoadBinaryCode(wasmModuleSrcPath)};`, | 
					
						
							| 
									
										
										
										
											2018-04-30 14:35:06 +08:00
										 |  |  | 							"var promise;", | 
					
						
							|  |  |  | 							this.supportsStreaming | 
					
						
							|  |  |  | 								? Template.asString([ | 
					
						
							|  |  |  | 										"if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {", | 
					
						
							|  |  |  | 										Template.indent([ | 
					
						
							|  |  |  | 											"promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {", | 
					
						
							|  |  |  | 											Template.indent([ | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 												`return WebAssembly.instantiate(items[0], ${createImportObject( | 
					
						
							|  |  |  | 													"items[1]" | 
					
						
							|  |  |  | 												)});`
 | 
					
						
							| 
									
										
										
										
											2018-04-30 14:35:06 +08:00
										 |  |  | 											]), | 
					
						
							|  |  |  | 											"});" | 
					
						
							|  |  |  | 										]), | 
					
						
							|  |  |  | 										"} else if(typeof WebAssembly.instantiateStreaming === 'function') {", | 
					
						
							|  |  |  | 										Template.indent([ | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 											`promise = WebAssembly.instantiateStreaming(req, ${createImportObject( | 
					
						
							|  |  |  | 												"importObject" | 
					
						
							|  |  |  | 											)});`
 | 
					
						
							| 
									
										
										
										
											2018-04-30 14:35:06 +08:00
										 |  |  | 										]) | 
					
						
							|  |  |  | 								  ]) | 
					
						
							|  |  |  | 								: Template.asString([ | 
					
						
							|  |  |  | 										"if(importObject instanceof Promise) {", | 
					
						
							|  |  |  | 										Template.indent([ | 
					
						
							|  |  |  | 											"var bytesPromise = req.then(function(x) { return x.arrayBuffer(); });", | 
					
						
							|  |  |  | 											"promise = Promise.all([", | 
					
						
							|  |  |  | 											Template.indent([ | 
					
						
							|  |  |  | 												"bytesPromise.then(function(bytes) { return WebAssembly.compile(bytes); }),", | 
					
						
							|  |  |  | 												"importObject" | 
					
						
							|  |  |  | 											]), | 
					
						
							|  |  |  | 											"]).then(function(items) {", | 
					
						
							|  |  |  | 											Template.indent([ | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 												`return WebAssembly.instantiate(items[0], ${createImportObject( | 
					
						
							|  |  |  | 													"items[1]" | 
					
						
							|  |  |  | 												)});`
 | 
					
						
							| 
									
										
										
										
											2018-04-30 14:35:06 +08:00
										 |  |  | 											]), | 
					
						
							|  |  |  | 											"});" | 
					
						
							|  |  |  | 										]) | 
					
						
							|  |  |  | 								  ]), | 
					
						
							|  |  |  | 							"} else {", | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 							Template.indent([ | 
					
						
							| 
									
										
										
										
											2018-04-30 14:35:06 +08:00
										 |  |  | 								"var bytesPromise = req.then(function(x) { return x.arrayBuffer(); });", | 
					
						
							|  |  |  | 								"promise = bytesPromise.then(function(bytes) {", | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 								Template.indent([ | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 									`return WebAssembly.instantiate(bytes, ${createImportObject( | 
					
						
							|  |  |  | 										"importObject" | 
					
						
							|  |  |  | 									)});`
 | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 								]), | 
					
						
							| 
									
										
										
										
											2018-04-30 14:35:06 +08:00
										 |  |  | 								"});" | 
					
						
							| 
									
										
										
										
											2018-04-28 17:09:13 +08:00
										 |  |  | 							]), | 
					
						
							| 
									
										
										
										
											2018-04-30 14:35:06 +08:00
										 |  |  | 							"}", | 
					
						
							|  |  |  | 							"promises.push(installedWasmModules[wasmModuleId] = promise.then(function(res) {", | 
					
						
							| 
									
										
										
										
											2018-04-28 17:09:13 +08:00
										 |  |  | 							Template.indent([ | 
					
						
							|  |  |  | 								`return ${ | 
					
						
							|  |  |  | 									mainTemplate.requireFn | 
					
						
							| 
									
										
										
										
											2018-05-09 22:19:31 +08:00
										 |  |  | 								}.w[wasmModuleId] = (res.instance || res).exports;`
 | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 							]), | 
					
						
							| 
									
										
										
										
											2018-04-28 17:09:13 +08:00
										 |  |  | 							"}));" | 
					
						
							|  |  |  | 						]), | 
					
						
							|  |  |  | 						"}" | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 					]), | 
					
						
							|  |  |  | 					"});" | 
					
						
							|  |  |  | 				]); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		mainTemplate.hooks.requireExtensions.tap( | 
					
						
							| 
									
										
										
										
											2018-04-28 01:02:02 +08:00
										 |  |  | 			"WasmMainTemplatePlugin", | 
					
						
							| 
									
										
										
										
											2018-08-14 22:40:37 +08:00
										 |  |  | 			(source, { chunk }) => { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 				const chunkGraph = this.compilation.chunkGraph; | 
					
						
							|  |  |  | 				if ( | 
					
						
							|  |  |  | 					!chunkGraph.hasModuleInGraph(chunk, m => | 
					
						
							|  |  |  | 						m.type.startsWith("webassembly") | 
					
						
							|  |  |  | 					) | 
					
						
							|  |  |  | 				) { | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 					return source; | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 				return Template.asString([ | 
					
						
							|  |  |  | 					source, | 
					
						
							|  |  |  | 					"", | 
					
						
							| 
									
										
										
										
											2018-05-09 22:19:31 +08:00
										 |  |  | 					"// object with all WebAssembly.instance exports", | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 					`${mainTemplate.requireFn}.w = {};` | 
					
						
							|  |  |  | 				]); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2018-04-28 01:02:02 +08:00
										 |  |  | 		mainTemplate.hooks.hash.tap("WasmMainTemplatePlugin", hash => { | 
					
						
							|  |  |  | 			hash.update("WasmMainTemplatePlugin"); | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 			hash.update("1"); | 
					
						
							|  |  |  | 			hash.update(`${mainTemplate.outputOptions.webassemblyModuleFilename}`); | 
					
						
							| 
									
										
										
										
											2018-06-06 05:38:29 +08:00
										 |  |  | 			hash.update(`${this.mangleImports}`); | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2018-04-28 16:02:12 +08:00
										 |  |  | 		mainTemplate.hooks.hashForChunk.tap( | 
					
						
							|  |  |  | 			"WasmMainTemplatePlugin", | 
					
						
							|  |  |  | 			(hash, chunk) => { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 				const chunkModuleMaps = this.compilation.chunkGraph.getChunkModuleMaps( | 
					
						
							|  |  |  | 					chunk, | 
					
						
							|  |  |  | 					m => m.type.startsWith("webassembly") | 
					
						
							| 
									
										
										
										
											2018-04-28 16:02:12 +08:00
										 |  |  | 				); | 
					
						
							|  |  |  | 				hash.update(JSON.stringify(chunkModuleMaps.id)); | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 				const wasmModules = getAllWasmModules( | 
					
						
							|  |  |  | 					this.compilation.chunkGraph, | 
					
						
							|  |  |  | 					chunk | 
					
						
							|  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2018-04-28 16:02:12 +08:00
										 |  |  | 				for (const module of wasmModules) { | 
					
						
							|  |  |  | 					hash.update(module.hash); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2018-03-14 23:13:03 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-28 01:02:02 +08:00
										 |  |  | module.exports = WasmMainTemplatePlugin; |