Skip to main content

script/dom/bindings/
frozenarray.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 js::context::JSContext;
6use js::conversions::ToJSValConvertible;
7use js::jsapi::Heap;
8use js::jsval::JSVal;
9use js::rust::MutableHandleValue;
10use script_bindings::cell::DomRefCell;
11
12use crate::dom::bindings::utils::to_frozen_array;
13
14#[derive(JSTraceable)]
15#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
16pub(crate) struct CachedFrozenArray {
17    frozen_value: DomRefCell<Option<Heap<JSVal>>>,
18}
19
20impl CachedFrozenArray {
21    pub(crate) fn new() -> CachedFrozenArray {
22        CachedFrozenArray {
23            frozen_value: DomRefCell::new(None),
24        }
25    }
26
27    pub(crate) fn get_or_init<F: FnOnce() -> Vec<T>, T: ToJSValConvertible>(
28        &self,
29        cx: &mut JSContext,
30        f: F,
31        mut retval: MutableHandleValue,
32    ) {
33        if let Some(inner) = &*self.frozen_value.borrow() {
34            retval.set(inner.get());
35            return;
36        }
37
38        let array = f();
39        to_frozen_array(cx, array.as_slice(), retval.reborrow());
40
41        // Safety: need to create the Heap value in its final memory location before setting it.
42        *self.frozen_value.safe_borrow_mut(cx.no_gc()) = Some(Heap::default());
43        self.frozen_value
44            .borrow()
45            .as_ref()
46            .unwrap()
47            .set(retval.get());
48    }
49
50    pub(crate) fn clear(&self) {
51        *self.frozen_value.borrow_mut() = None;
52    }
53}