1use blitz_dom::NodeId;
4use boa_engine::object::JsObject;
5use boa_engine::{Context, Finalize, JsData, JsNativeError, JsResult, JsValue, Trace};
6use boa_gc::GcRefCell;
7
8use crate::dom::{define_method, dom_ctx, this_node_id};
9
10#[derive(Trace, Finalize, JsData)]
12pub struct MediaLoadRequest {
13 #[unsafe_ignore_trace]
14 pub node_id: NodeId,
15 pub element: JsObject,
16}
17
18#[derive(Trace, Finalize, JsData)]
19struct MediaLoads {
20 pending: GcRefCell<Vec<MediaLoadRequest>>,
21}
22
23pub(crate) fn install(proto: &JsObject, context: &mut Context) {
24 context.insert_data(MediaLoads {
25 pending: GcRefCell::new(Vec::new()),
26 });
27 define_method(proto, "load", 0, load, context);
28}
29
30fn load(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
31 let node_id = this_node_id(this)?;
32 let ctx = dom_ctx(context)?;
33 let valid = ctx.doc.borrow().get_node(node_id).is_some_and(|node| {
34 node.element_data().is_some_and(|element| {
35 element.name.ns.as_ref() == "http://www.w3.org/1999/xhtml"
36 && matches!(element.name.local.as_ref(), "audio" | "video")
37 })
38 });
39 if !valid {
40 return Err(JsNativeError::typ()
41 .with_message("Illegal HTMLMediaElement receiver")
42 .into());
43 }
44 let element = this.as_object().expect("validated media wrapper");
45 {
46 let loads = context
47 .get_data::<MediaLoads>()
48 .expect("media loads installed");
49 let mut pending = loads.pending.borrow_mut();
50 pending.retain(|request| request.node_id != node_id);
51 pending.push(MediaLoadRequest { node_id, element });
52 }
53 ctx.doc.borrow().shell_provider.request_redraw();
54 Ok(JsValue::undefined())
55}
56
57pub fn take_load_requests(context: &mut Context) -> Vec<MediaLoadRequest> {
62 let Some(loads) = context.get_data::<MediaLoads>() else {
63 return Vec::new();
64 };
65 std::mem::take(&mut *loads.pending.borrow_mut())
66}