2 个版本
0.1.1 | 2024 年 6 月 14 日 |
---|---|
0.1.0 | 2024 年 3 月 22 日 |
#1884 在 Web 编程
每月 221 次下载
用于 integrationos-domain
29KB
407 行
js-sandbox-ios
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