龙空技术网

javy:将 JavaScript 转化为 WebAssembly如此简单!

高级前端进阶 1775

前言:

而今姐妹们对“js 图片格式转换为文字”大致比较关心,你们都想要知道一些“js 图片格式转换为文字”的相关资讯。那么小编同时在网摘上网罗了一些有关“js 图片格式转换为文字””的相关知识,希望同学们能喜欢,看官们一起来了解一下吧!

大家好,很高兴又见面了,我是"高级前端‬进阶‬",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!

高级前端‬进阶

前言

本文主要和大家介绍将 JavaScript 转化为 WebAssembly的工具链 javy。在年初,我也确实使用 WebAssembly 将客户端应用成功移植到了 Web,这也是为什么我一直对 WebAssembly 充满好奇的原因。我甚至在头条上开了一个合集《WebAssembly 前沿技术》来专门探讨 WebAssembly ,并将持续关注 WebAssembly 的最新动态。

下面是已发布部分文章传送门:

《 2023 年让 WebAssembly 大火的 10+应用!》《 万字长文!2023 年 WebAssembly 各个运行时性能对比!》《 让 JavaScript 在 WebAssembly 上加速运行!》

正如大家所看到的,当我们还在迟疑是否要在日常开发中引入 WebAssembly 的时候,很多优秀的应用、工具已经开始吃 WebAssembly 的红利了,而且取得了不错的成就,这可能也是为什么各个浏览器厂商、开发者如此热衷 WebAssembly 的原因吧。

WebAssembly 中的 JavaScript 是最近技术圈发展的产物,但是将 JavaScript 编译成 WebAssembly 不同于使用 JavaScript 与 WebAssembly 模块通信。本文重点介绍如何获取 JavaScript 代码并将其构建到 WebAssembly 模块中。

话不多说,直接开始进入正题!

1.如何将 JavaScript 编译为 WebAssembly1.1 构建环境准备rustup稳定的 Rust 环境(rustup install stable && rustup default stable)wasm32-wasi,可以通过 rustup target add wasm32-wasi 安装cmake,根据操作系统和体系结构,默认情况下可能不会安装它。 在 Mac 上,可以通过 brew install cmake 与 homebrew 一起安装Rosetta 2 如果在 Apple Silicon 上运行 MacOS,可以通过 softwareupdate --install-rosetta 安装通过运行 make download-wasi-sdk 安装 wasi-sdk1.2 开发环境准备wasmtime-cli,可以通过 cargo install wasmtime-cli 安装(cargo-wasi 需要)cargo-wasi,可以通过 cargo install cargo-wasi安装 wizer,可以通过 cargo install wizer --all-features 安装1.3 开始使用 Javy

安装所有依赖项后运行 make,现在应该可以访问 target/release/javy 中的可执行文件。或者可以运行 make && cargo install --path crates/cli, 运行命令后,将获得可执行文件的全局安装。

Javy 底层基于 QuickJS, 用于在 WebAssembly 上运行 JavaScript 代码。 Javy 获取 JavaScript 代码,并在 WebAssembly 嵌入式 JavaScript 运行时中执行它。下面是官方对 Javy 的定位:

Javy: A JavaScript to WebAssembly toolchain

Javy 生成的模块仅设计为 WASI 并遵循命令模式, 任何输入都必须通过 stdin 传递,任何输出都将放在 stdout 中,这在从自定义嵌入调用 Javy 模块时尤为重要。

在像 Wasmtime 这样的运行时中,wasmtime-wasi 可用于设置输入和检索输出。比如下面的 JS 代码:

