Forráskód Böngészése

LibWeb: Convert HTMLCollection to use IDL special operations

Luke Wilde 3 éve
szülő
commit
37347cbcb6

+ 0 - 28
Userland/Libraries/LibWeb/Bindings/HTMLCollectionWrapperCustom.cpp

@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#include <LibWeb/Bindings/HTMLCollectionWrapper.h>
-#include <LibWeb/Bindings/NodeWrapper.h>
-#include <LibWeb/Bindings/NodeWrapperFactory.h>
-#include <LibWeb/DOM/Element.h>
-
-namespace Web::Bindings {
-
-JS::Value HTMLCollectionWrapper::internal_get(JS::PropertyName const& property_name, JS::Value receiver) const
-{
-    if (property_name.is_symbol())
-        return Base::internal_get(property_name, receiver);
-    DOM::Element* item = nullptr;
-    if (property_name.is_string())
-        item = const_cast<DOM::HTMLCollection&>(impl()).named_item(property_name.to_string());
-    else if (property_name.is_number())
-        item = const_cast<DOM::HTMLCollection&>(impl()).item(property_name.as_number());
-    if (!item)
-        return Base::internal_get(property_name, receiver);
-    return wrap(global_object(), *item);
-}
-
-}

+ 3 - 0
Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h

@@ -56,6 +56,8 @@
 #include <LibWeb/Bindings/HTMLButtonElementPrototype.h>
 #include <LibWeb/Bindings/HTMLCanvasElementConstructor.h>
 #include <LibWeb/Bindings/HTMLCanvasElementPrototype.h>
+#include <LibWeb/Bindings/HTMLCollectionConstructor.h>
+#include <LibWeb/Bindings/HTMLCollectionPrototype.h>
 #include <LibWeb/Bindings/HTMLDListElementConstructor.h>
 #include <LibWeb/Bindings/HTMLDListElementPrototype.h>
 #include <LibWeb/Bindings/HTMLDataElementConstructor.h>
@@ -278,6 +280,7 @@
     ADD_WINDOW_OBJECT_INTERFACE(HTMLBRElement)             \
     ADD_WINDOW_OBJECT_INTERFACE(HTMLButtonElement)         \
     ADD_WINDOW_OBJECT_INTERFACE(HTMLCanvasElement)         \
+    ADD_WINDOW_OBJECT_INTERFACE(HTMLCollection)            \
     ADD_WINDOW_OBJECT_INTERFACE(HTMLDataElement)           \
     ADD_WINDOW_OBJECT_INTERFACE(HTMLDataListElement)       \
     ADD_WINDOW_OBJECT_INTERFACE(HTMLDetailsElement)        \

+ 0 - 1
Userland/Libraries/LibWeb/CMakeLists.txt

