1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 20:07:35 +00:00

LibWeb: Remove unecessary dependence on Window from DOM and WebIDL

These classes only needed Window to get at its realm. Pass a realm
directly to construct DOM and WebIDL classes.

This change importantly removes the guarantee that a Document will
always have a non-null Window object. Only Documents created by a
BrowsingContext will have a non-null Window object. Documents created by
for example, DocumentFragment, will not have a Window (soon).

This incremental commit leaves some workarounds in place to keep other
parts of the code building.
This commit is contained in:
Andrew Kaster 2022-09-25 16:15:49 -06:00 committed by Linus Groh
parent 8407bf60c5
commit 8de7e49a56
56 changed files with 364 additions and 326 deletions

View file

@ -4,23 +4,24 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/AbortController.h>
#include <LibWeb/DOM/AbortSignal.h>
namespace Web::DOM {
JS::NonnullGCPtr<AbortController> AbortController::create_with_global_object(HTML::Window& window)
JS::NonnullGCPtr<AbortController> AbortController::construct_impl(JS::Realm& realm)
{
auto signal = AbortSignal::create_with_global_object(window);
return *window.heap().allocate<AbortController>(window.realm(), window, move(signal));
auto signal = AbortSignal::construct_impl(realm);
return *realm.heap().allocate<AbortController>(realm, realm, move(signal));
}
// https://dom.spec.whatwg.org/#dom-abortcontroller-abortcontroller
AbortController::AbortController(HTML::Window& window, JS::NonnullGCPtr<AbortSignal> signal)
: PlatformObject(window.realm())
AbortController::AbortController(JS::Realm& realm, JS::NonnullGCPtr<AbortSignal> signal)
: PlatformObject(realm)
, m_signal(move(signal))
{
set_prototype(&window.cached_web_prototype("AbortController"));
set_prototype(&Bindings::cached_web_prototype(realm, "AbortController"));
}
AbortController::~AbortController() = default;

View file

@ -16,7 +16,7 @@ class AbortController final : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(AbortController, Bindings::PlatformObject);
public:
static JS::NonnullGCPtr<AbortController> create_with_global_object(HTML::Window&);
static JS::NonnullGCPtr<AbortController> construct_impl(JS::Realm&);
virtual ~AbortController() override;
@ -26,7 +26,7 @@ public:
void abort(JS::Value reason);
private:
AbortController(HTML::Window&, JS::NonnullGCPtr<AbortSignal>);
AbortController(JS::Realm&, JS::NonnullGCPtr<AbortSignal>);
virtual void visit_edges(Cell::Visitor&) override;

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/AbortSignal.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/EventDispatcher.h>
@ -11,15 +12,20 @@
namespace Web::DOM {
JS::NonnullGCPtr<AbortSignal> AbortSignal::create_with_global_object(HTML::Window& window)
JS::NonnullGCPtr<AbortSignal> AbortSignal::construct_impl(JS::Realm& realm)
{
return *window.heap().allocate<AbortSignal>(window.realm(), window);
return *realm.heap().allocate<AbortSignal>(realm, realm);
}
AbortSignal::AbortSignal(JS::Realm& realm)
: EventTarget(realm)
{
set_prototype(&Bindings::cached_web_prototype(realm, "AbortSignal"));
}
AbortSignal::AbortSignal(HTML::Window& window)
: EventTarget(window.realm())
: AbortSignal(window.realm())
{
set_prototype(&window.cached_web_prototype("AbortSignal"));
}
// https://dom.spec.whatwg.org/#abortsignal-add
@ -44,7 +50,7 @@ void AbortSignal::signal_abort(JS::Value reason)
if (!reason.is_undefined())
m_abort_reason = reason;
else
m_abort_reason = WebIDL::AbortError::create(global_object(), "Aborted without reason").ptr();
m_abort_reason = WebIDL::AbortError::create(realm(), "Aborted without reason").ptr();
// 3. For each algorithm in signals abort algorithms: run algorithm.
for (auto& algorithm : m_abort_algorithms)
@ -54,7 +60,7 @@ void AbortSignal::signal_abort(JS::Value reason)
m_abort_algorithms.clear();
// 5. Fire an event named abort at signal.
dispatch_event(*Event::create(global_object(), HTML::EventNames::abort));
dispatch_event(*Event::create(realm(), HTML::EventNames::abort));
}
void AbortSignal::set_onabort(WebIDL::CallbackType* event_handler)

View file

@ -10,7 +10,6 @@
#include <AK/Weakable.h>
#include <LibWeb/DOM/EventTarget.h>
#include <LibWeb/Forward.h>
#include <LibWeb/HTML/Window.h>
namespace Web::DOM {
@ -19,7 +18,7 @@ class AbortSignal final : public EventTarget {
WEB_PLATFORM_OBJECT(AbortSignal, EventTarget);
public:
static JS::NonnullGCPtr<AbortSignal> create_with_global_object(HTML::Window&);
static JS::NonnullGCPtr<AbortSignal> construct_impl(JS::Realm&);
virtual ~AbortSignal() override = default;
@ -40,6 +39,7 @@ public:
JS::ThrowCompletionOr<void> throw_if_aborted() const;
private:
explicit AbortSignal(JS::Realm&);
explicit AbortSignal(HTML::Window&);
virtual void visit_edges(JS::Cell::Visitor&) override;

View file

@ -4,14 +4,14 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/AbstractRange.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/Window.h>
namespace Web::DOM {
AbstractRange::AbstractRange(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset)
: Bindings::PlatformObject(start_container.document().window().cached_web_prototype("AbstractRange"))
: Bindings::PlatformObject(Bindings::cached_web_prototype(start_container.realm(), "AbstractRange"))
, m_start_container(start_container)
, m_start_offset(start_offset)
, m_end_container(end_container)

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/Attr.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Element.h>
@ -23,7 +24,7 @@ Attr::Attr(Document& document, FlyString local_name, String value, Element const
, m_value(move(value))
, m_owner_element(owner_element)
{
set_prototype(&window().cached_web_prototype("Attr"));
set_prototype(&Bindings::cached_web_prototype(document.realm(), "Attr"));
}
void Attr::visit_edges(Cell::Visitor& visitor)
@ -69,7 +70,7 @@ void Attr::set_value(String value)
void Attr::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 attributes local name, attributes namespace, oldValue, « », « », null, and null.
element.queue_mutation_record(MutationType::attributes, local_name(), namespace_uri(), old_value, StaticNodeList::create(window(), {}), StaticNodeList::create(window(), {}), nullptr, nullptr);
element.queue_mutation_record(MutationType::attributes, local_name(), namespace_uri(), old_value, StaticNodeList::create(realm(), {}), StaticNodeList::create(realm(), {}), 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 attributes local name, oldValue, newValue, and attributes namespace.

View file

@ -12,7 +12,7 @@ namespace Web::DOM {
CDATASection::CDATASection(Document& document, String const& data)
: Text(document, NodeType::CDATA_SECTION_NODE, data)
{
set_prototype(&window().cached_web_prototype("CDATASection"));
set_prototype(&Bindings::cached_web_prototype(realm(), "CDATASection"));
}
CDATASection::~CDATASection() = default;

View file

@ -17,7 +17,7 @@ CharacterData::CharacterData(Document& document, NodeType type, String const& da
: Node(document, type)
, m_data(data)
{
set_prototype(&window().ensure_web_prototype<Bindings::CharacterDataPrototype>("CharacterData"));
set_prototype(&Bindings::ensure_web_prototype<Bindings::CharacterDataPrototype>(document.realm(), "CharacterData"));
}
// https://dom.spec.whatwg.org/#dom-characterdata-data
@ -38,7 +38,7 @@ WebIDL::ExceptionOr<String> CharacterData::substring_data(size_t offset, size_t
// 2. If offset is greater than length, then throw an "IndexSizeError" DOMException.
if (offset > length)
return WebIDL::IndexSizeError::create(global_object(), "Substring offset out of range.");
return WebIDL::IndexSizeError::create(realm(), "Substring offset out of range.");
// 3. If offset plus count is greater than length, return a string whose value is the code units from the offsetth code unit
// to the end of nodes data, and then return.
@ -57,14 +57,14 @@ WebIDL::ExceptionOr<void> CharacterData::replace_data(size_t offset, size_t coun
// 2. If offset is greater than length, then throw an "IndexSizeError" DOMException.
if (offset > length)
return WebIDL::IndexSizeError::create(global_object(), "Replacement offset out of range.");
return WebIDL::IndexSizeError::create(realm(), "Replacement offset out of range.");
// 3. If offset plus count is greater than length, then set count to length minus offset.
if (offset + count > length)
count = length - offset;
// 4. Queue a mutation record of "characterData" for node with null, null, nodes data, « », « », null, and null.
queue_mutation_record(MutationType::characterData, {}, {}, m_data, StaticNodeList::create(window(), {}), StaticNodeList::create(window(), {}), nullptr, nullptr);
queue_mutation_record(MutationType::characterData, {}, {}, m_data, StaticNodeList::create(realm(), {}), StaticNodeList::create(realm(), {}), nullptr, nullptr);
// 5. Insert data into nodes data after offset code units.
// 6. Let delete offset be offset + datas length.

View file

@ -34,7 +34,7 @@ public:
WebIDL::ExceptionOr<void> replace_data(size_t offset, size_t count, String const&);
protected:
explicit CharacterData(Document&, NodeType, String const&);
CharacterData(Document&, NodeType, String const&);
private:
String m_data;

View file

@ -16,9 +16,10 @@ Comment::Comment(Document& document, String const& data)
}
// https://dom.spec.whatwg.org/#dom-comment-comment
JS::NonnullGCPtr<Comment> Comment::create_with_global_object(HTML::Window& window, String const& data)
JS::NonnullGCPtr<Comment> Comment::construct_impl(JS::Realm& realm, String const& data)
{
return *window.heap().allocate<Comment>(window.realm(), window.associated_document(), data);
auto& window = verify_cast<HTML::Window>(realm.global_object());
return *realm.heap().allocate<Comment>(realm, window.associated_document(), data);
}
}

View file

@ -15,13 +15,13 @@ class Comment final : public CharacterData {
WEB_PLATFORM_OBJECT(Comment, CharacterData);
public:
static JS::NonnullGCPtr<Comment> create_with_global_object(HTML::Window&, String const& data);
static JS::NonnullGCPtr<Comment> construct_impl(JS::Realm&, String const& data);
virtual ~Comment() override = default;
virtual FlyString node_name() const override { return "#comment"; }
private:
explicit Comment(Document&, String const&);
Comment(Document&, String const&);
};
template<>

View file

@ -5,32 +5,27 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/Realm.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/CustomEvent.h>
#include <LibWeb/HTML/Window.h>
namespace Web::DOM {
CustomEvent* CustomEvent::create(HTML::Window& window_object, FlyString const& event_name, CustomEventInit const& event_init)
CustomEvent* CustomEvent::create(JS::Realm& realm, FlyString const& event_name, CustomEventInit const& event_init)
{
return window_object.heap().allocate<CustomEvent>(window_object.realm(), window_object, event_name, event_init);
return realm.heap().allocate<CustomEvent>(realm, realm, event_name, event_init);
}
CustomEvent* CustomEvent::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, CustomEventInit const& event_init)
CustomEvent* CustomEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, CustomEventInit const& event_init)
{
return create(window_object, event_name, event_init);
return create(realm, event_name, event_init);
}
CustomEvent::CustomEvent(HTML::Window& window_object, FlyString const& event_name)
: Event(window_object, event_name)
{
set_prototype(&window_object.cached_web_prototype("CustomEvent"));
}
CustomEvent::CustomEvent(HTML::Window& window_object, FlyString const& event_name, CustomEventInit const& event_init)
: Event(window_object, event_name, event_init)
CustomEvent::CustomEvent(JS::Realm& realm, FlyString const& event_name, CustomEventInit const& event_init)
: Event(realm, event_name, event_init)
, m_detail(event_init.detail)
{
set_prototype(&window_object.cached_web_prototype("CustomEvent"));
set_prototype(&Bindings::cached_web_prototype(realm, "CustomEvent"));
}
CustomEvent::~CustomEvent() = default;

View file

@ -20,11 +20,8 @@ class CustomEvent : public Event {
WEB_PLATFORM_OBJECT(CustomEvent, Event);
public:
static CustomEvent* create(HTML::Window&, FlyString const& event_name, CustomEventInit const& event_init = {});
static CustomEvent* create_with_global_object(HTML::Window&, FlyString const& event_name, CustomEventInit const& event_init);
CustomEvent(HTML::Window&, FlyString const& event_name);
CustomEvent(HTML::Window&, FlyString const& event_name, CustomEventInit const& event_init);
static CustomEvent* create(JS::Realm&, FlyString const& event_name, CustomEventInit const& event_init = {});
static CustomEvent* construct_impl(JS::Realm&, FlyString const& event_name, CustomEventInit const& event_init);
virtual ~CustomEvent() override;
@ -36,6 +33,8 @@ public:
void init_custom_event(String const& type, bool bubbles, bool cancelable, JS::Value detail);
private:
CustomEvent(JS::Realm&, FlyString const& event_name, CustomEventInit const& event_init);
// https://dom.spec.whatwg.org/#dom-customevent-initcustomevent-type-bubbles-cancelable-detail-detail
JS::Value m_detail { JS::js_null() };
};

View file

@ -5,6 +5,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/DOM/DOMImplementation.h>
#include <LibWeb/DOM/Document.h>
@ -12,19 +13,18 @@
#include <LibWeb/DOM/ElementFactory.h>
#include <LibWeb/DOM/Text.h>
#include <LibWeb/HTML/Origin.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/Namespace.h>
namespace Web::DOM {
JS::NonnullGCPtr<DOMImplementation> DOMImplementation::create(Document& document)
{
auto& window = document.window();
return *window.heap().allocate<DOMImplementation>(document.realm(), document);
auto& realm = document.realm();
return *realm.heap().allocate<DOMImplementation>(realm, document);
}
DOMImplementation::DOMImplementation(Document& document)
: PlatformObject(document.window().cached_web_prototype("DOMImplementation"))
: PlatformObject(Bindings::cached_web_prototype(document.realm(), "DOMImplementation"))
, m_document(document)
{
}
@ -41,7 +41,7 @@ void DOMImplementation::visit_edges(Cell::Visitor& visitor)
WebIDL::ExceptionOr<JS::NonnullGCPtr<Document>> DOMImplementation::create_document(String const& namespace_, String const& qualified_name, JS::GCPtr<DocumentType> doctype) const
{
// FIXME: This should specifically be an XML document.
auto xml_document = Document::create(Bindings::main_thread_internal_window_object());
auto xml_document = Document::create(realm());
xml_document->set_ready_for_post_load_tasks(true);
@ -71,7 +71,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Document>> DOMImplementation::create_docume
// https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
JS::NonnullGCPtr<Document> DOMImplementation::create_html_document(String const& title) const
{
auto html_document = Document::create(Bindings::main_thread_internal_window_object());
auto html_document = Document::create(realm());
html_document->set_content_type("text/html");
html_document->set_ready_for_post_load_tasks(true);
@ -105,7 +105,7 @@ JS::NonnullGCPtr<Document> DOMImplementation::create_html_document(String const&
// https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype
WebIDL::ExceptionOr<JS::NonnullGCPtr<DocumentType>> DOMImplementation::create_document_type(String const& qualified_name, String const& public_id, String const& system_id)
{
TRY(Document::validate_qualified_name(global_object(), qualified_name));
TRY(Document::validate_qualified_name(realm(), qualified_name));
auto document_type = DocumentType::create(document());
document_type->set_name(qualified_name);
document_type->set_public_id(public_id);

View file

@ -61,7 +61,7 @@ DOMTokenList* DOMTokenList::create(Element const& associated_element, FlyString
// https://dom.spec.whatwg.org/#ref-for-domtokenlist%E2%91%A0%E2%91%A2
DOMTokenList::DOMTokenList(Element const& associated_element, FlyString associated_attribute)
: Bindings::LegacyPlatformObject(associated_element.window().cached_web_prototype("DOMTokenList"))
: Bindings::LegacyPlatformObject(Bindings::cached_web_prototype(associated_element.realm(), "DOMTokenList"))
, m_associated_element(associated_element)
, m_associated_attribute(move(associated_attribute))
{
@ -234,9 +234,9 @@ void DOMTokenList::set_value(String value)
WebIDL::ExceptionOr<void> DOMTokenList::validate_token(StringView token) const
{
if (token.is_empty())
return WebIDL::SyntaxError::create(global_object(), "Non-empty DOM tokens are not allowed");
return WebIDL::SyntaxError::create(realm(), "Non-empty DOM tokens are not allowed");
if (any_of(token, is_ascii_space))
return WebIDL::InvalidCharacterError::create(global_object(), "DOM tokens containing ASCII whitespace are not allowed");
return WebIDL::InvalidCharacterError::create(realm(), "DOM tokens containing ASCII whitespace are not allowed");
return {};
}

View file

@ -223,9 +223,9 @@ JS::NonnullGCPtr<Document> Document::create_and_initialize(Type type, String con
// FIXME: and cross-origin opener policy is navigationParams's cross-origin opener policy,
// FIXME: load timing info is loadTimingInfo,
// and navigation id is navigationParams's id.
auto document = Document::create(*window);
auto document = Document::create(window->realm());
document->m_type = type;
document->m_content_type = content_type;
document->m_content_type = move(content_type);
document->set_origin(navigation_params.origin);
document->m_policy_container = navigation_params.policy_container;
document->m_active_sandboxing_flag_set = navigation_params.final_sandboxing_flag_set;
@ -276,24 +276,27 @@ JS::NonnullGCPtr<Document> Document::create_and_initialize(Type type, String con
return document;
}
JS::NonnullGCPtr<Document> Document::create_with_global_object(HTML::Window& window)
JS::NonnullGCPtr<Document> Document::construct_impl(JS::Realm& realm)
{
return Document::create(window);
return Document::create(realm);
}
JS::NonnullGCPtr<Document> Document::create(JS::Realm& realm, AK::URL const& url)
{
return *realm.heap().allocate<Document>(realm, realm, url);
}
JS::NonnullGCPtr<Document> Document::create(HTML::Window& window, AK::URL const& url)
{
auto& realm = window.realm();
return *realm.heap().allocate<Document>(realm, window, url);
return create(window.realm(), url);
}
Document::Document(HTML::Window& window, const AK::URL& url)
: ParentNode(window.realm(), *this, NodeType::DOCUMENT_NODE)
Document::Document(JS::Realm& realm, const AK::URL& url)
: ParentNode(realm, *this, NodeType::DOCUMENT_NODE)
, m_style_computer(make<CSS::StyleComputer>(*this))
, m_url(url)
, m_window(window)
{
set_prototype(&window.cached_web_prototype("Document"));
set_prototype(&Bindings::cached_web_prototype(realm, "Document"));
HTML::main_thread_event_loop().register_document({}, *this);
@ -374,11 +377,11 @@ WebIDL::ExceptionOr<void> Document::run_the_document_write_steps(String input)
{
// 1. If document is an XML document, then throw an "InvalidStateError" DOMException.
if (m_type == Type::XML)
return WebIDL::InvalidStateError::create(global_object(), "write() called on XML document.");
return WebIDL::InvalidStateError::create(realm(), "write() called on XML document.");
// 2. If document's throw-on-dynamic-markup-insertion counter is greater than 0, then throw an "InvalidStateError" DOMException.
if (m_throw_on_dynamic_markup_insertion_counter > 0)
return WebIDL::InvalidStateError::create(global_object(), "throw-on-dynamic-markup-insertion-counter greater than zero.");
return WebIDL::InvalidStateError::create(realm(), "throw-on-dynamic-markup-insertion-counter greater than zero.");
// 3. If document's active parser was aborted is true, then return.
if (m_active_parser_was_aborted)
@ -409,18 +412,18 @@ WebIDL::ExceptionOr<Document*> Document::open(String const&, String const&)
{
// 1. If document is an XML document, then throw an "InvalidStateError" DOMException exception.
if (m_type == Type::XML)
return WebIDL::InvalidStateError::create(global_object(), "open() called on XML document.");
return WebIDL::InvalidStateError::create(realm(), "open() called on XML document.");
// 2. If document's throw-on-dynamic-markup-insertion counter is greater than 0, then throw an "InvalidStateError" DOMException.
if (m_throw_on_dynamic_markup_insertion_counter > 0)
return WebIDL::InvalidStateError::create(global_object(), "throw-on-dynamic-markup-insertion-counter greater than zero.");
return WebIDL::InvalidStateError::create(realm(), "throw-on-dynamic-markup-insertion-counter greater than zero.");
// FIXME: 3. Let entryDocument be the entry global object's associated Document.
auto& entry_document = *this;
// 4. If document's origin is not same origin to entryDocument's origin, then throw a "SecurityError" DOMException.
if (origin() != entry_document.origin())
return WebIDL::SecurityError::create(global_object(), "Document.origin() not the same as entryDocument's.");
return WebIDL::SecurityError::create(realm(), "Document.origin() not the same as entryDocument's.");
// 5. If document has an active parser whose script nesting level is greater than 0, then return document.
if (m_parser && m_parser->script_nesting_level() > 0)
@ -480,11 +483,11 @@ WebIDL::ExceptionOr<void> Document::close()
{
// 1. If document is an XML document, then throw an "InvalidStateError" DOMException exception.
if (m_type == Type::XML)
return WebIDL::InvalidStateError::create(global_object(), "close() called on XML document.");
return WebIDL::InvalidStateError::create(realm(), "close() called on XML document.");
// 2. If document's throw-on-dynamic-markup-insertion counter is greater than 0, then throw an "InvalidStateError" DOMException.
if (m_throw_on_dynamic_markup_insertion_counter > 0)
return WebIDL::InvalidStateError::create(global_object(), "throw-on-dynamic-markup-insertion-counter greater than zero.");
return WebIDL::InvalidStateError::create(realm(), "throw-on-dynamic-markup-insertion-counter greater than zero.");
// 3. If there is no script-created parser associated with the document, then return.
if (!m_parser)
@ -588,7 +591,7 @@ HTML::HTMLElement* Document::body()
WebIDL::ExceptionOr<void> Document::set_body(HTML::HTMLElement* new_body)
{
if (!is<HTML::HTMLBodyElement>(new_body) && !is<HTML::HTMLFrameSetElement>(new_body))
return WebIDL::HierarchyRequestError::create(global_object(), "Invalid document body element, must be 'body' or 'frameset'");
return WebIDL::HierarchyRequestError::create(realm(), "Invalid document body element, must be 'body' or 'frameset'");
auto* existing_body = body();
if (existing_body) {
@ -598,7 +601,7 @@ WebIDL::ExceptionOr<void> Document::set_body(HTML::HTMLElement* new_body)
auto* document_element = this->document_element();
if (!document_element)
return WebIDL::HierarchyRequestError::create(global_object(), "Missing document element");
return WebIDL::HierarchyRequestError::create(realm(), "Missing document element");
(void)TRY(document_element->append_child(*new_body));
return {};
@ -1118,7 +1121,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Element>> Document::create_element(FlyStrin
// 1. If localName does not match the Name production, then throw an "InvalidCharacterError" DOMException.
if (!is_valid_name(local_name))
return WebIDL::InvalidCharacterError::create(global_object(), "Invalid character in tag name.");
return WebIDL::InvalidCharacterError::create(realm(), "Invalid character in tag name.");
// 2. If this is an HTML document, then set localName to localName in ASCII lowercase.
if (document_type() == Type::HTML)
@ -1142,7 +1145,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Element>> Document::create_element(FlyStrin
WebIDL::ExceptionOr<JS::NonnullGCPtr<Element>> Document::create_element_ns(String const& namespace_, String const& qualified_name)
{
// 1. Let namespace, prefix, and localName be the result of passing namespace and qualifiedName to validate and extract.
auto extracted_qualified_name = TRY(validate_and_extract(global_object(), namespace_, qualified_name));
auto extracted_qualified_name = TRY(validate_and_extract(realm(), namespace_, qualified_name));
// FIXME: 2. Let is be null.
// FIXME: 3. If options is a dictionary and options["is"] exists, then set is to it.
@ -1174,7 +1177,8 @@ JS::NonnullGCPtr<Range> Document::create_range()
// https://dom.spec.whatwg.org/#dom-document-createevent
WebIDL::ExceptionOr<JS::NonnullGCPtr<Event>> Document::create_event(String const& interface)
{
auto& window_object = window();
auto& realm = this->realm();
auto& window = verify_cast<HTML::Window>(realm.global_object());
// NOTE: This is named event here, since we do step 5 and 6 as soon as possible for each case.
// 1. Let constructor be null.
@ -1184,46 +1188,46 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Event>> Document::create_event(String const
// then set constructor to the interface in the second column on the same row as the matching string:
auto interface_lowercase = interface.to_lowercase();
if (interface_lowercase == "beforeunloadevent") {
event = Event::create(window_object, ""); // FIXME: Create BeforeUnloadEvent
event = Event::create(realm, ""); // FIXME: Create BeforeUnloadEvent
} else if (interface_lowercase == "compositionevent") {
event = Event::create(window_object, ""); // FIXME: Create CompositionEvent
event = Event::create(realm, ""); // FIXME: Create CompositionEvent
} else if (interface_lowercase == "customevent") {
event = CustomEvent::create(window_object, "");
event = CustomEvent::create(realm, "");
} else if (interface_lowercase == "devicemotionevent") {
event = Event::create(window_object, ""); // FIXME: Create DeviceMotionEvent
event = Event::create(realm, ""); // FIXME: Create DeviceMotionEvent
} else if (interface_lowercase == "deviceorientationevent") {
event = Event::create(window_object, ""); // FIXME: Create DeviceOrientationEvent
event = Event::create(realm, ""); // FIXME: Create DeviceOrientationEvent
} else if (interface_lowercase == "dragevent") {
event = Event::create(window_object, ""); // FIXME: Create DragEvent
event = Event::create(realm, ""); // FIXME: Create DragEvent
} else if (interface_lowercase.is_one_of("event", "events")) {
event = Event::create(window_object, "");
event = Event::create(realm, "");
} else if (interface_lowercase == "focusevent") {
event = UIEvents::FocusEvent::create(window_object, "");
event = UIEvents::FocusEvent::create(window, "");
} else if (interface_lowercase == "hashchangeevent") {
event = Event::create(window_object, ""); // FIXME: Create HashChangeEvent
event = Event::create(realm, ""); // FIXME: Create HashChangeEvent
} else if (interface_lowercase == "htmlevents") {
event = Event::create(window_object, "");
event = Event::create(realm, "");
} else if (interface_lowercase == "keyboardevent") {
event = UIEvents::KeyboardEvent::create(window_object, "");
event = UIEvents::KeyboardEvent::create(window, "");
} else if (interface_lowercase == "messageevent") {
event = HTML::MessageEvent::create(window_object, "");
event = HTML::MessageEvent::create(window, "");
} else if (interface_lowercase.is_one_of("mouseevent", "mouseevents")) {
event = UIEvents::MouseEvent::create(window_object, "");
event = UIEvents::MouseEvent::create(window, "");
} else if (interface_lowercase == "storageevent") {
event = Event::create(window_object, ""); // FIXME: Create StorageEvent
event = Event::create(realm, ""); // FIXME: Create StorageEvent
} else if (interface_lowercase == "svgevents") {
event = Event::create(window_object, "");
event = Event::create(realm, "");
} else if (interface_lowercase == "textevent") {
event = Event::create(window_object, ""); // FIXME: Create CompositionEvent
event = Event::create(realm, ""); // FIXME: Create CompositionEvent
} else if (interface_lowercase == "touchevent") {
event = Event::create(window_object, ""); // FIXME: Create TouchEvent
event = Event::create(realm, ""); // FIXME: Create TouchEvent
} else if (interface_lowercase.is_one_of("uievent", "uievents")) {
event = UIEvents::UIEvent::create(window_object, "");
event = UIEvents::UIEvent::create(window, "");
}
// 3. If constructor is null, then throw a "NotSupportedError" DOMException.
if (!event) {
return WebIDL::NotSupportedError::create(global_object(), "No constructor for interface found");
return WebIDL::NotSupportedError::create(realm, "No constructor for interface found");
}
// FIXME: 4. If the interface indicated by constructor is not exposed on the relevant global object of this, then throw a "NotSupportedError" DOMException.
@ -1293,7 +1297,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> Document::import_node(JS::NonnullGCP
{
// 1. If node is a document or shadow root, then throw a "NotSupportedError" DOMException.
if (is<Document>(*node) || is<ShadowRoot>(*node))
return WebIDL::NotSupportedError::create(global_object(), "Cannot import a document or shadow root.");
return WebIDL::NotSupportedError::create(realm(), "Cannot import a document or shadow root.");
// 2. Return a clone of node, with this and the clone children flag set if deep is true.
return node->clone_node(this, deep);
@ -1340,10 +1344,10 @@ void Document::adopt_node(Node& node)
WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> Document::adopt_node_binding(JS::NonnullGCPtr<Node> node)
{
if (is<Document>(*node))
return WebIDL::NotSupportedError::create(global_object(), "Cannot adopt a document into a document");
return WebIDL::NotSupportedError::create(realm(), "Cannot adopt a document into a document");
if (is<ShadowRoot>(*node))
return WebIDL::HierarchyRequestError::create(global_object(), "Cannot adopt a shadow root into a document");
return WebIDL::HierarchyRequestError::create(realm(), "Cannot adopt a shadow root into a document");
if (is<DocumentFragment>(*node) && verify_cast<DocumentFragment>(*node).host())
return node;
@ -1447,7 +1451,7 @@ void Document::update_readiness(HTML::DocumentReadyState readiness_value)
}
// 4. Fire an event named readystatechange at document.
dispatch_event(*Event::create(window(), HTML::EventNames::readystatechange));
dispatch_event(*Event::create(realm(), HTML::EventNames::readystatechange));
}
Page* Document::page()
@ -1465,7 +1469,7 @@ EventTarget* Document::get_parent(Event const& event)
if (event.type() == HTML::EventNames::load)
return nullptr;
return &window();
return m_window;
}
// https://html.spec.whatwg.org/#completely-loaded
@ -1495,7 +1499,7 @@ void Document::completely_finish_loading()
// 5. Otherwise, if container is non-null, then queue an element task on the DOM manipulation task source given container to fire an event named load at container.
else if (container) {
container->queue_an_element_task(HTML::Task::Source::DOMManipulation, [container]() mutable {
container->dispatch_event(*DOM::Event::create(container->window(), HTML::EventNames::load));
container->dispatch_event(*DOM::Event::create(container->realm(), HTML::EventNames::load));
});
}
}
@ -1625,7 +1629,7 @@ void Document::update_the_visibility_state(HTML::VisibilityState visibility_stat
// FIXME: 3. Run any page visibility change steps which may be defined in other specifications, with visibility state and document.
// 4. Fire an event named visibilitychange at document, with its bubbles attribute initialized to true.
auto event = DOM::Event::create(window(), HTML::EventNames::visibilitychange);
auto event = DOM::Event::create(realm(), HTML::EventNames::visibilitychange);
event->set_bubbles(true);
dispatch_event(event);
}
@ -1646,7 +1650,7 @@ void Document::run_the_resize_steps()
return;
m_last_viewport_size = viewport_size;
window().dispatch_event(*DOM::Event::create(window(), UIEvents::EventNames::resize));
window().dispatch_event(*DOM::Event::create(realm(), UIEvents::EventNames::resize));
update_layout();
}
@ -1658,14 +1662,14 @@ void Document::run_the_scroll_steps()
for (auto& target : m_pending_scroll_event_targets) {
// 1. If target is a Document, fire an event named scroll that bubbles at target and fire an event named scroll at the VisualViewport that is associated with target.
if (is<Document>(*target)) {
auto event = DOM::Event::create(window(), HTML::EventNames::scroll);
auto event = DOM::Event::create(realm(), HTML::EventNames::scroll);
event->set_bubbles(true);
target->dispatch_event(*event);
// FIXME: Fire at the associated VisualViewport
}
// 2. Otherwise, fire an event named scroll at target.
else {
auto event = DOM::Event::create(window(), HTML::EventNames::scroll);
auto event = DOM::Event::create(realm(), HTML::EventNames::scroll);
target->dispatch_event(*event);
}
}
@ -1802,14 +1806,14 @@ bool Document::is_valid_name(String const& name)
}
// https://dom.spec.whatwg.org/#validate
WebIDL::ExceptionOr<Document::PrefixAndTagName> Document::validate_qualified_name(JS::Object& global_object, String const& qualified_name)
WebIDL::ExceptionOr<Document::PrefixAndTagName> Document::validate_qualified_name(JS::Realm& realm, String const& qualified_name)
{
if (qualified_name.is_empty())
return WebIDL::InvalidCharacterError::create(global_object, "Empty string is not a valid qualified name.");
return WebIDL::InvalidCharacterError::create(realm, "Empty string is not a valid qualified name.");
Utf8View utf8view { qualified_name };
if (!utf8view.validate())
return WebIDL::InvalidCharacterError::create(global_object, "Invalid qualified name.");
return WebIDL::InvalidCharacterError::create(realm, "Invalid qualified name.");
Optional<size_t> colon_offset;
@ -1819,19 +1823,19 @@ WebIDL::ExceptionOr<Document::PrefixAndTagName> Document::validate_qualified_nam
auto code_point = *it;
if (code_point == ':') {
if (colon_offset.has_value())
return WebIDL::InvalidCharacterError::create(global_object, "More than one colon (:) in qualified name.");
return WebIDL::InvalidCharacterError::create(realm, "More than one colon (:) in qualified name.");
colon_offset = utf8view.byte_offset_of(it);
at_start_of_name = true;
continue;
}
if (at_start_of_name) {
if (!is_valid_name_start_character(code_point))
return WebIDL::InvalidCharacterError::create(global_object, "Invalid start of qualified name.");
return WebIDL::InvalidCharacterError::create(realm, "Invalid start of qualified name.");
at_start_of_name = false;
continue;
}
if (!is_valid_name_character(code_point))
return WebIDL::InvalidCharacterError::create(global_object, "Invalid character in qualified name.");
return WebIDL::InvalidCharacterError::create(realm, "Invalid character in qualified name.");
}
if (!colon_offset.has_value())
@ -1841,10 +1845,10 @@ WebIDL::ExceptionOr<Document::PrefixAndTagName> Document::validate_qualified_nam
};
if (*colon_offset == 0)
return WebIDL::InvalidCharacterError::create(global_object, "Qualified name can't start with colon (:).");
return WebIDL::InvalidCharacterError::create(realm, "Qualified name can't start with colon (:).");
if (*colon_offset >= (qualified_name.length() - 1))
return WebIDL::InvalidCharacterError::create(global_object, "Qualified name can't end with colon (:).");
return WebIDL::InvalidCharacterError::create(realm, "Qualified name can't end with colon (:).");
return Document::PrefixAndTagName {
.prefix = qualified_name.substring_view(0, *colon_offset),
@ -2164,7 +2168,7 @@ void Document::unload(bool recursive_flag, Optional<DocumentUnloadTimingInfo> un
// then fire an event named unload at document's relevant global object, with legacy target override flag set.
// FIXME: The legacy target override flag is currently set by a virtual override of dispatch_event()
// We should reorganize this so that the flag appears explicitly here instead.
auto event = DOM::Event::create(global_object(), HTML::EventNames::unload);
auto event = DOM::Event::create(realm(), HTML::EventNames::unload);
global_object().dispatch_event(event);
}

View file

@ -23,6 +23,7 @@
#include <LibWeb/Cookie/Cookie.h>
#include <LibWeb/DOM/NonElementParentNode.h>
#include <LibWeb/DOM/ParentNode.h>
#include <LibWeb/HTML/BrowsingContext.h>
#include <LibWeb/HTML/CrossOrigin/CrossOriginOpenerPolicy.h>
#include <LibWeb/HTML/DocumentReadyState.h>
#include <LibWeb/HTML/HTMLScriptElement.h>
@ -82,8 +83,9 @@ public:
static JS::NonnullGCPtr<Document> create_and_initialize(Type, String content_type, HTML::NavigationParams);
static JS::NonnullGCPtr<Document> create(JS::Realm&, AK::URL const& url = "about:blank"sv);
static JS::NonnullGCPtr<Document> create(HTML::Window&, AK::URL const& url = "about:blank"sv);
static JS::NonnullGCPtr<Document> create_with_global_object(HTML::Window&);
static JS::NonnullGCPtr<Document> construct_impl(JS::Realm&);
virtual ~Document() override;
size_t next_layout_node_serial_id(Badge<Layout::Node>) { return m_next_layout_node_serial_id++; }
@ -367,7 +369,7 @@ public:
FlyString prefix;
FlyString tag_name;
};
static WebIDL::ExceptionOr<PrefixAndTagName> validate_qualified_name(JS::Object& global_object, String const& qualified_name);
static WebIDL::ExceptionOr<PrefixAndTagName> validate_qualified_name(JS::Realm&, String const& qualified_name);
JS::NonnullGCPtr<NodeIterator> create_node_iterator(Node& root, unsigned what_to_show, JS::GCPtr<NodeFilter>);
JS::NonnullGCPtr<TreeWalker> create_tree_walker(Node& root, unsigned what_to_show, JS::GCPtr<NodeFilter>);
@ -440,7 +442,7 @@ protected:
virtual void visit_edges(Cell::Visitor&) override;
private:
Document(HTML::Window&, AK::URL const&);
Document(JS::Realm&, AK::URL const&);
// ^HTML::GlobalEventHandlers
virtual EventTarget& global_event_handlers_to_event_target(FlyString const&) final { return *this; }

View file

@ -12,7 +12,7 @@ namespace Web::DOM {
DocumentFragment::DocumentFragment(Document& document)
: ParentNode(document, NodeType::DOCUMENT_FRAGMENT_NODE)
{
set_prototype(&window().cached_web_prototype("DocumentFragment"));
set_prototype(&Bindings::cached_web_prototype(realm(), "DocumentFragment"));
}
void DocumentFragment::visit_edges(Cell::Visitor& visitor)
@ -27,9 +27,10 @@ void DocumentFragment::set_host(Web::DOM::Element* element)
}
// https://dom.spec.whatwg.org/#dom-documentfragment-documentfragment
JS::NonnullGCPtr<DocumentFragment> DocumentFragment::create_with_global_object(HTML::Window& window)
JS::NonnullGCPtr<DocumentFragment> DocumentFragment::construct_impl(JS::Realm& realm)
{
return *window.heap().allocate<DocumentFragment>(window.realm(), window.associated_document());
auto& window = verify_cast<HTML::Window>(realm.global_object());
return *realm.heap().allocate<DocumentFragment>(realm, window.associated_document());
}
}

View file

@ -19,7 +19,7 @@ class DocumentFragment
WEB_PLATFORM_OBJECT(DocumentFragment, ParentNode);
public:
static JS::NonnullGCPtr<DocumentFragment> create_with_global_object(HTML::Window& window);
static JS::NonnullGCPtr<DocumentFragment> construct_impl(JS::Realm& realm);
virtual ~DocumentFragment() override = default;

View file

@ -17,7 +17,7 @@ JS::NonnullGCPtr<DocumentType> DocumentType::create(Document& document)
DocumentType::DocumentType(Document& document)
: Node(document, NodeType::DOCUMENT_TYPE_NODE)
{
set_prototype(&window().cached_web_prototype("DocumentType"));
set_prototype(&Bindings::cached_web_prototype(realm(), "DocumentType"));
}
}

View file

@ -54,7 +54,7 @@ Element::Element(Document& document, DOM::QualifiedName qualified_name)
: ParentNode(document, NodeType::ELEMENT_NODE)
, m_qualified_name(move(qualified_name))
{
set_prototype(&window().cached_web_prototype("Element"));
set_prototype(&Bindings::cached_web_prototype(document.realm(), "Element"));
make_html_uppercased_qualified_name();
}
@ -95,7 +95,7 @@ WebIDL::ExceptionOr<void> Element::set_attribute(FlyString const& name, String c
// 1. If qualifiedName does not match the Name production in XML, then throw an "InvalidCharacterError" DOMException.
// FIXME: Proper name validation
if (name.is_empty())
return WebIDL::InvalidCharacterError::create(global_object(), "Attribute name must not be empty");
return WebIDL::InvalidCharacterError::create(realm(), "Attribute name must not be empty");
// 2. If this is in the HTML namespace and its node document is an HTML document, then set qualifiedName to qualifiedName in ASCII lowercase.
// FIXME: Handle the second condition, assume it is an HTML document for now.
@ -126,14 +126,14 @@ WebIDL::ExceptionOr<void> Element::set_attribute(FlyString const& name, String c
}
// https://dom.spec.whatwg.org/#validate-and-extract
WebIDL::ExceptionOr<QualifiedName> validate_and_extract(JS::Object& global_object, FlyString namespace_, FlyString qualified_name)
WebIDL::ExceptionOr<QualifiedName> validate_and_extract(JS::Realm& realm, FlyString namespace_, FlyString qualified_name)
{
// 1. If namespace is the empty string, then set it to null.
if (namespace_.is_empty())
namespace_ = {};
// 2. Validate qualifiedName.
TRY(Document::validate_qualified_name(global_object, qualified_name));
TRY(Document::validate_qualified_name(realm, qualified_name));
// 3. Let prefix be null.
FlyString prefix = {};
@ -150,19 +150,19 @@ WebIDL::ExceptionOr<QualifiedName> validate_and_extract(JS::Object& global_objec
// 6. If prefix is non-null and namespace is null, then throw a "NamespaceError" DOMException.
if (!prefix.is_null() && namespace_.is_null())
return WebIDL::NamespaceError::create(global_object, "Prefix is non-null and namespace is null.");
return WebIDL::NamespaceError::create(realm, "Prefix is non-null and namespace is null.");
// 7. If prefix is "xml" and namespace is not the XML namespace, then throw a "NamespaceError" DOMException.
if (prefix == "xml"sv && namespace_ != Namespace::XML)
return WebIDL::NamespaceError::create(global_object, "Prefix is 'xml' and namespace is not the XML namespace.");
return WebIDL::NamespaceError::create(realm, "Prefix is 'xml' and namespace is not the XML namespace.");
// 8. If either qualifiedName or prefix is "xmlns" and namespace is not the XMLNS namespace, then throw a "NamespaceError" DOMException.
if ((qualified_name == "xmlns"sv || prefix == "xmlns"sv) && namespace_ != Namespace::XMLNS)
return WebIDL::NamespaceError::create(global_object, "Either qualifiedName or prefix is 'xmlns' and namespace is not the XMLNS namespace.");
return WebIDL::NamespaceError::create(realm, "Either qualifiedName or prefix is 'xmlns' and namespace is not the XMLNS namespace.");
// 9. If namespace is the XMLNS namespace and neither qualifiedName nor prefix is "xmlns", then throw a "NamespaceError" DOMException.
if (namespace_ == Namespace::XMLNS && !(qualified_name == "xmlns"sv || prefix == "xmlns"sv))
return WebIDL::NamespaceError::create(global_object, "Namespace is the XMLNS namespace and neither qualifiedName nor prefix is 'xmlns'.");
return WebIDL::NamespaceError::create(realm, "Namespace is the XMLNS namespace and neither qualifiedName nor prefix is 'xmlns'.");
// 10. Return namespace, prefix, and localName.
return QualifiedName { local_name, prefix, namespace_ };
@ -172,7 +172,7 @@ WebIDL::ExceptionOr<QualifiedName> validate_and_extract(JS::Object& global_objec
WebIDL::ExceptionOr<void> Element::set_attribute_ns(FlyString const& namespace_, FlyString const& qualified_name, String const& value)
{
// 1. Let namespace, prefix, and localName be the result of passing namespace and qualifiedName to validate and extract.
auto extracted_qualified_name = TRY(validate_and_extract(global_object(), namespace_, qualified_name));
auto extracted_qualified_name = TRY(validate_and_extract(realm(), namespace_, qualified_name));
// FIXME: 2. Set an attribute value for this using localName, value, and also prefix and namespace.
@ -203,7 +203,7 @@ WebIDL::ExceptionOr<bool> Element::toggle_attribute(FlyString const& name, Optio
// 1. If qualifiedName does not match the Name production in XML, then throw an "InvalidCharacterError" DOMException.
// FIXME: Proper name validation
if (name.is_empty())
return WebIDL::InvalidCharacterError::create(global_object(), "Attribute name must not be empty");
return WebIDL::InvalidCharacterError::create(realm(), "Attribute name must not be empty");
// 2. If this is in the HTML namespace and its node document is an HTML document, then set qualifiedName to qualifiedName in ASCII lowercase.
// FIXME: Handle the second condition, assume it is an HTML document for now.
@ -451,7 +451,7 @@ WebIDL::ExceptionOr<bool> Element::matches(StringView selectors) const
{
auto maybe_selectors = parse_selector(CSS::Parser::ParsingContext(static_cast<ParentNode&>(const_cast<Element&>(*this))), selectors);
if (!maybe_selectors.has_value())
return WebIDL::SyntaxError::create(global_object(), "Failed to parse selector");
return WebIDL::SyntaxError::create(realm(), "Failed to parse selector");
auto sel = maybe_selectors.value();
for (auto& s : sel) {
@ -466,7 +466,7 @@ WebIDL::ExceptionOr<DOM::Element const*> Element::closest(StringView selectors)
{
auto maybe_selectors = parse_selector(CSS::Parser::ParsingContext(static_cast<ParentNode&>(const_cast<Element&>(*this))), selectors);
if (!maybe_selectors.has_value())
return WebIDL::SyntaxError::create(global_object(), "Failed to parse selector");
return WebIDL::SyntaxError::create(realm(), "Failed to parse selector");
auto matches_selectors = [](CSS::SelectorList const& selector_list, Element const* element) {
for (auto& selector : selector_list) {
@ -780,7 +780,7 @@ WebIDL::ExceptionOr<void> Element::insert_adjacent_html(String position, String
// If context is null or a Document, throw a "NoModificationAllowedError" DOMException.
if (!context || context->is_document())
return WebIDL::NoModificationAllowedError::create(window(), "insertAdjacentHTML: context is null or a Document"sv);
return WebIDL::NoModificationAllowedError::create(realm(), "insertAdjacentHTML: context is null or a Document"sv);
}
// - If position is an ASCII case-insensitive match for the string "afterbegin"
// - If position is an ASCII case-insensitive match for the string "beforeend"
@ -791,7 +791,7 @@ WebIDL::ExceptionOr<void> Element::insert_adjacent_html(String position, String
// Otherwise
else {
// Throw a "SyntaxError" DOMException.
return WebIDL::SyntaxError::create(window(), "insertAdjacentHTML: invalid position argument"sv);
return WebIDL::SyntaxError::create(realm(), "insertAdjacentHTML: invalid position argument"sv);
}
// 2. If context is not an Element or the following are all true:
@ -878,7 +878,7 @@ WebIDL::ExceptionOr<JS::GCPtr<Node>> Element::insert_adjacent(String const& wher
// -> Otherwise
// Throw a "SyntaxError" DOMException.
return WebIDL::SyntaxError::create(global_object(), String::formatted("Unknown position '{}'. Must be one of 'beforebegin', 'afterbegin', 'beforeend' or 'afterend'"sv, where));
return WebIDL::SyntaxError::create(realm(), String::formatted("Unknown position '{}'. Must be one of 'beforebegin', 'afterbegin', 'beforeend' or 'afterend'"sv, where));
}
// https://dom.spec.whatwg.org/#dom-element-insertadjacentelement

View file

@ -179,6 +179,6 @@ private:
template<>
inline bool Node::fast_is<Element>() const { return is_element(); }
WebIDL::ExceptionOr<QualifiedName> validate_and_extract(JS::Object& global_object, FlyString namespace_, FlyString qualified_name);
WebIDL::ExceptionOr<QualifiedName> validate_and_extract(JS::Realm&, FlyString namespace_, FlyString qualified_name);
}

View file

@ -7,6 +7,7 @@
*/
#include <AK/TypeCasts.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/Event.h>
#include <LibWeb/DOM/Node.h>
#include <LibWeb/DOM/ShadowRoot.h>
@ -14,25 +15,30 @@
namespace Web::DOM {
JS::NonnullGCPtr<Event> Event::create(HTML::Window& window_object, FlyString const& event_name, EventInit const& event_init)
JS::NonnullGCPtr<Event> Event::create(JS::Realm& realm, FlyString const& event_name, EventInit const& event_init)
{
return *window_object.heap().allocate<Event>(window_object.realm(), window_object, event_name, event_init);
return *realm.heap().allocate<Event>(realm, realm, event_name, event_init);
}
JS::NonnullGCPtr<Event> Event::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, EventInit const& event_init)
JS::NonnullGCPtr<Event> Event::create(HTML::Window& window, FlyString const& event_name, EventInit const& event_init)
{
return create(window_object, event_name, event_init);
return create(window.realm(), event_name, event_init);
}
Event::Event(HTML::Window& window, FlyString const& type)
: PlatformObject(window.cached_web_prototype("Event"))
JS::NonnullGCPtr<Event> Event::construct_impl(JS::Realm& realm, FlyString const& event_name, EventInit const& event_init)
{
return create(realm, event_name, event_init);
}
Event::Event(JS::Realm& realm, FlyString const& type)
: PlatformObject(Bindings::cached_web_prototype(realm, "Event"))
, m_type(type)
, m_initialized(true)
{
}
Event::Event(HTML::Window& window, FlyString const& type, EventInit const& event_init)
: PlatformObject(window.cached_web_prototype("Event"))
Event::Event(JS::Realm& realm, FlyString const& type, EventInit const& event_init)
: PlatformObject(Bindings::cached_web_prototype(realm, "Event"))
, m_type(type)
, m_bubbles(event_init.bubbles)
, m_cancelable(event_init.cancelable)
@ -41,6 +47,16 @@ Event::Event(HTML::Window& window, FlyString const& type, EventInit const& event
{
}
Event::Event(HTML::Window& window, FlyString const& type, EventInit const& event_init)
: Event(window.realm(), type, event_init)
{
}
Event::Event(HTML::Window& window, FlyString const& type)
: Event(window.realm(), type)
{
}
void Event::visit_edges(Visitor& visitor)
{
Base::visit_edges(visitor);

View file

@ -9,7 +9,6 @@
#include <AK/FlyString.h>
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/DOM/EventTarget.h>
#include <LibWeb/HTML/Window.h>
namespace Web::DOM {
@ -46,9 +45,12 @@ public:
using Path = Vector<PathEntry>;
static JS::NonnullGCPtr<Event> create(JS::Realm&, FlyString const& event_name, EventInit const& event_init = {});
static JS::NonnullGCPtr<Event> create(HTML::Window&, FlyString const& event_name, EventInit const& event_init = {});
static JS::NonnullGCPtr<Event> create_with_global_object(HTML::Window&, FlyString const& event_name, EventInit const& event_init);
static JS::NonnullGCPtr<Event> construct_impl(JS::Realm&, FlyString const& event_name, EventInit const& event_init);
Event(JS::Realm&, FlyString const& type);
Event(JS::Realm&, FlyString const& type, EventInit const& event_init);
Event(HTML::Window&, FlyString const& type);
Event(HTML::Window&, FlyString const& type, EventInit const& event_init);

View file

@ -227,10 +227,10 @@ WebIDL::ExceptionOr<bool> EventTarget::dispatch_event_binding(Event& event)
{
// 1. If events dispatch flag is set, or if its initialized flag is not set, then throw an "InvalidStateError" DOMException.
if (event.dispatched())
return WebIDL::InvalidStateError::create(global_object(), "The event is already being dispatched.");
return WebIDL::InvalidStateError::create(realm(), "The event is already being dispatched.");
if (!event.initialized())
return WebIDL::InvalidStateError::create(global_object(), "Cannot dispatch an uninitialized event.");
return WebIDL::InvalidStateError::create(realm(), "Cannot dispatch an uninitialized event.");
// 2. Initialize events isTrusted attribute to false.
event.set_is_trusted(false);

View file

@ -22,7 +22,7 @@ class EventTarget : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(EventTarget, Bindings::PlatformObject);
public:
virtual ~EventTarget();
virtual ~EventTarget() override;
virtual bool is_focusable() const { return false; }

View file

@ -5,10 +5,10 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/Element.h>
#include <LibWeb/DOM/HTMLCollection.h>
#include <LibWeb/DOM/ParentNode.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/Namespace.h>
namespace Web::DOM {
@ -19,7 +19,7 @@ JS::NonnullGCPtr<HTMLCollection> HTMLCollection::create(ParentNode& root, Functi
}
HTMLCollection::HTMLCollection(ParentNode& root, Function<bool(Element const&)> filter)
: LegacyPlatformObject(root.window().cached_web_prototype("HTMLCollection"))
: LegacyPlatformObject(Bindings::cached_web_prototype(root.realm(), "HTMLCollection"))
, m_root(root)
, m_filter(move(filter))
{

View file

@ -11,13 +11,13 @@
namespace Web::DOM {
JS::NonnullGCPtr<NodeList> LiveNodeList::create(HTML::Window& window, Node& root, Function<bool(Node const&)> filter)
JS::NonnullGCPtr<NodeList> LiveNodeList::create(JS::Realm& realm, Node& root, Function<bool(Node const&)> filter)
{
return *window.heap().allocate<LiveNodeList>(window.realm(), window, root, move(filter));
return *realm.heap().allocate<LiveNodeList>(realm, realm, root, move(filter));
}
LiveNodeList::LiveNodeList(HTML::Window& window, Node& root, Function<bool(Node const&)> filter)
: NodeList(window)
LiveNodeList::LiveNodeList(JS::Realm& realm, Node& root, Function<bool(Node const&)> filter)
: NodeList(realm)
, m_root(root)
, m_filter(move(filter))
{

View file

@ -18,7 +18,7 @@ class LiveNodeList final : public NodeList {
WEB_PLATFORM_OBJECT(LiveNodeList, NodeList);
public:
static JS::NonnullGCPtr<NodeList> create(HTML::Window&, Node& root, Function<bool(Node const&)> filter);
static JS::NonnullGCPtr<NodeList> create(JS::Realm&, Node& root, Function<bool(Node const&)> filter);
virtual ~LiveNodeList() override;
virtual u32 length() const override;
@ -27,7 +27,7 @@ public:
virtual bool is_supported_property_index(u32) const override;
private:
LiveNodeList(HTML::Window&, Node& root, Function<bool(Node const&)> filter);
LiveNodeList(JS::Realm&, Node& root, Function<bool(Node const&)> filter);
virtual void visit_edges(Cell::Visitor&) override;

View file

@ -4,29 +4,29 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/DOM/MutationObserver.h>
#include <LibWeb/DOM/Node.h>
#include <LibWeb/HTML/Window.h>
namespace Web::DOM {
JS::NonnullGCPtr<MutationObserver> MutationObserver::create_with_global_object(HTML::Window& window, JS::GCPtr<WebIDL::CallbackType> callback)
JS::NonnullGCPtr<MutationObserver> MutationObserver::construct_impl(JS::Realm& realm, JS::GCPtr<WebIDL::CallbackType> callback)
{
return *window.heap().allocate<MutationObserver>(window.realm(), window, callback);
return *realm.heap().allocate<MutationObserver>(realm, realm, callback);
}
// https://dom.spec.whatwg.org/#dom-mutationobserver-mutationobserver
MutationObserver::MutationObserver(HTML::Window& window, JS::GCPtr<WebIDL::CallbackType> callback)
: PlatformObject(window.realm())
MutationObserver::MutationObserver(JS::Realm& realm, JS::GCPtr<WebIDL::CallbackType> callback)
: PlatformObject(realm)
, m_callback(move(callback))
{
set_prototype(&window.cached_web_prototype("MutationObserver"));
set_prototype(&Bindings::cached_web_prototype(realm, "MutationObserver"));
// 1. Set thiss callback to callback.
// 2. Append this to thiss relevant agents mutation observers.
auto* agent_custom_data = verify_cast<Bindings::WebEngineCustomData>(window.vm().custom_data());
auto* agent_custom_data = verify_cast<Bindings::WebEngineCustomData>(realm.vm().custom_data());
agent_custom_data->mutation_observers.append(*this);
}

View file

@ -32,7 +32,7 @@ class MutationObserver final : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(MutationObserver, Bindings::PlatformObject);
public:
static JS::NonnullGCPtr<MutationObserver> create_with_global_object(HTML::Window&, JS::GCPtr<WebIDL::CallbackType>);
static JS::NonnullGCPtr<MutationObserver> construct_impl(JS::Realm&, JS::GCPtr<WebIDL::CallbackType>);
virtual ~MutationObserver() override;
WebIDL::ExceptionOr<void> observe(Node& target, MutationObserverInit options = {});
@ -50,7 +50,7 @@ public:
}
private:
MutationObserver(HTML::Window&, JS::GCPtr<WebIDL::CallbackType>);
MutationObserver(JS::Realm&, JS::GCPtr<WebIDL::CallbackType>);
virtual void visit_edges(Cell::Visitor&) override;

View file

@ -5,20 +5,20 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/MutationRecord.h>
#include <LibWeb/DOM/Node.h>
#include <LibWeb/DOM/NodeList.h>
#include <LibWeb/HTML/Window.h>
namespace Web::DOM {
JS::NonnullGCPtr<MutationRecord> MutationRecord::create(HTML::Window& window, FlyString const& type, Node& target, NodeList& added_nodes, NodeList& removed_nodes, Node* previous_sibling, Node* next_sibling, String const& attribute_name, String const& attribute_namespace, String const& old_value)
JS::NonnullGCPtr<MutationRecord> MutationRecord::create(JS::Realm& realm, FlyString const& type, Node& target, NodeList& added_nodes, NodeList& removed_nodes, Node* previous_sibling, Node* next_sibling, String const& attribute_name, String const& attribute_namespace, String const& old_value)
{
return *window.heap().allocate<MutationRecord>(window.realm(), window, type, target, added_nodes, removed_nodes, previous_sibling, next_sibling, attribute_name, attribute_namespace, old_value);
return *realm.heap().allocate<MutationRecord>(realm, realm, type, target, added_nodes, removed_nodes, previous_sibling, next_sibling, attribute_name, attribute_namespace, old_value);
}
MutationRecord::MutationRecord(HTML::Window& window, FlyString const& type, Node& target, NodeList& added_nodes, NodeList& removed_nodes, Node* previous_sibling, Node* next_sibling, String const& attribute_name, String const& attribute_namespace, String const& old_value)
: PlatformObject(window.realm())
MutationRecord::MutationRecord(JS::Realm& realm, FlyString const& type, Node& target, NodeList& added_nodes, NodeList& removed_nodes, Node* previous_sibling, Node* next_sibling, String const& attribute_name, String const& attribute_namespace, String const& old_value)
: PlatformObject(realm)
, m_type(type)
, m_target(JS::make_handle(target))
, m_added_nodes(added_nodes)
@ -29,7 +29,7 @@ MutationRecord::MutationRecord(HTML::Window& window, FlyString const& type, Node
, m_attribute_namespace(attribute_namespace)
, m_old_value(old_value)
{
set_prototype(&window.cached_web_prototype("MutationRecord"));
set_prototype(&Bindings::cached_web_prototype(realm, "MutationRecord"));
}
MutationRecord::~MutationRecord() = default;

View file

@ -15,7 +15,7 @@ class MutationRecord : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(MutationRecord, Bindings::PlatformObject);
public:
static JS::NonnullGCPtr<MutationRecord> create(HTML::Window&, FlyString const& type, Node& target, NodeList& added_nodes, NodeList& removed_nodes, Node* previous_sibling, Node* next_sibling, String const& attribute_name, String const& attribute_namespace, String const& old_value);
static JS::NonnullGCPtr<MutationRecord> create(JS::Realm&, FlyString const& type, Node& target, NodeList& added_nodes, NodeList& removed_nodes, Node* previous_sibling, Node* next_sibling, String const& attribute_name, String const& attribute_namespace, String const& old_value);
virtual ~MutationRecord() override;
@ -30,7 +30,7 @@ public:
String const& old_value() const { return m_old_value; }
private:
MutationRecord(HTML::Window& window, FlyString const& type, Node& target, NodeList& added_nodes, NodeList& removed_nodes, Node* previous_sibling, Node* next_sibling, String const& attribute_name, String const& attribute_namespace, String const& old_value);
MutationRecord(JS::Realm& realm, FlyString const& type, Node& target, NodeList& added_nodes, NodeList& removed_nodes, Node* previous_sibling, Node* next_sibling, String const& attribute_name, String const& attribute_namespace, String const& old_value);
virtual void visit_edges(Cell::Visitor&) override;
FlyString m_type;

View file

@ -19,7 +19,7 @@ JS::NonnullGCPtr<NamedNodeMap> NamedNodeMap::create(Element& element)
}
NamedNodeMap::NamedNodeMap(Element& element)
: Bindings::LegacyPlatformObject(element.window().cached_web_prototype("NamedNodeMap"))
: Bindings::LegacyPlatformObject(Bindings::cached_web_prototype(element.realm(), "NamedNodeMap"))
, m_element(element)
{
}
@ -93,7 +93,7 @@ WebIDL::ExceptionOr<Attr const*> NamedNodeMap::remove_named_item(StringView qual
// 2. If attr is null, then throw a "NotFoundError" DOMException.
if (!attribute)
return WebIDL::NotFoundError::create(global_object(), String::formatted("Attribute with name '{}' not found", qualified_name));
return WebIDL::NotFoundError::create(realm(), String::formatted("Attribute with name '{}' not found", qualified_name));
// 3. Return attr.
return nullptr;
@ -137,7 +137,7 @@ WebIDL::ExceptionOr<Attr const*> NamedNodeMap::set_attribute(Attr& attribute)
{
// 1. If attrs element is neither null nor element, throw an "InUseAttributeError" DOMException.
if ((attribute.owner_element() != nullptr) && (attribute.owner_element() != &associated_element()))
return WebIDL::InUseAttributeError::create(global_object(), "Attribute must not already be in use"sv);
return WebIDL::InUseAttributeError::create(realm(), "Attribute must not already be in use"sv);
// 2. Let oldAttr be the result of getting an attribute given attrs namespace, attrs local name, and element.
// FIXME: When getNamedItemNS is implemented, use that instead.

View file

@ -315,24 +315,24 @@ WebIDL::ExceptionOr<void> Node::ensure_pre_insertion_validity(JS::NonnullGCPtr<N
{
// 1. If parent is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException.
if (!is<Document>(this) && !is<DocumentFragment>(this) && !is<Element>(this))
return WebIDL::HierarchyRequestError::create(global_object(), "Can only insert into a document, document fragment or element");
return WebIDL::HierarchyRequestError::create(realm(), "Can only insert into a document, document fragment or element");
// 2. If node is a host-including inclusive ancestor of parent, then throw a "HierarchyRequestError" DOMException.
if (node->is_host_including_inclusive_ancestor_of(*this))
return WebIDL::HierarchyRequestError::create(global_object(), "New node is an ancestor of this node");
return WebIDL::HierarchyRequestError::create(realm(), "New node is an ancestor of this node");
// 3. If child is non-null and its parent is not parent, then throw a "NotFoundError" DOMException.
if (child && child->parent() != this)
return WebIDL::NotFoundError::create(global_object(), "This node is not the parent of the given child");
return WebIDL::NotFoundError::create(realm(), "This node is not the parent of the given child");
// FIXME: All the following "Invalid node type for insertion" messages could be more descriptive.
// 4. If node is not a DocumentFragment, DocumentType, Element, or CharacterData node, then throw a "HierarchyRequestError" DOMException.
if (!is<DocumentFragment>(*node) && !is<DocumentType>(*node) && !is<Element>(*node) && !is<Text>(*node) && !is<Comment>(*node) && !is<ProcessingInstruction>(*node))
return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion");
// 5. If either node is a Text node and parent is a document, or node is a doctype and parent is not a document, then throw a "HierarchyRequestError" DOMException.
if ((is<Text>(*node) && is<Document>(this)) || (is<DocumentType>(*node) && !is<Document>(this)))
return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion");
// 6. If parent is a document, and any of the statements below, switched on the interface node implements, are true, then throw a "HierarchyRequestError" DOMException.
if (is<Document>(this)) {
@ -343,18 +343,18 @@ WebIDL::ExceptionOr<void> Node::ensure_pre_insertion_validity(JS::NonnullGCPtr<N
auto node_element_child_count = verify_cast<DocumentFragment>(*node).child_element_count();
if ((node_element_child_count > 1 || node->has_child_of_type<Text>())
|| (node_element_child_count == 1 && (has_child_of_type<Element>() || is<DocumentType>(child.ptr()) || (child && child->has_following_node_of_type_in_tree_order<DocumentType>())))) {
return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion");
}
} else if (is<Element>(*node)) {
// Element
// If parent has an element child, child is a doctype, or child is non-null and a doctype is following child.
if (has_child_of_type<Element>() || is<DocumentType>(child.ptr()) || (child && child->has_following_node_of_type_in_tree_order<DocumentType>()))
return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion");
} else if (is<DocumentType>(*node)) {
// DocumentType
// parent has a doctype child, child is non-null and an element is preceding child, or child is null and parent has an element child.
if (has_child_of_type<DocumentType>() || (child && child->has_preceding_node_of_type_in_tree_order<Element>()) || (!child && has_child_of_type<Element>()))
return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion");
}
}
@ -385,7 +385,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(window(), {}), StaticNodeList::create(window(), nodes), nullptr, nullptr);
node->queue_tree_mutation_record(StaticNodeList::create(realm(), {}), StaticNodeList::create(realm(), nodes), nullptr, nullptr);
}
// 5. If child is non-null, then:
@ -447,7 +447,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(window(), move(nodes)), StaticNodeList::create(window(), {}), previous_sibling.ptr(), child.ptr());
queue_tree_mutation_record(StaticNodeList::create(realm(), move(nodes)), StaticNodeList::create(realm(), {}), previous_sibling.ptr(), child.ptr());
// 9. Run the children changed steps for parent.
children_changed();
@ -487,7 +487,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> Node::pre_remove(JS::NonnullGCPtr<No
{
// 1. If childs parent is not parent, then throw a "NotFoundError" DOMException.
if (child->parent() != this)
return WebIDL::NotFoundError::create(global_object(), "Child does not belong to this node");
return WebIDL::NotFoundError::create(realm(), "Child does not belong to this node");
// 2. Remove child.
child->remove();
@ -598,7 +598,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(window(), {}), StaticNodeList::create(window(), move(removed_nodes)), old_previous_sibling.ptr(), old_next_sibling.ptr());
parent->queue_tree_mutation_record(StaticNodeList::create(realm(), {}), StaticNodeList::create(realm(), move(removed_nodes)), old_previous_sibling.ptr(), old_next_sibling.ptr());
}
// 21. Run the children changed steps for parent.
@ -612,25 +612,25 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> Node::replace_child(JS::NonnullGCPtr
{
// If parent is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException.
if (!is<Document>(this) && !is<DocumentFragment>(this) && !is<Element>(this))
return WebIDL::HierarchyRequestError::create(global_object(), "Can only insert into a document, document fragment or element");
return WebIDL::HierarchyRequestError::create(realm(), "Can only insert into a document, document fragment or element");
// 2. If node is a host-including inclusive ancestor of parent, then throw a "HierarchyRequestError" DOMException.
if (node->is_host_including_inclusive_ancestor_of(*this))
return WebIDL::HierarchyRequestError::create(global_object(), "New node is an ancestor of this node");
return WebIDL::HierarchyRequestError::create(realm(), "New node is an ancestor of this node");
// 3. If childs parent is not parent, then throw a "NotFoundError" DOMException.
if (child->parent() != this)
return WebIDL::NotFoundError::create(global_object(), "This node is not the parent of the given child");
return WebIDL::NotFoundError::create(realm(), "This node is not the parent of the given child");
// FIXME: All the following "Invalid node type for insertion" messages could be more descriptive.
// 4. If node is not a DocumentFragment, DocumentType, Element, or CharacterData node, then throw a "HierarchyRequestError" DOMException.
if (!is<DocumentFragment>(*node) && !is<DocumentType>(*node) && !is<Element>(*node) && !is<Text>(*node) && !is<Comment>(*node) && !is<ProcessingInstruction>(*node))
return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion");
// 5. If either node is a Text node and parent is a document, or node is a doctype and parent is not a document, then throw a "HierarchyRequestError" DOMException.
if ((is<Text>(*node) && is<Document>(this)) || (is<DocumentType>(*node) && !is<Document>(this)))
return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion");
// If parent is a document, and any of the statements below, switched on the interface node implements, are true, then throw a "HierarchyRequestError" DOMException.
if (is<Document>(this)) {
@ -641,18 +641,18 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> Node::replace_child(JS::NonnullGCPtr
auto node_element_child_count = verify_cast<DocumentFragment>(*node).child_element_count();
if ((node_element_child_count > 1 || node->has_child_of_type<Text>())
|| (node_element_child_count == 1 && (first_child_of_type<Element>() != child || child->has_following_node_of_type_in_tree_order<DocumentType>()))) {
return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion");
}
} else if (is<Element>(*node)) {
// Element
// parent has an element child that is not child or a doctype is following child.
if (first_child_of_type<Element>() != child || child->has_following_node_of_type_in_tree_order<DocumentType>())
return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion");
} else if (is<DocumentType>(*node)) {
// DocumentType
// parent has a doctype child that is not child, or an element is preceding child.
if (first_child_of_type<DocumentType>() != node || child->has_preceding_node_of_type_in_tree_order<Element>())
return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion");
return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion");
}
}
@ -690,7 +690,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> Node::replace_child(JS::NonnullGCPtr
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(window(), move(nodes)), StaticNodeList::create(window(), move(removed_nodes)), previous_sibling.ptr(), reference_child.ptr());
queue_tree_mutation_record(StaticNodeList::create(realm(), move(nodes)), StaticNodeList::create(realm(), move(removed_nodes)), previous_sibling.ptr(), reference_child.ptr());
// 15. Return child.
return child;
@ -723,7 +723,7 @@ JS::NonnullGCPtr<Node> Node::clone_node(Document* document, bool clone_children)
else if (is<Document>(this)) {
// Document
auto document_ = verify_cast<Document>(this);
auto document_copy = Document::create(Bindings::main_thread_internal_window_object(), document_->url());
auto document_copy = Document::create(this->realm(), document_->url());
// Set copys encoding, content type, URL, origin, type, and mode to those of node.
document_copy->set_encoding(document_->encoding());
@ -796,7 +796,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> Node::clone_node_binding(bool deep)
{
// 1. If this is a shadow root, then throw a "NotSupportedError" DOMException.
if (is<ShadowRoot>(*this))
return WebIDL::NotSupportedError::create(global_object(), "Cannot clone shadow root");
return WebIDL::NotSupportedError::create(realm(), "Cannot clone shadow root");
// 2. Return a clone of this, with the clone children flag set if deep is true.
return clone_node(nullptr, deep);
@ -863,7 +863,7 @@ ParentNode* Node::parent_or_shadow_host()
JS::NonnullGCPtr<NodeList> Node::child_nodes()
{
if (!m_child_nodes) {
m_child_nodes = LiveNodeList::create(window(), *this, [this](auto& node) {
m_child_nodes = LiveNodeList::create(realm(), *this, [this](auto& node) {
return is_parent_of(node);
});
}
@ -1143,7 +1143,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(window(), move(added_nodes)), StaticNodeList::create(window(), move(removed_nodes)), nullptr, nullptr);
queue_tree_mutation_record(StaticNodeList::create(realm(), move(added_nodes)), StaticNodeList::create(realm(), move(removed_nodes)), nullptr, nullptr);
}
// https://dom.spec.whatwg.org/#string-replace-all
@ -1382,7 +1382,7 @@ void Node::queue_mutation_record(FlyString const& type, String attribute_name, S
for (auto& interested_observer : interested_observers) {
// 1. Let record be a new MutationRecord object with its type set to type, target set to target, attributeName set to name, attributeNamespace set to namespace, oldValue set to mappedOldValue,
// addedNodes set to addedNodes, removedNodes set to removedNodes, previousSibling set to previousSibling, and nextSibling set to nextSibling.
auto record = MutationRecord::create(window(), type, *this, added_nodes, removed_nodes, previous_sibling, next_sibling, attribute_name, attribute_namespace, /* mappedOldValue */ interested_observer.value);
auto record = MutationRecord::create(realm(), type, *this, added_nodes, removed_nodes, previous_sibling, next_sibling, attribute_name, attribute_namespace, /* mappedOldValue */ interested_observer.value);
// 2. Enqueue record to observers record queue.
interested_observer.key->enqueue_record({}, move(record));

View file

@ -12,7 +12,7 @@
namespace Web::DOM {
NodeIterator::NodeIterator(Node& root)
: PlatformObject(root.window().cached_web_prototype("NodeIterator"))
: PlatformObject(Bindings::cached_web_prototype(root.realm(), "NodeIterator"))
, m_root(root)
, m_reference({ root })
{
@ -130,7 +130,7 @@ JS::ThrowCompletionOr<NodeFilter::Result> NodeIterator::filter(Node& node)
{
// 1. If traversers active flag is set, then throw an "InvalidStateError" DOMException.
if (m_active)
return throw_completion(WebIDL::InvalidStateError::create(global_object(), "NodeIterator is already active"));
return throw_completion(WebIDL::InvalidStateError::create(realm(), "NodeIterator is already active"));
// 2. Let n be nodes nodeType attribute value 1.
auto n = node.node_type() - 1;

View file

@ -4,14 +4,14 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.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.cached_web_prototype("NodeList"))
NodeList::NodeList(JS::Realm& realm)
: LegacyPlatformObject(Bindings::cached_web_prototype(realm, "NodeList"))
{
}

View file

@ -25,7 +25,7 @@ public:
virtual bool is_supported_property_index(u32) const override;
protected:
explicit NodeList(HTML::Window&);
explicit NodeList(JS::Realm&);
};
}

View file

@ -22,7 +22,7 @@ WebIDL::ExceptionOr<JS::GCPtr<Element>> ParentNode::query_selector(StringView se
{
auto maybe_selectors = parse_selector(CSS::Parser::ParsingContext(*this), selector_text);
if (!maybe_selectors.has_value())
return WebIDL::SyntaxError::create(global_object(), "Failed to parse selector");
return WebIDL::SyntaxError::create(realm(), "Failed to parse selector");
auto selectors = maybe_selectors.value();
@ -45,7 +45,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<NodeList>> ParentNode::query_selector_all(S
{
auto maybe_selectors = parse_selector(CSS::Parser::ParsingContext(*this), selector_text);
if (!maybe_selectors.has_value())
return WebIDL::SyntaxError::create(global_object(), "Failed to parse selector");
return WebIDL::SyntaxError::create(realm(), "Failed to parse selector");
auto selectors = maybe_selectors.value();
@ -60,7 +60,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<NodeList>> ParentNode::query_selector_all(S
return IterationDecision::Continue;
});
return StaticNodeList::create(window(), move(elements));
return StaticNodeList::create(realm(), move(elements));
}
JS::GCPtr<Element> ParentNode::first_element_child()

View file

@ -8,6 +8,7 @@
#pragma once
#include <AK/RefPtr.h>
#include <LibJS/Heap/Handle.h>
#include <LibWeb/DOM/Node.h>
#include <LibWeb/Forward.h>

View file

@ -6,6 +6,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/Comment.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/DocumentFragment.h>
@ -31,31 +32,32 @@ JS::NonnullGCPtr<Range> Range::create(HTML::Window& window)
JS::NonnullGCPtr<Range> Range::create(Document& document)
{
auto& window_object = document.window();
return *window_object.heap().allocate<Range>(window_object.realm(), document);
auto& realm = document.realm();
return *realm.heap().allocate<Range>(realm, document);
}
JS::NonnullGCPtr<Range> Range::create(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset)
{
auto& window_object = start_container.document().window();
return *window_object.heap().allocate<Range>(window_object.realm(), start_container, start_offset, end_container, end_offset);
auto& realm = start_container.realm();
return *realm.heap().allocate<Range>(realm, start_container, start_offset, end_container, end_offset);
}
JS::NonnullGCPtr<Range> Range::create_with_global_object(HTML::Window& window)
JS::NonnullGCPtr<Range> Range::construct_impl(JS::Realm& realm)
{
auto& window = verify_cast<HTML::Window>(realm.global_object());
return Range::create(window);
}
Range::Range(Document& document)
: Range(document, 0, document, 0)
{
set_prototype(&document.window().cached_web_prototype("Range"));
set_prototype(&Bindings::cached_web_prototype(document.realm(), "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.window().cached_web_prototype("Range"));
set_prototype(&Bindings::cached_web_prototype(start_container.realm(), "Range"));
live_ranges().set(this);
}
@ -137,11 +139,11 @@ WebIDL::ExceptionOr<void> Range::set_start_or_end(Node& node, u32 offset, StartO
// 1. If node is a doctype, then throw an "InvalidNodeTypeError" DOMException.
if (is<DocumentType>(node))
return WebIDL::InvalidNodeTypeError::create(global_object(), "Node cannot be a DocumentType.");
return WebIDL::InvalidNodeTypeError::create(realm(), "Node cannot be a DocumentType.");
// 2. If offset is greater than nodes length, then throw an "IndexSizeError" DOMException.
if (offset > node.length())
return WebIDL::IndexSizeError::create(global_object(), String::formatted("Node does not contain a child at offset {}", offset));
return WebIDL::IndexSizeError::create(realm(), String::formatted("Node does not contain a child at offset {}", offset));
// 3. Let bp be the boundary point (node, offset).
@ -196,7 +198,7 @@ WebIDL::ExceptionOr<void> Range::set_start_before(Node& node)
// 2. If parent is null, then throw an "InvalidNodeTypeError" DOMException.
if (!parent)
return WebIDL::InvalidNodeTypeError::create(global_object(), "Given node has no parent.");
return WebIDL::InvalidNodeTypeError::create(realm(), "Given node has no parent.");
// 3. Set the start of this to boundary point (parent, nodes index).
return set_start_or_end(*parent, node.index(), StartOrEnd::Start);
@ -210,7 +212,7 @@ WebIDL::ExceptionOr<void> Range::set_start_after(Node& node)
// 2. If parent is null, then throw an "InvalidNodeTypeError" DOMException.
if (!parent)
return WebIDL::InvalidNodeTypeError::create(global_object(), "Given node has no parent.");
return WebIDL::InvalidNodeTypeError::create(realm(), "Given node has no parent.");
// 3. Set the start of this to boundary point (parent, nodes index plus 1).
return set_start_or_end(*parent, node.index() + 1, StartOrEnd::Start);
@ -224,7 +226,7 @@ WebIDL::ExceptionOr<void> Range::set_end_before(Node& node)
// 2. If parent is null, then throw an "InvalidNodeTypeError" DOMException.
if (!parent)
return WebIDL::InvalidNodeTypeError::create(global_object(), "Given node has no parent.");
return WebIDL::InvalidNodeTypeError::create(realm(), "Given node has no parent.");
// 3. Set the end of this to boundary point (parent, nodes index).
return set_start_or_end(*parent, node.index(), StartOrEnd::End);
@ -238,7 +240,7 @@ WebIDL::ExceptionOr<void> Range::set_end_after(Node& node)
// 2. If parent is null, then throw an "InvalidNodeTypeError" DOMException.
if (!parent)
return WebIDL::InvalidNodeTypeError::create(global_object(), "Given node has no parent.");
return WebIDL::InvalidNodeTypeError::create(realm(), "Given node has no parent.");
// 3. Set the end of this to boundary point (parent, nodes index plus 1).
return set_start_or_end(*parent, node.index() + 1, StartOrEnd::End);
@ -254,11 +256,11 @@ WebIDL::ExceptionOr<i16> Range::compare_boundary_points(u16 how, Range const& so
// - END_TO_START,
// then throw a "NotSupportedError" DOMException.
if (how != HowToCompareBoundaryPoints::START_TO_START && how != HowToCompareBoundaryPoints::START_TO_END && how != HowToCompareBoundaryPoints::END_TO_END && how != HowToCompareBoundaryPoints::END_TO_START)
return WebIDL::NotSupportedError::create(global_object(), String::formatted("Expected 'how' to be one of START_TO_START (0), START_TO_END (1), END_TO_END (2) or END_TO_START (3), got {}", how));
return WebIDL::NotSupportedError::create(realm(), String::formatted("Expected 'how' to be one of START_TO_START (0), START_TO_END (1), END_TO_END (2) or END_TO_START (3), got {}", how));
// 2. If thiss root is not the same as sourceRanges root, then throw a "WrongDocumentError" DOMException.
if (&root() != &source_range.root())
return WebIDL::WrongDocumentError::create(global_object(), "This range is not in the same tree as the source range.");
return WebIDL::WrongDocumentError::create(realm(), "This range is not in the same tree as the source range.");
JS::GCPtr<Node> this_point_node;
u32 this_point_offset = 0;
@ -339,7 +341,7 @@ WebIDL::ExceptionOr<void> Range::select(Node& node)
// 2. If parent is null, then throw an "InvalidNodeTypeError" DOMException.
if (!parent)
return WebIDL::InvalidNodeTypeError::create(global_object(), "Given node has no parent.");
return WebIDL::InvalidNodeTypeError::create(realm(), "Given node has no parent.");
// 3. Let index be nodes index.
auto index = node.index();
@ -381,7 +383,7 @@ WebIDL::ExceptionOr<void> Range::select_node_contents(Node const& node)
{
// 1. If node is a doctype, throw an "InvalidNodeTypeError" DOMException.
if (is<DocumentType>(node))
return WebIDL::InvalidNodeTypeError::create(global_object(), "Node cannot be a DocumentType.");
return WebIDL::InvalidNodeTypeError::create(realm(), "Node cannot be a DocumentType.");
// 2. Let length be the length of node.
auto length = node.length();
@ -474,11 +476,11 @@ WebIDL::ExceptionOr<bool> Range::is_point_in_range(Node const& node, u32 offset)
// 2. If node is a doctype, then throw an "InvalidNodeTypeError" DOMException.
if (is<DocumentType>(node))
return WebIDL::InvalidNodeTypeError::create(global_object(), "Node cannot be a DocumentType.");
return WebIDL::InvalidNodeTypeError::create(realm(), "Node cannot be a DocumentType.");
// 3. If offset is greater than nodes length, then throw an "IndexSizeError" DOMException.
if (offset > node.length())
return WebIDL::IndexSizeError::create(global_object(), String::formatted("Node does not contain a child at offset {}", offset));
return WebIDL::IndexSizeError::create(realm(), String::formatted("Node does not contain a child at offset {}", offset));
// 4. If (node, offset) is before start or after end, return false.
auto relative_position_to_start = position_of_boundary_point_relative_to_other_boundary_point(node, offset, m_start_container, m_start_offset);
@ -495,15 +497,15 @@ WebIDL::ExceptionOr<i16> Range::compare_point(Node const& node, u32 offset) cons
{
// 1. If nodes root is different from thiss root, then throw a "WrongDocumentError" DOMException.
if (&node.root() != &root())
return WebIDL::WrongDocumentError::create(global_object(), "Given node is not in the same document as the range.");
return WebIDL::WrongDocumentError::create(realm(), "Given node is not in the same document as the range.");
// 2. If node is a doctype, then throw an "InvalidNodeTypeError" DOMException.
if (is<DocumentType>(node))
return WebIDL::InvalidNodeTypeError::create(global_object(), "Node cannot be a DocumentType.");
return WebIDL::InvalidNodeTypeError::create(realm(), "Node cannot be a DocumentType.");
// 3. If offset is greater than nodes length, then throw an "IndexSizeError" DOMException.
if (offset > node.length())
return WebIDL::IndexSizeError::create(global_object(), String::formatted("Node does not contain a child at offset {}", offset));
return WebIDL::IndexSizeError::create(realm(), String::formatted("Node does not contain a child at offset {}", offset));
// 4. If (node, offset) is before start, return 1.
auto relative_position_to_start = position_of_boundary_point_relative_to_other_boundary_point(node, offset, m_start_container, m_start_offset);
@ -636,7 +638,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<DocumentFragment>> Range::extract()
// 12. If any member of contained children is a doctype, then throw a "HierarchyRequestError" DOMException.
for (auto const& child : contained_children) {
if (is<DocumentType>(*child))
return WebIDL::HierarchyRequestError::create(global_object(), "Contained child is a DocumentType");
return WebIDL::HierarchyRequestError::create(realm(), "Contained child is a DocumentType");
}
JS::GCPtr<Node> new_node;
@ -783,7 +785,7 @@ WebIDL::ExceptionOr<void> Range::insert(JS::NonnullGCPtr<Node> node)
if ((is<ProcessingInstruction>(*m_start_container) || is<Comment>(*m_start_container))
|| (is<Text>(*m_start_container) && !m_start_container->parent_node())
|| m_start_container.ptr() == node.ptr()) {
return WebIDL::HierarchyRequestError::create(global_object(), "Range has inappropriate start node for insertion");
return WebIDL::HierarchyRequestError::create(realm(), "Range has inappropriate start node for insertion");
}
// 2. Let referenceNode be null.
@ -854,11 +856,11 @@ WebIDL::ExceptionOr<void> Range::surround_contents(JS::NonnullGCPtr<Node> new_pa
if (is<Text>(*end_non_text_node))
end_non_text_node = end_non_text_node->parent_node();
if (start_non_text_node != end_non_text_node)
return WebIDL::InvalidStateError::create(global_object(), "Non-Text node is partially contained in range.");
return WebIDL::InvalidStateError::create(realm(), "Non-Text node is partially contained in range.");
// 2. If newParent is a Document, DocumentType, or DocumentFragment node, then throw an "InvalidNodeTypeError" DOMException.
if (is<Document>(*new_parent) || is<DocumentType>(*new_parent) || is<DocumentFragment>(*new_parent))
return WebIDL::InvalidNodeTypeError::create(global_object(), "Invalid parent node type");
return WebIDL::InvalidNodeTypeError::create(realm(), "Invalid parent node type");
// 3. Let fragment be the result of extracting this.
auto fragment = TRY(extract());
@ -962,7 +964,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<DocumentFragment>> Range::clone_the_content
// 12. If any member of contained children is a doctype, then throw a "HierarchyRequestError" DOMException.
for (auto const& child : contained_children) {
if (is<DocumentType>(*child))
return WebIDL::HierarchyRequestError::create(global_object(), "Contained child is a DocumentType");
return WebIDL::HierarchyRequestError::create(realm(), "Contained child is a DocumentType");
}
// 13. If first partially contained child is a CharacterData node, then:

View file

@ -19,10 +19,8 @@ public:
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(HTML::Window&);
static JS::NonnullGCPtr<Range> construct_impl(JS::Realm&);
explicit Range(Document&);
Range(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset);
virtual ~Range() override;
// FIXME: There are a ton of methods missing here.
@ -76,6 +74,9 @@ 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;

View file

@ -4,18 +4,18 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Heap/Heap.h>
#include <LibWeb/DOM/StaticNodeList.h>
#include <LibWeb/HTML/Window.h>
namespace Web::DOM {
JS::NonnullGCPtr<NodeList> StaticNodeList::create(HTML::Window& window, Vector<JS::Handle<Node>> static_nodes)
JS::NonnullGCPtr<NodeList> StaticNodeList::create(JS::Realm& realm, Vector<JS::Handle<Node>> static_nodes)
{
return *window.heap().allocate<StaticNodeList>(window.realm(), window, move(static_nodes));
return *realm.heap().allocate<StaticNodeList>(realm, realm, move(static_nodes));
}
StaticNodeList::StaticNodeList(HTML::Window& window, Vector<JS::Handle<Node>> static_nodes)
: NodeList(window)
StaticNodeList::StaticNodeList(JS::Realm& realm, Vector<JS::Handle<Node>> static_nodes)
: NodeList(realm)
{
for (auto& node : static_nodes)
m_static_nodes.append(*node);

View file

@ -16,7 +16,7 @@ class StaticNodeList final : public NodeList {
WEB_PLATFORM_OBJECT(StaticNodeList, NodeList);
public:
static JS::NonnullGCPtr<NodeList> create(HTML::Window&, Vector<JS::Handle<Node>>);
static JS::NonnullGCPtr<NodeList> create(JS::Realm&, Vector<JS::Handle<Node>>);
virtual ~StaticNodeList() override;
@ -26,7 +26,7 @@ public:
virtual bool is_supported_property_index(u32) const override;
private:
StaticNodeList(HTML::Window&, Vector<JS::Handle<Node>>);
StaticNodeList(JS::Realm&, Vector<JS::Handle<Node>>);
virtual void visit_edges(Cell::Visitor&) override;

View file

@ -6,8 +6,8 @@
*/
#include <AK/TypeCasts.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/Attr.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/DocumentType.h>
#include <LibWeb/DOM/StaticRange.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
@ -17,23 +17,23 @@ 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().window().cached_web_prototype("StaticRange"));
set_prototype(&Bindings::cached_web_prototype(start_container.realm(), "StaticRange"));
}
StaticRange::~StaticRange() = default;
// https://dom.spec.whatwg.org/#dom-staticrange-staticrange
WebIDL::ExceptionOr<StaticRange*> StaticRange::create_with_global_object(HTML::Window& window, StaticRangeInit& init)
WebIDL::ExceptionOr<StaticRange*> StaticRange::construct_impl(JS::Realm& realm, 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<Attr>(*init.start_container))
return WebIDL::InvalidNodeTypeError::create(window, "startContainer cannot be a DocumentType or Attribute node.");
return WebIDL::InvalidNodeTypeError::create(realm, "startContainer cannot be a DocumentType or Attribute node.");
if (is<DocumentType>(*init.end_container) || is<Attr>(*init.end_container))
return WebIDL::InvalidNodeTypeError::create(window, "endContainer cannot be a DocumentType or Attribute node.");
return WebIDL::InvalidNodeTypeError::create(realm, "endContainer cannot be a DocumentType or Attribute node.");
// 2. Set thiss start to (init["startContainer"], init["startOffset"]) and end to (init["endContainer"], init["endOffset"]).
return window.heap().allocate<StaticRange>(window.realm(), *init.start_container, init.start_offset, *init.end_container, init.end_offset);
return realm.heap().allocate<StaticRange>(realm, *init.start_container, init.start_offset, *init.end_container, init.end_offset);
}
}

View file

@ -24,7 +24,7 @@ class StaticRange final : public AbstractRange {
WEB_PLATFORM_OBJECT(StaticRange, JS::Object);
public:
static WebIDL::ExceptionOr<StaticRange*> create_with_global_object(HTML::Window&, StaticRangeInit& init);
static WebIDL::ExceptionOr<StaticRange*> construct_impl(JS::Realm&, StaticRangeInit& init);
StaticRange(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset);
virtual ~StaticRange() override;

View file

@ -4,9 +4,11 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/DOM/Range.h>
#include <LibWeb/DOM/Text.h>
#include <LibWeb/HTML/HTMLInputElement.h>
#include <LibWeb/HTML/Scripting/Environments.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/Layout/TextNode.h>
@ -15,13 +17,13 @@ namespace Web::DOM {
Text::Text(Document& document, String const& data)
: CharacterData(document, NodeType::TEXT_NODE, data)
{
set_prototype(&window().cached_web_prototype("Text"));
set_prototype(&Bindings::cached_web_prototype(realm(), "Text"));
}
Text::Text(Document& document, NodeType type, String const& data)
: CharacterData(document, type, data)
{
set_prototype(&window().cached_web_prototype("Text"));
set_prototype(&Bindings::cached_web_prototype(realm(), "Text"));
}
void Text::visit_edges(Cell::Visitor& visitor)
@ -31,9 +33,11 @@ void Text::visit_edges(Cell::Visitor& visitor)
}
// https://dom.spec.whatwg.org/#dom-text-text
JS::NonnullGCPtr<Text> Text::create_with_global_object(HTML::Window& window, String const& data)
JS::NonnullGCPtr<Text> Text::construct_impl(JS::Realm& realm, String const& data)
{
return *window.heap().allocate<Text>(window.realm(), window.associated_document(), data);
// The new Text(data) constructor steps are to set thiss data to data and thiss node document to current global objects associated Document.
auto& window = verify_cast<HTML::Window>(HTML::current_global_object());
return *realm.heap().allocate<Text>(realm, window.associated_document(), data);
}
void Text::set_owner_input_element(Badge<HTML::HTMLInputElement>, HTML::HTMLInputElement& input_element)
@ -50,7 +54,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Text>> Text::split_text(size_t offset)
// 2. If offset is greater than length, then throw an "IndexSizeError" DOMException.
if (offset > length)
return WebIDL::IndexSizeError::create(global_object(), "Split offset is greater than length");
return WebIDL::IndexSizeError::create(realm(), "Split offset is greater than length");
// 3. Let count be length minus offset.
auto count = length - offset;

View file

@ -18,7 +18,7 @@ class Text : public CharacterData {
public:
virtual ~Text() override = default;
static JS::NonnullGCPtr<Text> create_with_global_object(HTML::Window& window, String const& data);
static JS::NonnullGCPtr<Text> construct_impl(JS::Realm& window, String const& data);
// ^Node
virtual FlyString node_name() const override { return "#text"; }
@ -32,7 +32,7 @@ public:
WebIDL::ExceptionOr<JS::NonnullGCPtr<Text>> split_text(size_t offset);
protected:
explicit Text(Document&, String const&);
Text(Document&, String const&);
Text(Document&, NodeType, String const&);
virtual void visit_edges(Cell::Visitor&) override;

View file

@ -14,7 +14,7 @@
namespace Web::DOM {
TreeWalker::TreeWalker(Node& root)
: PlatformObject(root.window().cached_web_prototype("TreeWalker"))
: PlatformObject(Bindings::cached_web_prototype(root.realm(), "TreeWalker"))
, m_root(root)
, m_current(root)
{
@ -231,7 +231,7 @@ JS::ThrowCompletionOr<NodeFilter::Result> TreeWalker::filter(Node& node)
{
// 1. If traversers active flag is set, then throw an "InvalidStateError" DOMException.
if (m_active)
return throw_completion(WebIDL::InvalidStateError::create(global_object(), "NodeIterator is already active"));
return throw_completion(WebIDL::InvalidStateError::create(realm(), "NodeIterator is already active"));
// 2. Let n be nodes nodeType attribute value 1.
auto n = node.node_type() - 1;

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Heap/Heap.h>
#include <LibWeb/DOM/DocumentFragment.h>
#include <LibWeb/DOMParsing/InnerHTML.h>
#include <LibWeb/HTML/Parser/HTMLParser.h>

View file

@ -20,15 +20,15 @@
namespace Web::DOMParsing {
JS::NonnullGCPtr<XMLSerializer> XMLSerializer::create_with_global_object(HTML::Window& window)
JS::NonnullGCPtr<XMLSerializer> XMLSerializer::construct_impl(JS::Realm& realm)
{
return *window.heap().allocate<XMLSerializer>(window.realm(), window);
return *realm.heap().allocate<XMLSerializer>(realm, realm);
}
XMLSerializer::XMLSerializer(HTML::Window& window)
: PlatformObject(window.realm())
XMLSerializer::XMLSerializer(JS::Realm& realm)
: PlatformObject(realm)
{
set_prototype(&window.cached_web_prototype("XMLSerializer"));
set_prototype(&Bindings::cached_web_prototype(realm, "XMLSerializer"));
}
XMLSerializer::~XMLSerializer() = default;
@ -308,7 +308,7 @@ struct LocalNameSetEntry {
// https://w3c.github.io/DOM-Parsing/#dfn-xml-serialization-of-the-attributes
static WebIDL::ExceptionOr<String> serialize_element_attributes(DOM::Element const& element, HashMap<FlyString, Vector<String>>& namespace_prefix_map, u64& prefix_index, HashMap<String, String> const& local_prefixes_map, bool ignore_namespace_definition_attribute, RequireWellFormed require_well_formed)
{
auto& global_object = element.global_object();
auto& realm = element.realm();
// 1. Let result be the empty string.
StringBuilder result;
@ -331,7 +331,7 @@ static WebIDL::ExceptionOr<String> serialize_element_attributes(DOM::Element con
});
if (local_name_set_iterator != local_name_set.end())
return WebIDL::InvalidStateError::create(global_object, "Element contains two attributes with identical namespaces and local names");
return WebIDL::InvalidStateError::create(realm, "Element contains two attributes with identical namespaces and local names");
}
// 2. Create a new tuple consisting of attr's namespaceURI attribute and localName attribute, and add it to the localname set.
@ -384,12 +384,12 @@ static WebIDL::ExceptionOr<String> serialize_element_attributes(DOM::Element con
// 2. If the require well-formed flag is set (its value is true), and the value of attr's value attribute matches the XMLNS namespace,
// then throw an exception; the serialization of this attribute would produce invalid XML because the XMLNS namespace is reserved and cannot be applied as an element's namespace via XML parsing.
if (require_well_formed == RequireWellFormed::Yes && attribute->value() == Namespace::XMLNS)
return WebIDL::InvalidStateError::create(global_object, "The XMLNS namespace cannot be used as an element's namespace");
return WebIDL::InvalidStateError::create(realm, "The XMLNS namespace cannot be used as an element's namespace");
// 3. If the require well-formed flag is set (its value is true), and the value of attr's value attribute is the empty string,
// then throw an exception; namespace prefix declarations cannot be used to undeclare a namespace (use a default namespace declaration instead).
if (require_well_formed == RequireWellFormed::Yes && attribute->value().is_empty())
return WebIDL::InvalidStateError::create(global_object, "Attribute's value is empty");
return WebIDL::InvalidStateError::create(realm, "Attribute's value is empty");
// 4. [If] the attr's prefix matches the string "xmlns", then let candidate prefix be the string "xmlns".
if (attribute->prefix() == "xmlns"sv)
@ -432,12 +432,12 @@ static WebIDL::ExceptionOr<String> serialize_element_attributes(DOM::Element con
// or does not match the XML Name production or equals "xmlns" and attribute namespace is null, then throw an exception; the serialization of this attr would not be a well-formed attribute.
if (require_well_formed == RequireWellFormed::Yes) {
if (attribute->local_name().view().contains(':'))
return WebIDL::InvalidStateError::create(global_object, "Attribute's local name contains a colon");
return WebIDL::InvalidStateError::create(realm, "Attribute's local name contains a colon");
// FIXME: Check attribute's local name against the XML Name production.
if (attribute->local_name() == "xmlns"sv && attribute_namespace.is_null())
return WebIDL::InvalidStateError::create(global_object, "Attribute's local name is 'xmlns' and the attribute has no namespace");
return WebIDL::InvalidStateError::create(realm, "Attribute's local name is 'xmlns' and the attribute has no namespace");
}
// 9. Append the following strings to result, in the order listed:
@ -461,13 +461,13 @@ static WebIDL::ExceptionOr<String> serialize_element_attributes(DOM::Element con
// https://w3c.github.io/DOM-Parsing/#xml-serializing-an-element-node
static WebIDL::ExceptionOr<String> serialize_element(DOM::Element const& element, Optional<FlyString>& namespace_, HashMap<FlyString, Vector<String>>& namespace_prefix_map, u64& prefix_index, RequireWellFormed require_well_formed)
{
auto& global_object = element.global_object();
auto& realm = element.realm();
// 1. If the require well-formed flag is set (its value is true), and this node's localName attribute contains the character ":" (U+003A COLON) or does not match the XML Name production,
// then throw an exception; the serialization of this node would not be a well-formed element.
if (require_well_formed == RequireWellFormed::Yes) {
if (element.local_name().view().contains(':'))
return WebIDL::InvalidStateError::create(global_object, "Element's local name contains a colon");
return WebIDL::InvalidStateError::create(realm, "Element's local name contains a colon");
// FIXME: Check element's local name against the XML Char production.
}
@ -539,7 +539,7 @@ static WebIDL::ExceptionOr<String> serialize_element(DOM::Element const& element
if (prefix == "xmlns"sv) {
// 1. If the require well-formed flag is set, then throw an error. An Element with prefix "xmlns" will not legally round-trip in a conforming XML parser.
if (require_well_formed == RequireWellFormed::Yes)
return WebIDL::InvalidStateError::create(global_object, "Elements prefix is 'xmlns'");
return WebIDL::InvalidStateError::create(realm, "Elements prefix is 'xmlns'");
// 2. Let candidate prefix be the value of prefix.
candidate_prefix = prefix;
@ -706,7 +706,7 @@ static WebIDL::ExceptionOr<String> serialize_document(DOM::Document const& docum
// If the require well-formed flag is set (its value is true), and this node has no documentElement (the documentElement attribute's value is null),
// then throw an exception; the serialization of this node would not be a well-formed document.
if (require_well_formed == RequireWellFormed::Yes && !document.document_element())
return WebIDL::InvalidStateError::create(document.global_object(), "Document has no document element");
return WebIDL::InvalidStateError::create(document.realm(), "Document has no document element");
// Otherwise, run the following steps:
// 1. Let serialized document be an empty string.
@ -730,10 +730,10 @@ static WebIDL::ExceptionOr<String> serialize_comment(DOM::Comment const& comment
// FIXME: Check comment's data against the XML Char production.
if (comment.data().contains("--"sv))
return WebIDL::InvalidStateError::create(comment.global_object(), "Comment data contains two adjacent hyphens");
return WebIDL::InvalidStateError::create(comment.realm(), "Comment data contains two adjacent hyphens");
if (comment.data().ends_with('-'))
return WebIDL::InvalidStateError::create(comment.global_object(), "Comment data ends with a hyphen");
return WebIDL::InvalidStateError::create(comment.realm(), "Comment data ends with a hyphen");
}
// Otherwise, return the concatenation of "<!--", node's data, and "-->".
@ -788,7 +788,7 @@ static WebIDL::ExceptionOr<String> serialize_document_type(DOM::DocumentType con
// both a """ (U+0022 QUOTATION MARK) and a "'" (U+0027 APOSTROPHE), then throw an exception; the serialization of this node would not be a well-formed document type declaration.
// FIXME: Check systemId against the XML Char production.
if (document_type.system_id().contains('"') && document_type.system_id().contains('\''))
return WebIDL::InvalidStateError::create(document_type.global_object(), "Document type system ID contains both a quotation mark and an apostrophe");
return WebIDL::InvalidStateError::create(document_type.realm(), "Document type system ID contains both a quotation mark and an apostrophe");
}
// 3. Let markup be an empty string.
@ -850,16 +850,16 @@ static WebIDL::ExceptionOr<String> serialize_processing_instruction(DOM::Process
// 1. If the require well-formed flag is set (its value is true), and node's target contains a ":" (U+003A COLON) character
// or is an ASCII case-insensitive match for the string "xml", then throw an exception; the serialization of this node's target would not be well-formed.
if (processing_instruction.target().contains(':'))
return WebIDL::InvalidStateError::create(processing_instruction.global_object(), "Processing instruction target contains a colon");
return WebIDL::InvalidStateError::create(processing_instruction.realm(), "Processing instruction target contains a colon");
if (processing_instruction.target().equals_ignoring_case("xml"sv))
return WebIDL::InvalidStateError::create(processing_instruction.global_object(), "Processing instruction target is equal to 'xml'");
return WebIDL::InvalidStateError::create(processing_instruction.realm(), "Processing instruction target is equal to 'xml'");
// 2. If the require well-formed flag is set (its value is true), and node's data contains characters that are not matched by the XML Char production or contains
// the string "?>" (U+003F QUESTION MARK, U+003E GREATER-THAN SIGN), then throw an exception; the serialization of this node's data would not be well-formed.
// FIXME: Check data against the XML Char production.
if (processing_instruction.data().contains("?>"sv))
return WebIDL::InvalidStateError::create(processing_instruction.global_object(), "Processing instruction data contains a terminator");
return WebIDL::InvalidStateError::create(processing_instruction.realm(), "Processing instruction data contains a terminator");
}
// 3. Let markup be the concatenation of the following, in the order listed:

View file

@ -14,14 +14,14 @@ class XMLSerializer final : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(XMLSerializer, Bindings::PlatformObject);
public:
static JS::NonnullGCPtr<XMLSerializer> create_with_global_object(HTML::Window&);
static JS::NonnullGCPtr<XMLSerializer> construct_impl(JS::Realm&);
virtual ~XMLSerializer() override;
WebIDL::ExceptionOr<String> serialize_to_string(JS::NonnullGCPtr<DOM::Node> root);
private:
explicit XMLSerializer(HTML::Window&);
explicit XMLSerializer(JS::Realm&);
};
enum class RequireWellFormed {

View file

@ -10,6 +10,7 @@
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/HTML/MessageEvent.h>
#include <LibWeb/HTML/MessagePort.h>
#include <LibWeb/HTML/Window.h>
namespace Web::HTML {

View file

@ -12,7 +12,6 @@
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/Realm.h>
#include <LibWeb/HTML/BrowsingContext.h>
#include <LibWeb/HTML/EventLoop/EventLoop.h>
#include <LibWeb/HTML/Origin.h>

View file

@ -4,29 +4,27 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/HTML/Window.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/WebIDL/DOMException.h>
namespace Web::WebIDL {
JS::NonnullGCPtr<DOMException> DOMException::create(JS::Object& global_object, FlyString const& name, FlyString const& message)
JS::NonnullGCPtr<DOMException> DOMException::create(JS::Realm& realm, FlyString const& name, FlyString const& message)
{
auto& window = verify_cast<HTML::Window>(global_object);
return *window.heap().allocate<DOMException>(window.realm(), window, name, message);
return *realm.heap().allocate<DOMException>(realm, realm, name, message);
}
JS::NonnullGCPtr<DOMException> DOMException::create_with_global_object(JS::Object& global_object, FlyString const& message, FlyString const& name)
JS::NonnullGCPtr<DOMException> DOMException::construct_impl(JS::Realm& realm, FlyString const& message, FlyString const& name)
{
auto& window = verify_cast<HTML::Window>(global_object);
return *window.heap().allocate<DOMException>(window.realm(), window, name, message);
return *realm.heap().allocate<DOMException>(realm, realm, name, message);
}
DOMException::DOMException(HTML::Window& window, FlyString const& name, FlyString const& message)
: PlatformObject(window.realm())
DOMException::DOMException(JS::Realm& realm, FlyString const& name, FlyString const& message)
: PlatformObject(realm)
, m_name(name)
, m_message(message)
{
set_prototype(&window.cached_web_prototype("DOMException"));
set_prototype(&Bindings::cached_web_prototype(realm, "DOMException"));
}
DOMException::~DOMException() = default;

View file

@ -9,17 +9,18 @@
#include <AK/FlyString.h>
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/HTML/Scripting/Environments.h>
namespace Web::WebIDL {
#define TRY_OR_RETURN_OOM(global_object, expression) \
({ \
auto _temporary_result = (expression); \
if (_temporary_result.is_error()) { \
VERIFY(_temporary_result.error().code() == ENOMEM); \
return WebIDL::UnknownError::create(global_object, "Out of memory."sv); \
} \
_temporary_result.release_value(); \
#define TRY_OR_RETURN_OOM(realm, expression) \
({ \
auto _temporary_result = (expression); \
if (_temporary_result.is_error()) { \
VERIFY(_temporary_result.error().code() == ENOMEM); \
return WebIDL::UnknownError::create(realm, "Out of memory."sv); \
} \
_temporary_result.release_value(); \
})
// The following have a legacy code value but *don't* produce it as
@ -102,13 +103,11 @@ class DOMException final : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(DOMException, Bindings::PlatformObject);
public:
static JS::NonnullGCPtr<DOMException> create(JS::Object& global_object, FlyString const& name, FlyString const& message);
static JS::NonnullGCPtr<DOMException> create(JS::Realm& realm, FlyString const& name, FlyString const& message);
// JS constructor has message first, name second
// FIXME: This is a completely pointless footgun, let's use the same order for both factories.
static JS::NonnullGCPtr<DOMException> create_with_global_object(JS::Object& global_object, FlyString const& message, FlyString const& name);
static JS::NonnullGCPtr<DOMException> create(JS::Realm& realm, FlyString const& message);
static JS::NonnullGCPtr<DOMException> construct_impl(JS::Realm& realm, FlyString const& message, FlyString const& name);
virtual ~DOMException() override;
@ -117,20 +116,24 @@ public:
u16 code() const { return get_legacy_code_for_name(m_name); }
protected:
DOMException(HTML::Window&, FlyString const& name, FlyString const& message);
DOMException(JS::Realm&, FlyString const& name, FlyString const& message);
private:
FlyString m_name;
FlyString m_message;
};
#define __ENUMERATE(ErrorName) \
class ErrorName final { \
public: \
static JS::NonnullGCPtr<DOMException> create(JS::Object& global_object, FlyString const& message) \
{ \
return DOMException::create(global_object, #ErrorName, message); \
} \
#define __ENUMERATE(ErrorName) \
class ErrorName final { \
public: \
static JS::NonnullGCPtr<DOMException> create(JS::Realm& realm, FlyString const& message) \
{ \
return DOMException::create(realm, #ErrorName, message); \
} \
static JS::NonnullGCPtr<DOMException> create(JS::Object const& global_object, FlyString const& message) \
{ \
return create(HTML::relevant_realm(global_object), message); \
} \
};
ENUMERATE_DOM_EXCEPTION_ERROR_NAMES
#undef __ENUMERATE