Create a replacement for Cell<SM primitive>. Fixes #4337.

This commit is contained in:
Josh Matthews 2014-12-16 21:23:24 -05:00
parent b9edc2243a
commit 8ff3e6bbdc
4 changed files with 45 additions and 13 deletions

View file

@ -45,11 +45,13 @@
//! - `OptionalSettable`: allows assigning `Option` values of `JSRef`/`Temporary` to fields of `Option<JS<T>>` //! - `OptionalSettable`: allows assigning `Option` values of `JSRef`/`Temporary` to fields of `Option<JS<T>>`
//! - `RootedReference`: makes obtaining an `Option<JSRef<T>>` from an `Option<Root<T>>` easy //! - `RootedReference`: makes obtaining an `Option<JSRef<T>>` from an `Option<Root<T>>` easy
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflector, Reflectable}; use dom::bindings::utils::{Reflector, Reflectable};
use dom::node::Node; use dom::node::Node;
use dom::xmlhttprequest::{XMLHttpRequest, TrustedXHRAddress}; use dom::xmlhttprequest::{XMLHttpRequest, TrustedXHRAddress};
use dom::worker::{Worker, TrustedWorkerAddress}; use dom::worker::{Worker, TrustedWorkerAddress};
use js::jsapi::JSObject; use js::jsapi::JSObject;
use js::jsval::JSVal;
use layout_interface::TrustedNodeAddress; use layout_interface::TrustedNodeAddress;
use script_task::StackRoots; use script_task::StackRoots;
@ -194,6 +196,40 @@ impl<T: Reflectable> Reflectable for JS<T> {
} }
} }
pub trait HeapGCValue: JSTraceable {
}
impl HeapGCValue for JSVal {
}
impl<T: Reflectable> HeapGCValue for JS<T> {
}
/// A mutable holder for a GC-owned SpiderMonkey value stored on the heap.
/// Must be used in place of traditional interior mutability to ensure proper
/// GC barriers are enforced.
#[must_root]
#[jstraceable]
pub struct MutHeap<T: HeapGCValue+Copy> {
val: Cell<T>,
}
impl<T: HeapGCValue+Copy> MutHeap<T> {
pub fn new(initial: T) -> MutHeap<T> {
MutHeap {
val: Cell::new(initial),
}
}
pub fn set(&self, val: T) {
self.val.set(val)
}
pub fn get(&self) -> T {
self.val.get()
}
}
/// A mutable `JS<T>` value, with nullability represented by an enclosing /// A mutable `JS<T>` value, with nullability represented by an enclosing
/// Option wrapper. Must be used in place of traditional internal mutability /// Option wrapper. Must be used in place of traditional internal mutability
/// to ensure that the proper GC barriers are enforced. /// to ensure that the proper GC barriers are enforced.

View file

@ -8,19 +8,17 @@ use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::InheritTypes::{EventCast, CustomEventDerived}; use dom::bindings::codegen::InheritTypes::{EventCast, CustomEventDerived};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::{JSRef, Temporary, MutHeap};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, EventTypeId}; use dom::event::{Event, EventTypeId};
use js::jsapi::JSContext; use js::jsapi::JSContext;
use js::jsval::{JSVal, NullValue}; use js::jsval::{JSVal, NullValue};
use servo_util::str::DOMString; use servo_util::str::DOMString;
use std::cell::Cell;
#[dom_struct] #[dom_struct]
pub struct CustomEvent { pub struct CustomEvent {
event: Event, event: Event,
detail: Cell<JSVal>, detail: MutHeap<JSVal>,
} }
impl CustomEventDerived for Event { impl CustomEventDerived for Event {
@ -33,7 +31,7 @@ impl CustomEvent {
fn new_inherited(type_id: EventTypeId) -> CustomEvent { fn new_inherited(type_id: EventTypeId) -> CustomEvent {
CustomEvent { CustomEvent {
event: Event::new_inherited(type_id), event: Event::new_inherited(type_id),
detail: Cell::new(NullValue()), detail: MutHeap::new(NullValue()),
} }
} }

View file

@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::ErrorEventBinding::ErrorEventMethods;
use dom::bindings::codegen::InheritTypes::{EventCast, ErrorEventDerived}; use dom::bindings::codegen::InheritTypes::{EventCast, ErrorEventDerived};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::{JSRef, Temporary, MutHeap};
use js::jsapi::JSContext; use js::jsapi::JSContext;
use dom::bindings::trace::JSTraceable; use dom::bindings::trace::JSTraceable;
@ -27,7 +27,7 @@ pub struct ErrorEvent {
filename: DOMRefCell<DOMString>, filename: DOMRefCell<DOMString>,
lineno: Cell<u32>, lineno: Cell<u32>,
colno: Cell<u32>, colno: Cell<u32>,
error: Cell<JSVal> error: MutHeap<JSVal>,
} }
impl ErrorEventDerived for Event { impl ErrorEventDerived for Event {
@ -44,7 +44,7 @@ impl ErrorEvent {
filename: DOMRefCell::new("".to_string()), filename: DOMRefCell::new("".to_string()),
lineno: Cell::new(0), lineno: Cell::new(0),
colno: Cell::new(0), colno: Cell::new(0),
error: Cell::new(NullValue()) error: MutHeap::new(NullValue())
} }
} }

View file

@ -13,19 +13,17 @@ use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilter;
// use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilterConstants; // use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilterConstants;
use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, OptionalRootable, Temporary}; use dom::bindings::js::{JS, JSRef, OptionalRootable, Temporary, MutHeap};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::document::{Document, DocumentHelpers}; use dom::document::{Document, DocumentHelpers};
use dom::node::{Node, NodeHelpers}; use dom::node::{Node, NodeHelpers};
use std::cell::Cell;
// http://dom.spec.whatwg.org/#interface-treewalker // http://dom.spec.whatwg.org/#interface-treewalker
#[dom_struct] #[dom_struct]
pub struct TreeWalker { pub struct TreeWalker {
reflector_: Reflector, reflector_: Reflector,
root_node: JS<Node>, root_node: JS<Node>,
current_node: Cell<JS<Node>>, current_node: MutHeap<JS<Node>>,
what_to_show: u32, what_to_show: u32,
filter: Filter filter: Filter
} }
@ -37,7 +35,7 @@ impl TreeWalker {
TreeWalker { TreeWalker {
reflector_: Reflector::new(), reflector_: Reflector::new(),
root_node: JS::from_rooted(root_node), root_node: JS::from_rooted(root_node),
current_node: Cell::new(JS::from_rooted(root_node)), current_node: MutHeap::new(JS::from_rooted(root_node)),
what_to_show: what_to_show, what_to_show: what_to_show,
filter: filter filter: filter
} }