Fix #1264: support namespaced attribute selectors.

This commit is contained in:
Simon Sapin 2013-12-10 17:53:12 +00:00
parent 4b3defb282
commit b290823f4d
10 changed files with 27 additions and 29 deletions

View file

@ -112,7 +112,7 @@ impl ImageBoxInfo {
// TODO: This could probably go somewhere else // TODO: This could probably go somewhere else
pub fn image_width(&self, base: &Box) -> Au { pub fn image_width(&self, base: &Box) -> Au {
let attr_width: Option<int> = do base.node.with_imm_element |elt| { let attr_width: Option<int> = do base.node.with_imm_element |elt| {
match elt.get_attr("width") { match elt.get_attr(None, "width") {
Some(width) => { Some(width) => {
FromStr::from_str(width) FromStr::from_str(width)
} }
@ -136,7 +136,7 @@ impl ImageBoxInfo {
// TODO: This could probably go somewhere else // TODO: This could probably go somewhere else
pub fn image_height(&self, base: &Box) -> Au { pub fn image_height(&self, base: &Box) -> Au {
let attr_height: Option<int> = do base.node.with_imm_element |elt| { let attr_height: Option<int> = do base.node.with_imm_element |elt| {
match elt.get_attr("height") { match elt.get_attr(None, "height") {
Some(height) => { Some(height) => {
FromStr::from_str(height) FromStr::from_str(height)
} }

View file

@ -296,7 +296,7 @@ impl Document {
pub fn GetElementsByName(&self, name: DOMString) -> @mut HTMLCollection { pub fn GetElementsByName(&self, name: DOMString) -> @mut HTMLCollection {
self.createHTMLCollection(|elem| self.createHTMLCollection(|elem|
elem.get_attr("name").is_some() && eq_slice(elem.get_attr("name").unwrap(), name)) elem.get_attr(None, "name").is_some() && eq_slice(elem.get_attr(None, "name").unwrap(), name))
} }
pub fn createHTMLCollection(&self, callback: &fn(elem: &Element) -> bool) -> @mut HTMLCollection { pub fn createHTMLCollection(&self, callback: &fn(elem: &Element) -> bool) -> @mut HTMLCollection {
@ -374,7 +374,7 @@ fn foreach_ided_elements(root: &AbstractNode<ScriptView>,
} }
do node.with_imm_element |element| { do node.with_imm_element |element| {
match element.get_attr("id") { match element.get_attr(None, "id") {
Some(id) => { Some(id) => {
callback(&id.to_str(), &node); callback(&id.to_str(), &node);
} }

View file

@ -133,8 +133,8 @@ impl ElementLike for Element {
self.namespace.to_str().unwrap_or("") self.namespace.to_str().unwrap_or("")
} }
fn get_attr(&self, name: &str) -> Option<~str> { fn get_attr(&self, ns_url: Option<~str>, name: &str) -> Option<~str> {
self.get_attribute(None, name).map(|attr| attr.value.clone()) self.get_attribute(ns_url, name).map(|attr| attr.value.clone())
} }
fn get_link(&self) -> Option<~str>{ fn get_link(&self) -> Option<~str>{
@ -144,7 +144,7 @@ impl ElementLike for Element {
ElementNodeTypeId(HTMLAnchorElementTypeId) | ElementNodeTypeId(HTMLAnchorElementTypeId) |
ElementNodeTypeId(HTMLAreaElementTypeId) | ElementNodeTypeId(HTMLAreaElementTypeId) |
ElementNodeTypeId(HTMLLinkElementTypeId) ElementNodeTypeId(HTMLLinkElementTypeId)
=> self.get_attr("href"), => self.get_attr(None, "href"),
_ => None, _ => None,
} }
} }
@ -304,7 +304,7 @@ impl Element {
} }
pub fn Id(&self, _abstract_self: AbstractNode<ScriptView>) -> DOMString { pub fn Id(&self, _abstract_self: AbstractNode<ScriptView>) -> DOMString {
match self.get_attr(&"id") { match self.get_attr(None, "id") {
Some(x) => x, Some(x) => x,
None => ~"" None => ~""
} }
@ -327,7 +327,7 @@ impl Element {
} }
pub fn GetAttribute(&self, name: DOMString) -> Option<DOMString> { pub fn GetAttribute(&self, name: DOMString) -> Option<DOMString> {
self.get_attr(name).map(|s| s.to_owned()) self.get_attr(None, name).map(|s| s.to_owned())
} }
pub fn GetAttributeNS(&self, namespace: Option<DOMString>, local_name: DOMString) -> Option<DOMString> { pub fn GetAttributeNS(&self, namespace: Option<DOMString>, local_name: DOMString) -> Option<DOMString> {

View file

@ -58,7 +58,7 @@ impl HTMLDocument {
pub fn Links(&self) -> @mut HTMLCollection { pub fn Links(&self) -> @mut HTMLCollection {
self.parent.createHTMLCollection(|elem| self.parent.createHTMLCollection(|elem|
(eq_slice(elem.tag_name, "a") || eq_slice(elem.tag_name, "area")) (eq_slice(elem.tag_name, "a") || eq_slice(elem.tag_name, "area"))
&& elem.get_attr("href").is_some()) && elem.get_attr(None, "href").is_some())
} }
pub fn Forms(&self) -> @mut HTMLCollection { pub fn Forms(&self) -> @mut HTMLCollection {
@ -71,7 +71,7 @@ impl HTMLDocument {
pub fn Anchors(&self) -> @mut HTMLCollection { pub fn Anchors(&self) -> @mut HTMLCollection {
self.parent.createHTMLCollection(|elem| self.parent.createHTMLCollection(|elem|
eq_slice(elem.tag_name, "a") && elem.get_attr("name").is_some()) eq_slice(elem.tag_name, "a") && elem.get_attr(None, "name").is_some())
} }
pub fn Applets(&self) -> @mut HTMLCollection { pub fn Applets(&self) -> @mut HTMLCollection {

View file

@ -40,7 +40,7 @@ impl HTMLImageElement {
/// prefetching the image. This method must be called after `src` is changed. /// prefetching the image. This method must be called after `src` is changed.
pub fn update_image(&mut self, image_cache: ImageCacheTask, url: Option<Url>) { pub fn update_image(&mut self, image_cache: ImageCacheTask, url: Option<Url>) {
let elem = &mut self.htmlelement.element; let elem = &mut self.htmlelement.element;
let src_opt = elem.get_attr("src").map(|x| x.to_str()); let src_opt = elem.get_attr(None, "src").map(|x| x.to_str());
match src_opt { match src_opt {
None => {} None => {}
Some(src) => { Some(src) => {

View file

@ -29,7 +29,7 @@ impl HTMLScriptElement {
impl HTMLScriptElement { impl HTMLScriptElement {
pub fn Src(&self) -> DOMString { pub fn Src(&self) -> DOMString {
match self.htmlelement.element.get_attr("src") { match self.htmlelement.element.get_attr(None, "src") {
Some(s) => s.to_owned(), Some(s) => s.to_owned(),
None => ~"" None => ~""
} }

View file

@ -350,7 +350,7 @@ pub fn parse_html(cx: *JSContext,
// Handle CSS style sheets from <link> elements // Handle CSS style sheets from <link> elements
ElementNodeTypeId(HTMLLinkElementTypeId) => { ElementNodeTypeId(HTMLLinkElementTypeId) => {
do node.with_imm_element |element| { do node.with_imm_element |element| {
match (element.get_attr("rel"), element.get_attr("href")) { match (element.get_attr(None, "rel"), element.get_attr(None, "href")) {
(Some(rel), Some(href)) => { (Some(rel), Some(href)) => {
if "stylesheet" == rel { if "stylesheet" == rel {
debug!("found CSS stylesheet: {:s}", href); debug!("found CSS stylesheet: {:s}", href);
@ -369,7 +369,7 @@ pub fn parse_html(cx: *JSContext,
let iframe_chan = iframe_chan.take(); let iframe_chan = iframe_chan.take();
let sandboxed = iframe_element.is_sandboxed(); let sandboxed = iframe_element.is_sandboxed();
let elem = &mut iframe_element.htmlelement.element; let elem = &mut iframe_element.htmlelement.element;
let src_opt = elem.get_attr("src").map(|x| x.to_str()); let src_opt = elem.get_attr(None, "src").map(|x| x.to_str());
for src in src_opt.iter() { for src in src_opt.iter() {
let iframe_url = make_url(src.clone(), Some(url2.clone())); let iframe_url = make_url(src.clone(), Some(url2.clone()));
iframe_element.frame = Some(iframe_url.clone()); iframe_element.frame = Some(iframe_url.clone());
@ -470,7 +470,7 @@ pub fn parse_html(cx: *JSContext,
unsafe { unsafe {
let scriptnode: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(script); let scriptnode: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(script);
do scriptnode.with_imm_element |script| { do scriptnode.with_imm_element |script| {
match script.get_attr("src") { match script.get_attr(None, "src") {
Some(src) => { Some(src) => {
debug!("found script: {:s}", src); debug!("found script: {:s}", src);
let new_url = make_url(src.to_str(), Some(url3.clone())); let new_url = make_url(src.to_str(), Some(url3.clone()));

View file

@ -802,7 +802,7 @@ impl ScriptTask {
let mut anchors = doc_node.traverse_preorder().filter(|node| node.is_anchor_element()); let mut anchors = doc_node.traverse_preorder().filter(|node| node.is_anchor_element());
do anchors.find |node| { do anchors.find |node| {
do node.with_imm_element |elem| { do node.with_imm_element |elem| {
match elem.get_attr("name") { match elem.get_attr(None, "name") {
Some(name) => eq_slice(name, fragid), Some(name) => eq_slice(name, fragid),
None => false None => false
} }
@ -901,7 +901,7 @@ impl ScriptTask {
fn load_url_from_element(&self, page: @mut Page, element: &Element) { fn load_url_from_element(&self, page: @mut Page, element: &Element) {
// if the node's element is "a," load url from href attr // if the node's element is "a," load url from href attr
let attr = element.get_attr("href"); let attr = element.get_attr(None, "href");
for href in attr.iter() { for href in attr.iter() {
debug!("ScriptTask: clicked on link to {:s}", *href); debug!("ScriptTask: clicked on link to {:s}", *href);
let click_frag = href.starts_with("#"); let click_frag = href.starts_with("#");

View file

@ -74,13 +74,13 @@ impl SelectorMap {
let init_len = matching_rules_list[list_index].len(); let init_len = matching_rules_list[list_index].len();
static WHITESPACE: &'static [char] = &'static [' ', '\t', '\n', '\r', '\x0C']; static WHITESPACE: &'static [char] = &'static [' ', '\t', '\n', '\r', '\x0C'];
do node.with_imm_element_like |element: &E| { do node.with_imm_element_like |element: &E| {
match element.get_attr("id") { match element.get_attr(None, "id") {
Some(id) => SelectorMap::get_matching_rules_from_hash( Some(id) => SelectorMap::get_matching_rules_from_hash(
node, pseudo_element, &self.id_hash, id, &mut matching_rules_list[list_index]), node, pseudo_element, &self.id_hash, id, &mut matching_rules_list[list_index]),
None => {} None => {}
} }
match element.get_attr("class") { match element.get_attr(None, "class") {
Some(ref class_attr) => { Some(ref class_attr) => {
for class in class_attr.split_iter(WHITESPACE) { for class in class_attr.split_iter(WHITESPACE) {
SelectorMap::get_matching_rules_from_hash( SelectorMap::get_matching_rules_from_hash(
@ -434,7 +434,7 @@ fn matches_simple_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: Ele
// TODO: cache and intern IDs on elements. // TODO: cache and intern IDs on elements.
IDSelector(ref id) => { IDSelector(ref id) => {
do element.with_imm_element_like |element: &E| { do element.with_imm_element_like |element: &E| {
match element.get_attr("id") { match element.get_attr(None, "id") {
Some(attr) => str::eq_slice(attr, *id), Some(attr) => str::eq_slice(attr, *id),
None => false None => false
} }
@ -443,7 +443,7 @@ fn matches_simple_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: Ele
// TODO: cache and intern classe names on elements. // TODO: cache and intern classe names on elements.
ClassSelector(ref class) => { ClassSelector(ref class) => {
do element.with_imm_element_like |element: &E| { do element.with_imm_element_like |element: &E| {
match element.get_attr("class") { match element.get_attr(None, "class") {
None => false, None => false,
// TODO: case-sensitivity depends on the document type and quirks mode // TODO: case-sensitivity depends on the document type and quirks mode
Some(ref class_attr) Some(ref class_attr)
@ -642,12 +642,10 @@ fn matches_last_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementL
fn match_attribute<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>( fn match_attribute<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
attr: &AttrSelector, element: &T, f: &fn(&str)-> bool) -> bool { attr: &AttrSelector, element: &T, f: &fn(&str)-> bool) -> bool {
do element.with_imm_element_like |element: &E| { do element.with_imm_element_like |element: &E| {
match attr.namespace { // FIXME: avoid .clone() here? See #1367
Some(_) => false, // TODO, when the DOM supports namespaces on attributes match element.get_attr(attr.namespace.clone(), attr.name) {
None => match element.get_attr(attr.name) { None => false,
None => false, Some(value) => f(value)
Some(ref value) => f(value.as_slice())
}
} }
} }
} }

View file

@ -349,6 +349,6 @@ pub trait TreeNode<Ref: TreeNodeRef<Self>> {
pub trait ElementLike { pub trait ElementLike {
fn get_local_name<'a>(&'a self) -> &'a str; fn get_local_name<'a>(&'a self) -> &'a str;
fn get_namespace_url<'a>(&'a self) -> &'a str; fn get_namespace_url<'a>(&'a self) -> &'a str;
fn get_attr(&self, name: &str) -> Option<~str>; fn get_attr(&self, ns_url: Option<~str>, name: &str) -> Option<~str>;
fn get_link(&self) -> Option<~str>; fn get_link(&self) -> Option<~str>;
} }