mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Fix getElementsByTagName[NS] support to match the spec.
This commit is contained in:
parent
70e70fd1d9
commit
0b802ab018
5 changed files with 65 additions and 22 deletions
|
@ -351,12 +351,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
// http://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens
|
// http://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens
|
||||||
fn GetElementsByTagNameNS(&self, maybe_ns: Option<DOMString>, tag_name: DOMString) -> Temporary<HTMLCollection> {
|
fn GetElementsByTagNameNS(&self, maybe_ns: Option<DOMString>, tag_name: DOMString) -> Temporary<HTMLCollection> {
|
||||||
let window = self.window.root();
|
let window = self.window.root();
|
||||||
|
HTMLCollection::by_tag_name_ns(&*window, NodeCast::from_ref(self), tag_name, maybe_ns)
|
||||||
let namespace = match maybe_ns {
|
|
||||||
Some(namespace) => Namespace::from_str(namespace.as_slice()),
|
|
||||||
None => Null
|
|
||||||
};
|
|
||||||
HTMLCollection::by_tag_name_ns(&*window, NodeCast::from_ref(self), tag_name, namespace)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#dom-document-getelementsbyclassname
|
// http://dom.spec.whatwg.org/#dom-document-getelementsbyclassname
|
||||||
|
|
|
@ -224,9 +224,8 @@ pub trait ElementHelpers {
|
||||||
|
|
||||||
impl<'a> ElementHelpers for JSRef<'a, Element> {
|
impl<'a> ElementHelpers for JSRef<'a, Element> {
|
||||||
fn html_element_in_html_document(&self) -> bool {
|
fn html_element_in_html_document(&self) -> bool {
|
||||||
let is_html = self.namespace == namespace::HTML;
|
|
||||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
is_html && node.owner_doc().root().is_html_document
|
self.namespace == namespace::HTML && node.is_in_html_doc()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_local_name<'a>(&'a self) -> &'a Atom {
|
fn get_local_name<'a>(&'a self) -> &'a Atom {
|
||||||
|
@ -702,12 +701,8 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
|
|
||||||
fn GetElementsByTagNameNS(&self, maybe_ns: Option<DOMString>,
|
fn GetElementsByTagNameNS(&self, maybe_ns: Option<DOMString>,
|
||||||
localname: DOMString) -> Temporary<HTMLCollection> {
|
localname: DOMString) -> Temporary<HTMLCollection> {
|
||||||
let namespace = match maybe_ns {
|
|
||||||
Some(namespace) => Namespace::from_str(namespace.as_slice()),
|
|
||||||
None => Null
|
|
||||||
};
|
|
||||||
let window = window_from_node(self).root();
|
let window = window_from_node(self).root();
|
||||||
HTMLCollection::by_tag_name_ns(&*window, NodeCast::from_ref(self), localname, namespace)
|
HTMLCollection::by_tag_name_ns(&*window, NodeCast::from_ref(self), localname, maybe_ns)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn GetElementsByClassName(&self, classes: DOMString) -> Temporary<HTMLCollection> {
|
fn GetElementsByClassName(&self, classes: DOMString) -> Temporary<HTMLCollection> {
|
||||||
|
|
|
@ -8,14 +8,16 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, NodeCast};
|
||||||
use dom::bindings::global::Window;
|
use dom::bindings::global::Window;
|
||||||
use dom::bindings::js::{JS, JSRef, Temporary};
|
use dom::bindings::js::{JS, JSRef, Temporary};
|
||||||
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
|
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
|
||||||
use dom::element::{Element, AttributeHandlers};
|
use dom::element::{Element, AttributeHandlers, ElementHelpers};
|
||||||
use dom::node::{Node, NodeHelpers};
|
use dom::node::{Node, NodeHelpers};
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use servo_util::atom::Atom;
|
use servo_util::atom::Atom;
|
||||||
|
use servo_util::namespace;
|
||||||
use servo_util::namespace::Namespace;
|
use servo_util::namespace::Namespace;
|
||||||
use servo_util::str::{DOMString, split_html_space_chars};
|
use servo_util::str::{DOMString, split_html_space_chars};
|
||||||
|
|
||||||
use serialize::{Encoder, Encodable};
|
use serialize::{Encoder, Encodable};
|
||||||
|
use std::ascii::StrAsciiExt;
|
||||||
|
|
||||||
pub trait CollectionFilter {
|
pub trait CollectionFilter {
|
||||||
fn filter(&self, elem: &JSRef<Element>, root: &JSRef<Node>) -> bool;
|
fn filter(&self, elem: &JSRef<Element>, root: &JSRef<Node>) -> bool;
|
||||||
|
@ -59,36 +61,82 @@ impl HTMLCollection {
|
||||||
HTMLCollection::new(window, Live(JS::from_rooted(root), filter))
|
HTMLCollection::new(window, Live(JS::from_rooted(root), filter))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn all_elements(window: &JSRef<Window>, root: &JSRef<Node>,
|
||||||
|
namespace_filter: Option<Namespace>) -> Temporary<HTMLCollection> {
|
||||||
|
struct AllElementFilter {
|
||||||
|
namespace_filter: Option<Namespace>
|
||||||
|
}
|
||||||
|
impl CollectionFilter for AllElementFilter {
|
||||||
|
fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool {
|
||||||
|
match self.namespace_filter {
|
||||||
|
None => true,
|
||||||
|
Some(ref namespace) => elem.namespace == *namespace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let filter = AllElementFilter {namespace_filter: namespace_filter};
|
||||||
|
HTMLCollection::create(window, root, box filter)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn by_tag_name(window: &JSRef<Window>, root: &JSRef<Node>, tag: DOMString)
|
pub fn by_tag_name(window: &JSRef<Window>, root: &JSRef<Node>, tag: DOMString)
|
||||||
-> Temporary<HTMLCollection> {
|
-> Temporary<HTMLCollection> {
|
||||||
|
if tag.as_slice() == "*" {
|
||||||
|
return HTMLCollection::all_elements(window, root, None);
|
||||||
|
}
|
||||||
|
|
||||||
struct TagNameFilter {
|
struct TagNameFilter {
|
||||||
tag: Atom
|
tag: Atom,
|
||||||
|
ascii_lower_tag: Atom,
|
||||||
}
|
}
|
||||||
impl CollectionFilter for TagNameFilter {
|
impl CollectionFilter for TagNameFilter {
|
||||||
fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool {
|
fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool {
|
||||||
elem.deref().local_name == self.tag
|
if elem.html_element_in_html_document() {
|
||||||
|
elem.local_name == self.ascii_lower_tag
|
||||||
|
} else {
|
||||||
|
elem.local_name == self.tag
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let filter = TagNameFilter {
|
let filter = TagNameFilter {
|
||||||
tag: Atom::from_slice(tag.as_slice())
|
tag: Atom::from_slice(tag.as_slice()),
|
||||||
|
ascii_lower_tag: Atom::from_slice(tag.as_slice().to_ascii_lower().as_slice()),
|
||||||
};
|
};
|
||||||
HTMLCollection::create(window, root, box filter)
|
HTMLCollection::create(window, root, box filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn by_tag_name_ns(window: &JSRef<Window>, root: &JSRef<Node>, tag: DOMString,
|
pub fn by_tag_name_ns(window: &JSRef<Window>, root: &JSRef<Node>, tag: DOMString,
|
||||||
namespace: Namespace) -> Temporary<HTMLCollection> {
|
maybe_ns: Option<DOMString>) -> Temporary<HTMLCollection> {
|
||||||
|
let namespace_filter = match maybe_ns {
|
||||||
|
Some(namespace) => {
|
||||||
|
match namespace.as_slice() {
|
||||||
|
"*" => None,
|
||||||
|
ns => Some(Namespace::from_str(ns)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => Some(namespace::Null),
|
||||||
|
};
|
||||||
|
|
||||||
|
if tag.as_slice() == "*" {
|
||||||
|
return HTMLCollection::all_elements(window, root, namespace_filter);
|
||||||
|
}
|
||||||
struct TagNameNSFilter {
|
struct TagNameNSFilter {
|
||||||
tag: Atom,
|
tag: Atom,
|
||||||
namespace: Namespace
|
namespace_filter: Option<Namespace>
|
||||||
}
|
}
|
||||||
impl CollectionFilter for TagNameNSFilter {
|
impl CollectionFilter for TagNameNSFilter {
|
||||||
fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool {
|
fn filter(&self, elem: &JSRef<Element>, _root: &JSRef<Node>) -> bool {
|
||||||
elem.deref().namespace == self.namespace && elem.deref().local_name == self.tag
|
let ns_match = match self.namespace_filter {
|
||||||
|
Some(ref namespace) => {
|
||||||
|
elem.deref().namespace == *namespace
|
||||||
|
},
|
||||||
|
None => true
|
||||||
|
};
|
||||||
|
ns_match && elem.deref().local_name == self.tag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let filter = TagNameNSFilter {
|
let filter = TagNameNSFilter {
|
||||||
tag: Atom::from_slice(tag.as_slice()),
|
tag: Atom::from_slice(tag.as_slice()),
|
||||||
namespace: namespace
|
namespace_filter: namespace_filter
|
||||||
};
|
};
|
||||||
HTMLCollection::create(window, root, box filter)
|
HTMLCollection::create(window, root, box filter)
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,6 +389,7 @@ pub trait NodeHelpers {
|
||||||
|
|
||||||
fn owner_doc(&self) -> Temporary<Document>;
|
fn owner_doc(&self) -> Temporary<Document>;
|
||||||
fn set_owner_doc(&self, document: &JSRef<Document>);
|
fn set_owner_doc(&self, document: &JSRef<Document>);
|
||||||
|
fn is_in_html_doc(&self) -> bool;
|
||||||
|
|
||||||
fn wait_until_safe_to_modify_dom(&self);
|
fn wait_until_safe_to_modify_dom(&self);
|
||||||
|
|
||||||
|
@ -672,6 +673,10 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
|
||||||
self.owner_doc.assign(Some(document.clone()));
|
self.owner_doc.assign(Some(document.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_in_html_doc(&self) -> bool {
|
||||||
|
self.owner_doc().root().is_html_document
|
||||||
|
}
|
||||||
|
|
||||||
fn children(&self) -> AbstractNodeChildrenIterator {
|
fn children(&self) -> AbstractNodeChildrenIterator {
|
||||||
AbstractNodeChildrenIterator {
|
AbstractNodeChildrenIterator {
|
||||||
current_node: self.first_child.get().map(|node| (*node.root()).clone()),
|
current_node: self.first_child.get().map(|node| (*node.root()).clone()),
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
|
|
||||||
// test3: getElementsByTagName
|
// test3: getElementsByTagName
|
||||||
{
|
{
|
||||||
is(document.getElementsByTagName("DIV").length, 0);
|
is(document.getElementsByTagName("DIV").length, 5);
|
||||||
|
|
||||||
is(document.getElementsByTagName("div").length,
|
is(document.getElementsByTagName("div").length,
|
||||||
document.documentElement.getElementsByTagName("div").length);
|
document.documentElement.getElementsByTagName("div").length);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue