pub struct JSRefCell<T> {
value: RefCell<T>,
}Expand description
std::cell::RefCell that statically prevents borrow_mut panics
from occurring by borrowing due to GC using the NoGC marker.
If dynamic borrow checking is not needed, one should use JSCell instead.
If inner type is Copy one should use std::cell::Cell instead.
Fields§
§value: RefCell<T>Implementations§
Source§impl<T> JSRefCell<T>
impl<T> JSRefCell<T>
Sourcepub fn as_refcell(&self) -> &RefCell<T>
pub fn as_refcell(&self) -> &RefCell<T>
Returns a reference to the underlying RefCell.
This is not strictly unsafe, but it is not recommended to use this method unless you know what you are doing.
Mutable borrows from it can cause panics if a GC happens while the borrow is active,
which is why JSRefCell::borrow_mut should be used instead.
Sourcepub fn borrow(&self) -> Ref<'_, T>
pub fn borrow(&self) -> Ref<'_, T>
Immutably borrows the wrapped value.
The borrow lasts until the returned Ref exits scope. Multiple
immutable borrows can be taken out at the same time.
This is exactly the same as std::cell::RefCell::borrow.
§Panics
Panics if the value is currently mutably borrowed.
Sourcepub fn borrow_mut<'a: 'r, 'no_cx: 'r, 'r>(
&'a self,
_no_gc: &'no_cx NoGC,
) -> RefMut<'r, T>
pub fn borrow_mut<'a: 'r, 'no_cx: 'r, 'r>( &'a self, _no_gc: &'no_cx NoGC, ) -> RefMut<'r, T>
Mutably borrows the wrapped value.
The borrow lasts until the returned RefMut exits scope. The value
cannot be borrowed while this borrow is active.
This is similar to std::cell::RefCell::borrow_mut,
but it requires a &NoGC token to ensure that no GC can happen while the borrow is active,
which would otherwise cause a panic when tracing (which calls borrow).
§Examples
In simple cases one can use &NoGC to statically ensure no GC can happen in the whole function:
use mozjs::context::{JSContext, NoGC};
use mozjs::cell::JSRefCell;
fn f(no_gc: &NoGC, cell: &JSRefCell<String>) {
let mut mutably_borrowed = cell.borrow_mut(no_gc);
}But in more complex cases, a method might trigger a GC, and thus require a &mut JSContext.
In that case &JSContext can be used in place of &NoGC,
which will make RefMut bounded to the lifetime of the &JSContext
and thus prevent any GC from happening while it is alive.
use mozjs::context::{JSContext, NoGC};
use mozjs::cell::JSRefCell;
fn GC(cx: &mut JSContext) {}
fn f(cx: &mut JSContext, cell: &JSRefCell<String>) {
{
let mut mutably_borrowed = cell.borrow_mut(cx);
// do something with mutably_borrowed
// only &JSContext is available here
} // mutably_borrowed goes out of scope here
// so one can now use &mut JSContext
GC(cx);
}§Non-Example
use mozjs::context::{JSContext, NoGC};
use mozjs::cell::JSRefCell;
fn GC(cx: &mut JSContext) {}
fn f(cx: &mut JSContext, cell: &JSRefCell<String>) {
{
let mut mutably_borrowed = cell.borrow_mut(cx);
// do something with mutably_borrowed
// here one cannot use anything that might trigger a GC
// as that would require &mut JSContext
// but there is already existing &JSContext bounded at RefMut
GC(cx);
} // mutably_borrowed goes out of scope here
}§Panics
Panics if the value is currently borrowed.