| 
									
										
										
										
											2017-10-30 20:56:57 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | const t = require("@webassemblyjs/ast"); | 
					
						
							| 
									
										
										
										
											2018-03-01 22:07:43 +08:00
										 |  |  | const { decode } = require("@webassemblyjs/wasm-parser"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const { Tapable } = require("tapable"); | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency"); | 
					
						
							| 
									
										
										
										
											2017-10-30 20:56:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-11 02:19:30 +08:00
										 |  |  | /** @typedef {import("../Module")} Module */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-05-09 23:40:38 +08:00
										 |  |  |  * @param {t.ModuleImport} n the import | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  |  * @returns {boolean} true, if a memory was imported | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-05-09 23:40:38 +08:00
										 |  |  | const isMemoryImport = n => n.descr.type === "Memory"; | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-05-09 23:40:38 +08:00
										 |  |  |  * @param {t.ModuleImport} n the import | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  |  * @returns {boolean} true, if a table was imported | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-05-09 23:40:38 +08:00
										 |  |  | const isTableImport = n => n.descr.type === "Table"; | 
					
						
							| 
									
										
										
										
											2018-03-29 20:45:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-11 20:24:08 +08:00
										 |  |  | const JS_COMPAT_TYPES = new Set(["i32", "f32", "f64"]); | 
					
						
							| 
									
										
										
										
											2018-05-11 00:07:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {t.ModuleImport} moduleImport the import | 
					
						
							|  |  |  |  * @returns {null | string} the type incompatible with js types | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const getJsIncompatibleType = moduleImport => { | 
					
						
							|  |  |  | 	if (moduleImport.descr.type !== "FuncImportDescr") return null; | 
					
						
							|  |  |  | 	const signature = moduleImport.descr.signature; | 
					
						
							|  |  |  | 	for (const param of signature.params) { | 
					
						
							|  |  |  | 		if (!JS_COMPAT_TYPES.has(param.valtype)) | 
					
						
							|  |  |  | 			return `${param.valtype} as parameter`; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for (const type of signature.results) { | 
					
						
							|  |  |  | 		if (!JS_COMPAT_TYPES.has(type)) return `${type} as result`; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return null; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-28 15:50:29 +08:00
										 |  |  | const decoderOpts = { | 
					
						
							|  |  |  | 	ignoreCodeSection: true, | 
					
						
							| 
									
										
										
										
											2018-03-01 22:07:43 +08:00
										 |  |  | 	ignoreDataSection: true | 
					
						
							| 
									
										
										
										
											2018-02-28 15:50:29 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-30 20:56:57 +08:00
										 |  |  | class WebAssemblyParser extends Tapable { | 
					
						
							|  |  |  | 	constructor(options) { | 
					
						
							|  |  |  | 		super(); | 
					
						
							| 
									
										
										
										
											2017-11-28 23:54:26 +08:00
										 |  |  | 		this.hooks = {}; | 
					
						
							| 
									
										
										
										
											2017-10-30 20:56:57 +08:00
										 |  |  | 		this.options = options; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-28 04:06:39 +08:00
										 |  |  | 	parse(binary, state) { | 
					
						
							| 
									
										
										
										
											2017-12-14 08:21:44 +08:00
										 |  |  | 		// flag it as ESM
 | 
					
						
							| 
									
										
										
										
											2017-12-23 01:23:20 +08:00
										 |  |  | 		state.module.buildMeta.exportsType = "namespace"; | 
					
						
							| 
									
										
										
										
											2017-12-14 08:21:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-20 22:03:35 +08:00
										 |  |  | 		// parse it
 | 
					
						
							| 
									
										
										
										
											2018-02-28 15:50:29 +08:00
										 |  |  | 		const ast = decode(binary, decoderOpts); | 
					
						
							| 
									
										
										
										
											2018-02-20 22:03:35 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// extract imports and exports
 | 
					
						
							| 
									
										
										
										
											2018-03-01 22:07:43 +08:00
										 |  |  | 		const exports = (state.module.buildMeta.providedExports = []); | 
					
						
							| 
									
										
										
										
											2018-04-28 00:53:07 +08:00
										 |  |  | 		t.traverse(ast, { | 
					
						
							| 
									
										
										
										
											2018-03-01 22:07:43 +08:00
										 |  |  | 			ModuleExport({ node }) { | 
					
						
							| 
									
										
										
										
											2018-05-09 23:53:25 +08:00
										 |  |  | 				exports.push(node.name); | 
					
						
							| 
									
										
										
										
											2018-02-20 22:03:35 +08:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-01 22:07:43 +08:00
										 |  |  | 			ModuleImport({ node }) { | 
					
						
							| 
									
										
										
										
											2018-05-11 00:07:24 +08:00
										 |  |  | 				/** @type {false | string} */ | 
					
						
							| 
									
										
										
										
											2018-04-28 17:09:13 +08:00
										 |  |  | 				let onlyDirectImport = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-09 23:53:25 +08:00
										 |  |  | 				if (isMemoryImport(node) === true) { | 
					
						
							| 
									
										
										
										
											2018-05-11 00:07:24 +08:00
										 |  |  | 					onlyDirectImport = "Memory"; | 
					
						
							|  |  |  | 				} else if (isTableImport(node) === true) { | 
					
						
							|  |  |  | 					onlyDirectImport = "Table"; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					const incompatibleType = getJsIncompatibleType(node); | 
					
						
							|  |  |  | 					if (incompatibleType) { | 
					
						
							|  |  |  | 						onlyDirectImport = `Non-JS-compatible Func Sigurature (${incompatibleType})`; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-03-29 20:45:56 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-09 00:54:06 +08:00
										 |  |  | 				const dep = new WebAssemblyImportDependency( | 
					
						
							| 
									
										
										
										
											2018-05-09 23:53:25 +08:00
										 |  |  | 					node.module, | 
					
						
							|  |  |  | 					node.name, | 
					
						
							|  |  |  | 					node.descr, | 
					
						
							| 
									
										
										
										
											2018-04-28 17:09:13 +08:00
										 |  |  | 					onlyDirectImport | 
					
						
							| 
									
										
										
										
											2018-03-09 00:54:06 +08:00
										 |  |  | 				); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-20 22:03:35 +08:00
										 |  |  | 				state.module.addDependency(dep); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return state; | 
					
						
							| 
									
										
										
										
											2017-10-30 20:56:57 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = WebAssemblyParser; |