//从标准输入读取输入const input = readInput();//使用输入调用函数const result = foo(input);// 将结果写入标准输出writeOutput(result);// 入口函数function foo(input) {  return { foo: input.n + 1, newBar: input.bar + '!' };}// Read input from stdinfunction readInput() {  const chunkSize = 1024;  const inputChunks = [];  let totalBytes = 0;  //读取所有可用字节  while (1) {    const buffer = new Uint8Array(chunkSize);    // 标准输入文件描述符    const fd = 0;    const bytesRead = Javy.IO.readSync(fd, buffer);    totalBytes += bytesRead;    if (bytesRead === 0) {      break;    }    inputChunks.push(buffer.subarray(0, bytesRead));  }  // 将输入组装成单个 Uint8Array  const { finalBuffer } = inputChunks.reduce(    (context, chunk) => {      context.finalBuffer.set(chunk, context.bufferOffset);      context.bufferOffset += chunk.length;      return context;    },    { bufferOffset: 0, finalBuffer: new Uint8Array(totalBytes) }  );  return JSON.parse(new TextDecoder().decode(finalBuffer));}//将输出写入标准输出function writeOutput(output) {  const encodedOutput = new TextEncoder().encode(JSON.stringify(output));  const buffer = new Uint8Array(encodedOutput);  // 标准输出文件描述符  const fd = 1;  Javy.IO.writeSync(fd, buffer);}

通过以下方式从 JavaScript 创建 WebAssembly 二进制文件:

javy compile index.js -o destination/index.wasm

然后,可以使用 WebAssembly 引擎执行 WebAssembly 二进制文件:

$ echo '{ "n": 2, "bar": "baz" }' | wasmtime index.wasm{"foo":3,"newBar":"baz!"}%
2. 创建和使用动态链接模块

在某些情况下,开发者可能希望或需要使用 Javy 生成更小的 Wasm 模块。 在调用 Javy 时使用 -d 标志将创建一个动态链接模块,该模块的文件大小比静态链接模块小得多。 静态链接模块将 JS 引擎嵌入模块内部,而动态链接模块依赖 Wasm 导入来提供 JS 引擎。 动态链接模块有特殊要求,静态链接模块没有也不会在不满足这些要求的 WebAssembly 运行时中执行

要成功实例化和运行动态链接的 Javy 模块,执行环境必须提供一个 javy_quickjs_provider_v1 命名空间,用于导入该链接到 javy_quickjs_provider.wasm 模块提供的导出。 在不提供此导入的环境中无法实例化动态链接的模块。

动态链接的 Javy 模块与 QuickJS 绑定,因为它们使用 QuickJS 的字节码表示。

javy_quickjs_provider.wasm 模块在使用的 Javy 版本中作为资产提供,也可以通过运行 javy emit-provider -o <path> 将模块写入 <path> 来获取。

$ echo 'console.log("hello world!");' > my_code.js$ javy compile -d -o my_code.wasm my_code.js$ javy emit-provider -o provider.wasm$ wasmtime run --preload javy_quickjs_provider_v1=provider.wasm my_code.wasmhello world!
3.使用 quickjs-wasm-rs 构建自己的工具链

作为该项目一部分的 quickjs-wasm-rs crate 可以用作针对 Wasm 的 Rust crate 的一部分,以自定义 Rust crate 如何与 QuickJS 交互。

当尝试在 Wasm 模块中使用 JavaScript 而 Javy 不满足您的需求时,这可能很有用,因为 quickjs-wasm-rs 包含序列化程序,可以更轻松地在主机代码和 Wasm 代码之间发送结构化数据(例如,字符串或对象)。

4.其他相关讨论《知乎:JavaScript 能不能编译成 WebAssembly ?》《使用 Javy 和 msgpack-tools 将 JavaScript 编译为 WebAssembly》《让 JavaScript 在 WebAssembly 上加速运行!》5.本文总结

本文主要和大家介绍将 JavaScript 转化为 WebAssembly的工具链 javy。因为篇幅有限,文章并没有过多展开,如果有兴趣,可以在我的主页继续阅读,同时文末的参考资料提供了大量优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏!

参考资料

封面图:Navdeep Singh Gill | 13 October 2022的《WebAssembly vs JavaScript | The Ultimate Guide》

标签: #js 图片格式转换为文字