script_bindings/
inheritance.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//! The `Castable` trait.
6
7use std::mem;
8
9use crate::conversions::{DerivedFrom, IDLInterface, get_dom_class};
10use crate::reflector::DomObject;
11use crate::script_runtime::runtime_is_alive;
12
13/// A trait to hold the cast functions of IDL interfaces that either derive
14/// or are derived from other interfaces.
15pub trait Castable: IDLInterface + DomObject + Sized {
16    /// Check whether a DOM object implements one of its deriving interfaces.
17    fn is<T>(&self) -> bool
18    where
19        T: DerivedFrom<Self>,
20    {
21        // This is a weird place for this check to live, but it should catch any
22        // attempts to interact with DOM objects from Drop implementations that run
23        // as a result of the runtime shutting down and finalizing all remaining objects.
24        debug_assert!(
25            runtime_is_alive(),
26            "Attempting to interact with DOM objects after JS runtime has shut down."
27        );
28
29        let class = unsafe { get_dom_class(self.reflector().get_jsobject().get()).unwrap() };
30        T::derives(class)
31    }
32
33    /// Cast a DOM object upwards to one of the interfaces it derives from.
34    fn upcast<T>(&self) -> &T
35    where
36        T: Castable,
37        Self: DerivedFrom<T>,
38    {
39        unsafe { mem::transmute::<&Self, &T>(self) }
40    }
41
42    /// Cast a DOM object downwards to one of the interfaces it might implement.
43    fn downcast<T>(&self) -> Option<&T>
44    where
45        T: DerivedFrom<Self>,
46    {
47        if self.is::<T>() {
48            Some(unsafe { mem::transmute::<&Self, &T>(self) })
49        } else {
50            None
51        }
52    }
53}
54
55#[allow(missing_docs)]
56pub trait HasParent {
57    #[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
58    type Parent;
59    fn as_parent(&self) -> &Self::Parent;
60}