LibWeb: Make AbstractRange and subclasses GC-allocated
This commit is contained in:
parent
7c3db526b0
commit
bb547ce1c4
Notes:
sideshowbarker
2024-07-17 07:28:19 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/bb547ce1c4 Pull-request: https://github.com/SerenityOS/serenity/pull/14816 Reviewed-by: https://github.com/ADKaster Reviewed-by: https://github.com/linusg ✅
19 changed files with 111 additions and 64 deletions
|
@ -76,6 +76,7 @@ set(SOURCES
|
|||
Cookie/ParsedCookie.cpp
|
||||
DOM/AbortController.cpp
|
||||
DOM/AbortSignal.cpp
|
||||
DOM/AbstractRange.cpp
|
||||
DOM/Attribute.cpp
|
||||
DOM/Attribute.idl
|
||||
DOM/CDATASection.cpp
|
||||
|
|
25
Userland/Libraries/LibWeb/DOM/AbstractRange.cpp
Normal file
25
Userland/Libraries/LibWeb/DOM/AbstractRange.cpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/AbstractRangePrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/DOM/AbstractRange.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
AbstractRange::AbstractRange(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset)
|
||||
: Bindings::PlatformObject(start_container.document().preferred_window_object().ensure_web_prototype<Bindings::AbstractRangePrototype>("AbstractRange"))
|
||||
, m_start_container(start_container)
|
||||
, m_start_offset(start_offset)
|
||||
, m_end_container(end_container)
|
||||
, m_end_offset(end_offset)
|
||||
{
|
||||
}
|
||||
|
||||
AbstractRange::~AbstractRange() = default;
|
||||
|
||||
}
|
|
@ -1,23 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/RefCounted.h>
|
||||
#include <LibWeb/Bindings/Wrappable.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
class AbstractRange
|
||||
: public RefCounted<AbstractRange>
|
||||
, public Bindings::Wrappable {
|
||||
public:
|
||||
using WrapperType = Bindings::AbstractRangeWrapper;
|
||||
class AbstractRange : public Bindings::PlatformObject {
|
||||
JS_OBJECT(AbstractRange, Bindings::PlatformObject);
|
||||
|
||||
virtual ~AbstractRange() override = default;
|
||||
public:
|
||||
virtual ~AbstractRange() override;
|
||||
|
||||
AbstractRange& impl() { return *this; }
|
||||
|
||||
Node* start_container() { return m_start_container; }
|
||||
Node const* start_container() const { return m_start_container; }
|
||||
|
@ -35,13 +36,7 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
AbstractRange(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset)
|
||||
: m_start_container(start_container)
|
||||
, m_start_offset(start_offset)
|
||||
, m_end_container(end_container)
|
||||
, m_end_offset(end_offset)
|
||||
{
|
||||
}
|
||||
AbstractRange(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset);
|
||||
|
||||
NonnullRefPtr<Node> m_start_container;
|
||||
u32 m_start_offset;
|
||||
|
@ -51,3 +46,8 @@ protected:
|
|||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
inline JS::Object* wrap(JS::Realm&, Web::DOM::AbstractRange& object) { return &object; }
|
||||
using AbstractRangeWrapper = Web::DOM::AbstractRange;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[Exposed=Window]
|
||||
[Exposed=Window, NoInstanceWrapper]
|
||||
interface AbstractRange {
|
||||
readonly attribute Node startContainer;
|
||||
readonly attribute unsigned long startOffset;
|
||||
|
|
|
@ -1154,7 +1154,7 @@ NonnullRefPtr<Comment> Document::create_comment(String const& data)
|
|||
return adopt_ref(*new Comment(*this, data));
|
||||
}
|
||||
|
||||
NonnullRefPtr<Range> Document::create_range()
|
||||
JS::NonnullGCPtr<Range> Document::create_range()
|
||||
{
|
||||
return Range::create(*this);
|
||||
}
|
||||
|
|
|
@ -203,8 +203,8 @@ public:
|
|||
NonnullRefPtr<DocumentFragment> create_document_fragment();
|
||||
NonnullRefPtr<Text> create_text_node(String const& data);
|
||||
NonnullRefPtr<Comment> create_comment(String const& data);
|
||||
NonnullRefPtr<Range> create_range();
|
||||
ExceptionOr<JS::NonnullGCPtr<Event>> create_event(String const& interface);
|
||||
JS::NonnullGCPtr<Range> create_range();
|
||||
|
||||
void set_pending_parsing_blocking_script(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement*);
|
||||
HTML::HTMLScriptElement* pending_parsing_blocking_script() { return m_pending_parsing_blocking_script; }
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/RangePrototype.h>
|
||||
#include <LibWeb/DOM/Comment.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/DocumentFragment.h>
|
||||
|
@ -24,22 +25,24 @@ HashTable<Range*>& Range::live_ranges()
|
|||
return ranges;
|
||||
}
|
||||
|
||||
NonnullRefPtr<Range> Range::create(HTML::Window& window)
|
||||
JS::NonnullGCPtr<Range> Range::create(HTML::Window& window)
|
||||
{
|
||||
return Range::create(window.associated_document());
|
||||
}
|
||||
|
||||
NonnullRefPtr<Range> Range::create(Document& document)
|
||||
JS::NonnullGCPtr<Range> Range::create(Document& document)
|
||||
{
|
||||
return adopt_ref(*new Range(document));
|
||||
auto& window_object = document.preferred_window_object();
|
||||
return *window_object.heap().allocate<Range>(window_object.realm(), document);
|
||||
}
|
||||
|
||||
NonnullRefPtr<Range> Range::create(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset)
|
||||
JS::NonnullGCPtr<Range> Range::create(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset)
|
||||
{
|
||||
return adopt_ref(*new Range(start_container, start_offset, end_container, end_offset));
|
||||
auto& window_object = start_container.document().preferred_window_object();
|
||||
return *window_object.heap().allocate<Range>(window_object.realm(), start_container, start_offset, end_container, end_offset);
|
||||
}
|
||||
|
||||
NonnullRefPtr<Range> Range::create_with_global_object(Bindings::WindowObject& window)
|
||||
JS::NonnullGCPtr<Range> Range::create_with_global_object(Bindings::WindowObject& window)
|
||||
{
|
||||
return Range::create(window.impl());
|
||||
}
|
||||
|
@ -47,11 +50,13 @@ NonnullRefPtr<Range> Range::create_with_global_object(Bindings::WindowObject& wi
|
|||
Range::Range(Document& document)
|
||||
: Range(document, 0, document, 0)
|
||||
{
|
||||
set_prototype(&document.preferred_window_object().ensure_web_prototype<Bindings::RangePrototype>("Range"));
|
||||
}
|
||||
|
||||
Range::Range(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset)
|
||||
: AbstractRange(start_container, start_offset, end_container, end_offset)
|
||||
{
|
||||
set_prototype(&start_container.document().preferred_window_object().ensure_web_prototype<Bindings::RangePrototype>("Range"));
|
||||
live_ranges().set(this);
|
||||
}
|
||||
|
||||
|
@ -400,17 +405,17 @@ ExceptionOr<void> Range::select_node_contents(Node const& node)
|
|||
return {};
|
||||
}
|
||||
|
||||
NonnullRefPtr<Range> Range::clone_range() const
|
||||
JS::NonnullGCPtr<Range> Range::clone_range() const
|
||||
{
|
||||
return adopt_ref(*new Range(const_cast<Node&>(*m_start_container), m_start_offset, const_cast<Node&>(*m_end_container), m_end_offset));
|
||||
return *heap().allocate<Range>(shape().realm(), const_cast<Node&>(*m_start_container), m_start_offset, const_cast<Node&>(*m_end_container), m_end_offset);
|
||||
}
|
||||
|
||||
NonnullRefPtr<Range> Range::inverted() const
|
||||
JS::NonnullGCPtr<Range> Range::inverted() const
|
||||
{
|
||||
return adopt_ref(*new Range(const_cast<Node&>(*m_end_container), m_end_offset, const_cast<Node&>(*m_start_container), m_start_offset));
|
||||
return *heap().allocate<Range>(shape().realm(), const_cast<Node&>(*m_end_container), m_end_offset, const_cast<Node&>(*m_start_container), m_start_offset);
|
||||
}
|
||||
|
||||
NonnullRefPtr<Range> Range::normalized() const
|
||||
JS::NonnullGCPtr<Range> Range::normalized() const
|
||||
{
|
||||
if (m_start_container.ptr() == m_end_container.ptr()) {
|
||||
if (m_start_offset <= m_end_offset)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2020, the SerenityOS developers.
|
||||
* Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -12,16 +13,20 @@
|
|||
namespace Web::DOM {
|
||||
|
||||
class Range final : public AbstractRange {
|
||||
JS_OBJECT(Range, AbstractRange);
|
||||
|
||||
public:
|
||||
using WrapperType = Bindings::RangeWrapper;
|
||||
Range& impl() { return *this; }
|
||||
|
||||
static JS::NonnullGCPtr<Range> create(Document&);
|
||||
static JS::NonnullGCPtr<Range> create(HTML::Window&);
|
||||
static JS::NonnullGCPtr<Range> create(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset);
|
||||
static JS::NonnullGCPtr<Range> create_with_global_object(Bindings::WindowObject&);
|
||||
|
||||
explicit Range(Document&);
|
||||
Range(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset);
|
||||
virtual ~Range() override;
|
||||
|
||||
static NonnullRefPtr<Range> create(Document&);
|
||||
static NonnullRefPtr<Range> create(HTML::Window&);
|
||||
static NonnullRefPtr<Range> create(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset);
|
||||
static NonnullRefPtr<Range> create_with_global_object(Bindings::WindowObject&);
|
||||
|
||||
// FIXME: There are a ton of methods missing here.
|
||||
|
||||
ExceptionOr<void> set_start(Node& node, u32 offset);
|
||||
|
@ -44,9 +49,9 @@ public:
|
|||
|
||||
ExceptionOr<i16> compare_boundary_points(u16 how, Range const& source_range) const;
|
||||
|
||||
NonnullRefPtr<Range> inverted() const;
|
||||
NonnullRefPtr<Range> normalized() const;
|
||||
NonnullRefPtr<Range> clone_range() const;
|
||||
JS::NonnullGCPtr<Range> inverted() const;
|
||||
JS::NonnullGCPtr<Range> normalized() const;
|
||||
JS::NonnullGCPtr<Range> clone_range() const;
|
||||
|
||||
NonnullRefPtr<Node> common_ancestor_container() const;
|
||||
|
||||
|
@ -73,10 +78,6 @@ public:
|
|||
static HashTable<Range*>& live_ranges();
|
||||
|
||||
private:
|
||||
explicit Range(Document&);
|
||||
|
||||
Range(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset);
|
||||
|
||||
Node& root();
|
||||
Node const& root() const;
|
||||
|
||||
|
@ -97,3 +98,8 @@ private:
|
|||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
inline JS::Object* wrap(JS::Realm&, Web::DOM::Range& object) { return &object; }
|
||||
using RangeWrapper = Web::DOM::Range;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#import <DOM/Node.idl>
|
||||
#import <DOM/AbstractRange.idl>
|
||||
|
||||
[Exposed=Window]
|
||||
[Exposed=Window, NoInstanceWrapper]
|
||||
interface Range : AbstractRange {
|
||||
|
||||
constructor();
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/TypeCasts.h>
|
||||
#include <LibWeb/Bindings/StaticRangePrototype.h>
|
||||
#include <LibWeb/DOM/Attribute.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/DocumentType.h>
|
||||
#include <LibWeb/DOM/ExceptionOr.h>
|
||||
#include <LibWeb/DOM/StaticRange.h>
|
||||
|
@ -15,10 +18,13 @@ namespace Web::DOM {
|
|||
StaticRange::StaticRange(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset)
|
||||
: AbstractRange(start_container, start_offset, end_container, end_offset)
|
||||
{
|
||||
set_prototype(&start_container.document().preferred_window_object().ensure_web_prototype<Bindings::StaticRangePrototype>("StaticRange"));
|
||||
}
|
||||
|
||||
StaticRange::~StaticRange() = default;
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-staticrange-staticrange
|
||||
ExceptionOr<NonnullRefPtr<StaticRange>> StaticRange::create_with_global_object(JS::GlobalObject&, StaticRangeInit& init)
|
||||
ExceptionOr<StaticRange*> StaticRange::create_with_global_object(Bindings::WindowObject& window_object, StaticRangeInit& init)
|
||||
{
|
||||
// 1. If init["startContainer"] or init["endContainer"] is a DocumentType or Attr node, then throw an "InvalidNodeTypeError" DOMException.
|
||||
if (is<DocumentType>(*init.start_container) || is<Attribute>(*init.start_container))
|
||||
|
@ -28,7 +34,7 @@ ExceptionOr<NonnullRefPtr<StaticRange>> StaticRange::create_with_global_object(J
|
|||
return DOM::InvalidNodeTypeError::create("endContainer cannot be a DocumentType or Attribute node.");
|
||||
|
||||
// 2. Set this’s start to (init["startContainer"], init["startOffset"]) and end to (init["endContainer"], init["endOffset"]).
|
||||
return adopt_ref(*new StaticRange(*init.start_container, init.start_offset, *init.end_container, init.end_offset));
|
||||
return window_object.heap().allocate<StaticRange>(window_object.realm(), *init.start_container, init.start_offset, *init.end_container, init.end_offset);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -20,15 +21,20 @@ struct StaticRangeInit {
|
|||
};
|
||||
|
||||
class StaticRange final : public AbstractRange {
|
||||
JS_OBJECT(StaticRange, JS::Object);
|
||||
|
||||
public:
|
||||
using WrapperType = Bindings::StaticRangeWrapper;
|
||||
static ExceptionOr<StaticRange*> create_with_global_object(Bindings::WindowObject&, StaticRangeInit& init);
|
||||
|
||||
virtual ~StaticRange() override = default;
|
||||
|
||||
static ExceptionOr<NonnullRefPtr<StaticRange>> create_with_global_object(JS::GlobalObject&, StaticRangeInit& init);
|
||||
|
||||
private:
|
||||
StaticRange(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset);
|
||||
virtual ~StaticRange() override;
|
||||
|
||||
StaticRange& impl() { return *this; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
inline JS::Object* wrap(JS::Realm&, Web::DOM::StaticRange& object) { return &object; }
|
||||
using StaticRangeWrapper = Web::DOM::StaticRange;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#import <DOM/Node.idl>
|
||||
#import <DOM/AbstractRange.idl>
|
||||
|
||||
[Exposed=Window]
|
||||
[Exposed=Window, NoInstanceWrapper]
|
||||
interface StaticRange : AbstractRange {
|
||||
constructor(StaticRangeInit init);
|
||||
};
|
||||
|
|
|
@ -446,7 +446,6 @@ class URLSearchParamsIterator;
|
|||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
class AbstractRangeWrapper;
|
||||
class AbortControllerWrapper;
|
||||
class AbortSignalWrapper;
|
||||
class AttributeWrapper;
|
||||
|
@ -564,11 +563,9 @@ class PerformanceWrapper;
|
|||
class ProcessingInstructionWrapper;
|
||||
class RangeConstructor;
|
||||
class RangePrototype;
|
||||
class RangeWrapper;
|
||||
class ResizeObserverWrapper;
|
||||
class ScreenWrapper;
|
||||
class SelectionWrapper;
|
||||
class StaticRangeWrapper;
|
||||
class StorageWrapper;
|
||||
class SubtleCryptoWrapper;
|
||||
class SVGAnimatedLengthWrapper;
|
||||
|
|
|
@ -33,7 +33,7 @@ LayoutRange LayoutRange::normalized() const
|
|||
return { m_end, m_start };
|
||||
}
|
||||
|
||||
NonnullRefPtr<DOM::Range> LayoutRange::to_dom_range() const
|
||||
JS::NonnullGCPtr<DOM::Range> LayoutRange::to_dom_range() const
|
||||
{
|
||||
VERIFY(is_valid());
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/RefPtr.h>
|
||||
#include <LibJS/Heap/GCPtr.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/Layout/Node.h>
|
||||
|
||||
|
@ -48,7 +49,7 @@ public:
|
|||
|
||||
LayoutRange normalized() const;
|
||||
|
||||
NonnullRefPtr<DOM::Range> to_dom_range() const;
|
||||
JS::NonnullGCPtr<DOM::Range> to_dom_range() const;
|
||||
|
||||
private:
|
||||
LayoutPosition m_start;
|
||||
|
|
|
@ -660,11 +660,11 @@ bool EventHandler::handle_keydown(KeyCode key, unsigned modifiers, u32 code_poin
|
|||
m_browsing_context.set_cursor_position({ *range->start_container(), range->start_offset() });
|
||||
|
||||
if (key == KeyCode::Key_Backspace || key == KeyCode::Key_Delete) {
|
||||
m_edit_event_handler->handle_delete(range);
|
||||
m_edit_event_handler->handle_delete(*range);
|
||||
return true;
|
||||
}
|
||||
if (!should_ignore_keydown_event(code_point)) {
|
||||
m_edit_event_handler->handle_delete(range);
|
||||
m_edit_event_handler->handle_delete(*range);
|
||||
m_edit_event_handler->handle_insert(m_browsing_context.cursor_position(), code_point);
|
||||
m_browsing_context.increment_cursor_position_offset();
|
||||
return true;
|
||||
|
|
|
@ -48,7 +48,7 @@ String Selection::type() const
|
|||
TODO();
|
||||
}
|
||||
|
||||
NonnullRefPtr<DOM::Range> Selection::get_range_at(unsigned index)
|
||||
DOM::Range* Selection::get_range_at(unsigned index)
|
||||
{
|
||||
(void)index;
|
||||
TODO();
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
bool is_collapsed() const;
|
||||
unsigned range_count() const;
|
||||
String type() const;
|
||||
NonnullRefPtr<DOM::Range> get_range_at(unsigned index);
|
||||
DOM::Range* get_range_at(unsigned index);
|
||||
void add_range(DOM::Range&);
|
||||
void remove_range(DOM::Range&);
|
||||
void remove_all_ranges();
|
||||
|
|
|
@ -20,7 +20,7 @@ libweb_js_wrapper(CSS/MediaQueryListEvent NO_INSTANCE)
|
|||
libweb_js_wrapper(CSS/Screen)
|
||||
libweb_js_wrapper(CSS/StyleSheet NO_INSTANCE)
|
||||
libweb_js_wrapper(CSS/StyleSheetList NO_INSTANCE)
|
||||
libweb_js_wrapper(DOM/AbstractRange)
|
||||
libweb_js_wrapper(DOM/AbstractRange NO_INSTANCE)
|
||||
libweb_js_wrapper(DOM/Attribute)
|
||||
libweb_js_wrapper(DOM/AbortController)
|
||||
libweb_js_wrapper(DOM/AbortSignal)
|
||||
|
@ -45,9 +45,9 @@ libweb_js_wrapper(DOM/Node)
|
|||
libweb_js_wrapper(DOM/NodeIterator NO_INSTANCE)
|
||||
libweb_js_wrapper(DOM/NodeList)
|
||||
libweb_js_wrapper(DOM/ProcessingInstruction)
|
||||
libweb_js_wrapper(DOM/Range)
|
||||
libweb_js_wrapper(DOM/Range NO_INSTANCE)
|
||||
libweb_js_wrapper(DOM/ShadowRoot)
|
||||
libweb_js_wrapper(DOM/StaticRange)
|
||||
libweb_js_wrapper(DOM/StaticRange NO_INSTANCE)
|
||||
libweb_js_wrapper(DOM/Text)
|
||||
libweb_js_wrapper(DOM/TreeWalker NO_INSTANCE)
|
||||
libweb_js_wrapper(DOMParsing/XMLSerializer)
|
||||
|
|
Loading…
Add table
Reference in a new issue