mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
LibWeb: Add support for NodeList
This introduces 3 classes: NodeList, StaticNodeList and LiveNodeList. NodeList is the base of the static and live versions. Static is a snapshot whereas live acts on the underlying data and thus inhibits the same issues we have currently with HTMLCollection. They were split into separate classes to not have them weirdly mis-mashed together. The create functions for static and live both return a NNRP to the base class. This is to prevent having to do awkward casting at creation and/or return, as the bindings expect to see the base NodeList only.
This commit is contained in:
parent
bfd089fbd1
commit
8d6db36cbb
Notes:
sideshowbarker
2024-07-18 03:11:18 +09:00
Author: https://github.com/Lubrsi Commit: https://github.com/SerenityOS/serenity/commit/8d6db36cbb8 Pull-request: https://github.com/SerenityOS/serenity/pull/10317
10 changed files with 221 additions and 1 deletions
|
@ -1226,7 +1226,7 @@ static void generate_wrap_statement(SourceGenerator& generator, String const& va
|
|||
)~~~");
|
||||
} else if (type.name == "ArrayFromVector") {
|
||||
// FIXME: Remove this fake type hack once it's no longer needed.
|
||||
// Basically once we have NodeList we can throw this out.
|
||||
// Basically once we have sequence<T> we can throw this out.
|
||||
scoped_generator.append(R"~~~(
|
||||
auto* new_array = JS::Array::create(global_object, 0);
|
||||
for (auto& element : @value@)
|
||||
|
@ -2736,6 +2736,7 @@ void generate_prototype_implementation(IDL::Interface const& interface)
|
|||
#include <LibWeb/Bindings/ImageDataWrapper.h>
|
||||
#include <LibWeb/Bindings/LocationObject.h>
|
||||
#include <LibWeb/Bindings/MessagePortWrapper.h>
|
||||
#include <LibWeb/Bindings/NodeListWrapper.h>
|
||||
#include <LibWeb/Bindings/NodeWrapperFactory.h>
|
||||
#include <LibWeb/Bindings/PerformanceTimingWrapper.h>
|
||||
#include <LibWeb/Bindings/RangeWrapper.h>
|
||||
|
|
|
@ -212,6 +212,8 @@
|
|||
#include <LibWeb/Bindings/MouseEventConstructor.h>
|
||||
#include <LibWeb/Bindings/MouseEventPrototype.h>
|
||||
#include <LibWeb/Bindings/NodeConstructor.h>
|
||||
#include <LibWeb/Bindings/NodeListConstructor.h>
|
||||
#include <LibWeb/Bindings/NodeListPrototype.h>
|
||||
#include <LibWeb/Bindings/NodePrototype.h>
|
||||
#include <LibWeb/Bindings/PageTransitionEventConstructor.h>
|
||||
#include <LibWeb/Bindings/PageTransitionEventPrototype.h>
|
||||
|
@ -373,6 +375,7 @@
|
|||
ADD_WINDOW_OBJECT_INTERFACE(MessageEvent) \
|
||||
ADD_WINDOW_OBJECT_INTERFACE(MouseEvent) \
|
||||
ADD_WINDOW_OBJECT_INTERFACE(Node) \
|
||||
ADD_WINDOW_OBJECT_INTERFACE(NodeList) \
|
||||
ADD_WINDOW_OBJECT_INTERFACE(PageTransitionEvent) \
|
||||
ADD_WINDOW_OBJECT_INTERFACE(Performance) \
|
||||
ADD_WINDOW_OBJECT_INTERFACE(PerformanceTiming) \
|
||||
|
|
|
@ -66,12 +66,14 @@ set(SOURCES
|
|||
DOM/EventListener.cpp
|
||||
DOM/EventTarget.cpp
|
||||
DOM/HTMLCollection.cpp
|
||||
DOM/LiveNodeList.cpp
|
||||
DOM/Node.cpp
|
||||
DOM/ParentNode.cpp
|
||||
DOM/Position.cpp
|
||||
DOM/ProcessingInstruction.cpp
|
||||
DOM/Range.cpp
|
||||
DOM/ShadowRoot.cpp
|
||||
DOM/StaticNodeList.cpp
|
||||
DOM/Text.cpp
|
||||
DOM/Text.idl
|
||||
DOM/Timer.cpp
|
||||
|
@ -371,6 +373,7 @@ libweb_js_wrapper(DOM/HTMLCollection)
|
|||
libweb_js_wrapper(DOM/ProcessingInstruction)
|
||||
libweb_js_wrapper(DOM/ShadowRoot)
|
||||
libweb_js_wrapper(DOM/Node)
|
||||
libweb_js_wrapper(DOM/NodeList)
|
||||
libweb_js_wrapper(DOM/Range)
|
||||
libweb_js_wrapper(DOM/Text)
|
||||
libweb_js_wrapper(Geometry/DOMRect)
|
||||
|
|
54
Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp
Normal file
54
Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/DOM/LiveNodeList.h>
|
||||
#include <LibWeb/DOM/Node.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
LiveNodeList::LiveNodeList(Node& root, Function<bool(Node const&)> filter)
|
||||
: m_root(root)
|
||||
, m_filter(move(filter))
|
||||
{
|
||||
}
|
||||
|
||||
NonnullRefPtrVector<Node> LiveNodeList::collection() const
|
||||
{
|
||||
NonnullRefPtrVector<Node> nodes;
|
||||
m_root->for_each_in_inclusive_subtree_of_type<Node>([&](auto& node) {
|
||||
if (m_filter(node))
|
||||
nodes.append(node);
|
||||
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
return nodes;
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-nodelist-length
|
||||
u32 LiveNodeList::length() const
|
||||
{
|
||||
return collection().size();
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-nodelist-item
|
||||
Node const* LiveNodeList::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.
|
||||
auto nodes = collection();
|
||||
if (index >= nodes.size())
|
||||
return nullptr;
|
||||
return &nodes[index];
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#ref-for-dfn-supported-property-indices
|
||||
bool LiveNodeList::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 nodes represented by the collection.
|
||||
// If there are no such elements, then there are no supported property indices.
|
||||
return index < length();
|
||||
}
|
||||
|
||||
}
|
38
Userland/Libraries/LibWeb/DOM/LiveNodeList.h
Normal file
38
Userland/Libraries/LibWeb/DOM/LiveNodeList.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#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 {
|
||||
public:
|
||||
static NonnullRefPtr<NodeList> create(Node& root, Function<bool(Node const&)> filter)
|
||||
{
|
||||
return adopt_ref(*new LiveNodeList(root, move(filter)));
|
||||
}
|
||||
|
||||
virtual u32 length() const override;
|
||||
virtual Node const* item(u32 index) const override;
|
||||
|
||||
virtual bool is_supported_property_index(u32) const override;
|
||||
|
||||
private:
|
||||
LiveNodeList(Node& root, Function<bool(Node const&)> filter);
|
||||
|
||||
NonnullRefPtrVector<Node> collection() const;
|
||||
|
||||
NonnullRefPtr<Node> m_root;
|
||||
Function<bool(Node const&)> m_filter;
|
||||
};
|
||||
|
||||
}
|
37
Userland/Libraries/LibWeb/DOM/NodeList.h
Normal file
37
Userland/Libraries/LibWeb/DOM/NodeList.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@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>
|
||||
|
||||
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);
|
||||
|
||||
public:
|
||||
using WrapperType = Bindings::NodeListWrapper;
|
||||
|
||||
virtual ~NodeList() override = default;
|
||||
|
||||
virtual u32 length() const = 0;
|
||||
virtual Node const* item(u32 index) const = 0;
|
||||
|
||||
virtual bool is_supported_property_index(u32) const = 0;
|
||||
|
||||
protected:
|
||||
NodeList() = default;
|
||||
};
|
||||
|
||||
}
|
6
Userland/Libraries/LibWeb/DOM/NodeList.idl
Normal file
6
Userland/Libraries/LibWeb/DOM/NodeList.idl
Normal file
|
@ -0,0 +1,6 @@
|
|||
[Exposed=Window]
|
||||
interface NodeList {
|
||||
getter Node? item(unsigned long index);
|
||||
readonly attribute unsigned long length;
|
||||
iterable<Node>;
|
||||
};
|
39
Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp
Normal file
39
Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/DOM/StaticNodeList.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
StaticNodeList::StaticNodeList(NonnullRefPtrVector<Node>&& static_nodes)
|
||||
: m_static_nodes(move(static_nodes))
|
||||
{
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-nodelist-length
|
||||
u32 StaticNodeList::length() const
|
||||
{
|
||||
return m_static_nodes.size();
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-nodelist-item
|
||||
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];
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#ref-for-dfn-supported-property-indices
|
||||
bool StaticNodeList::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 nodes represented by the collection.
|
||||
// If there are no such elements, then there are no supported property indices.
|
||||
return index < m_static_nodes.size();
|
||||
}
|
||||
|
||||
}
|
35
Userland/Libraries/LibWeb/DOM/StaticNodeList.h
Normal file
35
Userland/Libraries/LibWeb/DOM/StaticNodeList.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/NonnullRefPtrVector.h>
|
||||
#include <LibWeb/DOM/Node.h>
|
||||
#include <LibWeb/DOM/NodeList.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
class StaticNodeList : public NodeList {
|
||||
public:
|
||||
static NonnullRefPtr<NodeList> create(NonnullRefPtrVector<Node>&& static_nodes)
|
||||
{
|
||||
return adopt_ref(*new StaticNodeList(move(static_nodes)));
|
||||
}
|
||||
|
||||
virtual ~StaticNodeList() override = default;
|
||||
|
||||
virtual u32 length() const override;
|
||||
virtual Node const* item(u32 index) const override;
|
||||
|
||||
virtual bool is_supported_property_index(u32) const override;
|
||||
|
||||
private:
|
||||
StaticNodeList(NonnullRefPtrVector<Node>&& static_nodes);
|
||||
|
||||
NonnullRefPtrVector<Node> m_static_nodes;
|
||||
};
|
||||
|
||||
}
|
|
@ -82,11 +82,14 @@ class EventHandler;
|
|||
class EventListener;
|
||||
class EventTarget;
|
||||
class HTMLCollection;
|
||||
class LiveNodeList;
|
||||
class Node;
|
||||
class NodeList;
|
||||
class ParentNode;
|
||||
class Position;
|
||||
class ProcessingInstruction;
|
||||
class ShadowRoot;
|
||||
class StaticNodeList;
|
||||
class Text;
|
||||
class Timer;
|
||||
class Window;
|
||||
|
@ -374,6 +377,7 @@ class MessageChannelWrapper;
|
|||
class MessageEventWrapper;
|
||||
class MessagePortWrapper;
|
||||
class MouseEventWrapper;
|
||||
class NodeListWrapper;
|
||||
class NodeWrapper;
|
||||
class PageTransitionEventWrapper;
|
||||
class PerformanceTimingWrapper;
|
||||
|
|
Loading…
Reference in a new issue