mirror of
https://github.com/servo/servo.git
synced 2025-06-23 16:44:33 +01:00
Use Cell/RefCell for interior mutability of Element.
This commit is contained in:
parent
6d9dcd087a
commit
b0239b5a5a
3 changed files with 31 additions and 24 deletions
|
@ -31,6 +31,7 @@ use servo_util::str::{DOMString, null_str_as_empty_ref, split_html_space_chars};
|
||||||
|
|
||||||
use std::ascii::StrAsciiExt;
|
use std::ascii::StrAsciiExt;
|
||||||
use std::cast;
|
use std::cast;
|
||||||
|
use std::cell::{Cell, RefCell};
|
||||||
|
|
||||||
#[deriving(Encodable)]
|
#[deriving(Encodable)]
|
||||||
pub struct Element {
|
pub struct Element {
|
||||||
|
@ -38,9 +39,9 @@ pub struct Element {
|
||||||
pub local_name: DOMString, // TODO: This should be an atom, not a DOMString.
|
pub local_name: DOMString, // TODO: This should be an atom, not a DOMString.
|
||||||
pub namespace: Namespace,
|
pub namespace: Namespace,
|
||||||
pub prefix: Option<DOMString>,
|
pub prefix: Option<DOMString>,
|
||||||
pub attrs: Vec<JS<Attr>>,
|
pub attrs: RefCell<Vec<JS<Attr>>>,
|
||||||
pub style_attribute: Option<style::PropertyDeclarationBlock>,
|
pub style_attribute: Option<style::PropertyDeclarationBlock>,
|
||||||
pub attr_list: Option<JS<AttrList>>
|
pub attr_list: Cell<Option<JS<AttrList>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ElementDerived for EventTarget {
|
impl ElementDerived for EventTarget {
|
||||||
|
@ -147,8 +148,8 @@ impl Element {
|
||||||
local_name: local_name,
|
local_name: local_name,
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
attrs: vec!(),
|
attrs: RefCell::new(vec!()),
|
||||||
attr_list: None,
|
attr_list: Cell::new(None),
|
||||||
style_attribute: None,
|
style_attribute: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,7 +168,9 @@ impl RawLayoutElementHelpers for Element {
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str)
|
unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str)
|
||||||
-> Option<&'static 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();
|
let attr = attr.unsafe_get();
|
||||||
name == (*attr).local_name && (*attr).namespace == *namespace
|
name == (*attr).local_name && (*attr).namespace == *namespace
|
||||||
}).map(|attr| {
|
}).map(|attr| {
|
||||||
|
@ -232,7 +235,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
||||||
let element: &Element = self.deref();
|
let element: &Element = self.deref();
|
||||||
let is_html_element = self.html_element_in_html_document();
|
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 {
|
let same_name = if is_html_element {
|
||||||
name.to_ascii_lower() == attr.local_name
|
name.to_ascii_lower() == attr.local_name
|
||||||
} else {
|
} else {
|
||||||
|
@ -284,7 +287,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
||||||
fn do_set_attribute(&mut self, local_name: DOMString, value: DOMString,
|
fn do_set_attribute(&mut self, local_name: DOMString, value: DOMString,
|
||||||
name: DOMString, namespace: Namespace,
|
name: DOMString, namespace: Namespace,
|
||||||
prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool) {
|
prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool) {
|
||||||
let idx = self.deref().attrs.iter()
|
let idx = self.deref().attrs.borrow().iter()
|
||||||
.map(|attr| attr.root())
|
.map(|attr| attr.root())
|
||||||
.position(|attr| cb(&*attr));
|
.position(|attr| cb(&*attr));
|
||||||
let (idx, set_type) = match idx {
|
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 window = window_from_node(self).root();
|
||||||
let attr = Attr::new(&*window, local_name.clone(), value.clone(),
|
let attr = Attr::new(&*window, local_name.clone(), value.clone(),
|
||||||
name, namespace.clone(), prefix, self);
|
name, namespace.clone(), prefix, self);
|
||||||
self.deref_mut().attrs.push_unrooted(&attr);
|
self.deref().attrs.borrow_mut().push_unrooted(&attr);
|
||||||
(self.deref().attrs.len() - 1, FirstSetAttr)
|
(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 {
|
fn remove_attribute(&mut self, namespace: Namespace, name: DOMString) -> ErrorResult {
|
||||||
let (_, local_name) = get_attribute_parts(name.clone());
|
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
|
attr.local_name == local_name
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -317,12 +320,12 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if namespace == namespace::Null {
|
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))
|
vtable_for(NodeCast::from_mut_ref(self))
|
||||||
.before_remove_attr(local_name.clone(), removed_raw_value);
|
.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
|
// http://dom.spec.whatwg.org/#dom-element-attributes
|
||||||
fn Attributes(&mut self) -> Temporary<AttrList> {
|
fn Attributes(&mut self) -> Temporary<AttrList> {
|
||||||
match self.attr_list {
|
match self.attr_list.get() {
|
||||||
None => (),
|
None => (),
|
||||||
Some(ref list) => return Temporary::new(list.clone()),
|
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 window = doc.deref().window.root();
|
||||||
let list = AttrList::new(&*window, self);
|
let list = AttrList::new(&*window, self);
|
||||||
self.attr_list.assign(Some(list));
|
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
|
// http://dom.spec.whatwg.org/#dom-element-getattribute
|
||||||
|
|
|
@ -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) {
|
fn serialize_elem(elem: &JSRef<Element>, open_elements: &mut Vec<~str>, html: &mut StrBuf) {
|
||||||
html.push_char('<');
|
html.push_char('<');
|
||||||
html.push_str(elem.deref().local_name);
|
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();
|
let attr = attr.root();
|
||||||
serialize_attr(&*attr, html);
|
serialize_attr(&*attr, html);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1297,8 +1297,8 @@ impl Node {
|
||||||
// FIXME: https://github.com/mozilla/servo/issues/1737
|
// FIXME: https://github.com/mozilla/servo/issues/1737
|
||||||
copy_elem.namespace = node_elem.namespace.clone();
|
copy_elem.namespace = node_elem.namespace.clone();
|
||||||
let window = document.deref().window.root();
|
let window = document.deref().window.root();
|
||||||
for attr in node_elem.attrs.iter().map(|attr| attr.root()) {
|
for attr in node_elem.attrs.borrow().iter().map(|attr| attr.root()) {
|
||||||
copy_elem.attrs.push_unrooted(
|
copy_elem.attrs.borrow_mut().push_unrooted(
|
||||||
&Attr::new(&*window,
|
&Attr::new(&*window,
|
||||||
attr.deref().local_name.clone(), attr.deref().value.clone(),
|
attr.deref().local_name.clone(), attr.deref().value.clone(),
|
||||||
attr.deref().name.clone(), attr.deref().namespace.clone(),
|
attr.deref().name.clone(), attr.deref().namespace.clone(),
|
||||||
|
@ -1766,9 +1766,11 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
|
let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
|
||||||
let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap();
|
let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap();
|
||||||
// FIXME: namespace prefix
|
// FIXME: namespace prefix
|
||||||
(element.deref().namespace == other_element.deref().namespace) &&
|
let element = element.deref();
|
||||||
(element.deref().local_name == other_element.deref().local_name) &&
|
let other_element = other_element.deref();
|
||||||
(element.deref().attrs.len() == other_element.deref().attrs.len())
|
(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 {
|
fn is_equal_processinginstruction(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
|
||||||
let pi: &JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap();
|
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 {
|
fn is_equal_element_attrs(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
|
||||||
let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
|
let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
|
||||||
let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap();
|
let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap();
|
||||||
assert!(element.deref().attrs.len() == other_element.deref().attrs.len());
|
let element = element.deref();
|
||||||
element.deref().attrs.iter().map(|attr| attr.root()).all(|attr| {
|
let other_element = other_element.deref();
|
||||||
other_element.deref().attrs.iter().map(|attr| attr.root()).any(|other_attr| {
|
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.namespace == other_attr.namespace) &&
|
||||||
(attr.local_name == other_attr.local_name) &&
|
(attr.local_name == other_attr.local_name) &&
|
||||||
(attr.value == other_attr.value)
|
(attr.value == other_attr.value)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue