///|
/// Scheduler Integration - Executes ExecuteScript tasks from scheduler
///
/// Bridges the JS runtime with the browser's task scheduler.
///|
/// Script executor that runs in the scheduler event loop
pub struct ScriptExecutor {
/// DOM tree for script execution
dom : @dom.DomTree
/// JS context (reused across executions)
ctx : JsContext
}
///|
/// Create a new script executor
pub fn ScriptExecutor::new(dom : @dom.DomTree) -> ScriptExecutor {
{ dom, ctx: JsContext::new(dom) }
}
///|
pub fn ScriptExecutor::new_deferred(dom : @dom.DomTree) -> ScriptExecutor {
{ dom, ctx: JsContext::new_deferred(dom) }
}
///|
/// Create a script executor with explicit JS runtime implementation.
pub fn ScriptExecutor::new_with_runtime(
dom : @dom.DomTree,
runtime : &JsRuntime,
) -> ScriptExecutor {
{
dom,
ctx: JsContext::new_with_runtime_and_mode(dom, runtime, DeferredFlush),
}
}
///|
/// Get accumulated logs from the JS context
pub fn ScriptExecutor::get_logs(self : ScriptExecutor) -> Array[String] {
self.ctx.get_logs()
}
///|
/// Clear accumulated logs
pub fn ScriptExecutor::clear_logs(self : ScriptExecutor) -> Unit {
self.ctx.clear_logs()
}
///|
/// Execute inline JavaScript source immediately against the current DOM.
pub fn ScriptExecutor::execute_source(
self : ScriptExecutor,
source : String,
) -> JsResult raise JsError {
self.ctx.execute(source)
}
///|
pub fn ScriptExecutor::tick(self : ScriptExecutor) -> Bool raise JsError {
self.ctx.tick()
}
///|
/// Enqueue a script for execution
pub fn enqueue_script(
scheduler : @scheduler.Scheduler,
source : String,
blocking : Bool,
) -> @scheduler.TaskId {
let constraint = if blocking {
// Parser-blocking script blocks DOM parsing
@scheduler.Blocking([@scheduler.DOM])
} else {
@scheduler.MainThreadOnly
}
// Async/defer script runs on main thread but doesn't block
scheduler.enqueue(@scheduler.ExecuteScript(source~), constraint)
}
///|
/// Enqueue a script with dependencies
pub fn enqueue_script_after(
scheduler : @scheduler.Scheduler,
source : String,
dependencies : Array[@scheduler.TaskId],
blocking : Bool,
) -> @scheduler.TaskId {
let constraint = if blocking {
@scheduler.Blocking([@scheduler.DOM])
} else {
@scheduler.MainThreadOnly
}
scheduler.enqueue_after(
@scheduler.ExecuteScript(source~),
constraint,
dependencies,
)
}