1#![deny(unsafe_code)]
3
4use std::error::Error;
5
6pub use v8;
8
9use v8::{
10 Context, ContextScope, CreateParams, HandleScope, Isolate, Local, OwnedIsolate, Script, Value,
11 V8,
12};
13
14mod err;
15
16pub use err::E;
17
18fn 初始化_v8() {
20 let 平台 = v8::new_default_platform(0, false).make_shared();
21 V8::initialize_platform(平台);
22 V8::initialize();
23}
24
25fn 创建实例() -> OwnedIsolate {
27 Isolate::new(CreateParams::default())
28}
29
30fn 编译_js<'a>(
32 范围: &mut HandleScope<'a>,
33 代码: &str,
34) -> Result<Local<'a, Script>, Box<dyn Error>> {
35 let 代码 = v8::String::new(范围, 代码).ok_or(E("v8 String::new".into()))?;
37 let 脚本 = Script::compile(范围, 代码, None).ok_or(E("v8 Script::compile".into()))?;
39
40 Ok(脚本)
41}
42
43#[derive(Debug)]
45pub struct Vm {
46 隔离: OwnedIsolate,
47}
48
49impl Vm {
50 pub fn new() -> Self {
52 初始化_v8();
53 let 隔离 = 创建实例();
54
55 Self { 隔离 }
56 }
57
58 fn run_js<T, F>(&mut self, code: &str, f: F) -> Result<T, Box<dyn Error>>
60 where
61 F: FnOnce(&mut ContextScope<HandleScope>, Option<Local<Value>>) -> T,
62 {
63 let mut 柄范围 = HandleScope::new(&mut self.隔离);
66 let 语境 = Context::new(&mut 柄范围, Default::default());
67 let mut 范围 = ContextScope::new(&mut 柄范围, 语境);
68
69 let 脚本 = 编译_js(&mut 范围, code)?;
70 let 结果 = 脚本.run(&mut 范围);
71
72 let o = f(&mut 范围, 结果);
73 Ok(o)
74 }
75
76 pub fn run_r<T, F>(&mut self, code: &str, f: F) -> Result<T, Box<dyn Error>>
78 where
79 F: FnOnce(&mut ContextScope<HandleScope>, Option<Local<Value>>) -> T,
80 {
81 self.run_js(code, f)
82 }
83
84 pub fn run(&mut self, code: &str) -> Result<(), Box<dyn Error>> {
86 self.run_js(code, |_, _| ())?;
87 Ok(())
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn it_works() {
97 let mut vm = Vm::new();
98 let r = vm
99 .run_r(
100 "1 + 2",
101 |s: &mut ContextScope<HandleScope>, v: Option<Local<Value>>| {
102 v.unwrap().uint32_value(s)
103 },
104 )
105 .unwrap();
106 assert_eq!(r, Some(3));
107 }
108}