You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							152 lines
						
					
					
						
							4.7 KiB
						
					
					
				
			
		
		
	
	
							152 lines
						
					
					
						
							4.7 KiB
						
					
					
				/* | 
						|
	MIT License http://www.opensource.org/licenses/mit-license.php | 
						|
	Author Tobias Koppers @sokra | 
						|
*/ | 
						|
"use strict"; | 
						|
 | 
						|
const Generator = require("../Generator"); | 
						|
const Template = require("../Template"); | 
						|
const { RawSource } = require("webpack-sources"); | 
						|
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency"); | 
						|
const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency"); | 
						|
 | 
						|
/** @typedef {import("../NormalModule")} NormalModule */ | 
						|
/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */ | 
						|
/** @typedef {import("webpack-sources").Source} Source */ | 
						|
/** @typedef {import("../Dependency").DependencyTemplate} DependencyTemplate */ | 
						|
 | 
						|
class WebAssemblyJavascriptGenerator extends Generator { | 
						|
	/** | 
						|
	 * @param {NormalModule} module module for which the code should be generated | 
						|
	 * @param {Map<Function, DependencyTemplate>} dependencyTemplates mapping from dependencies to templates | 
						|
	 * @param {RuntimeTemplate} runtimeTemplate the runtime template | 
						|
	 * @param {string} type which kind of code should be generated | 
						|
	 * @returns {Source} generated code | 
						|
	 */ | 
						|
	generate(module, dependencyTemplates, runtimeTemplate, type) { | 
						|
		const initIdentifer = Array.isArray(module.usedExports) | 
						|
			? Template.numberToIdentifer(module.usedExports.length) | 
						|
			: "__webpack_init__"; | 
						|
 | 
						|
		let needExportsCopy = false; | 
						|
		const importedModules = new Map(); | 
						|
		const initParams = []; | 
						|
		let index = 0; | 
						|
		for (const dep of module.dependencies) { | 
						|
			const depAsAny = /** @type {any} */ (dep); | 
						|
			if (dep.module) { | 
						|
				let importData = importedModules.get(dep.module); | 
						|
				if (importData === undefined) { | 
						|
					importedModules.set( | 
						|
						dep.module, | 
						|
						(importData = { | 
						|
							importVar: `m${index}`, | 
						|
							index, | 
						|
							request: | 
						|
								"userRequest" in depAsAny ? depAsAny.userRequest : undefined, | 
						|
							names: new Set(), | 
						|
							reexports: [] | 
						|
						}) | 
						|
					); | 
						|
					index++; | 
						|
				} | 
						|
				if (dep instanceof WebAssemblyImportDependency) { | 
						|
					importData.names.add(dep.name); | 
						|
					if (dep.description.type === "GlobalType") { | 
						|
						const exportName = dep.name; | 
						|
						const usedName = dep.module && dep.module.isUsed(exportName); | 
						|
 | 
						|
						if (dep.module) { | 
						|
							if (usedName) { | 
						|
								initParams.push( | 
						|
									runtimeTemplate.exportFromImport({ | 
						|
										module: dep.module, | 
						|
										request: dep.request, | 
						|
										importVar: importData.importVar, | 
						|
										originModule: module, | 
						|
										exportName: dep.name, | 
						|
										asiSafe: true, | 
						|
										isCall: false, | 
						|
										callContext: null | 
						|
									}) | 
						|
								); | 
						|
							} | 
						|
						} | 
						|
					} | 
						|
				} | 
						|
				if (dep instanceof WebAssemblyExportImportedDependency) { | 
						|
					importData.names.add(dep.name); | 
						|
					const usedName = module.isUsed(dep.exportName); | 
						|
					if (usedName) { | 
						|
						const exportProp = `${module.exportsArgument}[${JSON.stringify( | 
						|
							usedName | 
						|
						)}]`; | 
						|
						const defineStatement = Template.asString([ | 
						|
							`${exportProp} = ${runtimeTemplate.exportFromImport({ | 
						|
								module: dep.module, | 
						|
								request: dep.request, | 
						|
								importVar: importData.importVar, | 
						|
								originModule: module, | 
						|
								exportName: dep.name, | 
						|
								asiSafe: true, | 
						|
								isCall: false, | 
						|
								callContext: null | 
						|
							})};`, | 
						|
							`if(WebAssembly.Global) ${exportProp} = ` + | 
						|
								`new WebAssembly.Global({ value: ${JSON.stringify( | 
						|
									dep.valueType | 
						|
								)} }, ${exportProp});` | 
						|
						]); | 
						|
						importData.reexports.push(defineStatement); | 
						|
						needExportsCopy = true; | 
						|
					} | 
						|
				} | 
						|
			} | 
						|
		} | 
						|
		const importsCode = Template.asString( | 
						|
			Array.from( | 
						|
				importedModules, | 
						|
				([module, { importVar, request, reexports }]) => { | 
						|
					const importStatement = runtimeTemplate.importStatement({ | 
						|
						module, | 
						|
						request, | 
						|
						importVar, | 
						|
						originModule: module | 
						|
					}); | 
						|
					return importStatement + reexports.join("\n"); | 
						|
				} | 
						|
			) | 
						|
		); | 
						|
 | 
						|
		// create source | 
						|
		const source = new RawSource( | 
						|
			[ | 
						|
				'"use strict";', | 
						|
				"// Instantiate WebAssembly module", | 
						|
				"var wasmExports = __webpack_require__.w[module.i];", | 
						|
 | 
						|
				!Array.isArray(module.usedExports) | 
						|
					? `__webpack_require__.r(${module.exportsArgument});` | 
						|
					: "", | 
						|
 | 
						|
				// this must be before import for circular dependencies | 
						|
				"// export exports from WebAssembly module", | 
						|
				Array.isArray(module.usedExports) && !needExportsCopy | 
						|
					? `${module.moduleArgument}.exports = wasmExports;` | 
						|
					: "for(var name in wasmExports) " + | 
						|
					  `if(name != ${JSON.stringify(initIdentifer)}) ` + | 
						|
					  `${module.exportsArgument}[name] = wasmExports[name];`, | 
						|
				"// exec imports from WebAssembly module (for esm order)", | 
						|
				importsCode, | 
						|
				"", | 
						|
				"// exec wasm module", | 
						|
				`wasmExports[${JSON.stringify(initIdentifer)}](${initParams.join( | 
						|
					", " | 
						|
				)})` | 
						|
			].join("\n") | 
						|
		); | 
						|
		return source; | 
						|
	} | 
						|
} | 
						|
 | 
						|
module.exports = WebAssemblyJavascriptGenerator;
 | 
						|
 |