use blitz_dom::NodeId;
use boa_engine::object::JsObject;
use boa_engine::{Context, Finalize, JsData, JsNativeError, JsResult, JsValue, Trace};
use boa_gc::GcRefCell;
use crate::dom::{define_method, dom_ctx, this_node_id};
#[derive(Trace, Finalize, JsData)]
pub struct MediaLoadRequest {
#[unsafe_ignore_trace]
pub node_id: NodeId,
pub element: JsObject,
}
#[derive(Trace, Finalize, JsData)]
struct MediaLoads {
pending: GcRefCell<Vec<MediaLoadRequest>>,
}
pub(crate) fn install(proto: &JsObject, context: &mut Context) {
context.insert_data(MediaLoads {
pending: GcRefCell::new(Vec::new()),
});
define_method(proto, "load", 0, load, context);
}
fn load(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
let node_id = this_node_id(this)?;
let ctx = dom_ctx(context)?;
let valid = ctx.doc.borrow().get_node(node_id).is_some_and(|node| {
node.element_data().is_some_and(|element| {
element.name.ns.as_ref() == "http://www.w3.org/1999/xhtml"
&& matches!(element.name.local.as_ref(), "audio" | "video")
})
});
if !valid {
return Err(JsNativeError::typ()
.with_message("Illegal HTMLMediaElement receiver")
.into());
}
let element = this.as_object().expect("validated media wrapper");
{
let loads = context
.get_data::<MediaLoads>()
.expect("media loads installed");
let mut pending = loads.pending.borrow_mut();
pending.retain(|request| request.node_id != node_id);
pending.push(MediaLoadRequest { node_id, element });
}
ctx.doc.borrow().shell_provider.request_redraw();
Ok(JsValue::undefined())
}
pub fn take_load_requests(context: &mut Context) -> Vec<MediaLoadRequest> {
let Some(loads) = context.get_data::<MediaLoads>() else {
return Vec::new();
};
std::mem::take(&mut *loads.pending.borrow_mut())
}