aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/js.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bindings/js.rs')
-rw-r--r--components/script/dom/bindings/js.rs59
1 files changed, 58 insertions, 1 deletions
diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs
index a0521b17535..14f717f7455 100644
--- a/components/script/dom/bindings/js.rs
+++ b/components/script/dom/bindings/js.rs
@@ -54,6 +54,7 @@ use layout_interface::TrustedNodeAddress;
use script_task::StackRoots;
use std::cell::{Cell, RefCell};
+use std::default::Default;
use std::kinds::marker::ContravariantLifetime;
use std::mem;
@@ -192,6 +193,62 @@ impl<T: Reflectable> Reflectable for JS<T> {
}
}
+/// A mutable `JS<T>` value, with nullability represented by an enclosing
+/// Option wrapper. Must be used in place of traditional internal mutability
+/// to ensure that the proper GC barriers are enforced.
+#[must_root]
+#[jstraceable]
+pub struct MutNullableJS<T: Reflectable> {
+ ptr: Cell<Option<JS<T>>>
+}
+
+impl<T: Assignable<U>, U: Reflectable> MutNullableJS<U> {
+ pub fn new(initial: Option<T>) -> MutNullableJS<U> {
+ MutNullableJS {
+ ptr: Cell::new(initial.map(|initial| {
+ unsafe { initial.get_js() }
+ }))
+ }
+ }
+}
+
+impl<T: Reflectable> Default for MutNullableJS<T> {
+ fn default() -> MutNullableJS<T> {
+ MutNullableJS {
+ ptr: Cell::new(None)
+ }
+ }
+}
+
+impl<T: Reflectable> MutNullableJS<T> {
+ /// Store an unrooted value in this field. This is safe under the
+ /// assumption that `MutNullableJS<T>` values are only used as fields in
+ /// DOM types that are reachable in the GC graph, so this unrooted value
+ /// becomes transitively rooted for the lifetime of its new owner.
+ pub fn assign<U: Assignable<T>>(&self, val: Option<U>) {
+ self.ptr.set(val.map(|val| {
+ unsafe { val.get_js() }
+ }));
+ }
+
+ /// Set the inner value to null, without making API users jump through
+ /// useless type-ascription hoops.
+ pub fn clear(&self) {
+ self.assign(None::<JS<T>>);
+ }
+
+ /// Retrieve a copy of the current optional inner value.
+ pub fn get(&self) -> Option<Temporary<T>> {
+ self.ptr.get().map(Temporary::new)
+ }
+
+ /// Retrieve a copy of the inner optional `JS<T>`. For use by layout, which
+ /// can't use safe types like Temporary.
+ pub unsafe fn get_inner(&self) -> Option<JS<T>> {
+ self.ptr.get()
+ }
+}
+
impl<T: Reflectable> JS<T> {
/// Returns an unsafe pointer to the interior of this JS object without touching the borrow
/// flags. This is the only method that be safely accessed from layout. (The fact that this
@@ -245,7 +302,7 @@ impl<'a, 'b, T: Reflectable> OptionalRootedReference<T> for Option<Option<Root<'
/// Trait that allows extracting a `JS<T>` value from a variety of rooting-related containers,
/// which in general is an unsafe operation since they can outlive the rooted lifetime of the
/// original value.
-/*definitely not public*/ trait Assignable<T> {
+pub trait Assignable<T> {
unsafe fn get_js(&self) -> JS<T>;
}