script_bindings/
finalize.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//! Generic finalizer implementations for DOM binding implementations.
6
7use std::any::type_name;
8use std::{mem, ptr};
9
10use js::glue::JS_GetReservedSlot;
11use js::jsapi::JSObject;
12use js::jsval::UndefinedValue;
13use js::rust::GCMethods;
14
15use crate::codegen::PrototypeList::PROTO_OR_IFACE_LENGTH;
16use crate::utils::{ProtoOrIfaceArray, get_proto_or_iface_array};
17use crate::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable};
18
19/// Drop the resources held by reserved slots of a global object
20unsafe fn do_finalize_global(obj: *mut JSObject) {
21    unsafe {
22        let protolist = get_proto_or_iface_array(obj);
23        let list = (*protolist).as_mut_ptr();
24        for idx in 0..PROTO_OR_IFACE_LENGTH as isize {
25            let entry = list.offset(idx);
26            let value = *entry;
27            <*mut JSObject>::post_barrier(entry, value, ptr::null_mut());
28        }
29        let _: Box<ProtoOrIfaceArray> = Box::from_raw(protolist);
30    }
31}
32
33/// # Safety
34/// `this` must point to a valid, non-null instance of T.
35pub(crate) unsafe fn finalize_common<T>(this: *const T) {
36    if !this.is_null() {
37        // The pointer can be null if the object is the unforgeable holder of that interface.
38        let _ = unsafe { Box::from_raw(this as *mut T) };
39    }
40    debug!("{} finalize: {:p}", type_name::<T>(), this);
41}
42
43/// # Safety
44/// `obj` must point to a valid, non-null JS object.
45/// `this` must point to a valid, non-null instance of T.
46pub(crate) unsafe fn finalize_global<T>(obj: *mut JSObject, this: *const T) {
47    unsafe {
48        do_finalize_global(obj);
49        finalize_common::<T>(this);
50    }
51}
52
53/// # Safety
54/// `obj` must point to a valid, non-null JS object.
55/// `this` must point to a valid, non-null instance of T.
56pub(crate) unsafe fn finalize_weak_referenceable<T: WeakReferenceable>(
57    obj: *mut JSObject,
58    this: *const T,
59) {
60    let mut slot = UndefinedValue();
61    unsafe { JS_GetReservedSlot(obj, DOM_WEAK_SLOT, &mut slot) };
62    let weak_box_ptr = slot.to_private() as *mut WeakBox<T>;
63    if !weak_box_ptr.is_null() {
64        let count = {
65            let weak_box = unsafe { &*weak_box_ptr };
66            assert!(weak_box.value.get().is_some());
67            assert!(weak_box.count.get() > 0);
68            weak_box.value.set(None);
69            let count = weak_box.count.get() - 1;
70            weak_box.count.set(count);
71            count
72        };
73        if count == 0 {
74            mem::drop(unsafe { Box::from_raw(weak_box_ptr) });
75        }
76    }
77    unsafe { finalize_common::<T>(this) };
78}