| //! Disassembly calling function for `wasm32` targets. | 
 | use wasm_bindgen::prelude::*; | 
 |  | 
 | use crate::Function; | 
 | use std::collections::HashSet; | 
 |  | 
 | #[wasm_bindgen(module = "child_process")] | 
 | extern "C" { | 
 |     #[wasm_bindgen(js_name = execFileSync)] | 
 |     fn exec_file_sync(cmd: &str, args: &js_sys::Array, opts: &js_sys::Object) -> Buffer; | 
 | } | 
 |  | 
 | #[wasm_bindgen(module = "buffer")] | 
 | extern "C" { | 
 |     type Buffer; | 
 |     #[wasm_bindgen(method, js_name = toString)] | 
 |     fn to_string(this: &Buffer) -> String; | 
 | } | 
 |  | 
 | #[wasm_bindgen] | 
 | extern "C" { | 
 |     #[wasm_bindgen(js_namespace = require)] | 
 |     fn resolve(module: &str) -> String; | 
 |     #[wasm_bindgen(js_namespace = console, js_name = log)] | 
 |     pub fn js_console_log(s: &str); | 
 | } | 
 |  | 
 | pub(crate) fn disassemble_myself() -> HashSet<Function> { | 
 |     use std::path::Path; | 
 |     ::console_error_panic_hook::set_once(); | 
 |     // Our wasm module in the wasm-bindgen test harness is called | 
 |     // "wasm-bindgen-test_bg". When running in node this is actually a shim JS | 
 |     // file. Ask node where that JS file is, and then we use that with a wasm | 
 |     // extension to find the wasm file itself. | 
 |     let js_shim = resolve("wasm-bindgen-test_bg"); | 
 |     let js_shim = Path::new(&js_shim).with_extension("wasm"); | 
 |  | 
 |     // Execute `wasm2wat` synchronously, waiting for and capturing all of its | 
 |     // output. Note that we pass in a custom `maxBuffer` parameter because we're | 
 |     // generating a ton of output that needs to be buffered. | 
 |     let args = js_sys::Array::new(); | 
 |     args.push(&js_shim.display().to_string().into()); | 
 |     args.push(&"--enable-simd".into()); | 
 |     let opts = js_sys::Object::new(); | 
 |     js_sys::Reflect::set(&opts, &"maxBuffer".into(), &(200 * 1024 * 1024).into()).unwrap(); | 
 |     let output = exec_file_sync("wasm2wat", &args, &opts).to_string(); | 
 |  | 
 |     let mut ret: HashSet<Function> = HashSet::new(); | 
 |     let mut lines = output.lines().map(|s| s.trim()); | 
 |     while let Some(line) = lines.next() { | 
 |         // If this isn't a function, we don't care about it. | 
 |         if !line.starts_with("(func ") { | 
 |             continue; | 
 |         } | 
 |  | 
 |         let mut function = Function { | 
 |             name: String::new(), | 
 |             instrs: Vec::new(), | 
 |         }; | 
 |  | 
 |         // Empty functions will end in `))` so there's nothing to do, otherwise | 
 |         // we'll have a bunch of following lines which are instructions. | 
 |         // | 
 |         // Lines that have an imbalanced `)` mark the end of a function. | 
 |         if !line.ends_with("))") { | 
 |             while let Some(line) = lines.next() { | 
 |                 function.instrs.push(line.to_string()); | 
 |                 if !line.starts_with("(") && line.ends_with(")") { | 
 |                     break; | 
 |                 } | 
 |             } | 
 |         } | 
 |         // The second element here split on whitespace should be the name of | 
 |         // the function, skipping the type/params/results | 
 |         function.name = line.split_whitespace().nth(1).unwrap().to_string(); | 
 |         if function.name.starts_with("$") { | 
 |             function.name = function.name[1..].to_string() | 
 |         } | 
 |  | 
 |         if !function.name.contains("stdarch_test_shim") { | 
 |             continue; | 
 |         } | 
 |  | 
 |         assert!(ret.insert(function)); | 
 |     } | 
 |     return ret; | 
 | } |