xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

WebAssembly Development Guide All In One

WebAssembly Development Guide All In One

WebAssembly 开发指南 All In One

WebAssembly 1.0 has shipped in 4 major browser engines.

https://webassembly.org

specs

https://webassembly.org/specs/

https://webassembly.github.io/spec/core/

https://webassembly.github.io/spec/core/text/index.html#text-format

WebAssembly Specification Release 2.0 (Draft 2022-09-01)

https://webassembly.github.io/spec/core/_download/WebAssembly.pdf

Developer's Guide

https://webassembly.org/getting-started/developers-guide/

Compile a WebAssembly module

C/C++

Rust

https://doc.rust-lang.org/stable/cargo/
https://doc.rust-lang.org/cargo/appendix/glossary.html#crate


// if declared `ferris_says` as dependencies in `Cargo.toml` file
// it's no need import external crate `ferris_says` anymore ✅
// extern crate ferris_says;
// can't find crate ❌
use ferris_says::say;
use std::io::{stdout, BufWriter};

fn main() {
  println!("🦀 Hello, world!");
  println!("$ rustc -V");
  println!("rustc 1.63.0 (4b91a6ea7 2022-08-08)");
  // 调用 function
  add(1, 2);
  println!("\ncowsay 🐮");
  let stdout = stdout();
  // let message = String::from("Hello fellow Rustaceans!");
  let message = String::from("🦀 Hello Rust 🦀!");
  let width = message.chars().count();
  let mut writer = BufWriter::new(stdout.lock());
  say(message.as_bytes(), width, &mut writer).unwrap();
}


// fn 定义 function
fn add(left: usize, right: usize) -> usize {
  // {} 插值,占位符
  println!("\n🦀 left = {}, right = {}", left, right);
  println!("🦀🦀 left + right = {}", left + right);
  println!("🦀🦀🦀 left = {}, right = {}, left + right = {}", left, right, left + right);
  left + right
}


AssemblyScript (a TypeScript-like syntax)

https://www.assemblyscript.org/introduction.html
https://github.com/AssemblyScript/assemblyscript


Use the compiled WebAssembly

https://developer.mozilla.org/en-US/docs/WebAssembly/Loading_and_running

To use WebAssembly in JavaScript, you first need to pull your module into memory before compilation/instantiation.
This article provides a reference for the different mechanisms that can be used to fetch WebAssembly bytecode, as well as how to compile/instantiate then run it.

要在 JavaScript 中使用 WebAssembly,首先需要在编译/实例化之前将模块拉入内存。
本文提供了可用于获取 WebAssembly 字节码的不同机制的参考,以及如何编译/实例化然后运行它。

demo


const test = async (moduleBytes) => {
  try {
    // This will throw a ReferenceError on platforms where BigInt is not supported.
    // Please do not change the test value to BigInt literal (i.e. 0n), cause in that case a SyntaxError will be thrown before an execution.
    console.log('🚀 moduleBytes =', moduleBytes);
    const instance = await WebAssembly.instantiate(moduleBytes);
    console.log('✅ instance =', instance);
    // {module: Module, instance: Instance}
    const {b}= instance.instance.exports;
    return b(BigInt(0)) === BigInt(0);
  } catch (e) {
    return false;
  }
};


// IIFE
(() => {
  // const WebA_URL = `https://cdn.xgqfrms.xyz/webassembly/math-sqrt-demo.wasm`;
  const WebA_URL = `./math-sqrt-demo.wasm`;
  const ThrowErrorInfo = () => {throw new Error(`fetch WASM failed!`)};
  fetch(`${WebA_URL}`)
  .then(res => res.ok ? res.arrayBuffer() : ThrowErrorInfo())
  // .then(bytes => WebAssembly.compile(bytes))
  .then(bytes => {
    test(bytes);
    console.log(`🚀 bytes =`, bytes);
    // ArrayBuffer(65)
    const module = WebAssembly.compile(bytes);
    // async / await: WebAssembly.compile
    console.log(`👻 module =`, module);
    // Promise {<pending>}
    // ⚠️ ⏰ 编译
    return WebAssembly.compile(bytes);
  })
  // .then(module => WebAssembly.instantiate(module))
  .then(module => {
    console.log(`👻👻 module =`, module);
    // Module {}
    // async / await: WebAssembly.instantiate
    const instance = WebAssembly.instantiate(module);
    console.log(`✅✅ instance =`, instance);
    // Promise {<fulfilled>: Instance}
    return WebAssembly.instantiate(module);
  })
  // .then(instance => window.WebAssembly.Sqrt = instance.exports.sqrt);
  .then(instance => {
    console.log(`✅✅✅ instance =`, instance);
    console.log(`instance.exports =`, instance, instance.exports);
    // console.log(`instance.instance.exports =`, instance.instance.exports);
    // app.js:12 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'exports') ❌
    if(!window.WA) {
      window.WA = {};
      window.WA.sqrt = instance.exports.sqrt;
      console.log(`window.WA.sqrt(4) =`, window.WA.sqrt(4), window.WA.sqrt(4) === 2 ? `✅` : `❌`);
    }
    // window.WebAssembly
    const result = instance.exports.sqrt(4);
    console.log(`sqrt(4)'s result =`, result, result === 2 ? `✅` : `❌`)
    setTimeout(() => {
      const app = document.querySelector(`#app`);
      app.innerHTML = ``;
      app.insertAdjacentHTML(`beforeend`, `sqrt(4)'s result = ${result} ${result === 2 ? '✅' : '❌'}`);
    }, 1000);
  });
})();




