servo: Merge #3531 - Implement MutNullableJS for mutable, nullable member pointers to DOM objects (from Ms2ger:MutNullableJS); r=Ms2ger

Extracted from #3527.

Source-Repo: https://github.com/servo/servo
Source-Revision: bae5440689c67f425f94ec27bf0f61ff955dc290
This commit is contained in:
Josh Matthews 2014-10-01 09:09:28 -06:00
Родитель 5ac3634894
Коммит 179c7b7dcc
11 изменённых файлов: 171 добавлений и 109 удалений

Просмотреть файл

@ -54,6 +54,7 @@ use layout_interface::TrustedNodeAddress;
use script_task::StackRoots; use script_task::StackRoots;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::default::Default;
use std::kinds::marker::ContravariantLifetime; use std::kinds::marker::ContravariantLifetime;
use std::mem; 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> { impl<T: Reflectable> JS<T> {
/// Returns an unsafe pointer to the interior of this JS object without touching the borrow /// 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 /// 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, /// 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 /// which in general is an unsafe operation since they can outlive the rooted lifetime of the
/// original value. /// original value.
/*definitely not public*/ trait Assignable<T> { pub trait Assignable<T> {
unsafe fn get_js(&self) -> JS<T>; unsafe fn get_js(&self) -> JS<T>;
} }

Просмотреть файл

@ -21,7 +21,7 @@ use dom::bindings::error::{ErrorResult, Fallible, NotSupported, InvalidCharacter
use dom::bindings::error::{HierarchyRequest, NamespaceError}; use dom::bindings::error::{HierarchyRequest, NamespaceError};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::global; use dom::bindings::global;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable, TemporaryPushable}; use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary, OptionalSettable, TemporaryPushable};
use dom::bindings::js::OptionalRootable; use dom::bindings::js::OptionalRootable;
use dom::bindings::trace::{Traceable, Untraceable}; use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
@ -57,12 +57,14 @@ use hubbub::hubbub::{QuirksMode, NoQuirks, LimitedQuirks, FullQuirks};
use layout_interface::{DocumentDamageLevel, ContentChangedDocumentDamage}; use layout_interface::{DocumentDamageLevel, ContentChangedDocumentDamage};
use servo_util::namespace; use servo_util::namespace;
use servo_util::str::{DOMString, split_html_space_chars}; use servo_util::str::{DOMString, split_html_space_chars};
use string_cache::Atom; use string_cache::Atom;
use url::Url;
use std::collections::hashmap::HashMap; use std::collections::hashmap::HashMap;
use std::ascii::StrAsciiExt; use std::ascii::StrAsciiExt;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use url::Url; use std::default::Default;
use time; use time;
#[deriving(PartialEq)] #[deriving(PartialEq)]
@ -79,7 +81,7 @@ pub struct Document {
reflector_: Reflector, reflector_: Reflector,
pub window: JS<Window>, pub window: JS<Window>,
idmap: Traceable<RefCell<HashMap<Atom, Vec<JS<Element>>>>>, idmap: Traceable<RefCell<HashMap<Atom, Vec<JS<Element>>>>>,
implementation: Cell<Option<JS<DOMImplementation>>>, implementation: MutNullableJS<DOMImplementation>,
content_type: DOMString, content_type: DOMString,
last_modified: Traceable<RefCell<Option<DOMString>>>, last_modified: Traceable<RefCell<Option<DOMString>>>,
pub encoding_name: Traceable<RefCell<DOMString>>, pub encoding_name: Traceable<RefCell<DOMString>>,
@ -288,7 +290,7 @@ impl Document {
reflector_: Reflector::new(), reflector_: Reflector::new(),
window: JS::from_rooted(window), window: JS::from_rooted(window),
idmap: Traceable::new(RefCell::new(HashMap::new())), idmap: Traceable::new(RefCell::new(HashMap::new())),
implementation: Cell::new(None), implementation: Default::default(),
content_type: match content_type { content_type: match content_type {
Some(string) => string.clone(), Some(string) => string.clone(),
None => match is_html_document { None => match is_html_document {
@ -382,7 +384,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
if self.implementation.get().is_none() { if self.implementation.get().is_none() {
self.implementation.assign(Some(DOMImplementation::new(self))); self.implementation.assign(Some(DOMImplementation::new(self)));
} }
Temporary::new(self.implementation.get().as_ref().unwrap().clone()) self.implementation.get().unwrap()
} }
// http://dom.spec.whatwg.org/#dom-document-url // http://dom.spec.whatwg.org/#dom-document-url

Просмотреть файл

@ -12,7 +12,7 @@ use dom::bindings::codegen::Bindings::ElementBinding;
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods; use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
use dom::bindings::codegen::InheritTypes::{ElementDerived, NodeCast}; use dom::bindings::codegen::InheritTypes::{ElementDerived, NodeCast};
use dom::bindings::js::{JS, JSRef, Temporary, TemporaryPushable}; use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary, TemporaryPushable};
use dom::bindings::js::{OptionalSettable, OptionalRootable, Root}; use dom::bindings::js::{OptionalSettable, OptionalRootable, Root};
use dom::bindings::trace::Traceable; use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
@ -38,7 +38,8 @@ use servo_util::namespace;
use servo_util::str::DOMString; use servo_util::str::DOMString;
use std::ascii::StrAsciiExt; use std::ascii::StrAsciiExt;
use std::cell::{Cell, RefCell}; use std::cell::RefCell;
use std::default::Default;
use std::mem; use std::mem;
use string_cache::{Atom, Namespace}; use string_cache::{Atom, Namespace};
@ -51,8 +52,8 @@ pub struct Element {
pub prefix: Option<DOMString>, pub prefix: Option<DOMString>,
pub attrs: RefCell<Vec<JS<Attr>>>, pub attrs: RefCell<Vec<JS<Attr>>>,
pub style_attribute: Traceable<RefCell<Option<style::PropertyDeclarationBlock>>>, pub style_attribute: Traceable<RefCell<Option<style::PropertyDeclarationBlock>>>,
pub attr_list: Cell<Option<JS<NamedNodeMap>>>, pub attr_list: MutNullableJS<NamedNodeMap>,
class_list: Cell<Option<JS<DOMTokenList>>>, class_list: MutNullableJS<DOMTokenList>,
} }
impl ElementDerived for EventTarget { impl ElementDerived for EventTarget {
@ -156,8 +157,8 @@ impl Element {
namespace: namespace, namespace: namespace,
prefix: prefix, prefix: prefix,
attrs: RefCell::new(vec!()), attrs: RefCell::new(vec!()),
attr_list: Cell::new(None), attr_list: Default::default(),
class_list: Cell::new(None), class_list: Default::default(),
style_attribute: Traceable::new(RefCell::new(None)), style_attribute: Traceable::new(RefCell::new(None)),
} }
} }
@ -557,31 +558,25 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
// http://dom.spec.whatwg.org/#dom-element-classlist // http://dom.spec.whatwg.org/#dom-element-classlist
fn ClassList(self) -> Temporary<DOMTokenList> { fn ClassList(self) -> Temporary<DOMTokenList> {
match self.class_list.get() { if self.class_list.get().is_none() {
Some(class_list) => Temporary::new(class_list), let class_list = DOMTokenList::new(self, "class");
None => { self.class_list.assign(Some(class_list));
let class_list = DOMTokenList::new(self, "class").root();
self.class_list.assign(Some(class_list.deref().clone()));
Temporary::from_rooted(*class_list)
}
} }
self.class_list.get().unwrap()
} }
// http://dom.spec.whatwg.org/#dom-element-attributes // http://dom.spec.whatwg.org/#dom-element-attributes
fn Attributes(self) -> Temporary<NamedNodeMap> { fn Attributes(self) -> Temporary<NamedNodeMap> {
match self.attr_list.get() { if self.attr_list.get().is_none() {
None => (), let doc = {
Some(ref list) => return Temporary::new(list.clone()), let node: JSRef<Node> = NodeCast::from_ref(self);
node.owner_doc().root()
};
let window = doc.deref().window.root();
let list = NamedNodeMap::new(*window, self);
self.attr_list.assign(Some(list));
} }
self.attr_list.get().unwrap()
let doc = {
let node: JSRef<Node> = NodeCast::from_ref(self);
node.owner_doc().root()
};
let window = doc.deref().window.root();
let list = NamedNodeMap::new(*window, self);
self.attr_list.assign(Some(list));
Temporary::new(self.attr_list.get().as_ref().unwrap().clone())
} }
// http://dom.spec.whatwg.org/#dom-element-getattribute // http://dom.spec.whatwg.org/#dom-element-getattribute

Просмотреть файл

@ -6,12 +6,13 @@ use dom::bindings::codegen::Bindings::EventBinding;
use dom::bindings::codegen::Bindings::EventBinding::{EventConstants, EventMethods}; use dom::bindings::codegen::Bindings::EventBinding::{EventConstants, EventMethods};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::js::{MutNullableJS, JSRef, Temporary};
use dom::bindings::trace::Traceable; use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
use servo_util::str::DOMString; use servo_util::str::DOMString;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::default::Default;
use time; use time;
@ -40,8 +41,8 @@ pub enum EventTypeId {
pub struct Event { pub struct Event {
pub type_id: EventTypeId, pub type_id: EventTypeId,
reflector_: Reflector, reflector_: Reflector,
pub current_target: Cell<Option<JS<EventTarget>>>, pub current_target: MutNullableJS<EventTarget>,
pub target: Cell<Option<JS<EventTarget>>>, pub target: MutNullableJS<EventTarget>,
type_: Traceable<RefCell<DOMString>>, type_: Traceable<RefCell<DOMString>>,
pub phase: Traceable<Cell<EventPhase>>, pub phase: Traceable<Cell<EventPhase>>,
pub canceled: Traceable<Cell<bool>>, pub canceled: Traceable<Cell<bool>>,
@ -60,8 +61,8 @@ impl Event {
Event { Event {
type_id: type_id, type_id: type_id,
reflector_: Reflector::new(), reflector_: Reflector::new(),
current_target: Cell::new(None), current_target: Default::default(),
target: Cell::new(None), target: Default::default(),
phase: Traceable::new(Cell::new(PhaseNone)), phase: Traceable::new(Cell::new(PhaseNone)),
type_: Traceable::new(RefCell::new("".to_string())), type_: Traceable::new(RefCell::new("".to_string())),
canceled: Traceable::new(Cell::new(false)), canceled: Traceable::new(Cell::new(false)),
@ -108,11 +109,11 @@ impl<'a> EventMethods for JSRef<'a, Event> {
} }
fn GetTarget(self) -> Option<Temporary<EventTarget>> { fn GetTarget(self) -> Option<Temporary<EventTarget>> {
self.target.get().as_ref().map(|target| Temporary::new(target.clone())) self.target.get()
} }
fn GetCurrentTarget(self) -> Option<Temporary<EventTarget>> { fn GetCurrentTarget(self) -> Option<Temporary<EventTarget>> {
self.current_target.get().as_ref().map(|target| Temporary::new(target.clone())) self.current_target.get()
} }
fn DefaultPrevented(self) -> bool { fn DefaultPrevented(self) -> bool {
@ -158,7 +159,7 @@ impl<'a> EventMethods for JSRef<'a, Event> {
self.stop_immediate.deref().set(false); self.stop_immediate.deref().set(false);
self.canceled.deref().set(false); self.canceled.deref().set(false);
self.trusted.deref().set(false); self.trusted.deref().set(false);
self.target.set(None); self.target.clear();
*self.type_.deref().borrow_mut() = type_; *self.type_.deref().borrow_mut() = type_;
self.bubbles.deref().set(bubbles); self.bubbles.deref().set(bubbles);
self.cancelable.deref().set(cancelable); self.cancelable.deref().set(cancelable);

Просмотреть файл

@ -133,7 +133,7 @@ pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
event.dispatching.deref().set(false); event.dispatching.deref().set(false);
event.phase.deref().set(PhaseNone); event.phase.deref().set(PhaseNone);
event.current_target.set(None); event.current_target.clear();
!event.DefaultPrevented() !event.DefaultPrevented()
} }

Просмотреть файл

@ -9,7 +9,7 @@ use dom::bindings::codegen::InheritTypes::{UIEventCast, MouseEventDerived};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::global; use dom::bindings::global;
use dom::bindings::js::{JS, JSRef, RootedReference, Temporary, OptionalSettable}; use dom::bindings::js::{MutNullableJS, JSRef, RootedReference, Temporary, OptionalSettable};
use dom::bindings::trace::Traceable; use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, MouseEventTypeId}; use dom::event::{Event, MouseEventTypeId};
@ -18,6 +18,7 @@ use dom::uievent::UIEvent;
use dom::window::Window; use dom::window::Window;
use servo_util::str::DOMString; use servo_util::str::DOMString;
use std::cell::Cell; use std::cell::Cell;
use std::default::Default;
#[jstraceable] #[jstraceable]
#[must_root] #[must_root]
@ -32,7 +33,7 @@ pub struct MouseEvent {
pub alt_key: Traceable<Cell<bool>>, pub alt_key: Traceable<Cell<bool>>,
pub meta_key: Traceable<Cell<bool>>, pub meta_key: Traceable<Cell<bool>>,
pub button: Traceable<Cell<i16>>, pub button: Traceable<Cell<i16>>,
pub related_target: Cell<Option<JS<EventTarget>>> pub related_target: MutNullableJS<EventTarget>
} }
impl MouseEventDerived for Event { impl MouseEventDerived for Event {
@ -54,7 +55,7 @@ impl MouseEvent {
alt_key: Traceable::new(Cell::new(false)), alt_key: Traceable::new(Cell::new(false)),
meta_key: Traceable::new(Cell::new(false)), meta_key: Traceable::new(Cell::new(false)),
button: Traceable::new(Cell::new(0)), button: Traceable::new(Cell::new(0)),
related_target: Cell::new(None) related_target: Default::default(),
} }
} }
@ -142,7 +143,7 @@ impl<'a> MouseEventMethods for JSRef<'a, MouseEvent> {
} }
fn GetRelatedTarget(self) -> Option<Temporary<EventTarget>> { fn GetRelatedTarget(self) -> Option<Temporary<EventTarget>> {
self.related_target.get().clone().map(|target| Temporary::new(target)) self.related_target.get()
} }
fn InitMouseEvent(self, fn InitMouseEvent(self,

Просмотреть файл

@ -22,9 +22,9 @@ use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementDerived;
use dom::bindings::error::{Fallible, NotFound, HierarchyRequest, Syntax}; use dom::bindings::error::{Fallible, NotFound, HierarchyRequest, Syntax};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::global; use dom::bindings::global;
use dom::bindings::js::{JS, JSRef, RootedReference, Temporary, Root, OptionalUnrootable}; use dom::bindings::js::{JS, JSRef, RootedReference, Temporary, Root};
use dom::bindings::js::{OptionalSettable, TemporaryPushable, OptionalRootedRootable}; use dom::bindings::js::{OptionalSettable, TemporaryPushable, OptionalRootedRootable};
use dom::bindings::js::{ResultRootable, OptionalRootable}; use dom::bindings::js::{ResultRootable, OptionalRootable, MutNullableJS};
use dom::bindings::trace::{Traceable, Untraceable}; use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils; use dom::bindings::utils;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
@ -57,7 +57,8 @@ use js::jsapi::{JSContext, JSObject, JSRuntime};
use js::jsfriendapi; use js::jsfriendapi;
use libc; use libc;
use libc::uintptr_t; use libc::uintptr_t;
use std::cell::{Cell, RefCell, Ref, RefMut}; use std::cell::{RefCell, Ref, RefMut};
use std::default::Default;
use std::iter::{Map, Filter}; use std::iter::{Map, Filter};
use std::mem; use std::mem;
use style; use style;
@ -80,25 +81,25 @@ pub struct Node {
type_id: NodeTypeId, type_id: NodeTypeId,
/// The parent of this node. /// The parent of this node.
parent_node: Cell<Option<JS<Node>>>, parent_node: MutNullableJS<Node>,
/// The first child of this node. /// The first child of this node.
first_child: Cell<Option<JS<Node>>>, first_child: MutNullableJS<Node>,
/// The last child of this node. /// The last child of this node.
last_child: Cell<Option<JS<Node>>>, last_child: MutNullableJS<Node>,
/// The next sibling of this node. /// The next sibling of this node.
next_sibling: Cell<Option<JS<Node>>>, next_sibling: MutNullableJS<Node>,
/// The previous sibling of this node. /// The previous sibling of this node.
prev_sibling: Cell<Option<JS<Node>>>, prev_sibling: MutNullableJS<Node>,
/// The document that this node belongs to. /// The document that this node belongs to.
owner_doc: Cell<Option<JS<Document>>>, owner_doc: MutNullableJS<Document>,
/// The live list of children return by .childNodes. /// The live list of children return by .childNodes.
child_list: Cell<Option<JS<NodeList>>>, child_list: MutNullableJS<NodeList>,
/// A bitfield of flags for node items. /// A bitfield of flags for node items.
flags: Traceable<RefCell<NodeFlags>>, flags: Traceable<RefCell<NodeFlags>>,
@ -358,9 +359,9 @@ impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
} }
} }
child.prev_sibling.set(None); child.prev_sibling.clear();
child.next_sibling.set(None); child.next_sibling.clear();
child.parent_node.set(None); child.parent_node.clear();
} }
} }
@ -461,25 +462,25 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
} }
fn parent_node(self) -> Option<Temporary<Node>> { fn parent_node(self) -> Option<Temporary<Node>> {
self.deref().parent_node.get().map(|node| Temporary::new(node)) self.deref().parent_node.get()
} }
fn first_child(self) -> Option<Temporary<Node>> { fn first_child(self) -> Option<Temporary<Node>> {
self.deref().first_child.get().map(|node| Temporary::new(node)) self.deref().first_child.get()
} }
fn last_child(self) -> Option<Temporary<Node>> { fn last_child(self) -> Option<Temporary<Node>> {
self.deref().last_child.get().map(|node| Temporary::new(node)) self.deref().last_child.get()
} }
/// Returns the previous sibling of this node. Fails if this node is borrowed mutably. /// Returns the previous sibling of this node. Fails if this node is borrowed mutably.
fn prev_sibling(self) -> Option<Temporary<Node>> { fn prev_sibling(self) -> Option<Temporary<Node>> {
self.deref().prev_sibling.get().map(|node| Temporary::new(node)) self.deref().prev_sibling.get()
} }
/// Returns the next sibling of this node. Fails if this node is borrowed mutably. /// Returns the next sibling of this node. Fails if this node is borrowed mutably.
fn next_sibling(self) -> Option<Temporary<Node>> { fn next_sibling(self) -> Option<Temporary<Node>> {
self.deref().next_sibling.get().map(|node| Temporary::new(node)) self.deref().next_sibling.get()
} }
#[inline] #[inline]
@ -578,7 +579,7 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
fn is_parent_of(self, child: JSRef<Node>) -> bool { fn is_parent_of(self, child: JSRef<Node>) -> bool {
match child.parent_node() { match child.parent_node() {
Some(parent) if parent == Temporary::from_rooted(self) => true, Some(ref parent) if parent == &Temporary::from_rooted(self) => true,
_ => false _ => false
} }
} }
@ -651,7 +652,7 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
} }
fn owner_doc(self) -> Temporary<Document> { fn owner_doc(self) -> Temporary<Document> {
Temporary::new(self.owner_doc.get().as_ref().unwrap().clone()) self.owner_doc.get().unwrap()
} }
fn set_owner_doc(self, document: JSRef<Document>) { fn set_owner_doc(self, document: JSRef<Document>) {
@ -777,32 +778,32 @@ impl LayoutNodeHelpers for JS<Node> {
#[inline] #[inline]
unsafe fn parent_node_ref(&self) -> Option<JS<Node>> { unsafe fn parent_node_ref(&self) -> Option<JS<Node>> {
(*self.unsafe_get()).parent_node.get() (*self.unsafe_get()).parent_node.get_inner()
} }
#[inline] #[inline]
unsafe fn first_child_ref(&self) -> Option<JS<Node>> { unsafe fn first_child_ref(&self) -> Option<JS<Node>> {
(*self.unsafe_get()).first_child.get() (*self.unsafe_get()).first_child.get_inner()
} }
#[inline] #[inline]
unsafe fn last_child_ref(&self) -> Option<JS<Node>> { unsafe fn last_child_ref(&self) -> Option<JS<Node>> {
(*self.unsafe_get()).last_child.get() (*self.unsafe_get()).last_child.get_inner()
} }
#[inline] #[inline]
unsafe fn prev_sibling_ref(&self) -> Option<JS<Node>> { unsafe fn prev_sibling_ref(&self) -> Option<JS<Node>> {
(*self.unsafe_get()).prev_sibling.get() (*self.unsafe_get()).prev_sibling.get_inner()
} }
#[inline] #[inline]
unsafe fn next_sibling_ref(&self) -> Option<JS<Node>> { unsafe fn next_sibling_ref(&self) -> Option<JS<Node>> {
(*self.unsafe_get()).next_sibling.get() (*self.unsafe_get()).next_sibling.get_inner()
} }
#[inline] #[inline]
unsafe fn owner_doc_for_layout(&self) -> JS<Document> { unsafe fn owner_doc_for_layout(&self) -> JS<Document> {
(*self.unsafe_get()).owner_doc.get().unwrap() (*self.unsafe_get()).owner_doc.get_inner().unwrap()
} }
} }
@ -1025,13 +1026,13 @@ impl Node {
eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)), eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)),
type_id: type_id, type_id: type_id,
parent_node: Cell::new(None), parent_node: Default::default(),
first_child: Cell::new(None), first_child: Default::default(),
last_child: Cell::new(None), last_child: Default::default(),
next_sibling: Cell::new(None), next_sibling: Default::default(),
prev_sibling: Cell::new(None), prev_sibling: Default::default(),
owner_doc: Cell::new(doc.unrooted()), owner_doc: MutNullableJS::new(doc),
child_list: Cell::new(None), child_list: Default::default(),
flags: Traceable::new(RefCell::new(NodeFlags::new(type_id))), flags: Traceable::new(RefCell::new(NodeFlags::new(type_id))),
@ -1304,7 +1305,7 @@ impl Node {
fn pre_remove(child: JSRef<Node>, parent: JSRef<Node>) -> Fallible<Temporary<Node>> { fn pre_remove(child: JSRef<Node>, parent: JSRef<Node>) -> Fallible<Temporary<Node>> {
// Step 1. // Step 1.
match child.parent_node() { match child.parent_node() {
Some(node) if node != Temporary::from_rooted(parent) => return Err(NotFound), Some(ref node) if node != &Temporary::from_rooted(parent) => return Err(NotFound),
_ => () _ => ()
} }
@ -1535,7 +1536,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
// http://dom.spec.whatwg.org/#dom-node-parentnode // http://dom.spec.whatwg.org/#dom-node-parentnode
fn GetParentNode(self) -> Option<Temporary<Node>> { fn GetParentNode(self) -> Option<Temporary<Node>> {
self.parent_node.get().map(|node| Temporary::new(node)) self.parent_node.get()
} }
// http://dom.spec.whatwg.org/#dom-node-parentelement // http://dom.spec.whatwg.org/#dom-node-parentelement
@ -1558,34 +1559,34 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
fn ChildNodes(self) -> Temporary<NodeList> { fn ChildNodes(self) -> Temporary<NodeList> {
match self.child_list.get() { match self.child_list.get() {
None => (), None => (),
Some(ref list) => return Temporary::new(list.clone()), Some(list) => return list,
} }
let doc = self.owner_doc().root(); let doc = self.owner_doc().root();
let window = doc.deref().window.root(); let window = doc.deref().window.root();
let child_list = NodeList::new_child_list(*window, self); let child_list = NodeList::new_child_list(*window, self);
self.child_list.assign(Some(child_list)); self.child_list.assign(Some(child_list));
Temporary::new(self.child_list.get().as_ref().unwrap().clone()) self.child_list.get().unwrap()
} }
// http://dom.spec.whatwg.org/#dom-node-firstchild // http://dom.spec.whatwg.org/#dom-node-firstchild
fn GetFirstChild(self) -> Option<Temporary<Node>> { fn GetFirstChild(self) -> Option<Temporary<Node>> {
self.first_child.get().map(|node| Temporary::new(node)) self.first_child.get()
} }
// http://dom.spec.whatwg.org/#dom-node-lastchild // http://dom.spec.whatwg.org/#dom-node-lastchild
fn GetLastChild(self) -> Option<Temporary<Node>> { fn GetLastChild(self) -> Option<Temporary<Node>> {
self.last_child.get().map(|node| Temporary::new(node)) self.last_child.get()
} }
// http://dom.spec.whatwg.org/#dom-node-previoussibling // http://dom.spec.whatwg.org/#dom-node-previoussibling
fn GetPreviousSibling(self) -> Option<Temporary<Node>> { fn GetPreviousSibling(self) -> Option<Temporary<Node>> {
self.prev_sibling.get().map(|node| Temporary::new(node)) self.prev_sibling.get()
} }
// http://dom.spec.whatwg.org/#dom-node-nextsibling // http://dom.spec.whatwg.org/#dom-node-nextsibling
fn GetNextSibling(self) -> Option<Temporary<Node>> { fn GetNextSibling(self) -> Option<Temporary<Node>> {
self.next_sibling.get().map(|node| Temporary::new(node)) self.next_sibling.get()
} }
// http://dom.spec.whatwg.org/#dom-node-nodevalue // http://dom.spec.whatwg.org/#dom-node-nodevalue

Просмотреть файл

@ -9,7 +9,7 @@ use dom::bindings::codegen::InheritTypes::{EventCast, UIEventDerived};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::global; use dom::bindings::global;
use dom::bindings::js::{JS, JSRef, RootedReference, Temporary, OptionalSettable}; use dom::bindings::js::{MutNullableJS, JSRef, RootedReference, Temporary, OptionalSettable};
use dom::bindings::trace::Traceable; use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, EventTypeId, UIEventTypeId}; use dom::event::{Event, EventTypeId, UIEventTypeId};
@ -17,12 +17,13 @@ use dom::window::Window;
use servo_util::str::DOMString; use servo_util::str::DOMString;
use std::cell::Cell; use std::cell::Cell;
use std::default::Default;
#[jstraceable] #[jstraceable]
#[must_root] #[must_root]
pub struct UIEvent { pub struct UIEvent {
pub event: Event, pub event: Event,
view: Cell<Option<JS<Window>>>, view: MutNullableJS<Window>,
detail: Traceable<Cell<i32>> detail: Traceable<Cell<i32>>
} }
@ -36,7 +37,7 @@ impl UIEvent {
pub fn new_inherited(type_id: EventTypeId) -> UIEvent { pub fn new_inherited(type_id: EventTypeId) -> UIEvent {
UIEvent { UIEvent {
event: Event::new_inherited(type_id), event: Event::new_inherited(type_id),
view: Cell::new(None), view: Default::default(),
detail: Traceable::new(Cell::new(0)), detail: Traceable::new(Cell::new(0)),
} }
} }
@ -70,7 +71,7 @@ impl UIEvent {
impl<'a> UIEventMethods for JSRef<'a, UIEvent> { impl<'a> UIEventMethods for JSRef<'a, UIEvent> {
fn GetView(self) -> Option<Temporary<Window>> { fn GetView(self) -> Option<Temporary<Window>> {
self.view.get().map(|view| Temporary::new(view)) self.view.get()
} }
fn Detail(self) -> i32 { fn Detail(self) -> i32 {

Просмотреть файл

@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::EventTargetCast; use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::error::{Fallible, InvalidCharacter}; use dom::bindings::error::{Fallible, InvalidCharacter};
use dom::bindings::global; use dom::bindings::global;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable}; use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary, OptionalSettable};
use dom::bindings::trace::{Traceable, Untraceable}; use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::browsercontext::BrowserContext; use dom::browsercontext::BrowserContext;
@ -44,6 +44,7 @@ use std::cell::{Cell, RefCell};
use std::cmp; use std::cmp;
use std::comm::{channel, Sender}; use std::comm::{channel, Sender};
use std::comm::Select; use std::comm::Select;
use std::default::Default;
use std::hash::{Hash, sip}; use std::hash::{Hash, sip};
use std::io::timer::Timer; use std::io::timer::Timer;
use std::ptr; use std::ptr;
@ -81,16 +82,16 @@ pub struct Window {
eventtarget: EventTarget, eventtarget: EventTarget,
pub script_chan: ScriptChan, pub script_chan: ScriptChan,
pub control_chan: ScriptControlChan, pub control_chan: ScriptControlChan,
console: Cell<Option<JS<Console>>>, console: MutNullableJS<Console>,
location: Cell<Option<JS<Location>>>, location: MutNullableJS<Location>,
navigator: Cell<Option<JS<Navigator>>>, navigator: MutNullableJS<Navigator>,
pub image_cache_task: ImageCacheTask, pub image_cache_task: ImageCacheTask,
pub active_timers: Traceable<RefCell<HashMap<TimerId, TimerHandle>>>, pub active_timers: Traceable<RefCell<HashMap<TimerId, TimerHandle>>>,
next_timer_handle: Traceable<Cell<i32>>, next_timer_handle: Traceable<Cell<i32>>,
pub compositor: Untraceable<Box<ScriptListener+'static>>, pub compositor: Untraceable<Box<ScriptListener+'static>>,
pub browser_context: Traceable<RefCell<Option<BrowserContext>>>, pub browser_context: Traceable<RefCell<Option<BrowserContext>>>,
pub page: Rc<Page>, pub page: Rc<Page>,
performance: Cell<Option<JS<Performance>>>, performance: MutNullableJS<Performance>,
pub navigationStart: u64, pub navigationStart: u64,
pub navigationStartPrecise: f64, pub navigationStartPrecise: f64,
screen: Cell<Option<JS<Screen>>>, screen: Cell<Option<JS<Screen>>>,
@ -225,7 +226,7 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
let location = Location::new(self, page); let location = Location::new(self, page);
self.location.assign(Some(location)); self.location.assign(Some(location));
} }
Temporary::new(self.location.get().as_ref().unwrap().clone()) self.location.get().unwrap()
} }
fn Console(self) -> Temporary<Console> { fn Console(self) -> Temporary<Console> {
@ -233,7 +234,7 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
let console = Console::new(&global::Window(self)); let console = Console::new(&global::Window(self));
self.console.assign(Some(console)); self.console.assign(Some(console));
} }
Temporary::new(self.console.get().as_ref().unwrap().clone()) self.console.get().unwrap()
} }
fn Navigator(self) -> Temporary<Navigator> { fn Navigator(self) -> Temporary<Navigator> {
@ -241,7 +242,7 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
let navigator = Navigator::new(self); let navigator = Navigator::new(self);
self.navigator.assign(Some(navigator)); self.navigator.assign(Some(navigator));
} }
Temporary::new(self.navigator.get().as_ref().unwrap().clone()) self.navigator.get().unwrap()
} }
fn SetTimeout(self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 { fn SetTimeout(self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
@ -289,7 +290,7 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
let performance = Performance::new(self); let performance = Performance::new(self);
self.performance.assign(Some(performance)); self.performance.assign(Some(performance));
} }
Temporary::new(self.performance.get().as_ref().unwrap().clone()) self.performance.get().unwrap()
} }
fn GetOnclick(self) -> Option<EventHandlerNonNull> { fn GetOnclick(self) -> Option<EventHandlerNonNull> {
@ -529,16 +530,16 @@ impl Window {
eventtarget: EventTarget::new_inherited(WindowTypeId), eventtarget: EventTarget::new_inherited(WindowTypeId),
script_chan: script_chan, script_chan: script_chan,
control_chan: control_chan, control_chan: control_chan,
console: Cell::new(None), console: Default::default(),
compositor: Untraceable::new(compositor), compositor: Untraceable::new(compositor),
page: page, page: page,
location: Cell::new(None), location: Default::default(),
navigator: Cell::new(None), navigator: Default::default(),
image_cache_task: image_cache_task, image_cache_task: image_cache_task,
active_timers: Traceable::new(RefCell::new(HashMap::new())), active_timers: Traceable::new(RefCell::new(HashMap::new())),
next_timer_handle: Traceable::new(Cell::new(0)), next_timer_handle: Traceable::new(Cell::new(0)),
browser_context: Traceable::new(RefCell::new(None)), browser_context: Traceable::new(RefCell::new(None)),
performance: Cell::new(None), performance: Default::default(),
navigationStart: time::get_time().sec as u64, navigationStart: time::get_time().sec as u64,
navigationStartPrecise: time::precise_time_s(), navigationStartPrecise: time::precise_time_s(),
screen: Cell::new(None), screen: Cell::new(None),

Просмотреть файл

@ -13,7 +13,7 @@ use dom::bindings::conversions::ToJSValConvertible;
use dom::bindings::error::{Error, ErrorResult, Fallible, InvalidState, InvalidAccess}; use dom::bindings::error::{Error, ErrorResult, Fallible, InvalidState, InvalidAccess};
use dom::bindings::error::{Network, Syntax, Security, Abort, Timeout}; use dom::bindings::error::{Network, Syntax, Security, Abort, Timeout};
use dom::bindings::global::{GlobalField, GlobalRef, WorkerField}; use dom::bindings::global::{GlobalField, GlobalRef, WorkerField};
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootedRootable}; use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary, OptionalRootedRootable};
use dom::bindings::str::ByteString; use dom::bindings::str::ByteString;
use dom::bindings::trace::{Traceable, Untraceable}; use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
@ -53,6 +53,7 @@ use servo_util::task::spawn_named;
use std::ascii::StrAsciiExt; use std::ascii::StrAsciiExt;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::comm::{Sender, Receiver, channel}; use std::comm::{Sender, Receiver, channel};
use std::default::Default;
use std::io::{BufReader, MemWriter, Timer}; use std::io::{BufReader, MemWriter, Timer};
use std::from_str::FromStr; use std::from_str::FromStr;
use std::path::BytesContainer; use std::path::BytesContainer;
@ -115,7 +116,7 @@ pub struct XMLHttpRequest {
status_text: Traceable<RefCell<ByteString>>, status_text: Traceable<RefCell<ByteString>>,
response: Traceable<RefCell<ByteString>>, response: Traceable<RefCell<ByteString>>,
response_type: Traceable<Cell<XMLHttpRequestResponseType>>, response_type: Traceable<Cell<XMLHttpRequestResponseType>>,
response_xml: Cell<Option<JS<Document>>>, response_xml: MutNullableJS<Document>,
response_headers: Untraceable<RefCell<ResponseHeaderCollection>>, response_headers: Untraceable<RefCell<ResponseHeaderCollection>>,
// Associated concepts // Associated concepts
@ -149,7 +150,7 @@ impl XMLHttpRequest {
status_text: Traceable::new(RefCell::new(ByteString::new(vec!()))), status_text: Traceable::new(RefCell::new(ByteString::new(vec!()))),
response: Traceable::new(RefCell::new(ByteString::new(vec!()))), response: Traceable::new(RefCell::new(ByteString::new(vec!()))),
response_type: Traceable::new(Cell::new(_empty)), response_type: Traceable::new(Cell::new(_empty)),
response_xml: Cell::new(None), response_xml: Default::default(),
response_headers: Untraceable::new(RefCell::new(ResponseHeaderCollection::new())), response_headers: Untraceable::new(RefCell::new(ResponseHeaderCollection::new())),
request_method: Untraceable::new(RefCell::new(Get)), request_method: Untraceable::new(RefCell::new(Get)),
@ -667,7 +668,7 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
} }
} }
fn GetResponseXML(self) -> Option<Temporary<Document>> { fn GetResponseXML(self) -> Option<Temporary<Document>> {
self.response_xml.get().map(|response| Temporary::new(response)) self.response_xml.get()
} }
} }

