script/dom/
promisenativehandler.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
5use dom_struct::dom_struct;
6use js::jsapi::JSContext;
7use js::rust::HandleValue;
8use malloc_size_of::MallocSizeOf;
9
10use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
11use crate::dom::bindings::root::DomRoot;
12use crate::dom::bindings::trace::JSTraceable;
13use crate::dom::globalscope::GlobalScope;
14use crate::realms::InRealm;
15use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
16
17/// Types that implement the `Callback` trait follow the same rooting requirements
18/// as types that use the `#[dom_struct]` attribute.
19/// Prefer storing `Dom<T>` members inside them instead of `DomRoot<T>`
20/// to minimize redundant work by the garbage collector.
21pub(crate) trait Callback: JSTraceable + MallocSizeOf {
22    fn callback(&self, cx: SafeJSContext, v: HandleValue, realm: InRealm, can_gc: CanGc);
23}
24
25#[dom_struct]
26pub(crate) struct PromiseNativeHandler {
27    reflector: Reflector,
28    resolve: Option<Box<dyn Callback>>,
29    reject: Option<Box<dyn Callback>>,
30}
31
32impl PromiseNativeHandler {
33    pub(crate) fn new(
34        global: &GlobalScope,
35        resolve: Option<Box<dyn Callback>>,
36        reject: Option<Box<dyn Callback>>,
37        can_gc: CanGc,
38    ) -> DomRoot<PromiseNativeHandler> {
39        reflect_dom_object(
40            Box::new(PromiseNativeHandler {
41                reflector: Reflector::new(),
42                resolve,
43                reject,
44            }),
45            global,
46            can_gc,
47        )
48    }
49
50    #[allow(unsafe_code)]
51    fn callback(
52        callback: &Option<Box<dyn Callback>>,
53        cx: *mut JSContext,
54        v: HandleValue,
55        realm: InRealm,
56        can_gc: CanGc,
57    ) {
58        let cx = unsafe { SafeJSContext::from_ptr(cx) };
59        if let Some(ref callback) = *callback {
60            callback.callback(cx, v, realm, can_gc)
61        }
62    }
63
64    pub(crate) fn resolved_callback(
65        &self,
66        cx: *mut JSContext,
67        v: HandleValue,
68        realm: InRealm,
69        can_gc: CanGc,
70    ) {
71        PromiseNativeHandler::callback(&self.resolve, cx, v, realm, can_gc)
72    }
73
74    pub(crate) fn rejected_callback(
75        &self,
76        cx: *mut JSContext,
77        v: HandleValue,
78        realm: InRealm,
79        can_gc: CanGc,
80    ) {
81        PromiseNativeHandler::callback(&self.reject, cx, v, realm, can_gc)
82    }
83}