auto merge of #1025 : saneyuki/servo/attr, r=metajack

This commit is contained in:
bors-servo 2013-10-18 20:43:03 -07:00
commit 5c725b31af
2 changed files with 64 additions and 26 deletions

View file

@ -18,15 +18,15 @@ use servo_util::tree::{TreeNodeRef, ElementLike};
use js::jsapi::{JSContext, JSObject}; use js::jsapi::{JSContext, JSObject};
use std::cell::Cell;
use std::comm; use std::comm;
use std::str::eq_slice; use std::hashmap::HashMap;
use std::ascii::StrAsciiExt; use std::ascii::StrAsciiExt;
pub struct Element { pub struct Element {
node: Node<ScriptView>, node: Node<ScriptView>,
tag_name: ~str, // TODO: This should be an atom, not a ~str. tag_name: ~str, // TODO: This should be an atom, not a ~str.
attrs: ~[Attr], attrs: HashMap<~str, ~str>,
attrs_list: ~[~str], // store an order of attributes.
style_attribute: Option<Stylesheet>, style_attribute: Option<Stylesheet>,
} }
@ -131,15 +131,14 @@ impl ElementLike for Element {
} }
fn get_attr<'a>(&'a self, name: &str) -> Option<&'a str> { fn get_attr<'a>(&'a self, name: &str) -> Option<&'a str> {
// FIXME: Need an each() that links lifetimes in Rust.
for attr in self.attrs.iter() {
// FIXME: only case-insensitive in the HTML namespace (as opposed to SVG, etc.) // FIXME: only case-insensitive in the HTML namespace (as opposed to SVG, etc.)
if attr.name.eq_ignore_ascii_case(name) { let name = name.to_ascii_lower();
let val: &str = attr.value; let value: Option<&str> = self.attrs.find_equiv(&name).map(|&value| {
return Some(val); let value: &str = *value;
} value
} });
return None;
return value;
} }
} }
@ -148,7 +147,8 @@ impl<'self> Element {
Element { Element {
node: Node::new(ElementNodeTypeId(type_id), document), node: Node::new(ElementNodeTypeId(type_id), document),
tag_name: tag_name, tag_name: tag_name,
attrs: ~[], attrs: HashMap::new(),
attrs_list: ~[],
style_attribute: None, style_attribute: None,
} }
} }
@ -157,19 +157,20 @@ impl<'self> Element {
abstract_self: AbstractNode<ScriptView>, abstract_self: AbstractNode<ScriptView>,
raw_name: &DOMString, raw_name: &DOMString,
raw_value: &DOMString) { raw_value: &DOMString) {
let name = null_str_as_empty(raw_name); let name = null_str_as_empty(raw_name).to_ascii_lower();
let value_cell = Cell::new(null_str_as_empty(raw_value)); let value = null_str_as_empty(raw_value);
let mut found = false;
for attr in self.attrs.mut_iter() { // FIXME: reduce the time of `value.clone()`.
if eq_slice(attr.name, name) { self.attrs.mangle(name.clone(), value.clone(),
attr.value = value_cell.take().clone(); |new_name: &~str, new_value: ~str| {
found = true; // register to the ordered list.
break; self.attrs_list.push(new_name.clone());
} new_value
} },
if !found { |_, old_value: &mut ~str, new_value: ~str| {
self.attrs.push(Attr::new(name.to_str(), value_cell.take().clone())); // update value.
} *old_value = new_value;
});
if "style" == name { if "style" == name {
self.style_attribute = Some( self.style_attribute = Some(

View file

@ -0,0 +1,37 @@
<html>
<head id="foo">
<title></title>
<script src="harness.js"></script>
</head>
<body>
<div id="test" foo="bar"></div>
<script>
let test = document.getElementById("test");
{
let r1 = test.getAttribute("id");
is(r1, "test", "test1-0, Element.getAttribute().");
let r2 = test.getAttribute("foo");
is(r2, "bar", "test1-1, Element.getAttribute().");
}
{
let NAME = "hoge";
let VALUE = "fuga";
test.setAttribute(NAME, VALUE);
let r = test.getAttribute(NAME);
is(r, VALUE, "test2. Element.setAttribute().");
}
{
let NAME = "foo";
let VALUE = "mozilla";
test.setAttribute(NAME, VALUE);
let r = test.getAttribute(NAME);
is(r, VALUE, "test3, attribute update by Element.setAttribute().")
}
finish();
</script>
</body>
</html>