diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 3a9425c99c6..0b78a2f97ac 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -35,6 +35,7 @@ use css::node_style::StyledNode; use util::{LayoutDataAccess, LayoutDataWrapper, PrivateLayoutData, OpaqueNodeMethods}; use gfx::display_list::OpaqueNode; +use script::dom::bindings::cell::{Ref, RefMut}; use script::dom::bindings::codegen::InheritTypes::{ElementCast, HTMLIFrameElementCast, HTMLImageElementCast}; use script::dom::bindings::codegen::InheritTypes::{HTMLInputElementCast, TextCast}; use script::dom::bindings::js::JS; @@ -50,7 +51,6 @@ use script::dom::text::Text; use script::layout_interface::LayoutChan; use servo_msg::constellation_msg::{PipelineId, SubpageId}; use servo_util::str::{LengthOrPercentageOrAuto, is_whitespace}; -use std::cell::{RefCell, Ref, RefMut}; use std::kinds::marker::ContravariantLifetime; use std::mem; use style::computed_values::{content, display, white_space}; @@ -445,9 +445,7 @@ pub struct LayoutElement<'le> { impl<'le> LayoutElement<'le> { pub fn style_attribute(&self) -> &'le Option { let style: &Option = unsafe { - let style: &RefCell> = self.element.style_attribute(); - // cast to the direct reference to T placed on the head of RefCell - mem::transmute(style) + &*self.element.style_attribute().borrow_for_layout() }; style } diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index 3e81bb31943..f4dd6e85d7b 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::cell::{DOMRefCell, Ref}; use dom::bindings::codegen::Bindings::AttrBinding; use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::InheritTypes::NodeCast; @@ -15,7 +16,6 @@ use dom::virtualmethods::vtable_for; use devtools_traits::AttrInfo; use servo_util::str::{DOMString, split_html_space_chars}; -use std::cell::{Ref, RefCell}; use std::mem; use string_cache::{Atom, Namespace}; @@ -75,7 +75,7 @@ impl Str for AttrValue { pub struct Attr { reflector_: Reflector, local_name: Atom, - value: RefCell, + value: DOMRefCell, name: Atom, namespace: Namespace, prefix: Option, @@ -97,7 +97,7 @@ impl Attr { Attr { reflector_: Reflector::new(), local_name: local_name, - value: RefCell::new(value), + value: DOMRefCell::new(value), name: name, namespace: namespace, prefix: prefix, @@ -221,15 +221,14 @@ pub trait AttrHelpersForLayout { impl AttrHelpersForLayout for Attr { #[inline] unsafe fn value_ref_forever(&self) -> &'static str { - // cast to point to T in RefCell directly - let value = mem::transmute::<&RefCell, &AttrValue>(&self.value); + // This transmute is used to cheat the lifetime restriction. + let value = mem::transmute::<&AttrValue, &AttrValue>(self.value.borrow_for_layout()); value.as_slice() } #[inline] unsafe fn value_atom_forever(&self) -> Option { - // cast to point to T in RefCell directly - let value = mem::transmute::<&RefCell, &AttrValue>(&self.value); + let value = self.value.borrow_for_layout(); match *value { AtomAttrValue(ref val) => Some(val.clone()), _ => None, @@ -238,8 +237,8 @@ impl AttrHelpersForLayout for Attr { #[inline] unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]> { - // cast to point to T in RefCell directly - let value = mem::transmute::<&RefCell, &AttrValue>(&self.value); + // This transmute is used to cheat the lifetime restriction. + let value = mem::transmute::<&AttrValue, &AttrValue>(self.value.borrow_for_layout()); match *value { TokenListAttrValue(_, ref tokens) => Some(tokens.as_slice()), _ => None, diff --git a/components/script/dom/bindings/cell.rs b/components/script/dom/bindings/cell.rs new file mode 100644 index 00000000000..a4a15b7d5e7 --- /dev/null +++ b/components/script/dom/bindings/cell.rs @@ -0,0 +1,68 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::trace::JSTraceable; +use js::jsapi::{JSTracer}; + +use std::cell; +use std::cell::RefCell; +use std::mem; + +/// A mutable field in DOM for large sized value. +/// This has a special method to return the pointer of itself +/// for used in layout task. +/// This simply wraps `RefCell` to add the special method. +pub struct DOMRefCell { + base: RefCell, +} + +pub type Ref<'a, T> = cell::Ref<'a, T>; +pub type RefMut<'a, T> = cell::RefMut<'a, T>; + + +impl DOMRefCell { + #[inline(always)] + pub fn new(value: T) -> DOMRefCell { + DOMRefCell { + base: RefCell::new(value), + } + } + + #[inline(always)] + pub fn unwrap(self) -> T { + self.base.unwrap() + } + + #[inline(always)] + pub fn try_borrow<'a>(&'a self) -> Option> { + self.base.try_borrow() + } + + #[inline(always)] + pub fn borrow<'a>(&'a self) -> Ref<'a, T> { + self.base.borrow() + } + + #[inline(always)] + pub fn try_borrow_mut<'a>(&'a self) -> Option> { + self.base.try_borrow_mut() + } + + #[inline(always)] + pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> { + self.base.borrow_mut() + } + + /// This returns the pointer which refers T in `RefCell` directly. + pub unsafe fn borrow_for_layout<'a>(&'a self) -> &'a T { + let val = mem::transmute::<&RefCell, &T>(&self.base); + val + } +} + +impl JSTraceable for DOMRefCell { + fn trace(&self, trc: *mut JSTracer) { + (*self).base.borrow().trace(trc) + } +} diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs index 753a4336849..3a5ebcf6ab6 100644 --- a/components/script/dom/characterdata.rs +++ b/components/script/dom/characterdata.rs @@ -4,6 +4,7 @@ //! DOM bindings for `CharacterData`. +use dom::bindings::cell::{DOMRefCell, Ref}; use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods; use dom::bindings::codegen::InheritTypes::{CharacterDataDerived, NodeCast}; use dom::bindings::error::{Fallible, ErrorResult, IndexSize}; @@ -14,15 +15,12 @@ use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::node::{CommentNodeTypeId, Node, NodeTypeId, TextNodeTypeId, ProcessingInstructionNodeTypeId, NodeHelpers}; use servo_util::str::DOMString; -use std::cell::{Ref, RefCell}; -use std::mem; - #[jstraceable] #[must_root] #[privatize] pub struct CharacterData { node: Node, - data: RefCell, + data: DOMRefCell, } impl CharacterDataDerived for EventTarget { @@ -40,7 +38,7 @@ impl CharacterData { pub fn new_inherited(id: NodeTypeId, data: DOMString, document: JSRef) -> CharacterData { CharacterData { node: Node::new_inherited(id, document), - data: RefCell::new(data), + data: DOMRefCell::new(data), } } @@ -61,7 +59,7 @@ impl CharacterData { #[inline] pub unsafe fn data_for_layout<'a>(&'a self) -> &'a str { - mem::transmute::<&RefCell, &DOMString>(&self.data).as_slice() + self.data.borrow_for_layout().as_slice() } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index cb6a3c21800..d9f995720a8 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -7,6 +7,7 @@ use dom::attr::{Attr, ReplacedAttr, FirstSetAttr, AttrHelpers, AttrHelpersForLayout}; use dom::attr::{AttrValue, StringAttrValue, UIntAttrValue, AtomAttrValue}; use dom::namednodemap::NamedNodeMap; +use dom::bindings::cell::{DOMRefCell, Ref, RefMut}; use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::ElementBinding; use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; @@ -39,7 +40,6 @@ use servo_util::namespace; use servo_util::str::{DOMString, LengthOrPercentageOrAuto}; use std::ascii::StrAsciiExt; -use std::cell::{Ref, RefMut, RefCell}; use std::default::Default; use std::mem; use string_cache::{Atom, Namespace}; @@ -53,8 +53,8 @@ pub struct Element { local_name: Atom, namespace: Namespace, prefix: Option, - attrs: RefCell>>, - style_attribute: RefCell>, + attrs: DOMRefCell>>, + style_attribute: DOMRefCell>, attr_list: MutNullableJS, class_list: MutNullableJS, } @@ -160,10 +160,10 @@ impl Element { local_name: Atom::from_slice(local_name.as_slice()), namespace: namespace, prefix: prefix, - attrs: RefCell::new(vec!()), + attrs: DOMRefCell::new(vec!()), attr_list: Default::default(), class_list: Default::default(), - style_attribute: RefCell::new(None), + style_attribute: DOMRefCell::new(None), } } @@ -203,7 +203,7 @@ impl Element { } #[inline] - pub fn style_attribute<'a>(&'a self) -> &'a RefCell> { + pub fn style_attribute<'a>(&'a self) -> &'a DOMRefCell> { &self.style_attribute } } @@ -226,8 +226,7 @@ impl RawLayoutElementHelpers for Element { #[allow(unrooted_must_root)] unsafe fn get_attr_val_for_layout<'a>(&'a self, namespace: &Namespace, name: &Atom) -> Option<&'a str> { - // cast to point to T in RefCell directly - let attrs: *const Vec> = mem::transmute(&self.attrs); + let attrs = self.attrs.borrow_for_layout(); (*attrs).iter().find(|attr: & &JS| { let attr = attr.unsafe_get(); *name == (*attr).local_name_atom_forever() && @@ -241,8 +240,7 @@ impl RawLayoutElementHelpers for Element { #[inline] #[allow(unrooted_must_root)] unsafe fn get_attr_vals_for_layout<'a>(&'a self, name: &Atom) -> Vec<&'a str> { - // cast to point to T in RefCell directly - let attrs: *const Vec> = mem::transmute(&self.attrs); + let attrs = self.attrs.borrow_for_layout(); (*attrs).iter().filter_map(|attr: &JS| { let attr = attr.unsafe_get(); if *name == (*attr).local_name_atom_forever() { @@ -257,8 +255,7 @@ impl RawLayoutElementHelpers for Element { #[allow(unrooted_must_root)] unsafe fn get_attr_atom_for_layout(&self, namespace: &Namespace, name: &Atom) -> Option { - // cast to point to T in RefCell directly - let attrs: *const Vec> = mem::transmute(&self.attrs); + let attrs = self.attrs.borrow_for_layout(); (*attrs).iter().find(|attr: & &JS| { let attr = attr.unsafe_get(); *name == (*attr).local_name_atom_forever() && @@ -272,7 +269,7 @@ impl RawLayoutElementHelpers for Element { #[inline] #[allow(unrooted_must_root)] unsafe fn has_class_for_layout(&self, name: &Atom) -> bool { - let attrs: *const Vec> = mem::transmute(&self.attrs); + let attrs = self.attrs.borrow_for_layout(); (*attrs).iter().find(|attr: & &JS| { let attr = attr.unsafe_get(); (*attr).local_name_atom_forever() == atom!("class") @@ -287,7 +284,7 @@ impl RawLayoutElementHelpers for Element { #[inline] #[allow(unrooted_must_root)] unsafe fn get_classes_for_layout(&self) -> Option<&'static [Atom]> { - let attrs: *const Vec> = mem::transmute(&self.attrs); + let attrs = self.attrs.borrow_for_layout(); (*attrs).iter().find(|attr: & &JS| { let attr = attr.unsafe_get(); (*attr).local_name_atom_forever() == atom!("class") diff --git a/components/script/lib.rs b/components/script/lib.rs index 09bea1b73bd..03662371e0c 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -56,6 +56,7 @@ pub mod dom { /// The code to expose the DOM to JavaScript through IDL bindings. pub mod bindings { + pub mod cell; pub mod global; pub mod js; pub mod utils;