• ion引擎-让你在Rust中轻松嵌入和执行JS 代码
  • 发布于 1天前
  • 76 热度
    0 评论
引言:Rust 和 JavaScript,谁说不能在一起?
在当今的技术圈里,Rust 和 JavaScript 算得上是“技术界的金童玉女”。Rust 以高性能、内存安全著称,而 JavaScript 则是前端霸主、后端常客,几乎无处不在。那么问题来了:我们能不能让 Rust 程序也“运行” JavaScript?今天要介绍的这个项目 —— ion。 GitHub 地址: https://github.com/alshdavid/ion,就是这样一个“桥梁”:它是一个基于 Rust 的 JavaScript 运行时,让你在 Rust 中轻松嵌入和执行 JS 代码,简直是“Rust 里跑 JS,稳如老狗”。

接下来,我们就一起来看看,ion 到底有什么“魔法”!

一、ion 是什么?
ion 是一个专为 Rust 设计的 JavaScript 运行时,它的目标非常明确:让你在 Rust 中轻松集成 JS 引擎,比如用于插件系统、SSR(服务端渲染)、FaaS(函数即服务)等场景。
它的口号是:“A JavaScript Runtime for Rust”,简单直接,不绕弯子。
主要特性:
✅ 高层 API 设计简洁易用(灵感来自 napi-rs)
✅ 基于 Tokio 的事件循环
✅ 支持多线程
✅ 支持异步操作
✅ 可扩展的标准库接口(setTimeout、fs、fetch 等)

✅ 支持 ES Module、TypeScript、Node.js 模块解析等高级功能


二、为什么需要 ion?Node.js、Deno、Bun 不香了吗?
你可能会问:既然有 Node.js、Deno、Bun 这些成熟的 JS 运行时,为什么还要搞一个 ion?这个问题问得好!作者也在 README 中解释了为什么 ion 是一个更好的选择:
1. Node.js:太重、太难嵌入
虽然 Node.js 功能强大,但它并不适合嵌入到 Rust 中使用:
Node.js 不能静态编译,必须动态链接(libnode.dylib 等)
分发困难,依赖复杂

官方没有提供 C FFI 接口(虽然 PR 正在进行中)


2. Deno:API 太复杂、标准库耦合严重
Deno 是用 Rust 写的,理论上更适合嵌入,但它的用户层 API 非常复杂:
标准库和 CLI 耦合严重,想复用标准库必须 fork deno_cli

对于想在 Rust 中构建 JS 运行时的开发者来说,体验并不好


3. Bun:压根就不支持嵌入
Bun 虽然快,但它压根就没考虑嵌入式使用,所以直接排除。

三、ion 的核心设计哲学:模块化 + 可扩展
ion 的设计理念非常清晰:分层 + 可组合。它将运行时拆分为多个可插拔的模块,让开发者可以根据需求灵活定制。
核心组件:
JavaScript 引擎:使用 V8(Google 的高性能 JS 引擎)
事件循环:基于 Tokio 构建,支持异步
模块解析器:支持自定义模块解析逻辑(比如 Node.js 的 require、ESM 的 import)
扩展机制:允许添加自定义 JS 模块或全局函数(如 setTimeout、fetch 等)
预处理器:支持 TypeScript、JSX 等非原生 JS 文件的转换
ion 的结构层次:
核心运行时(Core Runtime):包含 JS 引擎、事件循环、Worker 支持等

用户层 API(Userland API):提供扩展机制,方便构建完整的运行时


四、实战演示:在 Rust 中运行 JS 是种什么体验?
ion 提供了丰富的 API,下面我们来看几个简单的例子。
1. 基础使用:执行 JS 表达式
use ion::*;

pubfn main() -> anyhow::Result<()> {
    let runtime = JsRuntime::initialize_once()?;
    let worker = runtime.spawn_worker()?;
    let ctx = worker.create_context()?;

    ctx.exec_blocking(|env| {
        let value = env.eval_script::<JsNumber>("1 + 1")?;
        let result = value.get_u32()?;
        println!("Returned: {}", result); // 输出:2
        Ok(())
    })?;
    Ok(())
}
2. 异步执行 JS
use ion::*;

pubfn main() -> anyhow::Result<()> {
    let runtime = JsRuntime::initialize_once()?;
    let worker = runtime.spawn_worker()?;
    let ctx = worker.create_context()?;

    ctx.exec_blocking(|env| {
        env.spawn_local({
            let env = env.clone();
            asyncmove {
                println!("Async Task Started");
                let value = env.eval_script::<JsNumber>("1 + 1")?;
                tokio::time::sleep(tokio::time::Duration::from_millis(1000)).await;
                println!("Async Task Returned: {}", value.get_u32()?);
                Ok(())
            }
        })?;

        Ok(())
    })?;

    Ok(())
}
3. 多线程调用 JS 函数
use ion::*;

pubfn main() -> anyhow::Result<()> {
    let runtime = JsRuntime::initialize_once()?;
    let worker = runtime.spawn_worker()?;
    let ctx = worker.create_context()?;
     // 堆代码 duidaima.com
    ctx.eval_script("globalThis.add = (a, b) => a + b")?;

    ctx.exec_blocking(|env| {
        let global_this = env.global_this()?;
        let function = global_this.get_named_property_unchecked::<JsFunction>("add")?;
        let tsfn = ThreadSafeFunction::new(&function)?;

        std::thread::spawn(move || {
            let ret: u32 = tsfn
                .call_blocking(
                    |env| Ok((1, 1)),
                    |env, ret| ret.cast::<JsNumber>()?.get_u32(),
                )
                .unwrap();

            println!("JavaScript function returned: {}", ret); // 输出:2
        });

        Ok(())
    })?;

    Ok(())
}
五、ion 的未来展望
ion 目前还在早期阶段(2025 年 8 月创建),但它已经展现出了强大的潜力。作者计划:
提供 C FFI 接口,让其他语言也能嵌入 ion
更好的 TypeScript 支持
更丰富的标准库扩展

支持 WASI 等新兴标准


六、结语:ion,不只是一个 JS 运行时,更是一个桥梁
ion 的出现,标志着 Rust 和 JavaScript 的融合进入了一个新阶段。它不仅是一个运行时,更是一个可扩展、可定制、可嵌入的 JS 引擎平台。对于希望在 Rust 中嵌入 JS 的开发者来说,ion 提供了一个轻量、高效、模块化的解决方案。如果你正在寻找一个可以在 Rust 中安全运行 JS 的工具,不妨试试 ion。
用户评论