script/dom/
macros.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5#[macro_export]
6macro_rules! make_getter(
7    ( $attr:ident, $htmlname:tt ) => (
8        fn $attr(&self) -> DOMString {
9            use $crate::dom::bindings::inheritance::Castable;
10            use $crate::dom::element::Element;
11            let element = self.upcast::<Element>();
12            element.get_string_attribute(&html5ever::local_name!($htmlname))
13        }
14    );
15);
16
17#[macro_export]
18macro_rules! make_bool_getter(
19    ( $attr:ident, $htmlname:tt ) => (
20        fn $attr(&self) -> bool {
21            use $crate::dom::bindings::inheritance::Castable;
22            use $crate::dom::element::Element;
23            let element = self.upcast::<Element>();
24            element.has_attribute(&html5ever::local_name!($htmlname))
25        }
26    );
27);
28
29#[macro_export]
30macro_rules! make_limited_int_setter(
31    ($attr:ident, $htmlname:tt, $default:expr) => (
32        fn $attr(&self, value: i32) -> $crate::dom::bindings::error::ErrorResult {
33            use $crate::dom::bindings::inheritance::Castable;
34            use $crate::dom::element::Element;
35            use $crate::script_runtime::CanGc;
36
37            let value = if value < 0 {
38                return Err($crate::dom::bindings::error::Error::IndexSize(None));
39            } else {
40                value
41            };
42
43            let element = self.upcast::<Element>();
44            element.set_int_attribute(&html5ever::local_name!($htmlname), value, CanGc::note());
45            Ok(())
46        }
47    );
48);
49
50#[macro_export]
51macro_rules! make_int_setter(
52    ($attr:ident, $htmlname:tt) => (
53        fn $attr(&self, cx: &mut js::context::JSContext, value: i32) {
54            use $crate::dom::bindings::inheritance::Castable;
55            use $crate::dom::element::Element;
56            use $crate::script_runtime::CanGc;
57
58            let element = self.upcast::<Element>();
59            element.set_int_attribute(&html5ever::local_name!($htmlname), value, CanGc::from_cx(cx))
60        }
61    );
62);
63
64#[macro_export]
65macro_rules! make_int_getter(
66    ($attr:ident, $htmlname:tt, $default:expr) => (
67        fn $attr(&self) -> i32 {
68            use $crate::dom::bindings::inheritance::Castable;
69            use $crate::dom::element::element::Element;
70            let element = self.upcast::<Element>();
71            element.get_int_attribute(&html5ever::local_name!($htmlname), $default)
72        }
73    );
74
75    ($attr:ident, $htmlname:tt) => {
76        make_int_getter!($attr, $htmlname, 0);
77    };
78);
79
80#[macro_export]
81macro_rules! make_uint_getter(
82    ($attr:ident, $htmlname:tt, $default:expr) => (
83        fn $attr(&self) -> u32 {
84            use $crate::dom::bindings::inheritance::Castable;
85            use $crate::dom::element::Element;
86            let element = self.upcast::<Element>();
87            element.get_uint_attribute(&html5ever::local_name!($htmlname), $default)
88        }
89    );
90    ($attr:ident, $htmlname:tt) => {
91        make_uint_getter!($attr, $htmlname, 0);
92    };
93);
94
95#[macro_export]
96macro_rules! make_url_getter(
97    ( $attr:ident, $htmlname:tt ) => (
98        fn $attr(&self) -> USVString {
99            use $crate::dom::bindings::inheritance::Castable;
100            use $crate::dom::element::Element;
101            let element = self.upcast::<Element>();
102            element.get_url_attribute(&html5ever::local_name!($htmlname))
103        }
104    );
105);
106
107#[macro_export]
108macro_rules! make_url_setter(
109    ( $attr:ident, $htmlname:tt ) => (
110        fn $attr(&self, value: USVString) {
111            use $crate::dom::bindings::inheritance::Castable;
112            use $crate::dom::element::Element;
113            use $crate::script_runtime::CanGc;
114            let element = self.upcast::<Element>();
115            element.set_url_attribute(&html5ever::local_name!($htmlname),
116                                         value, CanGc::note());
117        }
118    );
119);
120
121#[macro_export]
122macro_rules! make_form_action_getter(
123    ( $attr:ident, $htmlname:tt ) => (
124        fn $attr(&self) -> DOMString {
125            use $crate::dom::bindings::inheritance::Castable;
126            use $crate::dom::element::Element;
127            let element = self.upcast::<Element>();
128            let doc = $crate::dom::node::NodeTraits::owner_document(self);
129            let attr = element.get_attribute(&html5ever::local_name!($htmlname));
130            let value = attr.as_ref().map(|attr| attr.value());
131            let value = match value {
132                Some(ref value) if !value.is_empty() => &***value,
133                _ => return doc.url().into_string().into(),
134            };
135            match doc.encoding_parse_a_url(value) {
136                Ok(parsed) => parsed.into_string().into(),
137                Err(_) => value.to_owned().into(),
138            }
139        }
140    );
141);
142
143#[macro_export]
144macro_rules! make_labels_getter(
145    ( $attr:ident, $memo:ident ) => (
146        fn $attr(&self) -> DomRoot<NodeList> {
147            use $crate::dom::html::htmlelement::HTMLElement;
148            use $crate::dom::nodelist::NodeList;
149            self.$memo.or_init(|| NodeList::new_labels_list(
150                self.upcast::<Node>().owner_doc().window(),
151                self.upcast::<HTMLElement>(),
152                CanGc::note()
153                )
154            )
155        }
156    );
157);
158
159/// Implements the `To determine the state of an attribute` steps from
160/// <https://html.spec.whatwg.org/multipage/#keywords-and-enumerated-attributes>
161macro_rules! make_enumerated_getter(
162    ($attr:ident,
163        $htmlname:tt,
164        $($choices:literal)|+,
165        missing => $missing:literal,
166        invalid => $invalid:literal,
167        empty => $empty:literal
168    ) => (
169        fn $attr(&self) -> DOMString {
170            use $crate::dom::bindings::inheritance::Castable;
171            use $crate::dom::element::Element;
172            use $crate::dom::bindings::codegen::Bindings::AttrBinding::Attr_Binding::AttrMethods;
173
174            let attr_or_none = self.upcast::<Element>()
175                .get_attribute(&html5ever::local_name!($htmlname));
176            match attr_or_none  {
177                // Step 1. If the attribute is not specified:
178                None => {
179                    // Step 1.1. If the attribute has a missing value default state defined, then return that
180                    // missing value default state.
181                    // Step 1.2 Otherwise, return no state.
182                    return DOMString::from($missing);
183                },
184                Some(attr) => {
185                    // Step 2. If the attribute's value is an ASCII case-insensitive match for one of the keywords
186                    // defined for the attribute, then return the state represented by that keyword.
187                    let value: DOMString = attr.Value().to_ascii_lowercase().into();
188                    $(
189                        if value.str() == $choices {
190                            return value;
191                        }
192                    )+
193
194                    // Step 3. If the attribute has an empty value default state defined and the attribute's value
195                    // is the empty string, then return that empty value default state.
196                    if value.is_empty() {
197                        return DOMString::from($empty)
198                    }
199
200                    // Step 4. If the attribute has an invalid value default state defined, then return that invalid
201                    // value default state.
202                    // Step 5. Return no state.
203                    return DOMString::from($invalid);
204                }
205            }
206        }
207    );
208    ($attr:ident,
209        $htmlname:tt,
210        $($choices:literal)|+,
211    ) => (
212        make_enumerated_getter!(
213            $attr,
214            $htmlname,
215            $($choices)|+,
216            missing => "",
217            invalid => "",
218            empty => ""
219        );
220    );
221    ($attr:ident,
222        $htmlname:tt,
223        $($choices:literal)|+,
224        invalid => $invalid:literal
225    ) => (
226        make_enumerated_getter!(
227            $attr,
228            $htmlname,
229            $($choices)|+,
230            missing => "",
231            invalid => $invalid,
232            empty => $invalid
233        );
234    );
235    ($attr:ident,
236        $htmlname:tt,
237        $($choices:literal)|+,
238        missing => $missing:literal,
239    ) => (
240        make_enumerated_getter!(
241            $attr,
242            $htmlname,
243            $($choices)|+,
244            missing => $missing,
245            invalid => "",
246            empty => ""
247        );
248    );
249    ($attr:ident,
250        $htmlname:tt,
251        $($choices:literal)|+,
252        missing => $missing:literal,
253        invalid => $invalid:literal
254    ) => (
255        make_enumerated_getter!(
256            $attr,
257            $htmlname,
258            $($choices)|+,
259            missing => $missing,
260            invalid => $invalid,
261            empty => $invalid
262        );
263    );
264);
265
266// concat_idents! doesn't work for function name positions, so
267// we have to specify both the content name and the HTML name here
268#[macro_export]
269macro_rules! make_setter(
270    ( $attr:ident, $htmlname:tt ) => (
271        fn $attr(&self, value: DOMString) {
272            use $crate::dom::bindings::inheritance::Castable;
273            use $crate::dom::element::Element;
274            use $crate::script_runtime::CanGc;
275            let element = self.upcast::<Element>();
276            element.set_string_attribute(&html5ever::local_name!($htmlname), value, CanGc::note())
277        }
278    );
279);
280
281#[macro_export]
282macro_rules! make_bool_setter(
283    ( $attr:ident, $htmlname:tt ) => (
284        fn $attr(&self, value: bool) {
285            use $crate::dom::bindings::inheritance::Castable;
286            use $crate::dom::element::Element;
287            use $crate::script_runtime::CanGc;
288            let element = self.upcast::<Element>();
289            element.set_bool_attribute(&html5ever::local_name!($htmlname), value, CanGc::note())
290        }
291    );
292);
293
294#[macro_export]
295macro_rules! make_uint_setter(
296    ($attr:ident, $htmlname:tt, $default:expr) => (
297        fn $attr(&self, value: u32) {
298            use $crate::dom::bindings::inheritance::Castable;
299            use $crate::dom::element::Element;
300            use $crate::dom::values::UNSIGNED_LONG_MAX;
301            use $crate::script_runtime::CanGc;
302            let value = if value > UNSIGNED_LONG_MAX {
303                $default
304            } else {
305                value
306            };
307            let element = self.upcast::<Element>();
308            element.set_uint_attribute(&html5ever::local_name!($htmlname), value, CanGc::note())
309        }
310    );
311    ($attr:ident, $htmlname:tt) => {
312        make_uint_setter!($attr, $htmlname, 0);
313    };
314);
315
316#[macro_export]
317macro_rules! make_clamped_uint_setter(
318    ($attr:ident, $htmlname:tt, $min:expr, $max:expr, $default:expr) => (
319        fn $attr(&self, value: u32) {
320            use $crate::dom::bindings::inheritance::Castable;
321            use $crate::dom::element::Element;
322            use $crate::dom::values::UNSIGNED_LONG_MAX;
323            use $crate::script_runtime::CanGc;
324            let value = if value > UNSIGNED_LONG_MAX {
325                $default
326            } else {
327                value.clamp($min, $max)
328            };
329
330            let element = self.upcast::<Element>();
331            element.set_uint_attribute(&html5ever::local_name!($htmlname), value, CanGc::note())
332        }
333    );
334);
335
336#[macro_export]
337macro_rules! make_limited_uint_setter(
338    ($attr:ident, $htmlname:tt, $default:expr) => (
339        fn $attr(&self, value: u32) -> $crate::dom::bindings::error::ErrorResult {
340            use $crate::dom::bindings::inheritance::Castable;
341            use $crate::dom::element::Element;
342            use $crate::dom::values::UNSIGNED_LONG_MAX;
343            use $crate::script_runtime::CanGc;
344            let value = if value == 0 {
345                return Err($crate::dom::bindings::error::Error::IndexSize(None));
346            } else if value > UNSIGNED_LONG_MAX {
347                $default
348            } else {
349                value
350            };
351            let element = self.upcast::<Element>();
352            element.set_uint_attribute(&html5ever::local_name!($htmlname), value, CanGc::note());
353            Ok(())
354        }
355    );
356    ($attr:ident, $htmlname:tt) => {
357        make_limited_uint_setter!($attr, $htmlname, 1);
358    };
359);
360
361macro_rules! make_atomic_setter_inner(
362    ( $self:ident, $value:ident, $htmlname:tt, $can_gc:expr ) => (
363        use $crate::dom::bindings::inheritance::Castable;
364        use $crate::dom::element::Element;
365        use $crate::script_runtime::CanGc;
366        let element = $self.upcast::<Element>();
367        element.set_atomic_attribute(&html5ever::local_name!($htmlname), $value, $can_gc)
368    );
369);
370
371#[macro_export]
372macro_rules! make_atomic_setter(
373    ( $attr:ident, $htmlname:tt ) => (
374        fn $attr(&self, value: DOMString) {
375            make_atomic_setter_inner!(self, value, $htmlname, CanGc::note());
376        }
377    );
378    ( $cx:ident, $attr:ident, $htmlname:tt ) => (
379        fn $attr(&self, $cx: &mut js::context::JSContext, value: DOMString) {
380            make_atomic_setter_inner!(self, value, $htmlname, CanGc::from_cx($cx));
381        }
382    );
383);
384
385#[macro_export]
386macro_rules! make_legacy_color_setter(
387    ( $attr:ident, $htmlname:tt ) => (
388        fn $attr(&self, value: DOMString) {
389            use $crate::dom::bindings::inheritance::Castable;
390            use $crate::dom::element::Element;
391            use style::attr::AttrValue;
392            use $crate::script_runtime::CanGc;
393            let element = self.upcast::<Element>();
394            let value = AttrValue::from_legacy_color(value.into());
395            element.set_attribute(&html5ever::local_name!($htmlname), value, CanGc::note())
396        }
397    );
398);
399
400#[macro_export]
401macro_rules! make_dimension_setter(
402    ( $attr:ident, $htmlname:tt ) => (
403        fn $attr(&self, value: DOMString) {
404            use $crate::dom::bindings::inheritance::Castable;
405            use $crate::dom::element::Element;
406            use $crate::script_runtime::CanGc;
407            let element = self.upcast::<Element>();
408            let value = AttrValue::from_dimension(value.into());
409            element.set_attribute(&html5ever::local_name!($htmlname), value, CanGc::note())
410        }
411    );
412);
413
414#[macro_export]
415macro_rules! make_nonzero_dimension_setter(
416    ( $attr:ident, $htmlname:tt ) => (
417        fn $attr(&self, value: DOMString) {
418            use $crate::dom::bindings::inheritance::Castable;
419            use $crate::dom::element::Element;
420            use $crate::script_runtime::CanGc;
421            let element = self.upcast::<Element>();
422            let value = AttrValue::from_nonzero_dimension(value.into());
423            element.set_attribute(&html5ever::local_name!($htmlname), value, CanGc::note())
424        }
425    );
426);
427
428#[macro_export]
429macro_rules! make_dimension_uint_getter(
430    ($attr:ident, $htmlname:tt, $default:expr) => (
431        fn $attr(&self) -> u32 {
432            use style::attr::parse_unsigned_integer;
433            use $crate::dom::bindings::inheritance::Castable;
434            use $crate::dom::element::Element;
435            use $crate::dom::values::UNSIGNED_LONG_MAX;
436            let element = self.upcast::<Element>();
437            element
438                .get_attribute(&html5ever::local_name!($htmlname))
439                .map_or($default, |attribute| parse_unsigned_integer(attribute.value().chars())
440                    .map_or($default, |value| {
441                        if value > UNSIGNED_LONG_MAX {
442                            $default
443                        } else {
444                            value
445                        }
446                    })
447                )
448        }
449    );
450    ($attr:ident, $htmlname:tt) => {
451        make_dimension_uint_getter!($attr, $htmlname, 0);
452    };
453);
454
455#[macro_export]
456macro_rules! make_dimension_uint_setter(
457    ($attr:ident, $htmlname:tt, $default:expr) => (
458        fn $attr(&self, value: u32) {
459            use $crate::dom::bindings::inheritance::Castable;
460            use $crate::dom::element::Element;
461            use $crate::dom::values::UNSIGNED_LONG_MAX;
462            use $crate::script_runtime::CanGc;
463            let element = self.upcast::<Element>();
464            let value = if value > UNSIGNED_LONG_MAX {
465                $default
466            } else {
467                value
468            };
469            let value = AttrValue::from_dimension(value.to_string());
470            element.set_attribute(&html5ever::local_name!($htmlname), value, CanGc::note())
471        }
472    );
473    ($attr:ident, $htmlname:tt) => {
474        make_dimension_uint_setter!($attr, $htmlname, 0);
475    };
476);
477
478/// For use on non-jsmanaged types
479/// Use #[derive(JSTraceable)] on JS managed types
480macro_rules! unsafe_no_jsmanaged_fields(
481    ($($ty:ty),+) => (
482        $(
483            #[expect(unsafe_code)]
484            unsafe impl $crate::dom::bindings::trace::JSTraceable for $ty {
485                #[inline]
486                unsafe fn trace(&self, _: *mut ::js::jsapi::JSTracer) {
487                    // Do nothing
488                }
489            }
490        )+
491    );
492);
493
494/// These are used to generate a event handler which has no special case.
495macro_rules! define_event_handler(
496    ($handler: ty, $event_type: ident, $getter: ident, $setter: ident, $setter_fn: ident) => (
497        fn $getter(&self) -> Option<::std::rc::Rc<$handler>> {
498            use crate::dom::bindings::inheritance::Castable;
499            use crate::dom::eventtarget::EventTarget;
500            use crate::script_runtime::CanGc;
501            let eventtarget = self.upcast::<EventTarget>();
502            eventtarget.get_event_handler_common(stringify!($event_type), CanGc::note())
503        }
504
505        fn $setter(&self, listener: Option<::std::rc::Rc<$handler>>) {
506            use crate::dom::bindings::inheritance::Castable;
507            use crate::dom::eventtarget::EventTarget;
508            let eventtarget = self.upcast::<EventTarget>();
509            eventtarget.$setter_fn(stringify!($event_type), listener)
510        }
511    )
512);
513
514macro_rules! define_window_owned_event_handler(
515    ($handler: ty, $event_type: ident, $getter: ident, $setter: ident) => (
516        fn $getter(&self) -> Option<::std::rc::Rc<$handler>> {
517            let document = self.owner_document();
518            if document.has_browsing_context() {
519                document.window().$getter()
520            } else {
521                None
522            }
523        }
524
525        fn $setter(&self, listener: Option<::std::rc::Rc<$handler>>) {
526            let document = self.owner_document();
527            if document.has_browsing_context() {
528                document.window().$setter(listener)
529            }
530        }
531    )
532);
533
534macro_rules! event_handler(
535    ($event_type: ident, $getter: ident, $setter: ident) => (
536        define_event_handler!(
537            crate::dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull,
538            $event_type,
539            $getter,
540            $setter,
541            set_event_handler_common
542        );
543    )
544);
545
546macro_rules! error_event_handler(
547    ($event_type: ident, $getter: ident, $setter: ident) => (
548        define_event_handler!(
549            crate::dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull,
550            $event_type,
551            $getter,
552            $setter,
553            set_error_event_handler
554        );
555    )
556);
557
558macro_rules! beforeunload_event_handler(
559    ($event_type: ident, $getter: ident, $setter: ident) => (
560        define_event_handler!(
561            crate::dom::bindings::codegen::Bindings::EventHandlerBinding::OnBeforeUnloadEventHandlerNonNull,
562            $event_type,
563            $getter,
564            $setter,
565            set_beforeunload_event_handler
566        );
567    )
568);
569
570macro_rules! window_owned_event_handler(
571    ($event_type: ident, $getter: ident, $setter: ident) => (
572        define_window_owned_event_handler!(
573            crate::dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull,
574            $event_type,
575            $getter,
576            $setter
577        );
578    )
579);
580
581macro_rules! window_owned_beforeunload_event_handler(
582    ($event_type: ident, $getter: ident, $setter: ident) => (
583        define_window_owned_event_handler!(
584            crate::dom::bindings::codegen::Bindings::EventHandlerBinding::OnBeforeUnloadEventHandlerNonNull,
585            $event_type,
586            $getter,
587            $setter
588        );
589    )
590);
591
592// https://html.spec.whatwg.org/multipage/#globaleventhandlers
593// see webidls/EventHandler.webidl
594// As more methods get added, just update them here.
595macro_rules! global_event_handlers(
596    () => (
597        // These are special when on body/frameset elements
598        event_handler!(blur, GetOnblur, SetOnblur);
599        error_event_handler!(error, GetOnerror, SetOnerror);
600        event_handler!(focus, GetOnfocus, SetOnfocus);
601        event_handler!(load, GetOnload, SetOnload);
602        event_handler!(resize, GetOnresize, SetOnresize);
603        event_handler!(scroll, GetOnscroll, SetOnscroll);
604        global_event_handlers!(NoOnload);
605
606    );
607    (NoOnload) => (
608        event_handler!(abort, GetOnabort, SetOnabort);
609        event_handler!(auxclick, GetOnauxclick, SetOnauxclick);
610        event_handler!(animationstart, GetOnanimationstart, SetOnanimationstart);
611        event_handler!(animationiteration, GetOnanimationiteration, SetOnanimationiteration);
612        event_handler!(animationend, GetOnanimationend, SetOnanimationend);
613        event_handler!(animationcancel, GetOnanimationcancel, SetOnanimationcancel);
614        event_handler!(beforeinput, GetOnbeforeinput, SetOnbeforeinput);
615        event_handler!(beforematch, GetOnbeforematch, SetOnbeforematch);
616        event_handler!(beforetoggle, GetOnbeforetoggle, SetOnbeforetoggle);
617        event_handler!(cancel, GetOncancel, SetOncancel);
618        event_handler!(canplay, GetOncanplay, SetOncanplay);
619        event_handler!(canplaythrough, GetOncanplaythrough, SetOncanplaythrough);
620        event_handler!(change, GetOnchange, SetOnchange);
621        event_handler!(click, GetOnclick, SetOnclick);
622        event_handler!(close, GetOnclose, SetOnclose);
623        event_handler!(command, GetOncommand, SetOncommand);
624        event_handler!(contextlost, GetOncontextlost, SetOncontextlost);
625        event_handler!(contextmenu, GetOncontextmenu, SetOncontextmenu);
626        event_handler!(contextrestored, GetOncontextrestored, SetOncontextrestored);
627        event_handler!(copy, GetOncopy, SetOncopy);
628        event_handler!(cuechange, GetOncuechange, SetOncuechange);
629        event_handler!(cut, GetOncut, SetOncut);
630        event_handler!(dblclick, GetOndblclick, SetOndblclick);
631        event_handler!(drag, GetOndrag, SetOndrag);
632        event_handler!(dragend, GetOndragend, SetOndragend);
633        event_handler!(dragenter, GetOndragenter, SetOndragenter);
634        event_handler!(dragleave, GetOndragleave, SetOndragleave);
635        event_handler!(dragover, GetOndragover, SetOndragover);
636        event_handler!(dragstart, GetOndragstart, SetOndragstart);
637        event_handler!(drop, GetOndrop, SetOndrop);
638        event_handler!(durationchange, GetOndurationchange, SetOndurationchange);
639        event_handler!(emptied, GetOnemptied, SetOnemptied);
640        event_handler!(ended, GetOnended, SetOnended);
641        event_handler!(formdata, GetOnformdata, SetOnformdata);
642        event_handler!(input, GetOninput, SetOninput);
643        event_handler!(invalid, GetOninvalid, SetOninvalid);
644        event_handler!(keydown, GetOnkeydown, SetOnkeydown);
645        event_handler!(keypress, GetOnkeypress, SetOnkeypress);
646        event_handler!(keyup, GetOnkeyup, SetOnkeyup);
647        event_handler!(loadeddata, GetOnloadeddata, SetOnloadeddata);
648        event_handler!(loadedmetadata, GetOnloadedmetadata, SetOnloadedmetadata);
649        event_handler!(loadstart, GetOnloadstart, SetOnloadstart);
650        event_handler!(mousedown, GetOnmousedown, SetOnmousedown);
651        event_handler!(mouseenter, GetOnmouseenter, SetOnmouseenter);
652        event_handler!(mouseleave, GetOnmouseleave, SetOnmouseleave);
653        event_handler!(mousemove, GetOnmousemove, SetOnmousemove);
654        event_handler!(mouseout, GetOnmouseout, SetOnmouseout);
655        event_handler!(mouseover, GetOnmouseover, SetOnmouseover);
656        event_handler!(mouseup, GetOnmouseup, SetOnmouseup);
657        event_handler!(paste, GetOnpaste, SetOnpaste);
658        event_handler!(pause, GetOnpause, SetOnpause);
659        event_handler!(play, GetOnplay, SetOnplay);
660        event_handler!(playing, GetOnplaying, SetOnplaying);
661        event_handler!(pointercancel, GetOnpointercancel, SetOnpointercancel);
662        event_handler!(pointerdown, GetOnpointerdown, SetOnpointerdown);
663        event_handler!(pointerenter, GetOnpointerenter, SetOnpointerenter);
664        event_handler!(pointerleave, GetOnpointerleave, SetOnpointerleave);
665        event_handler!(pointermove, GetOnpointermove, SetOnpointermove);
666        event_handler!(pointerout, GetOnpointerout, SetOnpointerout);
667        event_handler!(pointerover, GetOnpointerover, SetOnpointerover);
668        event_handler!(pointerup, GetOnpointerup, SetOnpointerup);
669        event_handler!(progress, GetOnprogress, SetOnprogress);
670        event_handler!(ratechange, GetOnratechange, SetOnratechange);
671        event_handler!(reset, GetOnreset, SetOnreset);
672        event_handler!(scrollend, GetOnscrollend, SetOnscrollend);
673        event_handler!(securitypolicyviolation, GetOnsecuritypolicyviolation, SetOnsecuritypolicyviolation);
674        event_handler!(seeked, GetOnseeked, SetOnseeked);
675        event_handler!(seeking, GetOnseeking, SetOnseeking);
676        event_handler!(select, GetOnselect, SetOnselect);
677        event_handler!(selectionchange, GetOnselectionchange, SetOnselectionchange);
678        event_handler!(selectstart, GetOnselectstart, SetOnselectstart);
679        event_handler!(slotchange, GetOnslotchange, SetOnslotchange);
680        event_handler!(stalled, GetOnstalled, SetOnstalled);
681        event_handler!(submit, GetOnsubmit, SetOnsubmit);
682        event_handler!(suspend, GetOnsuspend, SetOnsuspend);
683        event_handler!(timeupdate, GetOntimeupdate, SetOntimeupdate);
684        event_handler!(toggle, GetOntoggle, SetOntoggle);
685        event_handler!(transitioncancel, GetOntransitioncancel, SetOntransitioncancel);
686        event_handler!(transitionend, GetOntransitionend, SetOntransitionend);
687        event_handler!(transitionrun, GetOntransitionrun, SetOntransitionrun);
688        event_handler!(volumechange, GetOnvolumechange, SetOnvolumechange);
689        event_handler!(waiting, GetOnwaiting, SetOnwaiting);
690        event_handler!(webkitanimationend, GetOnwebkitanimationend, SetOnwebkitanimationend);
691        event_handler!(webkitanimationiteration, GetOnwebkitanimationiteration, SetOnwebkitanimationiteration);
692        event_handler!(webkitanimationstart, GetOnwebkitanimationstart, SetOnwebkitanimationstart);
693        event_handler!(webkittransitionend, GetOnwebkittransitionend, SetOnwebkittransitionend);
694        event_handler!(wheel, GetOnwheel, SetOnwheel);
695    )
696);
697
698// https://html.spec.whatwg.org/multipage/#windoweventhandlers
699// see webidls/EventHandler.webidl
700// As more methods get added, just update them here.
701macro_rules! window_event_handlers(
702    () => (
703        event_handler!(afterprint, GetOnafterprint, SetOnafterprint);
704        event_handler!(beforeprint, GetOnbeforeprint, SetOnbeforeprint);
705        beforeunload_event_handler!(beforeunload, GetOnbeforeunload,
706                                    SetOnbeforeunload);
707        event_handler!(hashchange, GetOnhashchange, SetOnhashchange);
708        event_handler!(languagechange, GetOnlanguagechange,
709                       SetOnlanguagechange);
710        event_handler!(message, GetOnmessage, SetOnmessage);
711        event_handler!(messageerror, GetOnmessageerror, SetOnmessageerror);
712        event_handler!(offline, GetOnoffline, SetOnoffline);
713        event_handler!(online, GetOnonline, SetOnonline);
714        event_handler!(pagehide, GetOnpagehide, SetOnpagehide);
715        event_handler!(pagereveal, GetOnpagereveal, SetOnpagereveal);
716        event_handler!(pageshow, GetOnpageshow, SetOnpageshow);
717        event_handler!(pageswap, GetOnpageswap, SetOnpageswap);
718        event_handler!(popstate, GetOnpopstate, SetOnpopstate);
719        event_handler!(rejectionhandled, GetOnrejectionhandled,
720                       SetOnrejectionhandled);
721        event_handler!(storage, GetOnstorage, SetOnstorage);
722        event_handler!(unhandledrejection, GetOnunhandledrejection,
723                       SetOnunhandledrejection);
724        event_handler!(unload, GetOnunload, SetOnunload);
725        #[cfg(feature = "gamepad")]
726        event_handler!(gamepadconnected, GetOngamepadconnected, SetOngamepadconnected);
727        #[cfg(feature = "gamepad")]
728        event_handler!(gamepaddisconnected, GetOngamepaddisconnected, SetOngamepaddisconnected);
729    );
730    (ForwardToWindow) => (
731        window_owned_event_handler!(afterprint, GetOnafterprint,
732                                    SetOnafterprint);
733        window_owned_event_handler!(beforeprint, GetOnbeforeprint,
734                                    SetOnbeforeprint);
735        window_owned_beforeunload_event_handler!(beforeunload,
736                                                 GetOnbeforeunload,
737                                                 SetOnbeforeunload);
738        window_owned_event_handler!(hashchange, GetOnhashchange,
739                                    SetOnhashchange);
740        window_owned_event_handler!(languagechange, GetOnlanguagechange,
741                                    SetOnlanguagechange);
742        window_owned_event_handler!(message, GetOnmessage, SetOnmessage);
743        window_owned_event_handler!(messageerror, GetOnmessageerror, SetOnmessageerror);
744        window_owned_event_handler!(offline, GetOnoffline, SetOnoffline);
745        window_owned_event_handler!(online, GetOnonline, SetOnonline);
746        window_owned_event_handler!(pagehide, GetOnpagehide, SetOnpagehide);
747        window_owned_event_handler!(pagereveal, GetOnpagereveal, SetOnpagereveal);
748        window_owned_event_handler!(pageshow, GetOnpageshow, SetOnpageshow);
749        window_owned_event_handler!(pageswap, GetOnpageswap, SetOnpageswap);
750        window_owned_event_handler!(popstate, GetOnpopstate, SetOnpopstate);
751        window_owned_event_handler!(rejectionhandled, GetOnrejectionhandled,
752                                    SetOnrejectionhandled);
753        window_owned_event_handler!(storage, GetOnstorage, SetOnstorage);
754        window_owned_event_handler!(unhandledrejection, GetOnunhandledrejection,
755                                    SetOnunhandledrejection);
756        window_owned_event_handler!(unload, GetOnunload, SetOnunload);
757        #[cfg(feature = "gamepad")]
758        window_owned_event_handler!(gamepadconnected, GetOngamepadconnected, SetOngamepadconnected);
759        #[cfg(feature = "gamepad")]
760        window_owned_event_handler!(gamepaddisconnected, GetOngamepaddisconnected, SetOngamepaddisconnected);
761    );
762);
763
764/// DOM struct implementation for simple interfaces inheriting from PerformanceEntry.
765macro_rules! impl_performance_entry_struct(
766    ($binding:ident, $struct:ident, $type:path) => (
767        use servo_base::cross_process_instant::CrossProcessInstant;
768        use time::Duration;
769
770        use crate::dom::bindings::reflector::reflect_dom_object;
771        use crate::dom::bindings::root::DomRoot;
772        use crate::dom::bindings::str::DOMString;
773        use crate::dom::globalscope::GlobalScope;
774        use crate::dom::performance::performanceentry::{EntryType, PerformanceEntry};
775        use crate::script_runtime::CanGc;
776        use dom_struct::dom_struct;
777
778        #[dom_struct]
779        pub(crate) struct $struct {
780            entry: PerformanceEntry,
781        }
782
783        impl $struct {
784            fn new_inherited(name: DOMString, start_time: CrossProcessInstant, duration: Duration)
785                -> $struct {
786                $struct {
787                    entry: PerformanceEntry::new_inherited(name,
788                                                           $type,
789                                                           Some(start_time),
790                                                           duration)
791                }
792            }
793
794            #[cfg_attr(crown, expect(crown::unrooted_must_root))]
795            pub(crate) fn new(global: &GlobalScope,
796                       name: DOMString,
797                       start_time: CrossProcessInstant,
798                       duration: Duration) -> DomRoot<$struct> {
799                let entry = $struct::new_inherited(name, start_time, duration);
800                reflect_dom_object(Box::new(entry), global, CanGc::note())
801            }
802        }
803    );
804);
805
806macro_rules! handle_potential_webgl_error {
807    ($context:expr, $call:expr, $return_on_error:expr) => {
808        match $call {
809            Ok(ret) => ret,
810            Err(error) => {
811                $context.webgl_error(error);
812                $return_on_error
813            },
814        }
815    };
816    ($context:expr, $call:expr) => {
817        handle_potential_webgl_error!($context, $call, ())
818    };
819}