Serenity Operating System
1/*
2 * Copyright (c) 2021-2022, Andreas Kling <kling@serenityos.org>
3 * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#pragma once
9
10#include <AK/DeprecatedFlyString.h>
11#include <AK/Function.h>
12#include <LibJS/Heap/GCPtr.h>
13#include <LibWeb/Bindings/LegacyPlatformObject.h>
14#include <LibWeb/Forward.h>
15
16namespace Web::DOM {
17
18// NOTE: HTMLCollection is in the DOM namespace because it's part of the DOM specification.
19
20// This class implements a live, filtered view of a DOM subtree.
21// When constructing an HTMLCollection, you provide a root node + a filter.
22// The filter is a simple Function object that answers the question
23// "is this Element part of the collection?"
24
25// FIXME: HTMLCollection currently does no caching. It will re-filter on every access!
26// We should teach it how to cache results. The main challenge is invalidating
27// these caches, since this needs to happen on various kinds of DOM mutation.
28
29class HTMLCollection : public Bindings::LegacyPlatformObject {
30 WEB_PLATFORM_OBJECT(HTMLCollection, Bindings::LegacyPlatformObject);
31
32public:
33 static WebIDL::ExceptionOr<JS::NonnullGCPtr<HTMLCollection>> create(ParentNode& root, Function<bool(Element const&)> filter);
34
35 virtual ~HTMLCollection() override;
36
37 size_t length();
38 Element* item(size_t index) const;
39 Element* named_item(DeprecatedFlyString const& name) const;
40
41 JS::MarkedVector<Element*> collect_matching_elements() const;
42
43 virtual WebIDL::ExceptionOr<JS::Value> item_value(size_t index) const override;
44 virtual WebIDL::ExceptionOr<JS::Value> named_item_value(DeprecatedFlyString const& name) const override;
45 virtual Vector<DeprecatedString> supported_property_names() const override;
46 virtual bool is_supported_property_index(u32) const override;
47
48protected:
49 HTMLCollection(ParentNode& root, Function<bool(Element const&)> filter);
50
51 virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
52
53 JS::NonnullGCPtr<ParentNode> root() { return *m_root; }
54
55private:
56 virtual void visit_edges(Cell::Visitor&) override;
57
58 // ^Bindings::LegacyPlatformObject
59 virtual bool supports_indexed_properties() const override { return true; }
60 virtual bool supports_named_properties() const override { return true; }
61 virtual bool has_indexed_property_setter() const override { return false; }
62 virtual bool has_named_property_setter() const override { return false; }
63 virtual bool has_named_property_deleter() const override { return false; }
64 virtual bool has_legacy_override_built_ins_interface_extended_attribute() const override { return false; }
65 virtual bool has_legacy_unenumerable_named_properties_interface_extended_attribute() const override { return true; }
66 virtual bool has_global_interface_extended_attribute() const override { return false; }
67 virtual bool indexed_property_setter_has_identifier() const override { return false; }
68 virtual bool named_property_setter_has_identifier() const override { return false; }
69 virtual bool named_property_deleter_has_identifier() const override { return false; }
70
71 JS::NonnullGCPtr<ParentNode> m_root;
72 Function<bool(Element const&)> m_filter;
73};
74
75}