Просмотреть файл

@ -5,7 +5,7 @@
use dom::attr::AttrHelpers; use dom::attr::AttrHelpers;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast}; use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary};
use dom::bindings::js::OptionalRootable; use dom::bindings::js::OptionalRootable;
use dom::bindings::trace::{Traceable, Untraceable}; use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::GlobalStaticData; use dom::bindings::utils::GlobalStaticData;
@ -30,12 +30,14 @@ use servo_net::resource_task::ResourceTask;
use servo_util::str::DOMString; use servo_util::str::DOMString;
use std::cell::{Cell, RefCell, Ref, RefMut}; use std::cell::{Cell, RefCell, Ref, RefMut};
use std::comm::{channel, Receiver, Empty, Disconnected}; use std::comm::{channel, Receiver, Empty, Disconnected};
use std::default::Default;
use std::mem::replace; use std::mem::replace;
use std::rc::Rc; use std::rc::Rc;
use url::Url; use url::Url;
/// Encapsulates a handle to a frame and its associated layout information. /// Encapsulates a handle to a frame and its associated layout information.
#[jstraceable] #[jstraceable]
#[allow(unrooted_must_root)] // FIXME(#3543) should be must_root.
pub struct Page { pub struct Page {
/// Pipeline id associated with this page. /// Pipeline id associated with this page.
pub id: PipelineId, pub id: PipelineId,
@ -78,7 +80,7 @@ pub struct Page {
pub resize_event: Untraceable<Cell<Option<WindowSizeData>>>, pub resize_event: Untraceable<Cell<Option<WindowSizeData>>>,
/// Pending scroll to fragment event, if any /// Pending scroll to fragment event, if any
pub fragment_node: Cell<Option<JS<Element>>>, pub fragment_node: MutNullableJS<Element>,
/// Associated resource task for use by DOM objects like XMLHttpRequest /// Associated resource task for use by DOM objects like XMLHttpRequest
pub resource_task: Untraceable<ResourceTask>, pub resource_task: Untraceable<ResourceTask>,
@ -152,7 +154,7 @@ impl Page {
url: Untraceable::new(RefCell::new(None)), url: Untraceable::new(RefCell::new(None)),
next_subpage_id: Traceable::new(Cell::new(SubpageId(0))), next_subpage_id: Traceable::new(Cell::new(SubpageId(0))),
resize_event: Untraceable::new(Cell::new(None)), resize_event: Untraceable::new(Cell::new(None)),
fragment_node: Cell::new(None), fragment_node: Default::default(),
last_reflow_id: Traceable::new(Cell::new(0)), last_reflow_id: Traceable::new(Cell::new(0)),
resource_task: Untraceable::new(resource_task), resource_task: Untraceable::new(resource_task),
constellation_chan: Untraceable::new(constellation_chan), constellation_chan: Untraceable::new(constellation_chan),