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};
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 id = self.reflector().proto_id();
30 id >= T::PROTO_FIRST && id <= T::PROTO_LAST
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#[expect(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}