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::conversions::ToJSValConvertible;
6use js::jsapi::Heap;
7use js::jsval::JSVal;
8use js::rust::MutableHandleValue;
9
10use crate::dom::bindings::cell::DomRefCell;
11use crate::dom::bindings::utils::to_frozen_array;
12use crate::script_runtime::{CanGc, JSContext};
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        f: F,
30        cx: JSContext,
31        mut retval: MutableHandleValue,
32        can_gc: CanGc,
33    ) {
34        if let Some(inner) = &*self.frozen_value.borrow() {
35            retval.set(inner.get());
36            return;
37        }
38
39        let array = f();
40        to_frozen_array(array.as_slice(), cx, retval.reborrow(), can_gc);
41
42        // Safety: need to create the Heap value in its final memory location before setting it.
43        *self.frozen_value.borrow_mut() = Some(Heap::default());
44        self.frozen_value
45            .borrow()
46            .as_ref()
47            .unwrap()
48            .set(retval.get());
49    }
50
51    pub(crate) fn clear(&self) {
52        *self.frozen_value.borrow_mut() = None;
53    }
54}