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