auto merge of #2490 : saneyuki/servo/js, r=jdm

This only change to make `JS<T> ` to a POD type about #1854, except using `Cell`/`RefCell` for interior mutability.

Fix #1854

@jdm r?
This commit is contained in:
bors-servo 2014-05-29 16:21:57 -04:00
commit e511c04935
20 changed files with 212 additions and 161 deletions

View file

@ -136,6 +136,10 @@ pub struct LayoutNode<'a> {
/// Being chained to a ContravariantLifetime prevents `LayoutNode`s from escaping.
pub chain: ContravariantLifetime<'a>,
/// Padding to ensure the transmute `JS<T>` -> `LayoutNode`, `LayoutNode` -> `UnsafeLayoutNode`,
/// and `UnsafeLayoutNode` -> others.
pad: uint
}
impl<'ln> Clone for LayoutNode<'ln> {
@ -143,6 +147,7 @@ impl<'ln> Clone for LayoutNode<'ln> {
LayoutNode {
node: self.node.clone(),
chain: self.chain,
pad: 0,
}
}
}
@ -160,6 +165,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
LayoutNode {
node: node.transmute_copy(),
chain: self.chain,
pad: 0,
}
}
@ -175,7 +181,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
fn first_child(&self) -> Option<LayoutNode<'ln>> {
unsafe {
self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(node))
self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(&node))
}
}
@ -196,6 +202,7 @@ impl<'ln> LayoutNode<'ln> {
f(LayoutNode {
node: node,
chain: ContravariantLifetime,
pad: 0,
})
}
@ -223,19 +230,19 @@ impl<'ln> LayoutNode<'ln> {
impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
fn parent_node(&self) -> Option<LayoutNode<'ln>> {
unsafe {
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(node))
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(&node))
}
}
fn prev_sibling(&self) -> Option<LayoutNode<'ln>> {
unsafe {
self.node.prev_sibling_ref().map(|node| self.new_with_this_lifetime(node))
self.node.prev_sibling_ref().map(|node| self.new_with_this_lifetime(&node))
}
}
fn next_sibling(&self) -> Option<LayoutNode<'ln>> {
unsafe {
self.node.next_sibling_ref().map(|node| self.new_with_this_lifetime(node))
self.node.next_sibling_ref().map(|node| self.new_with_this_lifetime(&node))
}
}
@ -425,6 +432,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
node: LayoutNode {
node: node.transmute_copy(),
chain: self.node.chain,
pad: 0,
},
pseudo: Normal,
}
@ -463,7 +471,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
}
unsafe {
self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(node))
self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(&node))
}
}
@ -513,10 +521,10 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
/// Returns the next sibling of this node. Unsafe and private because this can lead to races.
unsafe fn next_sibling(&self) -> Option<ThreadSafeLayoutNode<'ln>> {
if self.pseudo == Before || self.pseudo == BeforeBlock {
return self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(node))
return self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(&node))
}
self.get_jsmanaged().next_sibling_ref().map(|node| self.new_with_this_lifetime(node))
self.get_jsmanaged().next_sibling_ref().map(|node| self.new_with_this_lifetime(&node))
}
/// Returns an iterator over this node's children.

View file

