use std::sync::{Arc, Mutex}; use crate::{Runtime, ScriptingError}; /// A struct that represents a function that will get called when the Promise is resolved. pub(crate) struct PromiseCallback { callback: V, following_promise: Arc>>, } /// Internal representation of a Promise. pub(crate) struct PromiseInner { pub(crate) callbacks: Vec>, #[allow(deprecated)] pub(crate) context: C, } /// A struct that represents a Promise. #[derive(Clone)] pub struct Promise { pub(crate) inner: Arc>>, } impl PromiseInner { /// Resolve the Promise. This will call all the callbacks that were added to the Promise. fn resolve(&mut self, runtime: &mut R, val: R::Value) -> Result<(), ScriptingError> where R: Runtime, { for callback in &self.callbacks { let next_val = runtime.call_fn_from_value(&callback.callback, &self.context, vec![val.clone()])?; callback .following_promise .lock() .expect("Failed to lock promise mutex") .resolve(runtime, next_val)?; } Ok(()) } } impl Promise { /// Acquire [Mutex] for writing the promise and resolve it. Call will be forwarded to [PromiseInner::resolve]. pub(crate) fn resolve( &mut self, runtime: &mut R, val: R::Value, ) -> Result<(), ScriptingError> where R: Runtime, { if let Ok(mut inner) = self.inner.lock() { inner.resolve(runtime, val)?; } Ok(()) } /// Register a callback that will be called when the [Promise] is resolved. #[cfg(any(feature = "rhai", feature = "lua"))] pub(crate) fn then(&mut self, callback: V) -> Self { let mut inner = self .inner .lock() .expect("Failed to lock inner promise mutex"); let following_inner = Arc::new(Mutex::new(PromiseInner { callbacks: vec![], context: inner.context.clone(), })); inner.callbacks.push(PromiseCallback { following_promise: following_inner.clone(), callback, }); Promise { inner: following_inner, } } }