summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-09-01 16:30:26 +0200
committerAndreas Kling <kling@serenityos.org>2022-09-06 00:27:09 +0200
commit48e0066371a3e4a4d5b743579747c76bf3c46ea4 (patch)
tree605e0481ff108445f96ff4011708496bc20463fc
parent8f4ea4e308ff8c3e89d99a24721df37af25895d1 (diff)
downloadserenity-48e0066371a3e4a4d5b743579747c76bf3c46ea4.zip
LibWeb: Make NodeList GC-allocated
-rw-r--r--Userland/Libraries/LibWeb/CMakeLists.txt1
-rw-r--r--Userland/Libraries/LibWeb/DOM/Attribute.cpp2
-rw-r--r--Userland/Libraries/LibWeb/DOM/CharacterData.cpp2
-rw-r--r--Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp22
-rw-r--r--Userland/Libraries/LibWeb/DOM/LiveNodeList.h18
-rw-r--r--Userland/Libraries/LibWeb/DOM/MutationRecord.cpp4
-rw-r--r--Userland/Libraries/LibWeb/DOM/Node.cpp23
-rw-r--r--Userland/Libraries/LibWeb/DOM/Node.h8
-rw-r--r--Userland/Libraries/LibWeb/DOM/NodeList.cpp34
-rw-r--r--Userland/Libraries/LibWeb/DOM/NodeList.h24
-rw-r--r--Userland/Libraries/LibWeb/DOM/ParentNode.cpp4
-rw-r--r--Userland/Libraries/LibWeb/DOM/ParentNode.h2
-rw-r--r--Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp22
-rw-r--r--Userland/Libraries/LibWeb/DOM/StaticNodeList.h14
-rw-r--r--Userland/Libraries/LibWeb/Forward.h1
-rw-r--r--Userland/Libraries/LibWeb/idl_files.cmake2
16 files changed, 127 insertions, 56 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt
index 47e1f8e865..5b021d25a1 100644
--- a/Userland/Libraries/LibWeb/CMakeLists.txt
+++ b/Userland/Libraries/LibWeb/CMakeLists.txt
@@ -104,6 +104,7 @@ set(SOURCES
DOM/Node.cpp
DOM/NodeFilter.cpp
DOM/NodeIterator.cpp
+ DOM/NodeList.cpp
DOM/NodeOperations.cpp
DOM/ParentNode.cpp
DOM/Position.cpp
diff --git a/Userland/Libraries/LibWeb/DOM/Attribute.cpp b/Userland/Libraries/LibWeb/DOM/Attribute.cpp
index 122e3d1ce3..f6254ce2e7 100644
--- a/Userland/Libraries/LibWeb/DOM/Attribute.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Attribute.cpp
@@ -70,7 +70,7 @@ void Attribute::set_value(String value)
void Attribute::handle_attribute_changes(Element& element, String const& old_value, [[maybe_unused]] String const& new_value)
{
// 1. Queue a mutation record of "attributes" for element with attribute’s local name, attribute’s namespace, oldValue, « », « », null, and null.
- element.queue_mutation_record(MutationType::attributes, local_name(), namespace_uri(), old_value, StaticNodeList::create({}), StaticNodeList::create({}), nullptr, nullptr);
+ element.queue_mutation_record(MutationType::attributes, local_name(), namespace_uri(), old_value, StaticNodeList::create(window(), {}), StaticNodeList::create(window(), {}), nullptr, nullptr);
// FIXME: 2. If element is custom, then enqueue a custom element callback reaction with element, callback name "attributeChangedCallback", and an argument list containing attribute’s local name, oldValue, newValue, and attribute’s namespace.
diff --git a/Userland/Libraries/LibWeb/DOM/CharacterData.cpp b/Userland/Libraries/LibWeb/DOM/CharacterData.cpp
index 929d477490..f13c28189d 100644
--- a/Userland/Libraries/LibWeb/DOM/CharacterData.cpp
+++ b/Userland/Libraries/LibWeb/DOM/CharacterData.cpp
@@ -64,7 +64,7 @@ ExceptionOr<void> CharacterData::replace_data(size_t offset, size_t count, Strin
count = length - offset;
// 4. Queue a mutation record of "characterData" for node with null, null, node’s data, « », « », null, and null.
- queue_mutation_record(MutationType::characterData, {}, {}, m_data, StaticNodeList::create({}), StaticNodeList::create({}), nullptr, nullptr);
+ queue_mutation_record(MutationType::characterData, {}, {}, m_data, StaticNodeList::create(window(), {}), StaticNodeList::create(window(), {}), nullptr, nullptr);
// 5. Insert data into node’s data after offset code units.
// 6. Let delete offset be offset + data’s length.
diff --git a/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp b/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp
index 5f19146094..9041c097c8 100644
--- a/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp
+++ b/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp
@@ -1,23 +1,39 @@
/*
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/DOM/LiveNodeList.h>
#include <LibWeb/DOM/Node.h>
+#include <LibWeb/HTML/Window.h>
namespace Web::DOM {
-LiveNodeList::LiveNodeList(Node& root, Function<bool(Node const&)> filter)
- : m_root(JS::make_handle(root))
+JS::NonnullGCPtr<NodeList> LiveNodeList::create(HTML::Window& window, Node& root, Function<bool(Node const&)> filter)
+{
+ return *window.heap().allocate<LiveNodeList>(window.realm(), window, root, move(filter));
+}
+
+LiveNodeList::LiveNodeList(HTML::Window& window, Node& root, Function<bool(Node const&)> filter)
+ : NodeList(window)
+ , m_root(root)
, m_filter(move(filter))
{
}
+LiveNodeList::~LiveNodeList() = default;
+
+void LiveNodeList::visit_edges(Cell::Visitor& visitor)
+{
+ Base::visit_edges(visitor);
+ visitor.visit(m_root.ptr());
+}
+
JS::MarkedVector<Node*> LiveNodeList::collection() const
{
- JS::MarkedVector<Node*> nodes(m_root->heap());
+ JS::MarkedVector<Node*> nodes(heap());
m_root->for_each_in_inclusive_subtree([&](auto& node) {
if (m_filter(node))
nodes.append(const_cast<Node*>(&node));
diff --git a/Userland/Libraries/LibWeb/DOM/LiveNodeList.h b/Userland/Libraries/LibWeb/DOM/LiveNodeList.h
index 4c35b9e2b0..8d23133e58 100644
--- a/Userland/Libraries/LibWeb/DOM/LiveNodeList.h
+++ b/Userland/Libraries/LibWeb/DOM/LiveNodeList.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -7,19 +8,18 @@
#pragma once
#include <AK/Function.h>
-#include <AK/NonnullRefPtrVector.h>
#include <LibWeb/DOM/NodeList.h>
namespace Web::DOM {
// FIXME: Just like HTMLCollection, LiveNodeList currently does no caching.
-class LiveNodeList : public NodeList {
+class LiveNodeList final : public NodeList {
+ WEB_PLATFORM_OBJECT(LiveNodeList, NodeList);
+
public:
- static NonnullRefPtr<NodeList> create(Node& root, Function<bool(Node const&)> filter)
- {
- return adopt_ref(*new LiveNodeList(root, move(filter)));
- }
+ static JS::NonnullGCPtr<NodeList> create(HTML::Window&, Node& root, Function<bool(Node const&)> filter);
+ virtual ~LiveNodeList() override;
virtual u32 length() const override;
virtual Node const* item(u32 index) const override;
@@ -27,11 +27,13 @@ public:
virtual bool is_supported_property_index(u32) const override;
private:
- LiveNodeList(Node& root, Function<bool(Node const&)> filter);
+ LiveNodeList(HTML::Window&, Node& root, Function<bool(Node const&)> filter);
+
+ virtual void visit_edges(Cell::Visitor&) override;
JS::MarkedVector<Node*> collection() const;
- JS::Handle<Node> m_root;
+ JS::NonnullGCPtr<Node> m_root;
Function<bool(Node const&)> m_filter;
};
diff --git a/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp b/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp
index 78fdbdb9c6..05ad9fd49d 100644
--- a/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp
+++ b/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp
@@ -40,8 +40,8 @@ public:
private:
FlyString m_type;
JS::Handle<Node> m_target;
- NonnullRefPtr<NodeList> m_added_nodes;
- NonnullRefPtr<NodeList> m_removed_nodes;
+ JS::Handle<NodeList> m_added_nodes;
+ JS::Handle<NodeList> m_removed_nodes;
JS::Handle<Node> m_previous_sibling;
JS::Handle<Node> m_next_sibling;
String m_attribute_name;
diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp
index fc08dac50d..24c4ba2b25 100644
--- a/Userland/Libraries/LibWeb/DOM/Node.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Node.cpp
@@ -376,7 +376,7 @@ void Node::insert_before(JS::NonnullGCPtr<Node> node, JS::GCPtr<Node> child, boo
// 2. Queue a tree mutation record for node with « », nodes, null, and null.
// NOTE: This step intentionally does not pay attention to the suppress observers flag.
- node->queue_tree_mutation_record(StaticNodeList::create({}), StaticNodeList::create(nodes), nullptr, nullptr);
+ node->queue_tree_mutation_record(StaticNodeList::create(window(), {}), StaticNodeList::create(window(), nodes), nullptr, nullptr);
}
// 5. If child is non-null, then:
@@ -438,7 +438,7 @@ void Node::insert_before(JS::NonnullGCPtr<Node> node, JS::GCPtr<Node> child, boo
// 8. If suppress observers flag is unset, then queue a tree mutation record for parent with nodes, « », previousSibling, and child.
if (!suppress_observers)
- queue_tree_mutation_record(StaticNodeList::create(move(nodes)), StaticNodeList::create({}), previous_sibling.ptr(), child.ptr());
+ queue_tree_mutation_record(StaticNodeList::create(window(), move(nodes)), StaticNodeList::create(window(), {}), previous_sibling.ptr(), child.ptr());
// 9. Run the children changed steps for parent.
children_changed();
@@ -589,7 +589,7 @@ void Node::remove(bool suppress_observers)
if (!suppress_observers) {
Vector<JS::Handle<Node>> removed_nodes;
removed_nodes.append(JS::make_handle(*this));
- parent->queue_tree_mutation_record(StaticNodeList::create({}), StaticNodeList::create(move(removed_nodes)), old_previous_sibling.ptr(), old_next_sibling.ptr());
+ parent->queue_tree_mutation_record(StaticNodeList::create(window(), {}), StaticNodeList::create(window(), move(removed_nodes)), old_previous_sibling.ptr(), old_next_sibling.ptr());
}
// 21. Run the children changed steps for parent.
@@ -681,7 +681,7 @@ ExceptionOr<JS::NonnullGCPtr<Node>> Node::replace_child(JS::NonnullGCPtr<Node> n
insert_before(node, reference_child, true);
// 14. Queue a tree mutation record for parent with nodes, removedNodes, previousSibling, and referenceChild.
- queue_tree_mutation_record(StaticNodeList::create(move(nodes)), StaticNodeList::create(move(removed_nodes)), previous_sibling.ptr(), reference_child.ptr());
+ queue_tree_mutation_record(StaticNodeList::create(window(), move(nodes)), StaticNodeList::create(window(), move(removed_nodes)), previous_sibling.ptr(), reference_child.ptr());
// 15. Return child.
return child;
@@ -851,11 +851,11 @@ ParentNode* Node::parent_or_shadow_host()
return verify_cast<ParentNode>(parent());
}
-NonnullRefPtr<NodeList> Node::child_nodes()
+JS::NonnullGCPtr<NodeList> Node::child_nodes()
{
// FIXME: This should return the same LiveNodeList object every time,
// but that would cause a reference cycle since NodeList refs the root.
- return LiveNodeList::create(*this, [this](auto& node) {
+ return LiveNodeList::create(window(), *this, [this](auto& node) {
return is_parent_of(node);
});
}
@@ -1133,7 +1133,7 @@ void Node::replace_all(JS::GCPtr<Node> node)
// 7. If either addedNodes or removedNodes is not empty, then queue a tree mutation record for parent with addedNodes, removedNodes, null, and null.
if (!added_nodes.is_empty() || !removed_nodes.is_empty())
- queue_tree_mutation_record(StaticNodeList::create(move(added_nodes)), StaticNodeList::create(move(removed_nodes)), nullptr, nullptr);
+ queue_tree_mutation_record(StaticNodeList::create(window(), move(added_nodes)), StaticNodeList::create(window(), move(removed_nodes)), nullptr, nullptr);
}
// https://dom.spec.whatwg.org/#string-replace-all
@@ -1319,7 +1319,7 @@ Painting::PaintableBox const* Node::paint_box() const
}
// https://dom.spec.whatwg.org/#queue-a-mutation-record
-void Node::queue_mutation_record(FlyString const& type, String attribute_name, String attribute_namespace, String old_value, NonnullRefPtr<NodeList> added_nodes, NonnullRefPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling)
+void Node::queue_mutation_record(FlyString const& type, String attribute_name, String attribute_namespace, String old_value, JS::NonnullGCPtr<NodeList> added_nodes, JS::NonnullGCPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling)
{
// 1. Let interestedObservers be an empty map.
// mutationObserver -> mappedOldValue
@@ -1379,7 +1379,7 @@ void Node::queue_mutation_record(FlyString const& type, String attribute_name, S
}
// https://dom.spec.whatwg.org/#queue-a-tree-mutation-record
-void Node::queue_tree_mutation_record(NonnullRefPtr<NodeList> added_nodes, NonnullRefPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling)
+void Node::queue_tree_mutation_record(JS::NonnullGCPtr<NodeList> added_nodes, JS::NonnullGCPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling)
{
// 1. Assert: either addedNodes or removedNodes is not empty.
VERIFY(added_nodes->length() > 0 || removed_nodes->length() > 0);
@@ -1483,4 +1483,9 @@ bool Node::is_following(Node const& other) const
return false;
}
+HTML::Window& Node::window() const
+{
+ return document().window();
+}
+
}
diff --git a/Userland/Libraries/LibWeb/DOM/Node.h b/Userland/Libraries/LibWeb/DOM/Node.h
index f4d4b90120..87d58e79e0 100644
--- a/Userland/Libraries/LibWeb/DOM/Node.h
+++ b/Userland/Libraries/LibWeb/DOM/Node.h
@@ -101,7 +101,7 @@ public:
// NOTE: This is intended for the JS bindings.
bool has_child_nodes() const { return has_children(); }
- NonnullRefPtr<NodeList> child_nodes();
+ JS::NonnullGCPtr<NodeList> child_nodes();
Vector<JS::Handle<Node>> children_as_vector() const;
virtual FlyString node_name() const = 0;
@@ -118,6 +118,8 @@ public:
Document& document() { return *m_document; }
Document const& document() const { return *m_document; }
+ HTML::Window& window() const;
+
JS::GCPtr<Document> owner_document() const;
const HTML::HTMLAnchorElement* enclosing_link_element() const;
@@ -220,7 +222,7 @@ public:
void add_registered_observer(RegisteredObserver& registered_observer) { m_registered_observer_list.append(registered_observer); }
- void queue_mutation_record(FlyString const& type, String attribute_name, String attribute_namespace, String old_value, NonnullRefPtr<NodeList> added_nodes, NonnullRefPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling);
+ void queue_mutation_record(FlyString const& type, String attribute_name, String attribute_namespace, String old_value, JS::NonnullGCPtr<NodeList> added_nodes, JS::NonnullGCPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling);
// https://dom.spec.whatwg.org/#concept-shadow-including-descendant
template<typename Callback>
@@ -639,7 +641,7 @@ protected:
NonnullRefPtrVector<RegisteredObserver> m_registered_observer_list;
private:
- void queue_tree_mutation_record(NonnullRefPtr<NodeList> added_nodes, NonnullRefPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling);
+ void queue_tree_mutation_record(JS::NonnullGCPtr<NodeList> added_nodes, JS::NonnullGCPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling);
void insert_before_impl(JS::NonnullGCPtr<Node>, JS::GCPtr<Node> child);
void append_child_impl(JS::NonnullGCPtr<Node>);
diff --git a/Userland/Libraries/LibWeb/DOM/NodeList.cpp b/Userland/Libraries/LibWeb/DOM/NodeList.cpp
new file mode 100644
index 0000000000..4bd7eb86f0
--- /dev/null
+++ b/Userland/Libraries/LibWeb/DOM/NodeList.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/Bindings/NodeListPrototype.h>
+#include <LibWeb/DOM/Node.h>
+#include <LibWeb/DOM/NodeList.h>
+#include <LibWeb/HTML/Window.h>
+
+namespace Web::DOM {
+
+NodeList::NodeList(HTML::Window& window)
+ : LegacyPlatformObject(window.ensure_web_prototype<Bindings::NodeListPrototype>("NodeList"))
+{
+}
+
+NodeList::~NodeList() = default;
+
+JS::Value NodeList::item_value(size_t index) const
+{
+ auto* node = item(index);
+ if (!node)
+ return JS::js_undefined();
+ return const_cast<Node*>(node);
+}
+
+bool NodeList::is_supported_property_index(u32 index) const
+{
+ return index < length();
+}
+
+}
diff --git a/Userland/Libraries/LibWeb/DOM/NodeList.h b/Userland/Libraries/LibWeb/DOM/NodeList.h
index 839098865c..94380ef677 100644
--- a/Userland/Libraries/LibWeb/DOM/NodeList.h
+++ b/Userland/Libraries/LibWeb/DOM/NodeList.h
@@ -1,37 +1,33 @@
/*
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
-#include <AK/Noncopyable.h>
-#include <AK/RefCounted.h>
-#include <LibWeb/Bindings/Wrappable.h>
-#include <LibWeb/Forward.h>
+#include <LibWeb/Bindings/LegacyPlatformObject.h>
namespace Web::DOM {
// https://dom.spec.whatwg.org/#nodelist
-class NodeList
- : public RefCounted<NodeList>
- , public Bindings::Wrappable {
- AK_MAKE_NONCOPYABLE(NodeList);
- AK_MAKE_NONMOVABLE(NodeList);
+class NodeList : public Bindings::LegacyPlatformObject {
+ WEB_PLATFORM_OBJECT(NodeList, Bindings::LegacyPlatformObject);
public:
- using WrapperType = Bindings::NodeListWrapper;
-
- virtual ~NodeList() override = default;
+ virtual ~NodeList() override;
virtual u32 length() const = 0;
virtual Node const* item(u32 index) const = 0;
- virtual bool is_supported_property_index(u32) const = 0;
+ virtual JS::Value item_value(size_t index) const override;
+ virtual bool is_supported_property_index(u32) const override;
protected:
- NodeList() = default;
+ explicit NodeList(HTML::Window&);
};
}
+
+WRAPPER_HACK(NodeList, Web::DOM)
diff --git a/Userland/Libraries/LibWeb/DOM/ParentNode.cpp b/Userland/Libraries/LibWeb/DOM/ParentNode.cpp
index de7fdd699a..42bbc2428a 100644
--- a/Userland/Libraries/LibWeb/DOM/ParentNode.cpp
+++ b/Userland/Libraries/LibWeb/DOM/ParentNode.cpp
@@ -38,7 +38,7 @@ ExceptionOr<JS::GCPtr<Element>> ParentNode::query_selector(StringView selector_t
return result;
}
-ExceptionOr<NonnullRefPtr<NodeList>> ParentNode::query_selector_all(StringView selector_text)
+ExceptionOr<JS::NonnullGCPtr<NodeList>> ParentNode::query_selector_all(StringView selector_text)
{
auto maybe_selectors = parse_selector(CSS::Parser::ParsingContext(*this), selector_text);
if (!maybe_selectors.has_value())
@@ -57,7 +57,7 @@ ExceptionOr<NonnullRefPtr<NodeList>> ParentNode::query_selector_all(StringView s
return IterationDecision::Continue;
});
- return StaticNodeList::create(move(elements));
+ return StaticNodeList::create(window(), move(elements));
}
JS::GCPtr<Element> ParentNode::first_element_child()
diff --git a/Userland/Libraries/LibWeb/DOM/ParentNode.h b/Userland/Libraries/LibWeb/DOM/ParentNode.h
index 384db0cb6f..a2667892dd 100644
--- a/Userland/Libraries/LibWeb/DOM/ParentNode.h
+++ b/Userland/Libraries/LibWeb/DOM/ParentNode.h
@@ -24,7 +24,7 @@ public:
u32 child_element_count() const;
ExceptionOr<JS::GCPtr<Element>> query_selector(StringView);
- ExceptionOr<NonnullRefPtr<NodeList>> query_selector_all(StringView);
+ ExceptionOr<JS::NonnullGCPtr<NodeList>> query_selector_all(StringView);
NonnullRefPtr<HTMLCollection> children();
diff --git a/Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp b/Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp
index fdcdfca9a6..052143aedd 100644
--- a/Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp
+++ b/Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp
@@ -5,17 +5,29 @@
*/
#include <LibWeb/DOM/StaticNodeList.h>
+#include <LibWeb/HTML/Window.h>
namespace Web::DOM {
-NonnullRefPtr<NodeList> StaticNodeList::create(Vector<JS::Handle<Node>> static_nodes)
+JS::NonnullGCPtr<NodeList> StaticNodeList::create(HTML::Window& window, Vector<JS::Handle<Node>> static_nodes)
{
- return adopt_ref(*new StaticNodeList(move(static_nodes)));
+ return *window.heap().allocate<StaticNodeList>(window.realm(), window, move(static_nodes));
}
-StaticNodeList::StaticNodeList(Vector<JS::Handle<Node>> static_nodes)
- : m_static_nodes(move(static_nodes))
+StaticNodeList::StaticNodeList(HTML::Window& window, Vector<JS::Handle<Node>> static_nodes)
+ : NodeList(window)
{
+ for (auto& node : static_nodes)
+ m_static_nodes.append(*node);
+}
+
+StaticNodeList::~StaticNodeList() = default;
+
+void StaticNodeList::visit_edges(Cell::Visitor& visitor)
+{
+ Base::visit_edges(visitor);
+ for (auto& node : m_static_nodes)
+ visitor.visit(node);
}
// https://dom.spec.whatwg.org/#dom-nodelist-length
@@ -30,7 +42,7 @@ Node const* StaticNodeList::item(u32 index) const
// The item(index) method must return the indexth node in the collection. If there is no indexth node in the collection, then the method must return null.
if (index >= m_static_nodes.size())
return nullptr;
- return m_static_nodes[index].ptr();
+ return &m_static_nodes[index];
}
// https://dom.spec.whatwg.org/#ref-for-dfn-supported-property-indices
diff --git a/Userland/Libraries/LibWeb/DOM/StaticNodeList.h b/Userland/Libraries/LibWeb/DOM/StaticNodeList.h
index 829aca3cce..842d03a8f9 100644
--- a/Userland/Libraries/LibWeb/DOM/StaticNodeList.h
+++ b/Userland/Libraries/LibWeb/DOM/StaticNodeList.h
@@ -12,11 +12,13 @@
namespace Web::DOM {
-class StaticNodeList : public NodeList {
+class StaticNodeList final : public NodeList {
+ WEB_PLATFORM_OBJECT(StaticNodeList, NodeList);
+
public:
- static NonnullRefPtr<NodeList> create(Vector<JS::Handle<Node>> static_nodes);
+ static JS::NonnullGCPtr<NodeList> create(HTML::Window&, Vector<JS::Handle<Node>>);
- virtual ~StaticNodeList() override = default;
+ virtual ~StaticNodeList() override;
virtual u32 length() const override;
virtual Node const* item(u32 index) const override;
@@ -24,9 +26,11 @@ public:
virtual bool is_supported_property_index(u32) const override;
private:
- StaticNodeList(Vector<JS::Handle<Node>> static_nodes);
+ StaticNodeList(HTML::Window&, Vector<JS::Handle<Node>>);
+
+ virtual void visit_edges(Cell::Visitor&) override;
- Vector<JS::Handle<Node>> m_static_nodes;
+ Vector<Node&> m_static_nodes;
};
}
diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h
index 9cff085408..fa0d028ab4 100644
--- a/Userland/Libraries/LibWeb/Forward.h
+++ b/Userland/Libraries/LibWeb/Forward.h
@@ -471,7 +471,6 @@ class LocationObject;
class MessageChannelWrapper;
class MutationObserverWrapper;
class MutationRecordWrapper;
-class NodeListWrapper;
class OptionConstructor;
class Path2DWrapper;
class RangePrototype;
diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake
index 9c22dabed3..6c0e0fc1a6 100644
--- a/Userland/Libraries/LibWeb/idl_files.cmake
+++ b/Userland/Libraries/LibWeb/idl_files.cmake
@@ -43,7 +43,7 @@ libweb_js_wrapper(DOM/MutationObserver)
libweb_js_wrapper(DOM/NamedNodeMap NO_INSTANCE)
libweb_js_wrapper(DOM/Node NO_INSTANCE)
libweb_js_wrapper(DOM/NodeIterator NO_INSTANCE)
-libweb_js_wrapper(DOM/NodeList)
+libweb_js_wrapper(DOM/NodeList NO_INSTANCE)
libweb_js_wrapper(DOM/ProcessingInstruction NO_INSTANCE)
libweb_js_wrapper(DOM/Range NO_INSTANCE)
libweb_js_wrapper(DOM/ShadowRoot NO_INSTANCE)