| 
									
										
										
										
											2018-04-28 00:53:07 +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-04-28 00:53:07 +08:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | const { RawSource } = require("webpack-sources"); | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | const Generator = require("../Generator"); | 
					
						
							| 
									
										
										
										
											2018-11-05 21:36:15 +08:00
										 |  |  | const RuntimeGlobals = require("../RuntimeGlobals"); | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | const Template = require("../Template"); | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency"); | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency"); | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-21 00:17:51 +08:00
										 |  |  | /** @typedef {import("webpack-sources").Source} Source */ | 
					
						
							| 
									
										
										
										
											2018-07-23 18:19:16 +08:00
										 |  |  | /** @typedef {import("../DependencyTemplates")} DependencyTemplates */ | 
					
						
							| 
									
										
										
										
											2018-07-18 00:57:03 +08:00
										 |  |  | /** @typedef {import("../Generator").GenerateContext} GenerateContext */ | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | /** @typedef {import("../NormalModule")} NormalModule */ | 
					
						
							|  |  |  | /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */ | 
					
						
							| 
									
										
										
										
											2018-07-21 00:17:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 22:00:32 +08:00
										 |  |  | const TYPES = new Set(["webassembly"]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | class WebAssemblyJavascriptGenerator extends Generator { | 
					
						
							| 
									
										
										
										
											2018-12-03 22:00:32 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @returns {Set<string>} available types (do not mutate) | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	getTypes() { | 
					
						
							|  |  |  | 		return TYPES; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-04 18:23:40 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {NormalModule} module the module | 
					
						
							|  |  |  | 	 * @param {string=} type source type | 
					
						
							|  |  |  | 	 * @returns {number} estimate size of the module | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	getSize(module, type) { | 
					
						
							|  |  |  | 		return 100 + module.dependencies.length * 5; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-21 00:17:51 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {NormalModule} module module for which the code should be generated | 
					
						
							| 
									
										
										
										
											2018-07-18 00:57:03 +08:00
										 |  |  | 	 * @param {GenerateContext} generateContext context for generate | 
					
						
							| 
									
										
										
										
											2018-07-21 00:17:51 +08:00
										 |  |  | 	 * @returns {Source} generated code | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2018-11-17 01:18:44 +08:00
										 |  |  | 	generate( | 
					
						
							|  |  |  | 		module, | 
					
						
							|  |  |  | 		{ runtimeTemplate, moduleGraph, chunkGraph, runtimeRequirements } | 
					
						
							|  |  |  | 	) { | 
					
						
							| 
									
										
										
										
											2018-08-16 19:55:41 +08:00
										 |  |  | 		const usedExports = moduleGraph.getUsedExports(module); | 
					
						
							| 
									
										
										
										
											2018-08-07 01:39:43 +08:00
										 |  |  | 		const initIdentifer = | 
					
						
							|  |  |  | 			usedExports && usedExports !== true | 
					
						
							|  |  |  | 				? Template.numberToIdentifer(usedExports.size) | 
					
						
							|  |  |  | 				: "__webpack_init__"; | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 		let needExportsCopy = false; | 
					
						
							|  |  |  | 		const importedModules = new Map(); | 
					
						
							|  |  |  | 		const initParams = []; | 
					
						
							|  |  |  | 		let index = 0; | 
					
						
							|  |  |  | 		for (const dep of module.dependencies) { | 
					
						
							| 
									
										
										
										
											2018-08-16 19:12:41 +08:00
										 |  |  | 			const depAsAny = /** @type {TODO} */ (dep); | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 			if (moduleGraph.getModule(dep)) { | 
					
						
							|  |  |  | 				let importData = importedModules.get(moduleGraph.getModule(dep)); | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 				if (importData === undefined) { | 
					
						
							|  |  |  | 					importedModules.set( | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 						moduleGraph.getModule(dep), | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 						(importData = { | 
					
						
							|  |  |  | 							importVar: `m${index}`, | 
					
						
							|  |  |  | 							index, | 
					
						
							| 
									
										
										
										
											2018-07-21 00:17:51 +08:00
										 |  |  | 							request: | 
					
						
							|  |  |  | 								"userRequest" in depAsAny ? depAsAny.userRequest : undefined, | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 							names: new Set(), | 
					
						
							|  |  |  | 							reexports: [] | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 					); | 
					
						
							|  |  |  | 					index++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (dep instanceof WebAssemblyImportDependency) { | 
					
						
							|  |  |  | 					importData.names.add(dep.name); | 
					
						
							|  |  |  | 					if (dep.description.type === "GlobalType") { | 
					
						
							|  |  |  | 						const exportName = dep.name; | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 						const usedName = | 
					
						
							|  |  |  | 							moduleGraph.getModule(dep) && | 
					
						
							| 
									
										
										
										
											2018-08-07 03:01:24 +08:00
										 |  |  | 							moduleGraph.getModule(dep).getUsedName(moduleGraph, exportName); | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 						if (moduleGraph.getModule(dep)) { | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 							if (usedName) { | 
					
						
							|  |  |  | 								initParams.push( | 
					
						
							|  |  |  | 									runtimeTemplate.exportFromImport({ | 
					
						
							| 
									
										
										
										
											2018-08-07 01:39:43 +08:00
										 |  |  | 										moduleGraph, | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 										module: moduleGraph.getModule(dep), | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 										request: dep.request, | 
					
						
							|  |  |  | 										importVar: importData.importVar, | 
					
						
							|  |  |  | 										originModule: module, | 
					
						
							|  |  |  | 										exportName: dep.name, | 
					
						
							|  |  |  | 										asiSafe: true, | 
					
						
							|  |  |  | 										isCall: false, | 
					
						
							| 
									
										
										
										
											2018-11-17 01:18:44 +08:00
										 |  |  | 										callContext: null, | 
					
						
							|  |  |  | 										runtimeRequirements | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 									}) | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (dep instanceof WebAssemblyExportImportedDependency) { | 
					
						
							|  |  |  | 					importData.names.add(dep.name); | 
					
						
							| 
									
										
										
										
											2018-08-07 03:01:24 +08:00
										 |  |  | 					const usedName = module.getUsedName(moduleGraph, dep.exportName); | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 					if (usedName) { | 
					
						
							| 
									
										
										
										
											2018-11-17 01:18:44 +08:00
										 |  |  | 						runtimeRequirements.add(RuntimeGlobals.exports); | 
					
						
							| 
									
										
										
										
											2018-10-24 17:24:39 +08:00
										 |  |  | 						const exportProp = `${module.exportsArgument}[${JSON.stringify( | 
					
						
							|  |  |  | 							usedName | 
					
						
							|  |  |  | 						)}]`;
 | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 						const defineStatement = Template.asString([ | 
					
						
							| 
									
										
										
										
											2018-10-24 17:24:39 +08:00
										 |  |  | 							`${exportProp} = ${runtimeTemplate.exportFromImport({ | 
					
						
							| 
									
										
										
										
											2018-08-07 01:39:43 +08:00
										 |  |  | 								moduleGraph, | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 								module: moduleGraph.getModule(dep), | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 								request: dep.request, | 
					
						
							|  |  |  | 								importVar: importData.importVar, | 
					
						
							|  |  |  | 								originModule: module, | 
					
						
							|  |  |  | 								exportName: dep.name, | 
					
						
							|  |  |  | 								asiSafe: true, | 
					
						
							|  |  |  | 								isCall: false, | 
					
						
							| 
									
										
										
										
											2018-11-17 01:18:44 +08:00
										 |  |  | 								callContext: null, | 
					
						
							|  |  |  | 								runtimeRequirements | 
					
						
							| 
									
										
										
										
											2018-10-24 17:24:39 +08:00
										 |  |  | 							})};`,
 | 
					
						
							|  |  |  | 							`if(WebAssembly.Global) ${exportProp} = ` + | 
					
						
							|  |  |  | 								`new WebAssembly.Global({ value: ${JSON.stringify( | 
					
						
							|  |  |  | 									dep.valueType | 
					
						
							|  |  |  | 								)} }, ${exportProp});`
 | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 						]); | 
					
						
							|  |  |  | 						importData.reexports.push(defineStatement); | 
					
						
							|  |  |  | 						needExportsCopy = true; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		const importsCode = Template.asString( | 
					
						
							|  |  |  | 			Array.from( | 
					
						
							|  |  |  | 				importedModules, | 
					
						
							|  |  |  | 				([module, { importVar, request, reexports }]) => { | 
					
						
							|  |  |  | 					const importStatement = runtimeTemplate.importStatement({ | 
					
						
							|  |  |  | 						module, | 
					
						
							| 
									
										
										
										
											2018-08-28 17:50:33 +08:00
										 |  |  | 						chunkGraph, | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 						request, | 
					
						
							|  |  |  | 						importVar, | 
					
						
							| 
									
										
										
										
											2018-11-17 01:18:44 +08:00
										 |  |  | 						originModule: module, | 
					
						
							|  |  |  | 						runtimeRequirements | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 					}); | 
					
						
							|  |  |  | 					return importStatement + reexports.join("\n"); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2018-04-28 15:57:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-17 01:18:44 +08:00
										 |  |  | 		const copyAllExports = | 
					
						
							|  |  |  | 			usedExports && usedExports !== true && !needExportsCopy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// need these globals
 | 
					
						
							|  |  |  | 		runtimeRequirements.add(RuntimeGlobals.module); | 
					
						
							|  |  |  | 		runtimeRequirements.add(RuntimeGlobals.wasmInstances); | 
					
						
							|  |  |  | 		if (usedExports === true) { | 
					
						
							|  |  |  | 			runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject); | 
					
						
							|  |  |  | 			runtimeRequirements.add(RuntimeGlobals.exports); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!copyAllExports) { | 
					
						
							|  |  |  | 			runtimeRequirements.add(RuntimeGlobals.exports); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-28 15:57:21 +08:00
										 |  |  | 		// create source
 | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | 		const source = new RawSource( | 
					
						
							|  |  |  | 			[ | 
					
						
							|  |  |  | 				'"use strict";', | 
					
						
							|  |  |  | 				"// Instantiate WebAssembly module", | 
					
						
							| 
									
										
										
										
											2018-11-17 01:18:44 +08:00
										 |  |  | 				`var wasmExports = ${RuntimeGlobals.wasmInstances}[${ | 
					
						
							|  |  |  | 					module.moduleArgument | 
					
						
							|  |  |  | 				}.i];`,
 | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-07 01:39:43 +08:00
										 |  |  | 				usedExports === true | 
					
						
							| 
									
										
										
										
											2018-11-05 21:36:15 +08:00
										 |  |  | 					? `${RuntimeGlobals.makeNamespaceObject}(${module.exportsArgument});` | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 					: "", | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-28 15:57:21 +08:00
										 |  |  | 				// this must be before import for circular dependencies
 | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | 				"// export exports from WebAssembly module", | 
					
						
							| 
									
										
										
										
											2018-11-17 01:18:44 +08:00
										 |  |  | 				copyAllExports | 
					
						
							| 
									
										
										
										
											2018-05-09 22:19:31 +08:00
										 |  |  | 					? `${module.moduleArgument}.exports = wasmExports;` | 
					
						
							|  |  |  | 					: "for(var name in wasmExports) " + | 
					
						
							|  |  |  | 					  `if(name != ${JSON.stringify(initIdentifer)}) ` + | 
					
						
							|  |  |  | 					  `${module.exportsArgument}[name] = wasmExports[name];`, | 
					
						
							| 
									
										
										
										
											2018-04-28 15:57:21 +08:00
										 |  |  | 				"// exec imports from WebAssembly module (for esm order)", | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 				importsCode, | 
					
						
							|  |  |  | 				"", | 
					
						
							| 
									
										
										
										
											2018-04-28 15:57:21 +08:00
										 |  |  | 				"// exec wasm module", | 
					
						
							| 
									
										
										
										
											2018-06-02 15:53:35 +08:00
										 |  |  | 				`wasmExports[${JSON.stringify(initIdentifer)}](${initParams.join( | 
					
						
							|  |  |  | 					", " | 
					
						
							|  |  |  | 				)})`
 | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | 			].join("\n") | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		return source; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = WebAssemblyJavascriptGenerator; |