1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use std::collections::HashMap;
use anyhow::{anyhow, Error, Result};
use v8::{self, Global, HandleScope, Local, PromiseResolver, Value};
use super::machine::Handle;
pub struct Promises {
counter: u64,
handle: Handle,
pending: HashMap<u64, Global<PromiseResolver>>,
}
pub enum Promise {
Success(u64, Box<dyn Resolved>),
Failure(u64, Box<dyn Resolved>),
}
pub struct Resolver {
id: u64,
tx: Handle,
}
pub trait Resolved: Send + 'static {
fn value<'s>(self: Box<Self>, scope: &mut HandleScope<'s>) -> Result<Local<'s, Value>>;
}
impl Promises {
pub fn new(handle: Handle) -> Self {
Self {
counter: 0,
handle: handle,
pending: HashMap::new(),
}
}
pub fn insert(local: Local<v8::Value>, resolver: Global<PromiseResolver>) -> Result<Resolver> {
let promises = Self::get(local)?;
let id = promises.counter;
let tx = promises.handle.clone();
promises.counter += 1;
promises.pending.insert(id, resolver);
Ok(Resolver { id, tx })
}
pub fn settle(local: Local<Value>, scope: &mut HandleScope, promise: Promise) -> Result<()> {
enum Value<'s> {
Success(Local<'s, v8::Value>),
Failure(Local<'s, v8::Value>),
}
let (id, value) = match promise {
Promise::Success(id, v) => (id, Value::Success(v.value(scope)?)),
Promise::Failure(id, v) => (id, Value::Failure(v.value(scope)?)),
};
if let Some(resolver) = Self::get(local)?.pending.remove(&id) {
let resolver = Local::new(scope, resolver);
match value {
Value::Success(v) => resolver.resolve(scope, v),
Value::Failure(v) => resolver.reject(scope, v),
};
}
Ok(())
}
fn get(local: Local<v8::Value>) -> Result<&mut Promises> {
let promises = Local::<v8::External>::try_from(local)?;
let promises = promises.value() as *mut Self;
Ok(unsafe { &mut *promises })
}
}
impl Resolver {
pub fn resolve(self, value: Box<dyn Resolved>) -> Result<()> {
match self.tx.done(Promise::Success(self.id, value)) {
Ok(()) => Ok(()),
Err(_) => Err(anyhow!("channel closed")),
}
}
pub fn reject(self, value: Box<dyn Resolved>) -> Result<()> {
match self.tx.done(Promise::Failure(self.id, value)) {
Ok(()) => Ok(()),
Err(_) => Err(anyhow!("channel closed")),
}
}
}
impl Resolved for Error {
fn value<'s>(self: Box<Self>, scope: &mut HandleScope<'s>) -> Result<Local<'s, Value>> {
let context = scope.get_current_context();
let global = context.global(scope);
let cause = format!("{self:?}");
let cause = v8::String::new(scope, &cause).unwrap();
let name = v8::String::new(scope, "Error").unwrap();
let ctor = global.get(scope, name.into()).unwrap();
let ctor = v8::Local::<v8::Function>::try_from(ctor)?;
let args = &[cause.into()];
Ok(ctor.new_instance(scope, args).unwrap().into())
}
}
impl Resolved for serde_json::Value {
fn value<'s>(self: Box<Self>, scope: &mut HandleScope<'s>) -> Result<Local<'s, Value>> {
Ok(serde_v8::to_v8(scope, self)?)
}
}