153 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /*
 | |
| 	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;
 | 
