| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const { RawSource } = require("webpack-sources"); | 
					
						
							|  |  |  | const Generator = require("../Generator"); | 
					
						
							| 
									
										
										
										
											2019-11-05 04:05:17 +08:00
										 |  |  | const InitFragment = require("../InitFragment"); | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | const RuntimeGlobals = require("../RuntimeGlobals"); | 
					
						
							|  |  |  | const Template = require("../Template"); | 
					
						
							|  |  |  | const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** @typedef {import("webpack-sources").Source} Source */ | 
					
						
							|  |  |  | /** @typedef {import("../DependencyTemplates")} DependencyTemplates */ | 
					
						
							|  |  |  | /** @typedef {import("../Generator").GenerateContext} GenerateContext */ | 
					
						
							|  |  |  | /** @typedef {import("../Module")} Module */ | 
					
						
							|  |  |  | /** @typedef {import("../NormalModule")} NormalModule */ | 
					
						
							|  |  |  | /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const TYPES = new Set(["webassembly"]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class AsyncWebAssemblyJavascriptGenerator extends Generator { | 
					
						
							|  |  |  | 	constructor(filenameTemplate) { | 
					
						
							|  |  |  | 		super(); | 
					
						
							|  |  |  | 		this.filenameTemplate = filenameTemplate; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-18 21:29:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2019-11-18 21:29:19 +08:00
										 |  |  | 	 * @param {NormalModule} module fresh module | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 	 * @returns {Set<string>} available types (do not mutate) | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2019-11-18 21:29:19 +08:00
										 |  |  | 	getTypes(module) { | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 		return TYPES; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {NormalModule} module the module | 
					
						
							|  |  |  | 	 * @param {string=} type source type | 
					
						
							|  |  |  | 	 * @returns {number} estimate size of the module | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	getSize(module, type) { | 
					
						
							|  |  |  | 		return 40 + module.dependencies.length * 10; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {NormalModule} module module for which the code should be generated | 
					
						
							|  |  |  | 	 * @param {GenerateContext} generateContext context for generate | 
					
						
							|  |  |  | 	 * @returns {Source} generated code | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2019-11-05 04:05:17 +08:00
										 |  |  | 	generate(module, generateContext) { | 
					
						
							|  |  |  | 		const { | 
					
						
							|  |  |  | 			runtimeTemplate, | 
					
						
							|  |  |  | 			chunkGraph, | 
					
						
							|  |  |  | 			moduleGraph, | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 			runtimeRequirements, | 
					
						
							|  |  |  | 			runtime | 
					
						
							| 
									
										
										
										
											2019-11-05 04:05:17 +08:00
										 |  |  | 		} = generateContext; | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 		runtimeRequirements.add(RuntimeGlobals.module); | 
					
						
							| 
									
										
										
										
											2019-12-05 05:54:26 +08:00
										 |  |  | 		runtimeRequirements.add(RuntimeGlobals.moduleId); | 
					
						
							| 
									
										
										
										
											2019-06-05 20:17:15 +08:00
										 |  |  | 		runtimeRequirements.add(RuntimeGlobals.exports); | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 		runtimeRequirements.add(RuntimeGlobals.instantiateWasm); | 
					
						
							| 
									
										
										
										
											2019-11-05 04:05:17 +08:00
										 |  |  | 		/** @type {InitFragment[]} */ | 
					
						
							|  |  |  | 		const initFragments = []; | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 		/** @type {Map<Module, { request: string, importVar: string }>} */ | 
					
						
							|  |  |  | 		const depModules = new Map(); | 
					
						
							|  |  |  | 		/** @type {Map<string, WebAssemblyImportDependency[]>} */ | 
					
						
							|  |  |  | 		const wasmDepsByRequest = new Map(); | 
					
						
							|  |  |  | 		for (const dep of module.dependencies) { | 
					
						
							|  |  |  | 			if (dep instanceof WebAssemblyImportDependency) { | 
					
						
							|  |  |  | 				const module = moduleGraph.getModule(dep); | 
					
						
							|  |  |  | 				if (!depModules.has(module)) { | 
					
						
							|  |  |  | 					depModules.set(module, { | 
					
						
							|  |  |  | 						request: dep.request, | 
					
						
							|  |  |  | 						importVar: `WEBPACK_IMPORTED_MODULE_${depModules.size}` | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				let list = wasmDepsByRequest.get(dep.request); | 
					
						
							|  |  |  | 				if (list === undefined) { | 
					
						
							|  |  |  | 					list = []; | 
					
						
							|  |  |  | 					wasmDepsByRequest.set(dep.request, list); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				list.push(dep); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const promises = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const importStatements = Array.from( | 
					
						
							|  |  |  | 			depModules, | 
					
						
							|  |  |  | 			([importedModule, { request, importVar }]) => { | 
					
						
							| 
									
										
										
										
											2019-06-05 17:15:25 +08:00
										 |  |  | 				if (moduleGraph.isAsync(importedModule)) { | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 					promises.push(importVar); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return runtimeTemplate.importStatement({ | 
					
						
							|  |  |  | 					update: false, | 
					
						
							|  |  |  | 					module: importedModule, | 
					
						
							|  |  |  | 					chunkGraph, | 
					
						
							|  |  |  | 					request, | 
					
						
							|  |  |  | 					originModule: module, | 
					
						
							|  |  |  | 					importVar, | 
					
						
							|  |  |  | 					runtimeRequirements | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2020-05-15 22:24:11 +08:00
										 |  |  | 		const importsCode = importStatements.map(([x]) => x).join(""); | 
					
						
							|  |  |  | 		const importsCompatCode = importStatements.map(([_, x]) => x).join(""); | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		const importObjRequestItems = Array.from( | 
					
						
							|  |  |  | 			wasmDepsByRequest, | 
					
						
							|  |  |  | 			([request, deps]) => { | 
					
						
							|  |  |  | 				const exportItems = deps.map(dep => { | 
					
						
							|  |  |  | 					const importedModule = moduleGraph.getModule(dep); | 
					
						
							|  |  |  | 					const importVar = depModules.get(importedModule).importVar; | 
					
						
							|  |  |  | 					return `${JSON.stringify( | 
					
						
							|  |  |  | 						dep.name | 
					
						
							|  |  |  | 					)}: ${runtimeTemplate.exportFromImport({ | 
					
						
							|  |  |  | 						moduleGraph, | 
					
						
							|  |  |  | 						module: importedModule, | 
					
						
							|  |  |  | 						request, | 
					
						
							|  |  |  | 						exportName: dep.name, | 
					
						
							|  |  |  | 						originModule: module, | 
					
						
							|  |  |  | 						asiSafe: true, | 
					
						
							|  |  |  | 						isCall: false, | 
					
						
							|  |  |  | 						callContext: false, | 
					
						
							| 
									
										
										
										
											2019-12-05 05:54:26 +08:00
										 |  |  | 						defaultInterop: true, | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 						importVar, | 
					
						
							| 
									
										
										
										
											2019-11-05 04:05:17 +08:00
										 |  |  | 						initFragments, | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 						runtime, | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 						runtimeRequirements | 
					
						
							|  |  |  | 					})}`;
 | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 				return Template.asString([ | 
					
						
							|  |  |  | 					`${JSON.stringify(request)}: {`, | 
					
						
							|  |  |  | 					Template.indent(exportItems.join(",\n")), | 
					
						
							|  |  |  | 					"}" | 
					
						
							|  |  |  | 				]); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const importsObj = | 
					
						
							|  |  |  | 			importObjRequestItems.length > 0 | 
					
						
							|  |  |  | 				? Template.asString([ | 
					
						
							|  |  |  | 						"{", | 
					
						
							|  |  |  | 						Template.indent(importObjRequestItems.join(",\n")), | 
					
						
							|  |  |  | 						"}" | 
					
						
							|  |  |  | 				  ]) | 
					
						
							|  |  |  | 				: undefined; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-05 20:17:15 +08:00
										 |  |  | 		const instantiateCall = | 
					
						
							| 
									
										
										
										
											2020-07-28 23:08:22 +08:00
										 |  |  | 			`${RuntimeGlobals.instantiateWasm}(${module.exportsArgument}, ${ | 
					
						
							|  |  |  | 				module.moduleArgument | 
					
						
							|  |  |  | 			}.id, ${JSON.stringify( | 
					
						
							|  |  |  | 				chunkGraph.getRenderedModuleHash(module, runtime) | 
					
						
							|  |  |  | 			)}` + (importsObj ? `, ${importsObj})` : `)`);
 | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-29 18:12:11 +08:00
										 |  |  | 		if (promises.length > 0) | 
					
						
							|  |  |  | 			runtimeRequirements.add(RuntimeGlobals.asyncModule); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-05 04:05:17 +08:00
										 |  |  | 		const source = new RawSource( | 
					
						
							| 
									
										
										
										
											2021-01-29 18:12:11 +08:00
										 |  |  | 			promises.length > 0 | 
					
						
							|  |  |  | 				? Template.asString([ | 
					
						
							|  |  |  | 						`var __webpack_instantiate__ = ${runtimeTemplate.basicFunction( | 
					
						
							|  |  |  | 							`[${promises.join(", ")}]`, | 
					
						
							|  |  |  | 							`${importsCompatCode}return ${instantiateCall};` | 
					
						
							|  |  |  | 						)}`,
 | 
					
						
							|  |  |  | 						`${RuntimeGlobals.asyncModule}(${ | 
					
						
							|  |  |  | 							module.moduleArgument | 
					
						
							|  |  |  | 						}, ${runtimeTemplate.basicFunction( | 
					
						
							|  |  |  | 							"__webpack_handle_async_dependencies__", | 
					
						
							|  |  |  | 							[ | 
					
						
							|  |  |  | 								importsCode, | 
					
						
							|  |  |  | 								`var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([${promises.join( | 
					
						
							|  |  |  | 									", " | 
					
						
							|  |  |  | 								)}]);`,
 | 
					
						
							|  |  |  | 								"return __webpack_async_dependencies__.then ? __webpack_async_dependencies__.then(__webpack_instantiate__) : __webpack_instantiate__(__webpack_async_dependencies__);" | 
					
						
							|  |  |  | 							] | 
					
						
							|  |  |  | 						)}, 1);`
 | 
					
						
							|  |  |  | 				  ]) | 
					
						
							|  |  |  | 				: `${importsCode}${importsCompatCode}module.exports = ${instantiateCall};` | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 		); | 
					
						
							| 
									
										
										
										
											2021-01-29 18:12:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-05 04:05:17 +08:00
										 |  |  | 		return InitFragment.addToSource(source, initFragments, generateContext); | 
					
						
							| 
									
										
										
										
											2019-05-24 18:30:43 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = AsyncWebAssemblyJavascriptGenerator; |