@ -13,6 +13,7 @@ use dom::virtualmethods::vtable_for;
use servo_util::namespace;
use servo_util::namespace::Namespace;
use servo_util::str::DOMString;
use std::cell::Cell;
pub enum AttrSettingType {
FirstSetAttr,
@ -29,7 +30,7 @@ pub struct Attr {
pub prefix: Option<DOMString>,
/// the element that owns this attribute.
pub owner: JS<Element>,
pub owner: Cell<JS<Element>>,
}
impl Reflectable for Attr {
@ -53,7 +54,7 @@ impl Attr {
name: name, //TODO: Intern attribute names
namespace: namespace,
prefix: prefix,
owner: owner.unrooted(),
owner: Cell::new(owner.unrooted()),
}
}
@ -65,7 +66,7 @@ impl Attr {
}
pub fn set_value(&mut self, set_type: AttrSettingType, value: DOMString) {
let mut owner = self.owner.root();
let mut owner = self.owner.get().root();
let node: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut *owner);
let namespace_is_null = self.namespace == namespace::Null;

View file

@ -39,11 +39,11 @@ pub trait AttrListMethods {
impl<'a> AttrListMethods for JSRef<'a, AttrList> {
fn Length(&self) -> u32 {
self.owner.root().attrs.len() as u32
self.owner.root().attrs.borrow().len() as u32
}
fn Item(&self, index: u32) -> Option<Temporary<Attr>> {
self.owner.root().attrs.as_slice().get(index as uint).map(|x| Temporary::new(x.clone()))
self.owner.root().attrs.borrow().as_slice().get(index as uint).map(|x| Temporary::new(x.clone()))
}
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Temporary<Attr>> {

View file

@ -47,7 +47,7 @@ use layout_interface::TrustedNodeAddress;
use script_task::StackRoots;
use std::cast;
use std::cell::RefCell;
use std::cell::{Cell, RefCell};
use std::kinds::marker::ContravariantLifetime;
/// A type that represents a JS-owned value that is rooted for the lifetime of this value.
@ -111,7 +111,7 @@ impl<T: Reflectable> Temporary<T> {
/// A rooted, JS-owned value. Must only be used as a field in other JS-owned types.
pub struct JS<T> {
ptr: RefCell<*mut T>
ptr: *T
}
impl<T> Eq for JS<T> {
@ -134,7 +134,7 @@ impl JS<Node> {
pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> JS<Node> {
let TrustedNodeAddress(addr) = inner;
JS {
ptr: RefCell::new(addr as *mut Node)
ptr: addr as *Node
}
}
}
@ -143,7 +143,7 @@ impl JS<XMLHttpRequest> {
pub unsafe fn from_trusted_xhr_address(inner: TrustedXHRAddress) -> JS<XMLHttpRequest> {
let TrustedXHRAddress(addr) = inner;
JS {
ptr: RefCell::new(addr as *mut XMLHttpRequest)
ptr: addr as *XMLHttpRequest
}
}
}
@ -152,7 +152,7 @@ impl<T: Reflectable> JS<T> {
/// Create a new JS-owned value wrapped from a raw Rust pointer.
pub unsafe fn from_raw(raw: *mut T) -> JS<T> {
JS {
ptr: RefCell::new(raw)
ptr: raw as *T
}
}
@ -269,6 +269,15 @@ impl<T: Assignable<U>, U: Reflectable> OptionalSettable<T> for Option<JS<U>> {
}
}
impl<T: Assignable<U>, U: Reflectable> OptionalSettable<T> for Cell<Option<JS<U>>> {
fn assign(&mut self, val: Option<T>) {
let mut item = self.get();
item.assign(val);
self.set(item);
}
}
/// Root a rootable Option type (used for Option<Temporary<T>>)
pub trait OptionalRootable<T> {
fn root<'a, 'b>(self) -> Option<Root<'a, 'b, T>>;
@ -394,7 +403,7 @@ pub struct Root<'a, 'b, T> {
/// Reference to rooted value that must not outlive this container
jsref: JSRef<'b, T>,
/// Pointer to underlying Rust data
ptr: RefCell<*mut T>,
ptr: *T,
/// On-stack JS pointer to assuage conservative stack scanner
js_ptr: *mut JSObject,
}
@ -445,25 +454,23 @@ impl<'a, 'b, T: Reflectable> DerefMut<JSRef<'b, T>> for Root<'a, 'b, T> {
impl<'a, T: Reflectable> Deref<T> for JSRef<'a, T> {
fn deref<'b>(&'b self) -> &'b T {
let borrow = self.ptr.borrow();
unsafe {
&**borrow
&*self.ptr
}
}
}
impl<'a, T: Reflectable> DerefMut<T> for JSRef<'a, T> {
fn deref_mut<'b>(&'b mut self) -> &'b mut T {
let mut borrowed = self.ptr.borrow_mut();
unsafe {
&mut **borrowed
&mut *(self.ptr as *mut T)
}
}
}
/// Encapsulates a reference to something that is guaranteed to be alive. This is freely copyable.
pub struct JSRef<'a, T> {
ptr: RefCell<*mut T>,
ptr: *T,
chain: ContravariantLifetime<'a>,
}
@ -495,7 +502,7 @@ impl<'a,T> JSRef<'a,T> {
pub fn unrooted(&self) -> JS<T> {
JS {
ptr: self.ptr.clone()
ptr: self.ptr
}
}
}

View file

@ -160,3 +160,23 @@ impl<S: Encoder<E>, E> Encodable<S, E> for Traceable<JSVal> {
Ok(())
}
}
/// for a field which contains DOMType
impl<T: Reflectable+Encodable<S, E>, S: Encoder<E>, E> Encodable<S, E> for Cell<JS<T>> {
fn encode(&self, s: &mut S) -> Result<(), E> {
self.get().encode(s)
}
}
impl<T: Reflectable+Encodable<S, E>, S: Encoder<E>, E> Encodable<S, E> for Cell<Option<JS<T>>> {
fn encode(&self, s: &mut S) -> Result<(), E> {
self.get().encode(s)
}
}
/// for a field which contains non-POD type contains DOMType
impl<T: Reflectable+Encodable<S, E>, S: Encoder<E>, E> Encodable<S, E> for RefCell<Vec<JS<T>>> {
fn encode(&self, s: &mut S) -> Result<(), E> {
self.borrow().encode(s)
}
}

View file

@ -18,9 +18,10 @@ pub struct ClientRectList {
impl ClientRectList {
pub fn new_inherited(window: &JSRef<Window>,
rects: Vec<JSRef<ClientRect>>) -> ClientRectList {
let rects = rects.iter().map(|rect| rect.unrooted()).collect();
ClientRectList {
reflector_: Reflector::new(),
rects: rects.iter().map(|rect| rect.unrooted()).collect(),
rects: rects,
window: window.unrooted(),
}
}
@ -44,8 +45,9 @@ impl<'a> ClientRectListMethods for JSRef<'a, ClientRectList> {
}
fn Item(&self, index: u32) -> Option<Temporary<ClientRect>> {
if index < self.rects.len() as u32 {
Some(Temporary::new(self.rects.get(index as uint).clone()))
let rects = &self.rects;
if index < rects.len() as u32 {
Some(Temporary::new(rects.get(index as uint).clone()))
} else {
None
}

View file

@ -31,6 +31,7 @@ use servo_util::str::{DOMString, null_str_as_empty_ref, split_html_space_chars};
use std::ascii::StrAsciiExt;
use std::cast;
use std::cell::{Cell, RefCell};
#[deriving(Encodable)]
pub struct Element {
@ -38,9 +39,9 @@ pub struct Element {
pub local_name: DOMString, // TODO: This should be an atom, not a DOMString.
pub namespace: Namespace,
pub prefix: Option<DOMString>,
pub attrs: Vec<JS<Attr>>,
pub attrs: RefCell<Vec<JS<Attr>>>,
pub style_attribute: Option<style::PropertyDeclarationBlock>,
pub attr_list: Option<JS<AttrList>>
pub attr_list: Cell<Option<JS<AttrList>>>
}
impl ElementDerived for EventTarget {
@ -147,8 +148,8 @@ impl Element {
local_name: local_name,
namespace: namespace,
prefix: prefix,
attrs: vec!(),
attr_list: None,
attrs: RefCell::new(vec!()),
attr_list: Cell::new(None),
style_attribute: None,
}
}
@ -167,7 +168,9 @@ impl RawLayoutElementHelpers for Element {
#[inline]
unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str)
-> Option<&'static str> {
self.attrs.iter().find(|attr: & &JS<Attr>| {
// cast to point to T in RefCell<T> directly
let attrs: *Vec<JS<Attr>> = cast::transmute(&self.attrs);
(*attrs).iter().find(|attr: & &JS<Attr>| {
let attr = attr.unsafe_get();
name == (*attr).local_name && (*attr).namespace == *namespace
}).map(|attr| {
@ -232,7 +235,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
let element: &Element = self.deref();
let is_html_element = self.html_element_in_html_document();
element.attrs.iter().map(|attr| attr.root()).find(|attr| {
element.attrs.borrow().iter().map(|attr| attr.root()).find(|attr| {
let same_name = if is_html_element {
name.to_ascii_lower() == attr.local_name
} else {
@ -284,7 +287,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
fn do_set_attribute(&mut self, local_name: DOMString, value: DOMString,
name: DOMString, namespace: Namespace,
prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool) {
let idx = self.deref().attrs.iter()
let idx = self.deref().attrs.borrow().iter()
.map(|attr| attr.root())
.position(|attr| cb(&*attr));
let (idx, set_type) = match idx {
@ -293,18 +296,18 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
let window = window_from_node(self).root();
let attr = Attr::new(&*window, local_name.clone(), value.clone(),
name, namespace.clone(), prefix, self);
self.deref_mut().attrs.push_unrooted(&attr);
(self.deref().attrs.len() - 1, FirstSetAttr)
self.deref().attrs.borrow_mut().push_unrooted(&attr);
(self.deref().attrs.borrow().len() - 1, FirstSetAttr)
}
};
self.deref_mut().attrs.get(idx).root().set_value(set_type, value);
self.deref().attrs.borrow().get(idx).root().set_value(set_type, value);
}
fn remove_attribute(&mut self, namespace: Namespace, name: DOMString) -> ErrorResult {
let (_, local_name) = get_attribute_parts(name.clone());
let idx = self.deref().attrs.iter().map(|attr| attr.root()).position(|attr| {
let idx = self.deref().attrs.borrow().iter().map(|attr| attr.root()).position(|attr| {
attr.local_name == local_name
});
@ -317,12 +320,12 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
}
if namespace == namespace::Null {
let removed_raw_value = self.deref().attrs.get(idx).root().Value();
let removed_raw_value = self.deref().attrs.borrow().get(idx).root().Value();
vtable_for(NodeCast::from_mut_ref(self))
.before_remove_attr(local_name.clone(), removed_raw_value);
}
self.deref_mut().attrs.remove(idx);
self.deref().attrs.borrow_mut().remove(idx);
}
};
@ -469,7 +472,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
// http://dom.spec.whatwg.org/#dom-element-attributes
fn Attributes(&mut self) -> Temporary<AttrList> {
match self.attr_list {
match self.attr_list.get() {
None => (),
Some(ref list) => return Temporary::new(list.clone()),
}
@ -481,7 +484,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
let window = doc.deref().window.root();
let list = AttrList::new(&*window, self);
self.attr_list.assign(Some(list));
Temporary::new(self.attr_list.get_ref().clone())
Temporary::new(self.attr_list.get().get_ref().clone())
}
// http://dom.spec.whatwg.org/#dom-element-getattribute

View file

@ -10,6 +10,7 @@ use dom::bindings::error::Fallible;
use dom::eventtarget::EventTarget;
use dom::window::Window;
use servo_util::str::DOMString;
use std::cell::Cell;
use geom::point::Point2D;
@ -46,8 +47,8 @@ pub enum EventTypeId {
pub struct Event {
pub type_id: EventTypeId,
pub reflector_: Reflector,
pub current_target: Option<JS<EventTarget>>,
pub target: Option<JS<EventTarget>>,
pub current_target: Cell<Option<JS<EventTarget>>>,
pub target: Cell<Option<JS<EventTarget>>>,
pub type_: DOMString,
pub phase: EventPhase,
pub canceled: bool,
@ -66,8 +67,8 @@ impl Event {
Event {
type_id: type_id,
reflector_: Reflector::new(),
current_target: None,
target: None,
current_target: Cell::new(None),
target: Cell::new(None),
phase: PhaseNone,
type_: "".to_owned(),
canceled: false,
@ -123,11 +124,11 @@ impl<'a> EventMethods for JSRef<'a, Event> {
}
fn GetTarget(&self) -> Option<Temporary<EventTarget>> {
self.target.as_ref().map(|target| Temporary::new(target.clone()))
self.target.get().as_ref().map(|target| Temporary::new(target.clone()))
}
fn GetCurrentTarget(&self) -> Option<Temporary<EventTarget>> {
self.current_target.as_ref().map(|target| Temporary::new(target.clone()))
self.current_target.get().as_ref().map(|target| Temporary::new(target.clone()))
}
fn DefaultPrevented(&self) -> bool {
@ -173,7 +174,7 @@ impl<'a> EventMethods for JSRef<'a, Event> {
self.stop_immediate = false;
self.canceled = false;
self.trusted = false;
self.target = None;
self.target.set(None);
self.type_ = type_;
self.bubbles = bubbles;
self.cancelable = cancelable;

View file

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

View file

@ -10,7 +10,6 @@ use dom::blob::Blob;
use dom::htmlformelement::HTMLFormElement;
use dom::window::Window;
use servo_util::str::DOMString;
use collections::hashmap::HashMap;
#[deriving(Encodable)]

View file

@ -106,7 +106,7 @@ fn serialize_doctype(doctype: &JSRef<DocumentType>, html: &mut StrBuf) {
fn serialize_elem(elem: &JSRef<Element>, open_elements: &mut Vec<~str>, html: &mut StrBuf) {
html.push_char('<');
html.push_str(elem.deref().local_name);
for attr in elem.deref().attrs.iter() {
for attr in elem.deref().attrs.borrow().iter() {
let attr = attr.root();
serialize_attr(&*attr, html);
};

View file

@ -12,6 +12,7 @@ use dom::eventtarget::EventTarget;
use dom::uievent::{UIEvent, UIEventMethods};
use dom::window::Window;
use servo_util::str::DOMString;
use std::cell::Cell;
#[deriving(Encodable)]
pub struct MouseEvent {
@ -25,7 +26,7 @@ pub struct MouseEvent {
pub alt_key: bool,
pub meta_key: bool,
pub button: u16,
pub related_target: Option<JS<EventTarget>>
pub related_target: Cell<Option<JS<EventTarget>>>
}
impl MouseEventDerived for Event {
@ -47,7 +48,7 @@ impl MouseEvent {
alt_key: false,
meta_key: false,
button: 0,
related_target: None
related_target: Cell::new(None)
}
}
@ -168,7 +169,7 @@ impl<'a> MouseEventMethods for JSRef<'a, MouseEvent> {
}
fn GetRelatedTarget(&self) -> Option<Temporary<EventTarget>> {
self.related_target.clone().map(|target| Temporary::new(target))
self.related_target.get().clone().map(|target| Temporary::new(target))
}
fn GetModifierState(&self, _keyArg: DOMString) -> bool {

View file

@ -41,7 +41,7 @@ use libc;
use libc::uintptr_t;
use std::cast::transmute;
use std::cast;
use std::cell::{RefCell, Ref, RefMut};
use std::cell::{Cell, RefCell, Ref, RefMut};
use std::iter::{Map, Filter};
use std::mem;
use style::ComputedValues;
@ -63,25 +63,25 @@ pub struct Node {
pub type_id: NodeTypeId,
/// The parent of this node.
pub parent_node: Option<JS<Node>>,
pub parent_node: Cell<Option<JS<Node>>>,
/// The first child of this node.
pub first_child: Option<JS<Node>>,
pub first_child: Cell<Option<JS<Node>>>,
/// The last child of this node.
pub last_child: Option<JS<Node>>,
pub last_child: Cell<Option<JS<Node>>>,
/// The next sibling of this node.
pub next_sibling: Option<JS<Node>>,
pub next_sibling: Cell<Option<JS<Node>>>,
/// The previous sibling of this node.
pub prev_sibling: Option<JS<Node>>,
pub prev_sibling: Cell<Option<JS<Node>>>,
/// The document that this node belongs to.
owner_doc: Option<JS<Document>>,
owner_doc: Cell<Option<JS<Document>>>,
/// The live list of children return by .childNodes.
pub child_list: Option<JS<NodeList>>,
pub child_list: Cell<Option<JS<NodeList>>>,
/// A bitfield of flags for node items.
flags: NodeFlags,
@ -327,26 +327,26 @@ impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
///
/// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.)
fn remove_child(&mut self, child: &mut JSRef<Node>) {
assert!(child.parent_node.is_some());
assert!(child.parent_node.get().is_some());
match child.prev_sibling.root() {
match child.prev_sibling.get().root() {
None => {
let next_sibling = child.next_sibling.root();
let next_sibling = child.next_sibling.get().root();
self.set_first_child(next_sibling.root_ref());
}
Some(ref mut prev_sibling) => {
let next_sibling = child.next_sibling.root();
let next_sibling = child.next_sibling.get().root();
prev_sibling.set_next_sibling(next_sibling.root_ref());
}
}
match child.next_sibling.root() {
match child.next_sibling.get().root() {
None => {
let prev_sibling = child.prev_sibling.root();
let prev_sibling = child.prev_sibling.get().root();
self.set_last_child(prev_sibling.root_ref());
}
Some(ref mut next_sibling) => {
let prev_sibling = child.prev_sibling.root();
let prev_sibling = child.prev_sibling.get().root();
next_sibling.set_prev_sibling(prev_sibling.root_ref());
}
}
@ -475,25 +475,25 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
}
fn parent_node(&self) -> Option<Temporary<Node>> {
self.deref().parent_node.clone().map(|node| Temporary::new(node))
self.deref().parent_node.get().map(|node| Temporary::new(node))
}
fn first_child(&self) -> Option<Temporary<Node>> {
self.deref().first_child.clone().map(|node| Temporary::new(node))
self.deref().first_child.get().map(|node| Temporary::new(node))
}
fn last_child(&self) -> Option<Temporary<Node>> {
self.deref().last_child.clone().map(|node| Temporary::new(node))
self.deref().last_child.get().map(|node| Temporary::new(node))
}
/// Returns the previous sibling of this node. Fails if this node is borrowed mutably.
fn prev_sibling(&self) -> Option<Temporary<Node>> {
self.deref().prev_sibling.clone().map(|node| Temporary::new(node))
self.deref().prev_sibling.get().map(|node| Temporary::new(node))
}
/// Returns the next sibling of this node. Fails if this node is borrowed mutably.
fn next_sibling(&self) -> Option<Temporary<Node>> {
self.deref().next_sibling.clone().map(|node| Temporary::new(node))
self.deref().next_sibling.get().map(|node| Temporary::new(node))
}
#[inline]
@ -593,12 +593,12 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
fn ancestors(&self) -> AncestorIterator {
AncestorIterator {
current: self.parent_node.clone().map(|node| (*node.root()).clone()),
current: self.parent_node.get().map(|node| (*node.root()).clone()),
}
}
fn owner_doc(&self) -> Temporary<Document> {
Temporary::new(self.owner_doc.get_ref().clone())
Temporary::new(self.owner_doc.get().get_ref().clone())
}
fn set_owner_doc(&mut self, document: &JSRef<Document>) {
@ -607,7 +607,7 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
fn children(&self) -> AbstractNodeChildrenIterator {
AbstractNodeChildrenIterator {
current_node: self.first_child.clone().map(|node| (*node.root()).clone()),
current_node: self.first_child.get().map(|node| (*node.root()).clone()),
}
}
@ -654,13 +654,13 @@ pub fn from_untrusted_node_address(runtime: *mut JSRuntime, candidate: Untrusted
pub trait LayoutNodeHelpers {
unsafe fn type_id_for_layout(&self) -> NodeTypeId;
unsafe fn parent_node_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
unsafe fn first_child_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
unsafe fn last_child_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
unsafe fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
unsafe fn parent_node_ref<'a>(&'a self) -> Option<JS<Node>>;
unsafe fn first_child_ref<'a>(&'a self) -> Option<JS<Node>>;
unsafe fn last_child_ref<'a>(&'a self) -> Option<JS<Node>>;
unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<JS<Node>>;
unsafe fn next_sibling_ref<'a>(&'a self) -> Option<JS<Node>>;
unsafe fn owner_doc_for_layout<'a>(&'a self) -> &'a JS<Document>;
unsafe fn owner_doc_for_layout<'a>(&'a self) -> JS<Document>;
unsafe fn is_element_for_layout(&self) -> bool;
}
@ -675,32 +675,32 @@ impl LayoutNodeHelpers for JS<Node> {
}
#[inline]
unsafe fn parent_node_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
(*self.unsafe_get()).parent_node.as_ref()
unsafe fn parent_node_ref<'a>(&'a self) -> Option<JS<Node>> {
(*self.unsafe_get()).parent_node.get()
}
#[inline]
unsafe fn first_child_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
(*self.unsafe_get()).first_child.as_ref()
unsafe fn first_child_ref<'a>(&'a self) -> Option<JS<Node>> {
(*self.unsafe_get()).first_child.get()
}
#[inline]
unsafe fn last_child_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
(*self.unsafe_get()).last_child.as_ref()
unsafe fn last_child_ref<'a>(&'a self) -> Option<JS<Node>> {
(*self.unsafe_get()).last_child.get()
}
#[inline]
unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
(*self.unsafe_get()).prev_sibling.as_ref()
unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<JS<Node>> {
(*self.unsafe_get()).prev_sibling.get()
}
#[inline]
unsafe fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
(*self.unsafe_get()).next_sibling.as_ref()
unsafe fn next_sibling_ref<'a>(&'a self) -> Option<JS<Node>> {
(*self.unsafe_get()).next_sibling.get()
}
unsafe fn owner_doc_for_layout<'a>(&'a self) -> &'a JS<Document> {
(*self.unsafe_get()).owner_doc.get_ref()
unsafe fn owner_doc_for_layout<'a>(&'a self) -> JS<Document> {
(*self.unsafe_get()).owner_doc.get().unwrap()
}
}
@ -822,7 +822,7 @@ impl<'a> Iterator<JSRef<'a, Node>> for NodeIterator {
self.current_node = match self.current_node.as_ref().map(|node| node.root()) {
None => {
if self.include_start {
Some(self.start_node.clone())
Some(self.start_node)
} else {
self.next_child(&*self.start_node.root())
.map(|child| child.unrooted())
@ -860,7 +860,7 @@ impl<'a> Iterator<JSRef<'a, Node>> for NodeIterator {
}
}
};
self.current_node.clone().map(|node| (*node.root()).clone())
self.current_node.map(|node| (*node.root()).clone())
}
}
@ -911,14 +911,14 @@ impl Node {
eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)),
type_id: type_id,
parent_node: None,
first_child: None,
last_child: None,
next_sibling: None,
prev_sibling: None,
parent_node: Cell::new(None),
first_child: Cell::new(None),
last_child: Cell::new(None),
next_sibling: Cell::new(None),
prev_sibling: Cell::new(None),
owner_doc: doc.unrooted(),
child_list: None,
owner_doc: Cell::new(doc.unrooted()),
child_list: Cell::new(None),
flags: NodeFlags::new(type_id),
@ -1297,8 +1297,8 @@ impl Node {
// FIXME: https://github.com/mozilla/servo/issues/1737
copy_elem.namespace = node_elem.namespace.clone();
let window = document.deref().window.root();
for attr in node_elem.attrs.iter().map(|attr| attr.root()) {
copy_elem.attrs.push_unrooted(
for attr in node_elem.attrs.borrow().iter().map(|attr| attr.root()) {
copy_elem.attrs.borrow_mut().push_unrooted(
&Attr::new(&*window,
attr.deref().local_name.clone(), attr.deref().value.clone(),
attr.deref().name.clone(), attr.deref().namespace.clone(),
@ -1427,12 +1427,12 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
// http://dom.spec.whatwg.org/#dom-node-parentnode
fn GetParentNode(&self) -> Option<Temporary<Node>> {
self.parent_node.clone().map(|node| Temporary::new(node))
self.parent_node.get().map(|node| Temporary::new(node))
}
// http://dom.spec.whatwg.org/#dom-node-parentelement
fn GetParentElement(&self) -> Option<Temporary<Element>> {
self.parent_node.clone()
self.parent_node.get()
.and_then(|parent| {
let parent = parent.root();
ElementCast::to_ref(&*parent).map(|elem| {
@ -1443,12 +1443,12 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
// http://dom.spec.whatwg.org/#dom-node-haschildnodes
fn HasChildNodes(&self) -> bool {
self.first_child.is_some()
self.first_child.get().is_some()
}
// http://dom.spec.whatwg.org/#dom-node-childnodes
fn ChildNodes(&mut self) -> Temporary<NodeList> {
match self.child_list {
match self.child_list.get() {
None => (),
Some(ref list) => return Temporary::new(list.clone()),
}
@ -1457,27 +1457,27 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
let window = doc.deref().window.root();
let child_list = NodeList::new_child_list(&*window, self);
self.child_list.assign(Some(child_list));
Temporary::new(self.child_list.get_ref().clone())
Temporary::new(self.child_list.get().get_ref().clone())
}
// http://dom.spec.whatwg.org/#dom-node-firstchild
fn GetFirstChild(&self) -> Option<Temporary<Node>> {
self.first_child.clone().map(|node| Temporary::new(node))
self.first_child.get().map(|node| Temporary::new(node))
}
// http://dom.spec.whatwg.org/#dom-node-lastchild
fn GetLastChild(&self) -> Option<Temporary<Node>> {
self.last_child.clone().map(|node| Temporary::new(node))
self.last_child.get().map(|node| Temporary::new(node))
}
// http://dom.spec.whatwg.org/#dom-node-previoussibling
fn GetPreviousSibling(&self) -> Option<Temporary<Node>> {
self.prev_sibling.clone().map(|node| Temporary::new(node))
self.prev_sibling.get().map(|node| Temporary::new(node))
}
// http://dom.spec.whatwg.org/#dom-node-nextsibling
fn GetNextSibling(&self) -> Option<Temporary<Node>> {
self.next_sibling.clone().map(|node| Temporary::new(node))
self.next_sibling.get().map(|node| Temporary::new(node))
}
// http://dom.spec.whatwg.org/#dom-node-nodevalue
@ -1766,9 +1766,11 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap();
// FIXME: namespace prefix
(element.deref().namespace == other_element.deref().namespace) &&
(element.deref().local_name == other_element.deref().local_name) &&
(element.deref().attrs.len() == other_element.deref().attrs.len())
let element = element.deref();
let other_element = other_element.deref();
(element.namespace == other_element.namespace) &&
(element.local_name == other_element.local_name) &&
(element.attrs.borrow().len() == other_element.attrs.borrow().len())
}
fn is_equal_processinginstruction(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
let pi: &JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap();
@ -1784,9 +1786,11 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
fn is_equal_element_attrs(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap();
assert!(element.deref().attrs.len() == other_element.deref().attrs.len());
element.deref().attrs.iter().map(|attr| attr.root()).all(|attr| {
other_element.deref().attrs.iter().map(|attr| attr.root()).any(|other_attr| {
let element = element.deref();
let other_element = other_element.deref();
assert!(element.attrs.borrow().len() == other_element.attrs.borrow().len());
element.attrs.borrow().iter().map(|attr| attr.root()).all(|attr| {
other_element.attrs.borrow().iter().map(|attr| attr.root()).any(|other_attr| {
(attr.namespace == other_attr.namespace) &&
(attr.local_name == other_attr.local_name) &&
(attr.value == other_attr.value)

View file

@ -7,7 +7,6 @@ use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::performancetiming::{PerformanceTiming, PerformanceTimingMethods};
use dom::window::Window;
use time;
pub type DOMHighResTimeStamp = f64;
@ -20,9 +19,10 @@ pub struct Performance {
impl Performance {
fn new_inherited(window: &JSRef<Window>) -> Performance {
let timing = PerformanceTiming::new(window).root().root_ref().unrooted();
Performance {
reflector_: Reflector::new(),
timing: PerformanceTiming::new(window).root().root_ref().unrooted(),
timing: timing,
}
}

View file

@ -15,10 +15,12 @@ use servo_util::str::DOMString;
use js::jsapi::JSContext;
use js::jsval::{JSVal, NullValue};
use std::cell::Cell;
#[deriving(Encodable)]
pub struct TestBinding {
pub reflector: Reflector,
pub window: JS<Window>,
pub window: Cell<JS<Window>>,
}
pub trait TestBindingMethods {
@ -243,19 +245,19 @@ pub trait TestBindingMethods {
impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
fn InterfaceAttribute(&self) -> Temporary<Blob> {
let window = self.window.root();
let window = self.window.get().root();
Blob::new(&*window)
}
fn GetInterfaceAttributeNullable(&self) -> Option<Temporary<Blob>> {
let window = self.window.root();
let window = self.window.get().root();
Some(Blob::new(&*window))
}
fn ReceiveInterface(&self) -> Temporary<Blob> {
let window = self.window.root();
let window = self.window.get().root();
Blob::new(&*window)
}
fn ReceiveNullableInterface(&self) -> Option<Temporary<Blob>> {
let window = self.window.root();
let window = self.window.get().root();
Some(Blob::new(&*window))
}
}

View file

@ -86,7 +86,7 @@ pub trait UIEventMethods {
impl<'a> UIEventMethods for JSRef<'a, UIEvent> {
fn GetView(&self) -> Option<Temporary<Window>> {
self.view.clone().map(|view| Temporary::new(view))
self.view.map(|view| Temporary::new(view))
}
fn Detail(&self) -> i32 {

View file

@ -6,11 +6,12 @@ use dom::bindings::codegen::BindingDeclarations::ValidityStateBinding;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::window::Window;
use std::cell::Cell;
#[deriving(Encodable)]
pub struct ValidityState {
pub reflector_: Reflector,
pub window: JS<Window>,
pub window: Cell<JS<Window>>,
pub state: u8,
}
@ -18,7 +19,7 @@ impl ValidityState {
pub fn new_inherited(window: &JSRef<Window>) -> ValidityState {
ValidityState {
reflector_: Reflector::new(),
window: window.unrooted(),
window: Cell::new(window.unrooted()),
state: 0,
}
}

View file

@ -30,6 +30,7 @@ use js::jsapi::{JS_GC, JS_GetRuntime};
use js::jsval::{NullValue, JSVal};
use collections::hashmap::HashMap;
use std::cell::Cell;
use std::cmp;
use std::comm::{channel, Sender};
use std::comm::Select;
@ -69,16 +70,16 @@ impl TimerHandle {
pub struct Window {
pub eventtarget: EventTarget,
pub script_chan: ScriptChan,
pub console: Option<JS<Console>>,
pub location: Option<JS<Location>>,
pub navigator: Option<JS<Navigator>>,
pub console: Cell<Option<JS<Console>>>,
pub location: Cell<Option<JS<Location>>>,
pub navigator: Cell<Option<JS<Navigator>>>,
pub image_cache_task: ImageCacheTask,
pub active_timers: Box<HashMap<TimerId, TimerHandle>>,
pub next_timer_handle: i32,
pub compositor: Untraceable<Box<ScriptListener>>,
pub browser_context: Option<BrowserContext>,
pub page: Rc<Page>,
pub performance: Option<JS<Performance>>,
pub performance: Cell<Option<JS<Performance>>>,
pub navigationStart: u64,
pub navigationStartPrecise: f64,
}
@ -200,28 +201,28 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
}
fn Location(&mut self) -> Temporary<Location> {
if self.location.is_none() {
if self.location.get().is_none() {
let page = self.deref().page.clone();
let location = Location::new(self, page);
self.location.assign(Some(location));
}
Temporary::new(self.location.get_ref().clone())
Temporary::new(self.location.get().get_ref().clone())
}
fn Console(&mut self) -> Temporary<Console> {
if self.console.is_none() {
if self.console.get().is_none() {
let console = Console::new(self);
self.console.assign(Some(console));
}
Temporary::new(self.console.get_ref().clone())
Temporary::new(self.console.get().get_ref().clone())
}
fn Navigator(&mut self) -> Temporary<Navigator> {
if self.navigator.is_none() {
if self.navigator.get().is_none() {
let navigator = Navigator::new(self);
self.navigator.assign(Some(navigator));
}
Temporary::new(self.navigator.get_ref().clone())
Temporary::new(self.navigator.get().get_ref().clone())
}
fn Confirm(&self, _message: DOMString) -> bool {
@ -269,11 +270,11 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
}
fn Performance(&mut self) -> Temporary<Performance> {
if self.performance.is_none() {
if self.performance.get().is_none() {
let performance = Performance::new(self);
self.performance.assign(Some(performance));
}
Temporary::new(self.performance.get_ref().clone())
Temporary::new(self.performance.get().get_ref().clone())
}
fn GetOnload(&self) -> Option<EventHandlerNonNull> {
@ -441,16 +442,16 @@ impl Window {
let win = box Window {
eventtarget: EventTarget::new_inherited(WindowTypeId),
script_chan: script_chan,
console: None,
console: Cell::new(None),
compositor: Untraceable::new(compositor),
page: page,
location: None,
navigator: None,
location: Cell::new(None),
navigator: Cell::new(None),
image_cache_task: image_cache_task,
active_timers: box HashMap::new(),
next_timer_handle: 0,
browser_context: None,
performance: None,
performance: Cell::new(None),
navigationStart: time::get_time().sec as u64,
navigationStartPrecise: time::precise_time_s(),
};

View file

@ -32,6 +32,7 @@ use url::Url;
use libc;
use libc::c_void;
use std::cell::Cell;
use std::comm::channel;
use std::io::{BufReader, MemWriter};
use std::from_str::FromStr;
@ -98,14 +99,14 @@ pub struct XMLHttpRequest {
ready_state: XMLHttpRequestState,
timeout: u32,
with_credentials: bool,
upload: Option<JS<XMLHttpRequestUpload>>,
upload: Cell<Option<JS<XMLHttpRequestUpload>>>,
response_url: DOMString,
status: u16,
status_text: ByteString,
response: ByteString,
response_type: XMLHttpRequestResponseType,
response_text: DOMString,
response_xml: Option<JS<Document>>,
response_xml: Cell<Option<JS<Document>>>,
response_headers: Untraceable<ResponseHeaderCollection>,
// Associated concepts
@ -129,14 +130,14 @@ impl XMLHttpRequest {
ready_state: Unsent,
timeout: 0u32,
with_credentials: false,
upload: None,
upload: Cell::new(None),
response_url: "".to_owned(),
status: 0,
status_text: ByteString::new(vec!()),
response: ByteString::new(vec!()),
response_type: _empty,
response_text: "".to_owned(),
response_xml: None,
response_xml: Cell::new(None),
response_headers: Untraceable::new(ResponseHeaderCollection::new()),
request_method: Untraceable::new(Get),
@ -385,7 +386,7 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
self.with_credentials = with_credentials
}
fn Upload(&self) -> Temporary<XMLHttpRequestUpload> {
Temporary::new(self.upload.get_ref().clone())
Temporary::new(self.upload.get().get_ref().clone())
}
fn Send(&mut self, data: Option<DOMString>) -> ErrorResult {
if self.ready_state != Opened || self.send_flag {
@ -407,7 +408,7 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
};
if !self.sync {
// Step 8
let upload_target = &*self.upload.root().unwrap();
let upload_target = &*self.upload.get().root().unwrap();
let event_target: &JSRef<EventTarget> = EventTargetCast::from_ref(upload_target);
if event_target.handlers.iter().len() > 0 {
self.upload_events = true;
@ -498,7 +499,7 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
self.response_text.clone()
}
fn GetResponseXML(&self) -> Option<Temporary<Document>> {
self.response_xml.clone().map(|response| Temporary::new(response))
self.response_xml.get().map(|response| Temporary::new(response))
}
}
@ -637,7 +638,7 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
fn dispatch_progress_event(&self, upload: bool, type_: DOMString, loaded: u64, total: Option<u64>) {
let win = &*self.global.root();
let upload_target = &*self.upload.root().unwrap();
let upload_target = &*self.upload.get().root().unwrap();
let mut progressevent = ProgressEvent::new(win, type_, false, false,
total.is_some(), loaded,
total.unwrap_or(0)).root();

View file

@ -162,7 +162,7 @@ pub struct Page {
resize_event: Untraceable<Cell<Option<Size2D<uint>>>>,
/// Pending scroll to fragment event, if any
fragment_node: Traceable<RefCell<Option<JS<Element>>>>,
fragment_node: Cell<Option<JS<Element>>>,
/// Associated resource task for use by DOM objects like XMLHttpRequest
pub resource_task: Untraceable<ResourceTask>,
@ -221,7 +221,7 @@ impl Page {
url: Untraceable::new(RefCell::new(None)),
next_subpage_id: Untraceable::new(Cell::new(SubpageId(0))),
resize_event: Untraceable::new(Cell::new(None)),
fragment_node: Traceable::new(RefCell::new(None)),
fragment_node: Cell::new(None),
last_reflow_id: Traceable::new(Cell::new(0)),
resource_task: Untraceable::new(resource_task),
constellation_chan: Untraceable::new(constellation_chan),
@ -1043,8 +1043,8 @@ impl ScriptTask {
let _ = wintarget.dispatch_event_with_target(Some((*doctarget).clone()),
&mut *event);
let mut fragment_node = page.fragment_node.deref().borrow_mut();
(*fragment_node).assign(fragment.map_or(None, |fragid| page.find_fragment_node(fragid)));
let mut fragment_node = page.fragment_node.get();
fragment_node.assign(fragment.map_or(None, |fragid| page.find_fragment_node(fragid)));
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(LoadCompleteMsg(page.id, url));
@ -1080,7 +1080,7 @@ impl ScriptTask {
page.reflow(ReflowForDisplay, self.chan.clone(), self.compositor)
}
let mut fragment_node = page.fragment_node.deref().borrow_mut();
let mut fragment_node = page.fragment_node.get();
match fragment_node.take().map(|node| node.root()) {
Some(node) => self.scroll_fragment_point(pipeline_id, &*node),
None => {}