use std::task::Poll;
use super::BrowserJsRuntime;
const MODULE_BUDGET: tokio::time::Duration = tokio::time::Duration::from_secs(10);
impl BrowserJsRuntime {
pub async fn load_module(&mut self, url: &str) -> Result<(), String> {
let specifier =
deno_core::ModuleSpecifier::parse(url).map_err(|e| format!("Invalid module URL {}: {}", url, e))?;
let module_id = tokio::time::timeout(MODULE_BUDGET, self.runtime.load_side_es_module(&specifier))
.await
.map_err(|_| format!("Module load timed out after {:?}", MODULE_BUDGET))?
.map_err(|e| format!("Module load error: {}", e))?;
self.evaluate_module(module_id, url).await
}
pub async fn load_inline_module(&mut self, code: &str, base_url: &str) -> Result<(), String> {
let specifier =
deno_core::ModuleSpecifier::parse(&format!("{}#inline-module-{}", base_url, self.object_counter))
.unwrap_or_else(|_| deno_core::ModuleSpecifier::parse("about:blank").unwrap());
self.object_counter += 1;
let module_id = tokio::time::timeout(
MODULE_BUDGET,
self.runtime
.load_side_es_module_from_code(&specifier, deno_core::ModuleCodeString::from(code.to_string())),
)
.await
.map_err(|_| format!("Inline module load timed out after {:?}", MODULE_BUDGET))?
.map_err(|e| format!("Inline module load error: {}", e))?;
self.evaluate_module(module_id, "inline module").await
}
async fn evaluate_module(&mut self, module_id: deno_core::ModuleId, name: &str) -> Result<(), String> {
let evaluation = self.runtime.mod_evaluate(module_id);
let waited = self.run_until_settled(evaluation, MODULE_BUDGET, name).await;
let options = deno_core::PollEventLoopOptions::default();
match waited {
Ok(Ok(())) => std::future::poll_fn(|cx| match self.runtime.poll_event_loop(cx, options) {
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
_ => Poll::Ready(Ok(())),
})
.await
.map_err(|e| format!("Module evaluation error: {}", e)),
Ok(Err(e)) => Err(format!("Module evaluation error: {}", e)),
Err(_) => {
tracing::warn!("Module evaluation timed out after {:?}: {}", MODULE_BUDGET, name);
Ok(())
}
}
}
}