Skip to content

Commit

Permalink
fix getElementsByTagName()
Browse files Browse the repository at this point in the history
  • Loading branch information
Maciej Skrzypkowski committed Nov 4, 2016
1 parent 0c6a277 commit af5d109
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 90 deletions.
15 changes: 5 additions & 10 deletions components/script/dom/document.rs
Expand Up @@ -2177,18 +2177,13 @@ impl DocumentMethods for Document {
}

// https://dom.spec.whatwg.org/#dom-document-getelementsbytagname
fn GetElementsByTagName(&self, tag_name: DOMString) -> Root<HTMLCollection> {
let tag_atom = LocalName::from(&*tag_name);
match self.tag_map.borrow_mut().entry(tag_atom.clone()) {
fn GetElementsByTagName(&self, qualified_name: DOMString) -> Root<HTMLCollection> {
let qualified_name = LocalName::from(&*qualified_name);
match self.tag_map.borrow_mut().entry(qualified_name.clone()) {
Occupied(entry) => Root::from_ref(entry.get()),
Vacant(entry) => {
let mut tag_copy = tag_name;
tag_copy.make_ascii_lowercase();
let ascii_lower_tag = LocalName::from(tag_copy);
let result = HTMLCollection::by_atomic_tag_name(&self.window,
self.upcast(),
tag_atom,
ascii_lower_tag);
let result = HTMLCollection::by_qualified_name(
&self.window, self.upcast(), qualified_name);
entry.insert(JS::from_ref(&*result));
result
}
Expand Down
2 changes: 1 addition & 1 deletion components/script/dom/element.rs
Expand Up @@ -1441,7 +1441,7 @@ impl ElementMethods for Element {
// https://dom.spec.whatwg.org/#dom-element-getelementsbytagname
fn GetElementsByTagName(&self, localname: DOMString) -> Root<HTMLCollection> {
let window = window_from_node(self);
HTMLCollection::by_tag_name(&window, self.upcast(), localname)
HTMLCollection::by_qualified_name(&window, self.upcast(), LocalName::from(&*localname))
}

// https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens
Expand Down
60 changes: 36 additions & 24 deletions components/script/dom/htmlcollection.rs
Expand Up @@ -15,7 +15,6 @@ use dom::node::Node;
use dom::window::Window;
use html5ever_atoms::{LocalName, QualName};
use servo_atoms::Atom;
use std::ascii::AsciiExt;
use std::cell::Cell;
use style::str::split_html_space_chars;

Expand Down Expand Up @@ -114,39 +113,52 @@ impl HTMLCollection {
}
}

pub fn by_tag_name(window: &Window, root: &Node, mut tag: DOMString)
-> Root<HTMLCollection> {
let tag_atom = LocalName::from(&*tag);
tag.make_ascii_lowercase();
let ascii_lower_tag = LocalName::from(tag); // FIXME(ajeffrey): don't clone atom if it was already lowercased.
HTMLCollection::by_atomic_tag_name(window, root, tag_atom, ascii_lower_tag)
}
// https://dom.spec.whatwg.org/#concept-getelementsbytagname
pub fn by_qualified_name(window: &Window, root: &Node, qualified_name: LocalName)
-> Root<HTMLCollection> {
// case 1
if qualified_name == local_name!("*") {
#[derive(JSTraceable, HeapSizeOf)]
struct AllFilter;
impl CollectionFilter for AllFilter {
fn filter(&self, _elem: &Element, _root: &Node) -> bool {
true
}
}
return HTMLCollection::create(window, root, box AllFilter);
}

pub fn by_atomic_tag_name(window: &Window, root: &Node, tag_atom: LocalName, ascii_lower_tag: LocalName)
-> Root<HTMLCollection> {
#[derive(JSTraceable, HeapSizeOf)]
struct TagNameFilter {
tag: LocalName,
ascii_lower_tag: LocalName,
struct HtmlDocumentFilter {
qualified_name: LocalName,
ascii_lower_qualified_name: LocalName,
}
impl CollectionFilter for TagNameFilter {
fn filter(&self, elem: &Element, _root: &Node) -> bool {
if self.tag == local_name!("*") {
true
} else if elem.html_element_in_html_document() {
*elem.local_name() == self.ascii_lower_tag
} else {
*elem.local_name() == self.tag
impl CollectionFilter for HtmlDocumentFilter {
fn filter(&self, elem: &Element, root: &Node) -> bool {
if root.is_in_html_doc() && elem.namespace() == &ns!(html) { // case 2
HTMLCollection::match_element(elem, &self.ascii_lower_qualified_name)
} else { // case 2 and 3
HTMLCollection::match_element(elem, &self.qualified_name)
}
}
}
let filter = TagNameFilter {
tag: tag_atom,
ascii_lower_tag: ascii_lower_tag,

let filter = HtmlDocumentFilter {
ascii_lower_qualified_name: qualified_name.to_ascii_lowercase(),
qualified_name: qualified_name,
};
HTMLCollection::create(window, root, box filter)
}

fn match_element(elem: &Element, qualified_name: &LocalName) -> bool {
match *elem.prefix() {
None => elem.local_name() == qualified_name,
Some(ref prefix) => qualified_name.starts_with(prefix as &str) &&
qualified_name.find(":") == Some((prefix as &str).len()) &&
qualified_name.ends_with(elem.local_name() as &str),
}
}

pub fn by_tag_name_ns(window: &Window, root: &Node, tag: DOMString,
maybe_ns: Option<DOMString>) -> Root<HTMLCollection> {
let local = LocalName::from(tag);
Expand Down
4 changes: 2 additions & 2 deletions components/script/dom/webidls/Document.webidl
Expand Up @@ -28,8 +28,8 @@ interface Document : Node {
readonly attribute DocumentType? doctype;
[Pure]
readonly attribute Element? documentElement;
HTMLCollection getElementsByTagName(DOMString localName);
HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
HTMLCollection getElementsByTagName(DOMString qualifiedName);
HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString qualifiedName);
HTMLCollection getElementsByClassName(DOMString classNames);

[NewObject, Throws]
Expand Down
Expand Up @@ -3,18 +3,8 @@
[HTML element with uppercase tag name matches in XHTML documents]
expected: FAIL

[Element in non-HTML namespace, prefix, lowercase name]
expected: FAIL

[Element in non-HTML namespace, prefix, uppercase name]
expected: FAIL

[Element in HTML namespace, no prefix, non-ascii characters in name]
expected: FAIL

[Element in HTML namespace, prefix, non-ascii characters in name]
expected: FAIL

[Element in non-HTML namespace, prefix, non-ascii characters in name]
expected: FAIL

Expand Up @@ -2,16 +2,3 @@
type: testharness
[Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)]
expected: FAIL
[Element in non-HTML namespace, prefix, lowercase name]
expected: FAIL
[Element in non-HTML namespace, prefix, uppercase name]
expected: FAIL
[Element in HTML namespace, prefix, non-ascii characters in name]
expected: FAIL
[Element in non-HTML namespace, prefix, non-ascii characters in name]
expected: FAIL
13 changes: 0 additions & 13 deletions tests/wpt/metadata/dom/nodes/Element-getElementsByTagName.html.ini
Expand Up @@ -2,16 +2,3 @@
type: testharness
[Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)]
expected: FAIL
[Element in non-HTML namespace, prefix, lowercase name]
expected: FAIL
[Element in non-HTML namespace, prefix, uppercase name]
expected: FAIL
[Element in HTML namespace, prefix, non-ascii characters in name]
expected: FAIL
[Element in non-HTML namespace, prefix, non-ascii characters in name]
expected: FAIL
17 changes: 0 additions & 17 deletions tests/wpt/metadata/dom/nodes/case.html.ini

This file was deleted.

0 comments on commit af5d109

Please sign in to comment.