1use dom_struct::dom_struct;
6use js::jsapi::Heap;
7use js::jsval::JSVal;
8use js::rust::{HandleObject, HandleValue, MutableHandleValue};
9use stylo_atoms::Atom;
10
11use crate::dom::bindings::codegen::Bindings::ExtendableEventBinding::ExtendableEvent_Binding::ExtendableEventMethods;
12use crate::dom::bindings::codegen::Bindings::ExtendableMessageEventBinding;
13use crate::dom::bindings::codegen::Bindings::ExtendableMessageEventBinding::ExtendableMessageEventMethods;
14use crate::dom::bindings::error::Fallible;
15use crate::dom::bindings::frozenarray::CachedFrozenArray;
16use crate::dom::bindings::inheritance::Castable;
17use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
18use crate::dom::bindings::root::{Dom, DomRoot};
19use crate::dom::bindings::str::DOMString;
20use crate::dom::bindings::trace::RootedTraceableBox;
21use crate::dom::event::Event;
22use crate::dom::eventtarget::EventTarget;
23use crate::dom::extendableevent::ExtendableEvent;
24use crate::dom::globalscope::GlobalScope;
25use crate::dom::messageport::MessagePort;
26use crate::dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
27use crate::script_runtime::{CanGc, JSContext};
28
29#[dom_struct]
30#[allow(non_snake_case)]
31pub(crate) struct ExtendableMessageEvent {
32 event: ExtendableEvent,
34 #[ignore_malloc_size_of = "mozjs"]
36 data: Heap<JSVal>,
37 origin: DOMString,
39 lastEventId: DOMString,
41 ports: Vec<Dom<MessagePort>>,
43 #[ignore_malloc_size_of = "mozjs"]
44 frozen_ports: CachedFrozenArray,
45}
46
47#[allow(non_snake_case)]
48impl ExtendableMessageEvent {
49 pub(crate) fn new_inherited(
50 origin: DOMString,
51 lastEventId: DOMString,
52 ports: Vec<DomRoot<MessagePort>>,
53 ) -> ExtendableMessageEvent {
54 ExtendableMessageEvent {
55 event: ExtendableEvent::new_inherited(),
56 data: Heap::default(),
57 origin,
58 lastEventId,
59 ports: ports
60 .into_iter()
61 .map(|port| Dom::from_ref(&*port))
62 .collect(),
63 frozen_ports: CachedFrozenArray::new(),
64 }
65 }
66
67 #[allow(clippy::too_many_arguments)]
68 pub(crate) fn new(
69 global: &GlobalScope,
70 type_: Atom,
71 bubbles: bool,
72 cancelable: bool,
73 data: HandleValue,
74 origin: DOMString,
75 lastEventId: DOMString,
76 ports: Vec<DomRoot<MessagePort>>,
77 can_gc: CanGc,
78 ) -> DomRoot<ExtendableMessageEvent> {
79 Self::new_with_proto(
80 global,
81 None,
82 type_,
83 bubbles,
84 cancelable,
85 data,
86 origin,
87 lastEventId,
88 ports,
89 can_gc,
90 )
91 }
92
93 #[allow(clippy::too_many_arguments)]
94 fn new_with_proto(
95 global: &GlobalScope,
96 proto: Option<HandleObject>,
97 type_: Atom,
98 bubbles: bool,
99 cancelable: bool,
100 data: HandleValue,
101 origin: DOMString,
102 lastEventId: DOMString,
103 ports: Vec<DomRoot<MessagePort>>,
104 can_gc: CanGc,
105 ) -> DomRoot<ExtendableMessageEvent> {
106 let ev = Box::new(ExtendableMessageEvent::new_inherited(
107 origin,
108 lastEventId,
109 ports,
110 ));
111 let ev = reflect_dom_object_with_proto(ev, global, proto, can_gc);
112 {
113 let event = ev.upcast::<Event>();
114 event.init_event(type_, bubbles, cancelable);
115 }
116 ev.data.set(data.get());
117
118 ev
119 }
120}
121
122#[allow(non_snake_case)]
123impl ExtendableMessageEvent {
124 pub(crate) fn dispatch_jsval(
125 target: &EventTarget,
126 scope: &GlobalScope,
127 message: HandleValue,
128 ports: Vec<DomRoot<MessagePort>>,
129 can_gc: CanGc,
130 ) {
131 let Extendablemessageevent = ExtendableMessageEvent::new(
132 scope,
133 atom!("message"),
134 false,
135 false,
136 message,
137 DOMString::new(),
138 DOMString::new(),
139 ports,
140 can_gc,
141 );
142 Extendablemessageevent
143 .upcast::<Event>()
144 .fire(target, can_gc);
145 }
146
147 pub(crate) fn dispatch_error(target: &EventTarget, scope: &GlobalScope, can_gc: CanGc) {
148 let init = ExtendableMessageEventBinding::ExtendableMessageEventInit::empty();
149 let ExtendableMsgEvent = ExtendableMessageEvent::new(
150 scope,
151 atom!("messageerror"),
152 init.parent.parent.bubbles,
153 init.parent.parent.cancelable,
154 init.data.handle(),
155 init.origin.clone(),
156 init.lastEventId.clone(),
157 init.ports.clone(),
158 can_gc,
159 );
160 ExtendableMsgEvent.upcast::<Event>().fire(target, can_gc);
161 }
162}
163
164impl ExtendableMessageEventMethods<crate::DomTypeHolder> for ExtendableMessageEvent {
165 fn Constructor(
167 worker: &ServiceWorkerGlobalScope,
168 proto: Option<HandleObject>,
169 can_gc: CanGc,
170 type_: DOMString,
171 init: RootedTraceableBox<ExtendableMessageEventBinding::ExtendableMessageEventInit>,
172 ) -> Fallible<DomRoot<ExtendableMessageEvent>> {
173 let global = worker.upcast::<GlobalScope>();
174 let ev = ExtendableMessageEvent::new_with_proto(
175 global,
176 proto,
177 Atom::from(type_),
178 init.parent.parent.bubbles,
179 init.parent.parent.cancelable,
180 init.data.handle(),
181 init.origin.clone(),
182 init.lastEventId.clone(),
183 vec![],
184 can_gc,
185 );
186 Ok(ev)
187 }
188
189 fn Data(&self, _cx: JSContext, mut retval: MutableHandleValue) {
191 retval.set(self.data.get())
192 }
193
194 fn Origin(&self) -> DOMString {
196 self.origin.clone()
197 }
198
199 fn LastEventId(&self) -> DOMString {
201 self.lastEventId.clone()
202 }
203
204 fn IsTrusted(&self) -> bool {
206 self.event.IsTrusted()
207 }
208
209 fn Ports(&self, cx: JSContext, can_gc: CanGc, retval: MutableHandleValue) {
211 self.frozen_ports.get_or_init(
212 || {
213 self.ports
214 .iter()
215 .map(|port| DomRoot::from_ref(&**port))
216 .collect()
217 },
218 cx,
219 retval,
220 can_gc,
221 );
222 }
223}