use crate::jsutils::helper_tasks::{add_helper_task, add_helper_task_async};
use crate::jsutils::JsError;
use crate::quickjs_utils::promises::QuickJsPromiseAdapter;
use crate::quickjsrealmadapter::QuickJsRealmAdapter;
use crate::quickjsvalueadapter::QuickJsValueAdapter;
use futures::Future;
#[allow(clippy::type_complexity)]
pub fn new_resolving_promise<P, R, M>(
realm: &QuickJsRealmAdapter,
producer: P,
mapper: M,
) -> Result<QuickJsValueAdapter, JsError>
where
R: Send + 'static,
P: FnOnce() -> Result<R, JsError> + Send + 'static,
M: FnOnce(&QuickJsRealmAdapter, R) -> Result<QuickJsValueAdapter, JsError> + Send + 'static,
{
let promise_ref = realm.create_promise()?;
let return_ref = promise_ref.js_promise_get_value(realm);
let id = realm.cache_promise(promise_ref);
let rti_ref = realm.get_runtime_facade_inner();
let realm_id = realm.get_realm_id().to_string();
add_helper_task(move || {
let produced_result = producer();
if let Some(rti) = rti_ref.upgrade() {
rti.add_rt_task_to_event_loop_void(move |rt| {
if let Some(realm) = rt.get_realm(realm_id.as_str()) {
let prom_ref_opt: Option<QuickJsPromiseAdapter> =
realm.consume_cached_promise(id);
if let Some(prom_ref) = prom_ref_opt {
match produced_result {
Ok(ok_res) => {
let raw_res = mapper(realm, ok_res);
match raw_res {
Ok(val_ref) => {
if let Err(e) = prom_ref.js_promise_resolve(realm, &val_ref)
{
log::error!(
"[{}] could not resolve promise5: {}",
realm.get_realm_id(),
e
);
}
}
Err(err) => {
let err_ref = realm
.create_error(
err.get_name(),
err.get_message(),
err.get_stack(),
)
.expect("could not create error");
if let Err(e) = prom_ref.js_promise_reject(realm, &err_ref)
{
log::error!(
"[{}] could not reject promise4: {}",
realm.get_realm_id(),
e
);
}
}
}
}
Err(err) => {
let err_ref = realm
.create_error(
err.get_name(),
err.get_message(),
err.get_stack(),
)
.expect("could not create error");
if let Err(e) = prom_ref.js_promise_reject(realm, &err_ref) {
log::error!(
"[{}] could not reject promise3: {}",
realm.get_realm_id(),
e
);
}
}
}
} else {
log::error!(
"async promise running for dropped realm: {} promise_id:{}",
realm_id,
id
);
}
} else {
log::error!("async promise running for dropped realm: {}", realm_id);
}
});
} else {
log::error!("async promise running for dropped runtime");
}
});
Ok(return_ref)
}
#[allow(clippy::type_complexity)]
pub(crate) fn new_resolving_promise_async<P, R, M>(
realm: &QuickJsRealmAdapter,
producer: P,
mapper: M,
) -> Result<QuickJsValueAdapter, JsError>
where
R: Send + 'static,
P: Future<Output = Result<R, JsError>> + Send + 'static,
M: FnOnce(&QuickJsRealmAdapter, R) -> Result<QuickJsValueAdapter, JsError> + Send + 'static,
{
let promise_ref = realm.create_promise()?;
let return_ref = promise_ref.js_promise_get_value(realm);
let id = realm.cache_promise(promise_ref);
let rti_ref = realm.get_runtime_facade_inner();
let realm_id = realm.get_realm_id().to_string();
let _ignore_result = add_helper_task_async(async move {
let produced_result = producer.await;
if let Some(rti) = rti_ref.upgrade() {
rti.add_rt_task_to_event_loop_void(move |rt| {
if let Some(realm) = rt.get_realm(realm_id.as_str()) {
let prom_ref_opt: Option<QuickJsPromiseAdapter> =
realm.consume_cached_promise(id);
if let Some(prom_ref) = prom_ref_opt {
match produced_result {
Ok(ok_res) => {
let raw_res = mapper(realm, ok_res);
match raw_res {
Ok(val_ref) => {
if let Err(e) = prom_ref.js_promise_resolve(realm, &val_ref)
{
log::error!(
"[{}] could not resolve promise: {}",
realm.get_realm_id(),
e
);
}
}
Err(err) => {
let err_ref = realm
.create_error(
err.get_name(),
err.get_message(),
err.get_stack(),
)
.expect("could not create err");
if let Err(e) = prom_ref.js_promise_reject(realm, &err_ref)
{
log::error!(
"[{}] could not reject promise: {}",
realm.get_realm_id(),
e
);
}
}
}
}
Err(err) => {
let err_ref = realm
.create_error(
err.get_name(),
err.get_message(),
err.get_stack(),
)
.expect("could not create str");
if let Err(e) = prom_ref.js_promise_reject(realm, &err_ref) {
log::error!(
"[{}] could not reject promise2: {}",
realm.get_realm_id(),
e
);
}
}
}
} else {
log::error!(
"async promise running on dropped realm: {} promise_id:{}",
realm_id,
id
);
}
} else {
log::error!("async promise running on dropped realm: {}", realm_id);
}
});
} else {
log::error!("async promise running on dropped runtime");
}
});
Ok(return_ref)
}