// WebAssembly.Instance

// const wasmInstance = new WebAssembly.Instance(wasmModule, {});
// const { addTwo } = wasmInstance.exports;
// for (let i = 0; i < 10; i++) {
//   console.log(addTwo(i, i));
// }

https://cdn.xgqfrms.xyz/webassembly/index.html

js function => s-exprs function 🦀

Inspect WebAssembly

debug WebAssembly

https://developer.chrome.com/blog/wasm-debugging-2020/

JS API

https://webassembly.org/getting-started/js-api/

We assume here that you already have a .wasm module, whether compiled from a C/C++ program or assembled directly from s-exprs.

;; s-exprs

;; 编译器

;; C/C++ => WASM (.c/.cpp => .wasm)
;; https://mbebenita.github.io/WasmExplorer/

;; WAT/WAST => WASM (.wat/.wast => .wasm)
;; https://webassembly.github.io/wabt/demo/wat2wasm/

;; Rust => WASM (.rs => .wasm)
;; https://github.com/yewstack/yew
;; https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_wasm


;; WebAssembly text format
;; To enable WebAssembly to be read and edited by humans, there is a textual representation of the wasm binary format.
;; 为了使 WebAssembly 能够被人类阅读和编辑,有一个 wasm 二进制格式的文本表示。

;; js's Math.sqrt(4) === 2
;; wat define method `sqrt`

(module
    (export "sqrt" (func $sqrt))
    (func $sqrt
        (param $num f32)
        (result f32)
        ;; (f32.sqrt (get_local $num))
        (f32.sqrt (local.get $num))
    )
)

js 执行 .wasm 文件的步骤 ✅


(() => {
  const log = console.log;
  log(`\n🎉在 js 执行 \`.wasm\` 文件的4个步骤: `);
  const ThrowErrorInfo = () => {
    throw new Error(`fetch WASM failed!`);
  };
  const WASM_URL = `https://cdn.xgqfrms.xyz/webassembly/math-sqrt-demo.wasm`;
  fetch(WASM_URL)
  .then(res => {
    // 1. 获取 wasm 转换成 ArrayBuffer 形式的 bytes 字节码
    log(`1. 获取 wasm 转换成 ArrayBuffer 形式的 bytes 字节码`);
    return res.ok ? res.arrayBuffer() : ThrowErrorInfo();
  })
  .then(bytes => {
    // async / await: WebAssembly.compile
    // 2. 使用 WebAssembly.compile 把 bytes 字节码编译成 module 模块
    log(`2. 使用 WebAssembly.compile 把 bytes 字节码编译成 module 模块`);
    return WebAssembly.compile(bytes);
  })
  .then(module => {
    // async / await: WebAssembly.instantiate
    // 3. 使用 WebAssembly.instantiate 把 module 模块实例化,并把模块中定义的方法 exports 导出
    log(`3. 使用 WebAssembly.instantiate 把 module 模块实例化,并把模块中定义的方法 exports 导出`)
    return WebAssembly.instantiate(module);
  })
  .then(instance => {
    // 4. 导入模块 exports 的方法
    log(`4. 导入模块 exports 的方法`);
    const {sqrt} = instance.exports;
    // global namespace (WebAssembly)
    if(!window.WebAssembly) {
      WebAssembly = {};
    }
    window.WebAssembly.sqrt = sqrt;
    console.log('\nsqrt(4) =', sqrt(4), sqrt(4) === 2 ? `✅` : `❌`);
    // sqrt(4) = 2 ✅
    console.log('\nWebAssembly.sqrt(4) =', WebAssembly.sqrt(4), WebAssembly.sqrt(4) === 2 ? `✅` : `❌`);
    // WebAssembly.sqrt(4) = 2 ✅
  });
})();

/*

🎉在 js 执行 `.wasm` 文件的4个步骤: 

1. 获取 wasm 转换成 ArrayBuffer 形式的 bytes 字节码
2. 使用 WebAssembly.compile 把 bytes 字节码编译成 module 模块
3. 使用 WebAssembly.instantiate 把 module 模块实例化,并把模块中定义的方法 exports 导出
4. 导入模块 exports 的方法

sqrt(4) = 2 ✅

WebAssembly.sqrt(4) = 2 ✅

*/

https://cdn.xgqfrms.xyz/

https://cdn.xgqfrms.xyz/webassembly/index.html

Advanced Tools

WABT - The WebAssembly Binary Toolkit

wat2wasm, 编译 .wat => .wasm

https://webassembly.github.io/wabt/demo/wat2wasm/index.html

wasm2wat, 反编译 .wasm => .wat

https://webassembly.github.io/wabt/demo/wasm2wat/index.html

https://github.com/WebAssembly/wabt

Binaryen - Compiler and toolchain infrastructure

https://github.com/WebAssembly/binaryen

S-expression / symbolic expression / s-exprs / S-表达式

https://en.wikipedia.org/wiki/S-expression

https://zh.wikipedia.org/wiki/S-表达式

WebAssembly on MDN

https://developer.mozilla.org/en-US/docs/WebAssembly

refs



©xgqfrms 2012-2020

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2022-09-06 11:53  xgqfrms  阅读(45)  评论(3编辑  收藏  举报