Change get_attr() to get_attr_val_for_layout().

The old code was used by both layout and script, but was erroneously
borrowing for the layout case (which causes parallelism
problems). script now uses only `value_ref()` or `get_attribute()`, and
layout now has its own unsafe version that dances around the borrows of
`@mut Attr`.
This commit is contained in:
Jack Moffitt 2014-01-22 17:02:21 -07:00
parent 539cf58f73
commit c443bcbfff
9 changed files with 50 additions and 34 deletions

View file

@ -65,6 +65,10 @@ impl Attr {
util::swap(&mut self.value, &mut value);
value
}
pub fn value_ref<'a>(&'a self) -> &'a str {
self.value.as_slice()
}
}
impl Attr {

View file

@ -366,7 +366,7 @@ impl Document {
pub fn GetElementsByName(&self, name: DOMString) -> @mut HTMLCollection {
self.createHTMLCollection(|elem|
elem.get_attr(Null, "name").is_some() && eq_slice(elem.get_attr(Null, "name").unwrap(), name))
elem.get_attribute(Null, "name").is_some() && eq_slice(elem.get_attribute(Null, "name").unwrap().value_ref(), name))
}
pub fn createHTMLCollection(&self, callback: |elem: &Element| -> bool) -> @mut HTMLCollection {
@ -456,9 +456,9 @@ fn foreach_ided_elements(root: &AbstractNode, callback: |&DOMString, &AbstractNo
}
node.with_imm_element(|element| {
match element.get_attr(Null, "id") {
match element.get_attribute(Null, "id") {
Some(id) => {
callback(&id.to_str(), &node);
callback(&id.Value(), &node);
}
None => ()
}

View file

@ -23,8 +23,10 @@ use layout_interface::{ContentBoxesResponse, ContentChangedDocumentDamage};
use layout_interface::{MatchSelectorsDocumentDamage};
use style;
use std::str::eq;
use std::ascii::StrAsciiExt;
use std::cast;
use std::str::eq;
use std::unstable::raw::Box;
pub struct Element {
node: Node,
@ -155,9 +157,19 @@ impl Element {
}).map(|&x| x)
}
// FIXME(pcwalton): This is kind of confusingly named relative to the above...
pub fn get_attr(&self, namespace: Namespace, name: &str) -> Option<~str> {
self.get_attribute(namespace, name).map(|attr| attr.value.clone())
pub unsafe fn get_attr_val_for_layout(&self, namespace: Namespace, name: &str)
-> Option<&'static str> {
// FIXME: only case-insensitive in the HTML namespace (as opposed to SVG, etc.)
let name = name.to_ascii_lower();
self.attrs.iter().find(|attr: & &@mut Attr| {
// unsafely avoid a borrow because this is accessed by many tasks
// during parallel layout
let attr: ***Box<Attr> = cast::transmute(attr);
name == (***attr).data.local_name && (***attr).data.namespace == namespace
}).map(|attr| {
let attr: **Box<Attr> = cast::transmute(attr);
cast::transmute((**attr).data.value.as_slice())
})
}
pub fn set_attr(&mut self, abstract_self: AbstractNode, name: DOMString, value: DOMString)
@ -352,8 +364,8 @@ impl Element {
}
pub fn get_string_attribute(&self, name: &str) -> DOMString {
match self.get_attr(Null, name) {
Some(x) => x,
match self.get_attribute(Null, name) {
Some(x) => x.Value(),
None => ~""
}
}
@ -390,7 +402,7 @@ impl Element {
}
pub fn GetAttribute(&self, name: DOMString) -> Option<DOMString> {
self.get_attr(Null, name).map(|s| s.to_owned())
self.get_attribute(Null, name).map(|s| s.Value())
}
pub fn GetAttributeNS(&self, namespace: Option<DOMString>, local_name: DOMString) -> Option<DOMString> {

View file

@ -11,7 +11,6 @@ use dom::window::Window;
use js::jsapi::JSTracer;
use std::str::eq_slice;
use style::TElement;
pub struct HTMLDocument {
parent: Document
@ -46,7 +45,7 @@ impl HTMLDocument {
pub fn Links(&self) -> @mut HTMLCollection {
self.parent.createHTMLCollection(|elem|
(eq_slice(elem.tag_name, "a") || eq_slice(elem.tag_name, "area"))
&& elem.get_attr(Null, "href").is_some())
&& elem.get_attribute(Null, "href").is_some())
}
pub fn Forms(&self) -> @mut HTMLCollection {
@ -59,7 +58,7 @@ impl HTMLDocument {
pub fn Anchors(&self) -> @mut HTMLCollection {
self.parent.createHTMLCollection(|elem|
eq_slice(elem.tag_name, "a") && elem.get_attr(Null, "name").is_some())
eq_slice(elem.tag_name, "a") && elem.get_attribute(Null, "name").is_some())
}
pub fn Applets(&self) -> @mut HTMLCollection {

View file

@ -15,7 +15,6 @@ use layout_interface::{ContentBoxQuery, ContentBoxResponse};
use servo_net::image_cache_task;
use servo_net::image_cache_task::ImageCacheTask;
use servo_util::url::make_url;
use style::TElement;
pub struct HTMLImageElement {
htmlelement: HTMLElement,
@ -41,7 +40,7 @@ impl HTMLImageElement {
/// prefetching the image. This method must be called after `src` is changed.
pub fn update_image(&mut self, image_cache: ImageCacheTask, url: Option<Url>) {
let elem = &mut self.htmlelement.element;
let src_opt = elem.get_attr(Null, "src").map(|x| x.to_str());
let src_opt = elem.get_attribute(Null, "src").map(|x| x.Value());
match src_opt {
None => {}
Some(src) => {