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.
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/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, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/16660263.html
未经授权禁止转载,违者必究!