@@ -3,7 +3,6 @@ set(SOURCES
     Bindings/EventListenerWrapper.cpp
     Bindings/EventTargetWrapperFactory.cpp
     Bindings/EventWrapperFactory.cpp
-    Bindings/HTMLCollectionWrapperCustom.cpp
     Bindings/IDLAbstractOperations.cpp
     Bindings/ImageConstructor.cpp
     Bindings/LocationObject.cpp

+ 60 - 7
Userland/Libraries/LibWeb/DOM/HTMLCollection.cpp

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
@@ -7,6 +8,7 @@
 #include <LibWeb/DOM/Element.h>
 #include <LibWeb/DOM/HTMLCollection.h>
 #include <LibWeb/DOM/ParentNode.h>
+#include <LibWeb/Namespace.h>
 
 namespace Web::DOM {
 
@@ -20,7 +22,7 @@ HTMLCollection::~HTMLCollection()
 {
 }
 
-Vector<NonnullRefPtr<Element>> HTMLCollection::collect_matching_elements()
+Vector<NonnullRefPtr<Element>> HTMLCollection::collect_matching_elements() const
 {
     Vector<NonnullRefPtr<Element>> elements;
     m_root->for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) {
@@ -31,31 +33,82 @@ Vector<NonnullRefPtr<Element>> HTMLCollection::collect_matching_elements()
     return elements;
 }
 
+// https://dom.spec.whatwg.org/#dom-htmlcollection-length
 size_t HTMLCollection::length()
 {
+    // The length getter steps are to return the number of nodes represented by the collection.
     return collect_matching_elements().size();
 }
 
-Element* HTMLCollection::item(size_t index)
+// https://dom.spec.whatwg.org/#dom-htmlcollection-item
+Element* HTMLCollection::item(size_t index) const
 {
+    // The item(index) method steps are to return the indexth element in the collection. If there is no indexth element in the collection, then the method must return null.
     auto elements = collect_matching_elements();
     if (index >= elements.size())
         return nullptr;
     return elements[index];
 }
 
-Element* HTMLCollection::named_item(FlyString const& name)
+// https://dom.spec.whatwg.org/#dom-htmlcollection-nameditem-key
+Element* HTMLCollection::named_item(FlyString const& name) const
 {
-    if (name.is_null())
+    // 1. If key is the empty string, return null.
+    if (name.is_empty())
         return nullptr;
     auto elements = collect_matching_elements();
-    // First look for an "id" attribute match
+    // 2. Return the first element in the collection for which at least one of the following is true:
+    //      - it has an ID which is key;
     if (auto it = elements.find_if([&](auto& entry) { return entry->attribute(HTML::AttributeNames::id) == name; }); it != elements.end())
         return *it;
-    // Then look for a "name" attribute match
-    if (auto it = elements.find_if([&](auto& entry) { return entry->name() == name; }); it != elements.end())
+    //      - it is in the HTML namespace and has a name attribute whose value is key;
+    if (auto it = elements.find_if([&](auto& entry) { return entry->namespace_() == Namespace::HTML && entry->name() == name; }); it != elements.end())
         return *it;
+    //    or null if there is no such element.
     return nullptr;
 }
 
+// https://dom.spec.whatwg.org/#ref-for-dfn-supported-property-names
+Vector<String> HTMLCollection::supported_property_names() const
+{
+    // 1. Let result be an empty list.
+    Vector<String> result;
+
+    // 2. For each element represented by the collection, in tree order:
+    auto elements = collect_matching_elements();
+
+    for (auto& element : elements) {
+        // 1. If element has an ID which is not in result, append element’s ID to result.
+        if (element->has_attribute(HTML::AttributeNames::id)) {
+            auto id = element->attribute(HTML::AttributeNames::id);
+
+            if (!result.contains_slow(id))
+                result.append(id);
+        }
+
+        // 2. If element is in the HTML namespace and has a name attribute whose value is neither the empty string nor is in result, append element’s name attribute value to result.
+        if (element->namespace_() == Namespace::HTML && element->has_attribute(HTML::AttributeNames::name)) {
+            auto name = element->attribute(HTML::AttributeNames::name);
+
+            if (!name.is_empty() && !result.contains_slow(name))
+                result.append(name);
+        }
+    }
+
+    // 3. Return result.
+    return result;
+}
+
+// https://dom.spec.whatwg.org/#ref-for-dfn-supported-property-indices%E2%91%A1
+bool HTMLCollection::is_supported_property_index(u32 index) const
+{
+    // The object’s supported property indices are the numbers in the range zero to one less than the number of elements represented by the collection.
+    // If there are no such elements, then there are no supported property indices.
+    auto elements = collect_matching_elements();
+    if (elements.is_empty())
+        return false;
+
+    return index < elements.size();
+}
+
 }

+ 6 - 3
Userland/Libraries/LibWeb/DOM/HTMLCollection.h

@@ -42,10 +42,13 @@ public:
     ~HTMLCollection();
 
     size_t length();
-    Element* item(size_t index);
-    Element* named_item(FlyString const& name);
+    Element* item(size_t index) const;
+    Element* named_item(FlyString const& name) const;
 
-    Vector<NonnullRefPtr<Element>> collect_matching_elements();
+    Vector<NonnullRefPtr<Element>> collect_matching_elements() const;
+
+    Vector<String> supported_property_names() const;
+    bool is_supported_property_index(u32) const;
 
 protected:
     HTMLCollection(ParentNode& root, Function<bool(Element const&)> filter);

+ 3 - 3
Userland/Libraries/LibWeb/DOM/HTMLCollection.idl

@@ -1,8 +1,8 @@
-[CustomGet]
+[Exposed=Window, LegacyUnenumerableNamedProperties]
 interface HTMLCollection {
 
     readonly attribute unsigned long length;
-    Element? item(unsigned long index);
-    Element? namedItem(DOMString name);
+    getter Element? item(unsigned long index);
+    getter Element? namedItem(DOMString name);
 
 };