Jelajahi Sumber

LibWeb: Make getElementById() always return first match in tree order

We had a const and non-const version of this function, with slightly
different behavior (oops!)

This patch consolidates the implementations and keeps only the correct
behavior in there.

Fixes an issue where comments were not collapsible on Hacker News.
Andreas Kling 1 tahun lalu
induk
melakukan
98f88d49de

+ 1 - 0
Tests/LibWeb/Text/expected/DOM/getElementById-multiple.txt

@@ -0,0 +1 @@
+   getElementById('foo') => 1

+ 7 - 0
Tests/LibWeb/Text/input/DOM/getElementById-multiple.html

@@ -0,0 +1,7 @@
+<div id="foo" n="1"></div><div id="foo" n="2"></div>
+<script src="../include.js"></script>
+<script>
+    test(() => {
+        println("getElementById('foo') => " + document.getElementById("foo").getAttribute("n"));
+    });
+</script>

+ 3 - 16
Userland/Libraries/LibWeb/DOM/NonElementParentNode.h

@@ -18,26 +18,13 @@ namespace Web::DOM {
 template<typename NodeType>
 class NonElementParentNode {
 public:
-    JS::GCPtr<Element const> get_element_by_id(FlyString const& id) const
-    {
-        JS::GCPtr<Element const> found_element;
-        static_cast<NodeType const*>(this)->template for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) {
-            if (element.id() == id) {
-                found_element = &element;
-                return TraversalDecision::Break;
-            }
-            return TraversalDecision::Continue;
-        });
-        return found_element;
-    }
-
-    JS::GCPtr<Element> get_element_by_id(FlyString const& id)
+    JS::GCPtr<Element> get_element_by_id(FlyString const& id) const
     {
         JS::GCPtr<Element> found_element;
-        static_cast<NodeType*>(this)->template for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) {
+        const_cast<NodeType*>(static_cast<NodeType const*>(this))->template for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) {
             if (element.id() == id) {
                 found_element = &element;
-                return TraversalDecision::Continue;
+                return TraversalDecision::Break;
             }
             return TraversalDecision::Continue;
         });