#javascript #js #standalone #script #plugin #sandbox #plugin-system

js-sandbox-ios

在安全的沙箱中执行 JavaScript 代码,并将数据在 JS 插件之间传输

2 个版本

0.1.1 2024 年 6 月 14 日
0.1.0 2024 年 3 月 22 日

#1884Web 编程

Download history 86/week @ 2024-05-03 93/week @ 2024-05-10 181/week @ 2024-05-17 82/week @ 2024-05-24 79/week @ 2024-05-31 62/week @ 2024-06-07 241/week @ 2024-06-14 96/week @ 2024-06-21 119/week @ 2024-06-28 20/week @ 2024-07-05 57/week @ 2024-07-12 44/week @ 2024-07-19 70/week @ 2024-07-26 45/week @ 2024-08-02 29/week @ 2024-08-09 69/week @ 2024-08-16

每月 221 次下载
用于 integrationos-domain

Zlib 许可证

29KB
407

js-sandbox-ios

crates.io docs.rs

js-sandbox 是一个 Rust 库,用于在安全的沙箱中从 Rust 执行 JavaScript 代码。它基于 Deno 项目,并使用 serde_json 进行序列化。

此库的主要重点是 将 JS 作为脚本语言嵌入 Rust 中。它不提供两种语言之间所有可能的集成,也不针对 JS 作为 Web 的客户端/服务器端语言的最大领域进行优化。

相反,js-sandbox 专注于从 Rust 调用独立的 JS 代码,并尽可能保持简单。典型用例是一个核心 Rust 应用程序,它集成了来自外部用户的脚本,例如插件系统或运行外部模组的游戏。

此库处于早期开发阶段,API 基本但功能强大。API 可能还会发生相当大的变化。

示例

从 JavaScript 打印

《你好,世界》示例 - 使用 JavaScript 打印内容 - 只有一行,应该是这样的

fn main() {
    js_sandbox_ios::eval_json("console.log('Hello Rust from JS')").expect("JS runs");
}

调用 JS 函数

一个非常基础的程序从 Rust 调用 JavaScript 函数 sub()。它传递一个参数并接受一个返回值,两者都通过 JSON 进行序列化

use js_sandbox_ios::{Script, AnyError};

fn main() -> Result<(), AnyError> {
    let js_code = "function sub(a, b) { return a - b; }";
    let mut script = Script::from_string(js_code)?;

    let result: i32 = script.call("sub", (7, 5))?;

    assert_eq!(result, 2);
    Ok(())
}

一个示例,它序列化一个 JSON 对象(Rust -> JS)并格式化一个字符串(JS -> Rust)

use js_sandbox_ios::{Script, AnyError};
use serde::Serialize;

#[derive(Serialize)]
struct Person {
    name: String,
    age: u8,
}

fn main() -> Result<(), AnyError> {
    let src = r#"
        function toString(person) {
            return "A person named " + person.name + " of age " + person.age;
        }"#;

    let mut script = Script::from_string(src)?;

    let person = Person { name: "Roger".to_string(), age: 42 };
    let result: String = script.call("toString", (person,))?;

    assert_eq!(result, "A person named Roger of age 42");
    Ok(())
}

加载 JS 文件

可以在运行时从任何 Path 加载 JavaScript 文件(例如第三方模组)。

如果您想将 UTF-8 编码的文件静态嵌入 Rust 可执行文件中,您还可以使用 std::include_str 宏。

use js_sandbox_ios::Script;

fn main() {
    // (1) at runtime:
    let mut script = Script::from_file("script.js").expect("load + init succeeds");

    // (2) at compile time:
    let code: &'static str = include_str!("script.js");
    let mut script = Script::from_string(code).expect("init succeeds");

    // use script as usual
}

在 JavaScript 中维护状态

可以初始化一个有状态的JS脚本,然后使用函数在一段时间内修改该状态。此示例在两次调用中追加一个字符串,然后在第三次调用中获取结果。

use js_sandbox_ios::{Script, AnyError};

fn main() -> Result<(), AnyError> {
    let src = r#"
        var total = '';
        function append(str) { total += str; }
        function get()       { return total; }"#;

    let mut script = Script::from_string(src)?;

    let _: () = script.call("append", ("hello",))?;
    let _: () = script.call("append", (" world",))?;
    let result: String = script.call("get", ())?;

    assert_eq!(result, "hello world");
    Ok(())
}

带超时调用脚本

JS代码可能包含长时间或永久运行的循环,这会阻塞Rust代码。可以在设置超时后终止JavaScript执行。

use js_sandbox_ios::{Script, JsError};

fn main() -> Result<(), JsError> {
    use std::time::Duration;
    let js_code = "function run_forever() { for(;;) {} }";
    let mut script = Script::from_string(js_code)?
        .with_timeout(Duration::from_millis(1000));

    let result: Result<String, JsError> = script.call("run_forever", ());

    assert_eq!(
        result.unwrap_err().to_string(),
        "Uncaught Error: execution terminated".to_string()
    );

    Ok(())
}

依赖项

~81MB
~1.5M SLoC