Promises, promises
This commit is contained in:
parent
17fdee51e6
commit
a2dafeea12
6 changed files with 303 additions and 102 deletions
|
|
@ -1,34 +1,69 @@
|
|||
use crate::{ContextRef, Value, ValueRef};
|
||||
use crate::{ContextRef, ValueResult};
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::mpsc::Sender;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Eq, PartialEq, Hash, Debug, Clone, Copy)]
|
||||
pub(crate) struct PromiseHandle(u64);
|
||||
|
||||
impl PromiseHandle {
|
||||
pub fn new() -> Self {
|
||||
static NEXT_ID: AtomicU64 = AtomicU64::new(0);
|
||||
PromiseHandle(NEXT_ID.fetch_add(1, Ordering::SeqCst))
|
||||
}
|
||||
}
|
||||
|
||||
pub type PromiseResult = Box<dyn Fn(&ContextRef) -> ValueResult + Send + 'static>;
|
||||
|
||||
pub(crate) enum PromiseEvent {
|
||||
Resolved(PromiseResult),
|
||||
Rejected(PromiseResult),
|
||||
}
|
||||
|
||||
/// A Promise is a small, thread-safe marker which represents a pending
|
||||
/// promise inside the JS runtime. This is how you complete the promise: you
|
||||
/// must either call `resolve` or `reject` before you drop the promise.
|
||||
#[derive(Debug)]
|
||||
pub struct Promise {
|
||||
pub object: Value,
|
||||
pub resolve_fn: Value,
|
||||
pub reject_fn: Value,
|
||||
complete: bool,
|
||||
handle: PromiseHandle,
|
||||
channel: Sender<(PromiseHandle, PromiseEvent)>,
|
||||
}
|
||||
|
||||
impl Promise {
|
||||
pub(crate) fn new(object: Value, resolve_fn: Value, reject_fn: Value) -> Self {
|
||||
pub(crate) fn new(
|
||||
handle: PromiseHandle,
|
||||
channel: Sender<(PromiseHandle, PromiseEvent)>,
|
||||
) -> Self {
|
||||
Promise {
|
||||
object,
|
||||
resolve_fn,
|
||||
reject_fn,
|
||||
complete: false,
|
||||
handle,
|
||||
channel,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dup(&self, ctx: &ContextRef) -> Self {
|
||||
Promise {
|
||||
object: self.object.dup(ctx),
|
||||
resolve_fn: self.resolve_fn.dup(ctx),
|
||||
reject_fn: self.reject_fn.dup(ctx),
|
||||
}
|
||||
pub fn resolve<T>(mut self, value: T)
|
||||
where
|
||||
T: Fn(&ContextRef) -> ValueResult + Send + 'static,
|
||||
{
|
||||
let _ = self
|
||||
.channel
|
||||
.send((self.handle, PromiseEvent::Resolved(Box::new(value))));
|
||||
self.complete = true;
|
||||
}
|
||||
|
||||
pub fn resolve(self, context: &ContextRef, value: &ValueRef) {
|
||||
let _ = self.resolve_fn.call(context, &[value]);
|
||||
}
|
||||
|
||||
pub fn reject(self, context: &ContextRef, value: &ValueRef) {
|
||||
let _ = self.reject_fn.call(context, &[value]);
|
||||
pub fn reject<T>(mut self, value: T)
|
||||
where
|
||||
T: Fn(&ContextRef) -> ValueResult + Send + 'static,
|
||||
{
|
||||
let _ = self
|
||||
.channel
|
||||
.send((self.handle, PromiseEvent::Rejected(Box::new(value))));
|
||||
self.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Promise {
|
||||
fn drop(&mut self) {
|
||||
assert!(self.complete);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue