getElementsByTagName unable to find SVG camelCase elements imported into HTML
authorrwlbuis@webkit.org <rwlbuis@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Apr 2012 12:34:25 +0000 (12:34 +0000)
committerrwlbuis@webkit.org <rwlbuis@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Apr 2012 12:34:25 +0000 (12:34 +0000)
https://bugs.webkit.org/show_bug.cgi?id=46800

Reviewed by Nikolas Zimmermann.

Source/WebCore:

Implement getElementsByTagName according to the algorithm in
http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-getelementsbytagname.
If the owner document of the element is html, the new class HTMLTagNodeList deals with
finding the match(es) based on this algorithm. If the owner document is non HTML, the existing
TagNodeList is used.

Implement getElementsByTagNameNS according to the algorithm in
http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-getelementsbytagnamens.
The existing TagNodeList implements this algorithm.

Cached results may have less hits after this change. Tag names that are equal when case
insensitive but different when case sensitive can't share the result due to above algorithms, i.e.
they would match differently in the non html part of the document.

Tests: fast/dom/getElementsByTagName-localName-matching.html
       fast/dom/getElementsByTagName-localName-matching2.xhtml
       svg/dom/getElementsByTagName-localName-matching.html

* dom/Node.cpp:
(WebCore::Node::getElementsByTagName): create TagNodeList depending on owner document type.
(WebCore::Node::getElementsByTagNameNS): do not lowercase localName for html.
* dom/TagNodeList.cpp:
(WebCore::HTMLTagNodeList::HTMLTagNodeList): add specialized TagNodeList for html matching rules.
(WebCore):
(WebCore::HTMLTagNodeList::nodeMatches):
* dom/TagNodeList.h:
(TagNodeList):
(HTMLTagNodeList):
(WebCore::HTMLTagNodeList::create):

LayoutTests:

Add tests for getElementsByTagName(NS) in html, xhtml, and svg documents.

* fast/dom/getElementsByTagName-localName-matching-expected.txt: Added.
* fast/dom/getElementsByTagName-localName-matching.html: Added.
* fast/dom/getElementsByTagName-localName-matching2-expected.txt: Added.
* fast/dom/getElementsByTagName-localName-matching2.xhtml: Added.
* svg/dom/getElementsByTagName-localName-matching-expected.txt: Added.
* svg/dom/getElementsByTagName-localName-matching.html: Added.
* svg/dom/script-tests/getElementsByTagName-localName-matching.js: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@113710 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/dom/getElementsByTagName-localName-matching-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/getElementsByTagName-localName-matching.html [new file with mode: 0644]
LayoutTests/fast/dom/getElementsByTagName-localName-matching2-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/getElementsByTagName-localName-matching2.xhtml [new file with mode: 0644]
LayoutTests/svg/dom/getElementsByTagName-localName-matching-expected.txt [new file with mode: 0644]
LayoutTests/svg/dom/getElementsByTagName-localName-matching.html [new file with mode: 0644]
LayoutTests/svg/dom/script-tests/getElementsByTagName-localName-matching.js [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/TagNodeList.cpp
Source/WebCore/dom/TagNodeList.h

index cb0a674..5db3517 100644 (file)
@@ -1,3 +1,20 @@
+2012-04-10  Rob Buis  <rbuis@rim.com>
+
+        getElementsByTagName unable to find SVG camelCase elements imported into HTML
+        https://bugs.webkit.org/show_bug.cgi?id=46800
+
+        Reviewed by Nikolas Zimmermann.
+
+        Add tests for getElementsByTagName(NS) in html, xhtml, and svg documents.
+
+        * fast/dom/getElementsByTagName-localName-matching-expected.txt: Added.
+        * fast/dom/getElementsByTagName-localName-matching.html: Added.
+        * fast/dom/getElementsByTagName-localName-matching2-expected.txt: Added.
+        * fast/dom/getElementsByTagName-localName-matching2.xhtml: Added.
+        * svg/dom/getElementsByTagName-localName-matching-expected.txt: Added.
+        * svg/dom/getElementsByTagName-localName-matching.html: Added.
+        * svg/dom/script-tests/getElementsByTagName-localName-matching.js: Added.
+
 2012-04-09  Alexander Pavlov  <apavlov@chromium.org>
 
         Web Inspector: [Device Metrics] Introduce the "Fit window" option
diff --git a/LayoutTests/fast/dom/getElementsByTagName-localName-matching-expected.txt b/LayoutTests/fast/dom/getElementsByTagName-localName-matching-expected.txt
new file mode 100644 (file)
index 0000000..12de14b
--- /dev/null
@@ -0,0 +1,25 @@
+PASS container.getElementsByTagName('linearGradient').length is 2
+PASS container.getElementsByTagName('lineargradient').length is 1
+PASS container.getElementsByTagName('LINEARGRADIENT').length is 1
+PASS container.getElementsByTagName('FOO').length is 2
+PASS container.getElementsByTagName('foo').length is 2
+PASS container.getElementsByTagName('Foo').length is 2
+PASS container.getElementsByTagName('img').length is 2
+PASS container.getElementsByTagName('IMG').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'linearGradient').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'lineargradient').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'LINEARGRADIENT').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'FOO').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'foo').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'Foo').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'img').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'IMG').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'linearGradient').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'lineargradient').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'LINEARGRADIENT').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'FOO').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'foo').length is 2
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'Foo').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'img').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'IMG').length is 0
+
diff --git a/LayoutTests/fast/dom/getElementsByTagName-localName-matching.html b/LayoutTests/fast/dom/getElementsByTagName-localName-matching.html
new file mode 100644 (file)
index 0000000..94fbf1f
--- /dev/null
@@ -0,0 +1,46 @@
+<!doctype html>
+<head>
+    <script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<div id="container"><FOO><foo><linearGradient/></foo></FOO><img/></div>
+
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+var container = document.getElementById('container');
+var svgdoc = new DOMParser().parseFromString(
+       '<svg xmlns="http://www.w3.org/2000/svg"><linearGradient></linearGradient><img/></svg>', 'text/xml');
+
+var elem = document.importNode(svgdoc.documentElement,true);
+container.appendChild(elem);
+
+shouldBe("container.getElementsByTagName('linearGradient').length", "2");
+shouldBe("container.getElementsByTagName('lineargradient').length", "1");
+shouldBe("container.getElementsByTagName('LINEARGRADIENT').length", "1");
+shouldBe("container.getElementsByTagName('FOO').length", "2");
+shouldBe("container.getElementsByTagName('foo').length", "2");
+shouldBe("container.getElementsByTagName('Foo').length", "2");
+shouldBe("container.getElementsByTagName('img').length", "2");
+shouldBe("container.getElementsByTagName('IMG').length", "1");
+
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'linearGradient').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'lineargradient').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'LINEARGRADIENT').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'FOO').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'foo').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'Foo').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'img').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'IMG').length", "0");
+
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'linearGradient').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'lineargradient').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'LINEARGRADIENT').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'FOO').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'foo').length", "2");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'Foo').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'img').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'IMG').length", "0");
+</script>
+</body>
diff --git a/LayoutTests/fast/dom/getElementsByTagName-localName-matching2-expected.txt b/LayoutTests/fast/dom/getElementsByTagName-localName-matching2-expected.txt
new file mode 100644 (file)
index 0000000..942d128
--- /dev/null
@@ -0,0 +1,25 @@
+PASS container.getElementsByTagName('linearGradient').length is 2
+PASS container.getElementsByTagName('lineargradient').length is 0
+PASS container.getElementsByTagName('LINEARGRADIENT').length is 0
+PASS container.getElementsByTagName('FOO').length is 1
+PASS container.getElementsByTagName('foo').length is 1
+PASS container.getElementsByTagName('Foo').length is 0
+PASS container.getElementsByTagName('img').length is 2
+PASS container.getElementsByTagName('IMG').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'linearGradient').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'lineargradient').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'LINEARGRADIENT').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'FOO').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'foo').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'Foo').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'img').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'IMG').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'linearGradient').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'lineargradient').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'LINEARGRADIENT').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'FOO').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'foo').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'Foo').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'img').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'IMG').length is 0
+
diff --git a/LayoutTests/fast/dom/getElementsByTagName-localName-matching2.xhtml b/LayoutTests/fast/dom/getElementsByTagName-localName-matching2.xhtml
new file mode 100644 (file)
index 0000000..ccac4fc
--- /dev/null
@@ -0,0 +1,47 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<div id="container"><FOO><foo><linearGradient/></foo></FOO><img/></div>
+
+<script><![CDATA[
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+var container = document.getElementById('container');
+var svgdoc = new DOMParser().parseFromString(
+       '<svg xmlns="http://www.w3.org/2000/svg"><linearGradient></linearGradient><img/></svg>', 'text/xml');
+
+var elem = document.importNode(svgdoc.documentElement,true);
+container.appendChild(elem);
+
+shouldBe("container.getElementsByTagName('linearGradient').length", "2");
+shouldBe("container.getElementsByTagName('lineargradient').length", "0");
+shouldBe("container.getElementsByTagName('LINEARGRADIENT').length", "0");
+shouldBe("container.getElementsByTagName('FOO').length", "1");
+shouldBe("container.getElementsByTagName('foo').length", "1");
+shouldBe("container.getElementsByTagName('Foo').length", "0");
+shouldBe("container.getElementsByTagName('img').length", "2");
+shouldBe("container.getElementsByTagName('IMG').length", "0");
+
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'linearGradient').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'lineargradient').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'LINEARGRADIENT').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'FOO').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'foo').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'Foo').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'img').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'IMG').length", "0");
+
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'linearGradient').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'lineargradient').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'LINEARGRADIENT').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'FOO').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'foo').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'Foo').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'img').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'IMG').length", "0");
+]]></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dom/getElementsByTagName-localName-matching-expected.txt b/LayoutTests/svg/dom/getElementsByTagName-localName-matching-expected.txt
new file mode 100644 (file)
index 0000000..542435b
--- /dev/null
@@ -0,0 +1,33 @@
+This test checks the behaviour of getElementsByTagName in a non-HTML document
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS container.getElementsByTagName('linearGradient').length is 1
+PASS container.getElementsByTagName('lineargradient').length is 0
+PASS container.getElementsByTagName('LINEARGRADIENT').length is 0
+PASS container.getElementsByTagName('FOO').length is 1
+PASS container.getElementsByTagName('foo').length is 1
+PASS container.getElementsByTagName('Foo').length is 0
+PASS container.getElementsByTagName('img').length is 1
+PASS container.getElementsByTagName('IMG').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'linearGradient').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'lineargradient').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'LINEARGRADIENT').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'FOO').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'foo').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'Foo').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'img').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'IMG').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'linearGradient').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'lineargradient').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'LINEARGRADIENT').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'FOO').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'foo').length is 1
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'Foo').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'img').length is 0
+PASS container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'IMG').length is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dom/getElementsByTagName-localName-matching.html b/LayoutTests/svg/dom/getElementsByTagName-localName-matching.html
new file mode 100644 (file)
index 0000000..217aba5
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/getElementsByTagName-localName-matching.js"></script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dom/script-tests/getElementsByTagName-localName-matching.js b/LayoutTests/svg/dom/script-tests/getElementsByTagName-localName-matching.js
new file mode 100644 (file)
index 0000000..9d37a1e
--- /dev/null
@@ -0,0 +1,38 @@
+description("This test checks the behaviour of getElementsByTagName in a non-HTML document");
+
+var documentString = "<svg xmlns='http://www.w3.org/2000/svg' width='400' height='400'>" +
+                     "<linearGradient/><img/><foreignObject><body xmlns='http://www.w3.org/1999/xhtml'><foo/><FOO/></body></foreignObject>" +
+                     "</svg>";
+
+var parser = new DOMParser();
+var svgDocument = parser.parseFromString(documentString, "image/svg+xml");
+var container = svgDocument.documentElement;
+
+shouldBe("container.getElementsByTagName('linearGradient').length", "1");
+shouldBe("container.getElementsByTagName('lineargradient').length", "0");
+shouldBe("container.getElementsByTagName('LINEARGRADIENT').length", "0");
+shouldBe("container.getElementsByTagName('FOO').length", "1");
+shouldBe("container.getElementsByTagName('foo').length", "1");
+shouldBe("container.getElementsByTagName('Foo').length", "0");
+shouldBe("container.getElementsByTagName('img').length", "1");
+shouldBe("container.getElementsByTagName('IMG').length", "0");
+
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'linearGradient').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'lineargradient').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'LINEARGRADIENT').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'FOO').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'foo').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'Foo').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'img').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'IMG').length", "0");
+
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'linearGradient').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'lineargradient').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'LINEARGRADIENT').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'FOO').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'foo').length", "1");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'Foo').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'img').length", "0");
+shouldBe("container.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'IMG').length", "0");
+
+var successfullyParsed = true;
index 388e9d0..0fdcf71 100644 (file)
@@ -1,3 +1,40 @@
+2012-04-10  Rob Buis  <rbuis@rim.com>
+
+        getElementsByTagName unable to find SVG camelCase elements imported into HTML
+        https://bugs.webkit.org/show_bug.cgi?id=46800
+
+        Reviewed by Nikolas Zimmermann.
+
+        Implement getElementsByTagName according to the algorithm in
+        http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-getelementsbytagname.
+        If the owner document of the element is html, the new class HTMLTagNodeList deals with
+        finding the match(es) based on this algorithm. If the owner document is non HTML, the existing
+        TagNodeList is used.
+
+        Implement getElementsByTagNameNS according to the algorithm in
+        http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-getelementsbytagnamens.
+        The existing TagNodeList implements this algorithm.
+
+        Cached results may have less hits after this change. Tag names that are equal when case
+        insensitive but different when case sensitive can't share the result due to above algorithms, i.e.
+        they would match differently in the non html part of the document.
+
+        Tests: fast/dom/getElementsByTagName-localName-matching.html
+               fast/dom/getElementsByTagName-localName-matching2.xhtml
+               svg/dom/getElementsByTagName-localName-matching.html
+
+        * dom/Node.cpp:
+        (WebCore::Node::getElementsByTagName): create TagNodeList depending on owner document type.
+        (WebCore::Node::getElementsByTagNameNS): do not lowercase localName for html.
+        * dom/TagNodeList.cpp:
+        (WebCore::HTMLTagNodeList::HTMLTagNodeList): add specialized TagNodeList for html matching rules.
+        (WebCore):
+        (WebCore::HTMLTagNodeList::nodeMatches):
+        * dom/TagNodeList.h:
+        (TagNodeList):
+        (HTMLTagNodeList):
+        (WebCore::HTMLTagNodeList::create):
+
 2012-04-09  Alexander Pavlov  <apavlov@chromium.org>
 
         Web Inspector: [Device Metrics] Introduce the "Fit window" option
index 0407527..4680f0d 100644 (file)
@@ -1606,17 +1606,17 @@ PassRefPtr<NodeList> Node::getElementsByTagName(const AtomicString& localName)
     if (localName.isNull())
         return 0;
 
-    String name = localName;
-    if (document()->isHTMLDocument())
-        name = localName.lower();
-
-    AtomicString localNameAtom = name;
+    AtomicString localNameAtom = localName;
 
     NodeListsNodeData::TagNodeListCache::AddResult result = ensureRareData()->ensureNodeLists(this)->m_tagNodeListCache.add(localNameAtom, 0);
     if (!result.isNewEntry)
         return PassRefPtr<TagNodeList>(result.iterator->second);
 
-    RefPtr<TagNodeList> list = TagNodeList::create(this, starAtom, localNameAtom);
+    RefPtr<TagNodeList> list;
+    if (document()->isHTMLDocument())
+        list = HTMLTagNodeList::create(this, starAtom, localNameAtom);
+    else
+        list = TagNodeList::create(this, starAtom, localNameAtom);
     result.iterator->second = list.get();
     return list.release();   
 }
@@ -1629,11 +1629,7 @@ PassRefPtr<NodeList> Node::getElementsByTagNameNS(const AtomicString& namespaceU
     if (namespaceURI == starAtom)
         return getElementsByTagName(localName);
 
-    String name = localName;
-    if (document()->isHTMLDocument())
-        name = localName.lower();
-
-    AtomicString localNameAtom = name;
+    AtomicString localNameAtom = localName;
 
     NodeListsNodeData::TagNodeListCacheNS::AddResult result
         = ensureRareData()->ensureNodeLists(this)->m_tagNodeListCacheNS.add(QualifiedName(nullAtom, localNameAtom, namespaceURI).impl(), 0);
index 3d01261..ac5cf53 100644 (file)
@@ -47,10 +47,29 @@ TagNodeList::~TagNodeList()
 
 bool TagNodeList::nodeMatches(Element* testNode) const
 {
+    // Implements http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-getelementsbytagnamens
     if (m_localName != starAtom && m_localName != testNode->localName())
         return false;
 
     return m_namespaceURI == starAtom || m_namespaceURI == testNode->namespaceURI();
 }
 
+HTMLTagNodeList::HTMLTagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
+    : TagNodeList(rootNode, namespaceURI, localName)
+    , m_loweredLocalName(localName.lower())
+{
+}
+
+bool HTMLTagNodeList::nodeMatches(Element* testNode) const
+{
+    // Implements http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-getelementsbytagname
+    if (m_localName != starAtom) {
+        const AtomicString& localName = testNode->isHTMLElement() ? m_loweredLocalName : m_localName;
+        if (localName != testNode->localName())
+            return false;
+    }
+
+    return m_namespaceURI == starAtom || m_namespaceURI == testNode->namespaceURI();
+}
+
 } // namespace WebCore
index 2927368..b8ccefe 100644 (file)
@@ -39,7 +39,7 @@ namespace WebCore {
 
         virtual ~TagNodeList();
 
-    private:
+    protected:
         TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName);
 
         virtual bool nodeMatches(Element*) const;
@@ -48,6 +48,20 @@ namespace WebCore {
         AtomicString m_localName;
     };
 
+    class HTMLTagNodeList : public TagNodeList {
+    public:
+        static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
+        {
+            return adoptRef(new HTMLTagNodeList(rootNode, namespaceURI, localName));
+        }
+
+    private:
+        HTMLTagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName);
+
+        virtual bool nodeMatches(Element*) const;
+
+        AtomicString m_loweredLocalName;
+    };
 } // namespace WebCore
 
 #endif // TagNodeList_h