WebAssembly JS API All In One
WebAssembly JS API All In One
在 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 ✅
*/
test
https://cdn.xgqfrms.xyz/index.html
demo
https://cdn.xgqfrms.xyz/webassembly/index.html
https://cdn.xgqfrms.xyz/webassembly/math-sqrt-demo.wasm
https://cdn.xgqfrms.xyz/webassembly/math-sqrt-demo.wast
https://cdn.xgqfrms.xyz/webassembly/math-sqrt-demo.wat
;; author xgqfrms, 2022.09.01
;; 编译器
;; 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)
;; get_local ❌ WebAssembly draft
;; (f32.sqrt (get_local $num))
;; local.get ✅ WebAssembly Specification
(f32.sqrt (local.get $num))
)
)
WebAseembly imports & exports
;; simple.wat => simple.wasm
;; simple.wast => simple.wasm
;; 使用 s-expr, 手动组装 WebAssembly Module
(module
(func $getYear (import "imports" "getYear") (param i32))
(func (export "printYear")
;; 写死 const
i32.const 2022
call $getYear
)
)
pass param ✅
;; simple-arg.wat
;; local.get
(module
(func $getYear (import "imports" "getYear") (param i32))
(func (export "printYear") (param $year i32)
(call $getYear(local.get $year))
)
)
// 2 和 1, 实例化
function instantiate(bytes, imports) {
return WebAssembly.compile(bytes).then(module => new WebAssembly.Instance(module, imports));
}
// two-level namespaces relfect
// 定义 imports 映射对象
const importObject = {
imports: {
getYear: year => console.log(`🎉 🇨🇳 🗓 this year is ${year}`),
}
};
fetch('https://cdn.xgqfrms.xyz/webassembly/imports-exports/simple.wasm')
// fetch('https://cdn.xgqfrms.xyz/webassembly/imports-exports/simple-arg.wasm')
// fetch('simple.wasm')
.then(response => response.arrayBuffer())
.then(bytes => instantiate(bytes, importObject))
.then(instance => {
const {printYear} = instance.exports;
printYear();
});
// console.log(`🎉 🇨🇳 🗓 this year is ${year}`)
// 2 和 1, 实例化
function instantiate(bytes, imports) {
return WebAssembly.compile(bytes).then(module => new WebAssembly.Instance(module, imports));
}
// two-level namespaces relfect
// 定义 imports 映射对象
const importObject = {
imports: {
getYear: year => console.log(`🎉 🇨🇳 🗓 this year is ${year}`),
}
};
// fetch('https://cdn.xgqfrms.xyz/webassembly/imports-exports/simple.wasm')
fetch('https://cdn.xgqfrms.xyz/webassembly/imports-exports/simple-arg.wasm')
// fetch('simple.wasm')
.then(response => response.arrayBuffer())
.then(bytes => instantiate(bytes, importObject))
.then(instance => {
const {printYear} = instance.exports;
const year = new Date().getFullYear();
printYear(year);
});
// console.log(`🎉 🇨🇳 🗓 this year is ${year}`)
https://cdn.xgqfrms.xyz/webassembly/imports-exports/simple.wat
https://cdn.xgqfrms.xyz/webassembly/imports-exports/simple-arg.wat
https://cdn.xgqfrms.xyz/webassembly/imports-exports/simple.wasm
https://cdn.xgqfrms.xyz/webassembly/imports-exports/simple-arg.wasm
wat2wasm
https://webassembly.github.io/wabt/demo/wat2wasm/
WebAssembly.Memory & ArrayBuffer
bytes 字节码
the unit of initial and maximum is WebAssembly pages which are fixed to be 64KB
.
// memory has an initial size of 10 pages, or `640KB` and a maximum size of `6400KB`, 即 `6.4MB`.
let memory = new WebAssembly.Memory({
initial: 10,
maximum:100,
});
// 赋值
// new Uint32Array(memory.buffer)[0] = 42;
const typedArray = new Uint32Array(memory.buffer);
typedArray[0] = 42;
// If a maximum is supplied upon creation attempts to grow past this maximum will throw a `RangeError` exception.
// pages + 1
memory.grow(1);
Just like functions, linear memories can be defined inside a module or imported. Similarly, a module may also optionally export its memory.
This means that JavaScript can get access to the memory of a WebAssembly instance either by creating a new WebAssembly.Memory and passing it in as an import or by receiving a Memory export.
就像函数一样,线性存储器可以在模块内部定义或导入。类似地,一个模块也可以选择导出它的内存。
这意味着 JavaScript 可以通过创建新的 WebAssembly.Memory 并将其作为导入或通过接收内存导出来访问 WebAssembly 实例的内存。
(module
;; 导出 memory, memo 线性存储器
(memory (export "mem") 1)
;; 导出 func, accumulate 积累/累加求和
(func (export "accumulate") (param $ptr i32) (param $length i32) …)
;; ... 省略了具体的方法体实现
;; (local.get($ptr))
;; (local.get($length))
)
// 获取 memo,转换成 TypedArray / ArrayBuffer
let i32ArrayBuffer = new Uint32Array(instance.exports.mem);
for (let i = 0; i < 10; i++) {
// 赋值, ??? memory 是引用类型
i32ArrayBuffer[i] = i;
}
// 传参数, 执行 accumulate
const sum = instance.exports.accumulate(0, 10);
// ???
// const {accumulate} = instance.exports;
Memory imports
are useful for two reasons:
- They allow JavaScript to fetch and create the initial contents of memory before or concurrent with module compilation.
- They allow a single Memory object to be imported by multiple instances, which is a critical building block for implementing dynamic linking in WebAssembly.
内存导入
很有用有两个原因:
- 它们允许 JavaScript 在模块编译之前或编译同时获取和创建内存的初始内容。
- 它们允许多个实例导入单个 Memory 对象,这是在 WebAssembly 中实现
动态链接
的关键构建块。
linear memory / arrayBuffer / TypedArray
https://webassembly.org/docs/semantics/#linear-memory
https://webassembly.org/docs/dynamic-linking
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
A TypedArray
object describes an array-like view
of an underlying binary data buffer
.
TypedArray 对象描述了底层二进制数据缓冲区
的类数组视图
。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
The ArrayBuffer
object is used to represent a generic, fixed-length raw binary data buffe
r.
ArrayBuffer 对象用于表示一个通用的、固定长度的原始二进制数据缓冲区
。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
refs
https://webassembly.org/getting-started/js-api/
https://developer.mozilla.org/zh-CN/docs/WebAssembly/Loading_and_running
©xgqfrms 2012-2025
www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!
原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/16663744.html
未经授权禁止转载,违者必究!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2021-09-07 Google 面试题 All In One
2020-09-07 Interview Questions All In One
2020-09-07 DNS & TXT recode & Google Search Console
2020-09-07 how to publish a dart package using Github Actions?
2020-09-07 Github Actions All In One
2019-09-07 Flutter & QRCode App
2018-09-07 Shape Detection API