diff --git a/Userland/Libraries/LibWeb/DOM/AbortController.cpp b/Userland/Libraries/LibWeb/DOM/AbortController.cpp index 563bb528dd..57b2c0c7e2 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortController.cpp +++ b/Userland/Libraries/LibWeb/DOM/AbortController.cpp @@ -4,23 +4,24 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include namespace Web::DOM { -JS::NonnullGCPtr AbortController::create_with_global_object(HTML::Window& window) +JS::NonnullGCPtr AbortController::construct_impl(JS::Realm& realm) { - auto signal = AbortSignal::create_with_global_object(window); - return *window.heap().allocate(window.realm(), window, move(signal)); + auto signal = AbortSignal::construct_impl(realm); + return *realm.heap().allocate(realm, realm, move(signal)); } // https://dom.spec.whatwg.org/#dom-abortcontroller-abortcontroller -AbortController::AbortController(HTML::Window& window, JS::NonnullGCPtr signal) - : PlatformObject(window.realm()) +AbortController::AbortController(JS::Realm& realm, JS::NonnullGCPtr 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; diff --git a/Userland/Libraries/LibWeb/DOM/AbortController.h b/Userland/Libraries/LibWeb/DOM/AbortController.h index f497e4bc88..040ed58a2e 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortController.h +++ b/Userland/Libraries/LibWeb/DOM/AbortController.h @@ -16,7 +16,7 @@ class AbortController final : public Bindings::PlatformObject { WEB_PLATFORM_OBJECT(AbortController, Bindings::PlatformObject); public: - static JS::NonnullGCPtr create_with_global_object(HTML::Window&); + static JS::NonnullGCPtr construct_impl(JS::Realm&); virtual ~AbortController() override; @@ -26,7 +26,7 @@ public: void abort(JS::Value reason); private: - AbortController(HTML::Window&, JS::NonnullGCPtr); + AbortController(JS::Realm&, JS::NonnullGCPtr); virtual void visit_edges(Cell::Visitor&) override; diff --git a/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp b/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp index 80f9f7619f..67540ba5fd 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp +++ b/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -11,15 +12,20 @@ namespace Web::DOM { -JS::NonnullGCPtr AbortSignal::create_with_global_object(HTML::Window& window) +JS::NonnullGCPtr AbortSignal::construct_impl(JS::Realm& realm) { - return *window.heap().allocate(window.realm(), window); + return *realm.heap().allocate(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 signal’s 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) diff --git a/Userland/Libraries/LibWeb/DOM/AbortSignal.h b/Userland/Libraries/LibWeb/DOM/AbortSignal.h index 36de000d2b..a4fcd8939b 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortSignal.h +++ b/Userland/Libraries/LibWeb/DOM/AbortSignal.h @@ -10,7 +10,6 @@ #include #include #include -#include namespace Web::DOM { @@ -19,7 +18,7 @@ class AbortSignal final : public EventTarget { WEB_PLATFORM_OBJECT(AbortSignal, EventTarget); public: - static JS::NonnullGCPtr create_with_global_object(HTML::Window&); + static JS::NonnullGCPtr construct_impl(JS::Realm&); virtual ~AbortSignal() override = default; @@ -40,6 +39,7 @@ public: JS::ThrowCompletionOr throw_if_aborted() const; private: + explicit AbortSignal(JS::Realm&); explicit AbortSignal(HTML::Window&); virtual void visit_edges(JS::Cell::Visitor&) override; diff --git a/Userland/Libraries/LibWeb/DOM/AbstractRange.cpp b/Userland/Libraries/LibWeb/DOM/AbstractRange.cpp index 24fa81674c..084586e76a 100644 --- a/Userland/Libraries/LibWeb/DOM/AbstractRange.cpp +++ b/Userland/Libraries/LibWeb/DOM/AbstractRange.cpp @@ -4,14 +4,14 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include -#include 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) diff --git a/Userland/Libraries/LibWeb/DOM/Attr.cpp b/Userland/Libraries/LibWeb/DOM/Attr.cpp index 076f538114..d63794aef5 100644 --- a/Userland/Libraries/LibWeb/DOM/Attr.cpp +++ b/Userland/Libraries/LibWeb/DOM/Attr.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -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 attribute’s local name, attribute’s namespace, oldValue, « », « », null, and null. - element.queue_mutation_record(MutationType::attributes, local_name(), namespace_uri(), old_value, StaticNodeList::create(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 attribute’s local name, oldValue, newValue, and attribute’s namespace. diff --git a/Userland/Libraries/LibWeb/DOM/CDATASection.cpp b/Userland/Libraries/LibWeb/DOM/CDATASection.cpp index 5c1937b231..ce465a6de1 100644 --- a/Userland/Libraries/LibWeb/DOM/CDATASection.cpp +++ b/Userland/Libraries/LibWeb/DOM/CDATASection.cpp @@ -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; diff --git a/Userland/Libraries/LibWeb/DOM/CharacterData.cpp b/Userland/Libraries/LibWeb/DOM/CharacterData.cpp index 29b8ed6d63..dfafb077b5 100644 --- a/Userland/Libraries/LibWeb/DOM/CharacterData.cpp +++ b/Userland/Libraries/LibWeb/DOM/CharacterData.cpp @@ -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("CharacterData")); + set_prototype(&Bindings::ensure_web_prototype(document.realm(), "CharacterData")); } // https://dom.spec.whatwg.org/#dom-characterdata-data @@ -38,7 +38,7 @@ WebIDL::ExceptionOr 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 node’s data, and then return. @@ -57,14 +57,14 @@ WebIDL::ExceptionOr 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, node’s 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 node’s data after offset code units. // 6. Let delete offset be offset + data’s length. diff --git a/Userland/Libraries/LibWeb/DOM/CharacterData.h b/Userland/Libraries/LibWeb/DOM/CharacterData.h index a97ecad4b0..5cf8cf678b 100644 --- a/Userland/Libraries/LibWeb/DOM/CharacterData.h +++ b/Userland/Libraries/LibWeb/DOM/CharacterData.h @@ -34,7 +34,7 @@ public: WebIDL::ExceptionOr 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; diff --git a/Userland/Libraries/LibWeb/DOM/Comment.cpp b/Userland/Libraries/LibWeb/DOM/Comment.cpp index b442edc0b2..dfd616220f 100644 --- a/Userland/Libraries/LibWeb/DOM/Comment.cpp +++ b/Userland/Libraries/LibWeb/DOM/Comment.cpp @@ -16,9 +16,10 @@ Comment::Comment(Document& document, String const& data) } // https://dom.spec.whatwg.org/#dom-comment-comment -JS::NonnullGCPtr Comment::create_with_global_object(HTML::Window& window, String const& data) +JS::NonnullGCPtr Comment::construct_impl(JS::Realm& realm, String const& data) { - return *window.heap().allocate(window.realm(), window.associated_document(), data); + auto& window = verify_cast(realm.global_object()); + return *realm.heap().allocate(realm, window.associated_document(), data); } } diff --git a/Userland/Libraries/LibWeb/DOM/Comment.h b/Userland/Libraries/LibWeb/DOM/Comment.h index 94b7a30f13..bca5c3061f 100644 --- a/Userland/Libraries/LibWeb/DOM/Comment.h +++ b/Userland/Libraries/LibWeb/DOM/Comment.h @@ -15,13 +15,13 @@ class Comment final : public CharacterData { WEB_PLATFORM_OBJECT(Comment, CharacterData); public: - static JS::NonnullGCPtr create_with_global_object(HTML::Window&, String const& data); + static JS::NonnullGCPtr 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<> diff --git a/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp b/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp index e69229cefa..c62a4a93c6 100644 --- a/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp +++ b/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp @@ -5,32 +5,27 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include -#include 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(window_object.realm(), window_object, event_name, event_init); + return realm.heap().allocate(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; diff --git a/Userland/Libraries/LibWeb/DOM/CustomEvent.h b/Userland/Libraries/LibWeb/DOM/CustomEvent.h index 5a389c6b53..d4b6e2f039 100644 --- a/Userland/Libraries/LibWeb/DOM/CustomEvent.h +++ b/Userland/Libraries/LibWeb/DOM/CustomEvent.h @@ -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() }; }; diff --git a/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp b/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp index 69da598dcd..910353fc42 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp +++ b/Userland/Libraries/LibWeb/DOM/DOMImplementation.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -12,19 +13,18 @@ #include #include #include -#include #include namespace Web::DOM { JS::NonnullGCPtr DOMImplementation::create(Document& document) { - auto& window = document.window(); - return *window.heap().allocate(document.realm(), document); + auto& realm = document.realm(); + return *realm.heap().allocate(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> DOMImplementation::create_document(String const& namespace_, String const& qualified_name, JS::GCPtr 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> DOMImplementation::create_docume // https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument JS::NonnullGCPtr 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 DOMImplementation::create_html_document(String const& // https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype WebIDL::ExceptionOr> 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); diff --git a/Userland/Libraries/LibWeb/DOM/DOMTokenList.cpp b/Userland/Libraries/LibWeb/DOM/DOMTokenList.cpp index 11fcdbdc0a..d474d1ccf1 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMTokenList.cpp +++ b/Userland/Libraries/LibWeb/DOM/DOMTokenList.cpp @@ -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 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 {}; } diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index e2c5ca2c0d..3afe844ddc 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -223,9 +223,9 @@ JS::NonnullGCPtr 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::create_and_initialize(Type type, String con return document; } -JS::NonnullGCPtr Document::create_with_global_object(HTML::Window& window) +JS::NonnullGCPtr Document::construct_impl(JS::Realm& realm) { - return Document::create(window); + return Document::create(realm); +} + +JS::NonnullGCPtr Document::create(JS::Realm& realm, AK::URL const& url) +{ + return *realm.heap().allocate(realm, realm, url); } JS::NonnullGCPtr Document::create(HTML::Window& window, AK::URL const& url) { - auto& realm = window.realm(); - return *realm.heap().allocate(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(*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 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::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 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 Document::set_body(HTML::HTMLElement* new_body) { if (!is(new_body) && !is(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 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> 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> Document::create_element(FlyStrin WebIDL::ExceptionOr> 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 Document::create_range() // https://dom.spec.whatwg.org/#dom-document-createevent WebIDL::ExceptionOr> Document::create_event(String const& interface) { - auto& window_object = window(); + auto& realm = this->realm(); + auto& window = verify_cast(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> 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> Document::import_node(JS::NonnullGCP { // 1. If node is a document or shadow root, then throw a "NotSupportedError" DOMException. if (is(*node) || is(*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> Document::adopt_node_binding(JS::NonnullGCPtr node) { if (is(*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(*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(*node) && verify_cast(*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(*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::validate_qualified_name(JS::Object& global_object, String const& qualified_name) +WebIDL::ExceptionOr 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 colon_offset; @@ -1819,19 +1823,19 @@ WebIDL::ExceptionOr 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::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 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); } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index 5969a115ca..b18edfba67 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -82,8 +83,9 @@ public: static JS::NonnullGCPtr create_and_initialize(Type, String content_type, HTML::NavigationParams); + static JS::NonnullGCPtr create(JS::Realm&, AK::URL const& url = "about:blank"sv); static JS::NonnullGCPtr create(HTML::Window&, AK::URL const& url = "about:blank"sv); - static JS::NonnullGCPtr create_with_global_object(HTML::Window&); + static JS::NonnullGCPtr construct_impl(JS::Realm&); virtual ~Document() override; size_t next_layout_node_serial_id(Badge) { return m_next_layout_node_serial_id++; } @@ -367,7 +369,7 @@ public: FlyString prefix; FlyString tag_name; }; - static WebIDL::ExceptionOr validate_qualified_name(JS::Object& global_object, String const& qualified_name); + static WebIDL::ExceptionOr validate_qualified_name(JS::Realm&, String const& qualified_name); JS::NonnullGCPtr create_node_iterator(Node& root, unsigned what_to_show, JS::GCPtr); JS::NonnullGCPtr create_tree_walker(Node& root, unsigned what_to_show, JS::GCPtr); @@ -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; } diff --git a/Userland/Libraries/LibWeb/DOM/DocumentFragment.cpp b/Userland/Libraries/LibWeb/DOM/DocumentFragment.cpp index 16d4a36daf..beaac1d61a 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentFragment.cpp +++ b/Userland/Libraries/LibWeb/DOM/DocumentFragment.cpp @@ -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::create_with_global_object(HTML::Window& window) +JS::NonnullGCPtr DocumentFragment::construct_impl(JS::Realm& realm) { - return *window.heap().allocate(window.realm(), window.associated_document()); + auto& window = verify_cast(realm.global_object()); + return *realm.heap().allocate(realm, window.associated_document()); } } diff --git a/Userland/Libraries/LibWeb/DOM/DocumentFragment.h b/Userland/Libraries/LibWeb/DOM/DocumentFragment.h index f377809f45..e0c5213d42 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentFragment.h +++ b/Userland/Libraries/LibWeb/DOM/DocumentFragment.h @@ -19,7 +19,7 @@ class DocumentFragment WEB_PLATFORM_OBJECT(DocumentFragment, ParentNode); public: - static JS::NonnullGCPtr create_with_global_object(HTML::Window& window); + static JS::NonnullGCPtr construct_impl(JS::Realm& realm); virtual ~DocumentFragment() override = default; diff --git a/Userland/Libraries/LibWeb/DOM/DocumentType.cpp b/Userland/Libraries/LibWeb/DOM/DocumentType.cpp index f71da375db..f5620412a5 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentType.cpp +++ b/Userland/Libraries/LibWeb/DOM/DocumentType.cpp @@ -17,7 +17,7 @@ JS::NonnullGCPtr 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")); } } diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index 686c73253c..df17923d9e 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -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 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 Element::set_attribute(FlyString const& name, String c } // https://dom.spec.whatwg.org/#validate-and-extract -WebIDL::ExceptionOr validate_and_extract(JS::Object& global_object, FlyString namespace_, FlyString qualified_name) +WebIDL::ExceptionOr 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 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 validate_and_extract(JS::Object& global_objec WebIDL::ExceptionOr 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 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 Element::matches(StringView selectors) const { auto maybe_selectors = parse_selector(CSS::Parser::ParsingContext(static_cast(const_cast(*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 Element::closest(StringView selectors) { auto maybe_selectors = parse_selector(CSS::Parser::ParsingContext(static_cast(const_cast(*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 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 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> 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 diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h index a315e31036..63f9176993 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.h +++ b/Userland/Libraries/LibWeb/DOM/Element.h @@ -179,6 +179,6 @@ private: template<> inline bool Node::fast_is() const { return is_element(); } -WebIDL::ExceptionOr validate_and_extract(JS::Object& global_object, FlyString namespace_, FlyString qualified_name); +WebIDL::ExceptionOr validate_and_extract(JS::Realm&, FlyString namespace_, FlyString qualified_name); } diff --git a/Userland/Libraries/LibWeb/DOM/Event.cpp b/Userland/Libraries/LibWeb/DOM/Event.cpp index 7527725c82..a6449f36c9 100644 --- a/Userland/Libraries/LibWeb/DOM/Event.cpp +++ b/Userland/Libraries/LibWeb/DOM/Event.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -14,25 +15,30 @@ namespace Web::DOM { -JS::NonnullGCPtr Event::create(HTML::Window& window_object, FlyString const& event_name, EventInit const& event_init) +JS::NonnullGCPtr Event::create(JS::Realm& realm, FlyString const& event_name, EventInit const& event_init) { - return *window_object.heap().allocate(window_object.realm(), window_object, event_name, event_init); + return *realm.heap().allocate(realm, realm, event_name, event_init); } -JS::NonnullGCPtr Event::create_with_global_object(HTML::Window& window_object, FlyString const& event_name, EventInit const& event_init) +JS::NonnullGCPtr 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::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); diff --git a/Userland/Libraries/LibWeb/DOM/Event.h b/Userland/Libraries/LibWeb/DOM/Event.h index 26903e233c..8120749930 100644 --- a/Userland/Libraries/LibWeb/DOM/Event.h +++ b/Userland/Libraries/LibWeb/DOM/Event.h @@ -9,7 +9,6 @@ #include #include #include -#include namespace Web::DOM { @@ -46,9 +45,12 @@ public: using Path = Vector; + static JS::NonnullGCPtr create(JS::Realm&, FlyString const& event_name, EventInit const& event_init = {}); static JS::NonnullGCPtr create(HTML::Window&, FlyString const& event_name, EventInit const& event_init = {}); - static JS::NonnullGCPtr create_with_global_object(HTML::Window&, FlyString const& event_name, EventInit const& event_init); + static JS::NonnullGCPtr 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); diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp index 244cad529e..82cdcd5aac 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp @@ -227,10 +227,10 @@ WebIDL::ExceptionOr EventTarget::dispatch_event_binding(Event& event) { // 1. If event’s 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 event’s isTrusted attribute to false. event.set_is_trusted(false); diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.h b/Userland/Libraries/LibWeb/DOM/EventTarget.h index 63afbfd6e2..e3656435cd 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.h +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.h @@ -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; } diff --git a/Userland/Libraries/LibWeb/DOM/HTMLCollection.cpp b/Userland/Libraries/LibWeb/DOM/HTMLCollection.cpp index f5b807aae2..f73238b283 100644 --- a/Userland/Libraries/LibWeb/DOM/HTMLCollection.cpp +++ b/Userland/Libraries/LibWeb/DOM/HTMLCollection.cpp @@ -5,10 +5,10 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include -#include #include namespace Web::DOM { @@ -19,7 +19,7 @@ JS::NonnullGCPtr HTMLCollection::create(ParentNode& root, Functi } HTMLCollection::HTMLCollection(ParentNode& root, Function filter) - : LegacyPlatformObject(root.window().cached_web_prototype("HTMLCollection")) + : LegacyPlatformObject(Bindings::cached_web_prototype(root.realm(), "HTMLCollection")) , m_root(root) , m_filter(move(filter)) { diff --git a/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp b/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp index 9041c097c8..019c918d37 100644 --- a/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp +++ b/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp @@ -11,13 +11,13 @@ namespace Web::DOM { -JS::NonnullGCPtr LiveNodeList::create(HTML::Window& window, Node& root, Function filter) +JS::NonnullGCPtr LiveNodeList::create(JS::Realm& realm, Node& root, Function filter) { - return *window.heap().allocate(window.realm(), window, root, move(filter)); + return *realm.heap().allocate(realm, realm, root, move(filter)); } -LiveNodeList::LiveNodeList(HTML::Window& window, Node& root, Function filter) - : NodeList(window) +LiveNodeList::LiveNodeList(JS::Realm& realm, Node& root, Function filter) + : NodeList(realm) , m_root(root) , m_filter(move(filter)) { diff --git a/Userland/Libraries/LibWeb/DOM/LiveNodeList.h b/Userland/Libraries/LibWeb/DOM/LiveNodeList.h index 8d23133e58..7aa602059f 100644 --- a/Userland/Libraries/LibWeb/DOM/LiveNodeList.h +++ b/Userland/Libraries/LibWeb/DOM/LiveNodeList.h @@ -18,7 +18,7 @@ class LiveNodeList final : public NodeList { WEB_PLATFORM_OBJECT(LiveNodeList, NodeList); public: - static JS::NonnullGCPtr create(HTML::Window&, Node& root, Function filter); + static JS::NonnullGCPtr create(JS::Realm&, Node& root, Function 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 filter); + LiveNodeList(JS::Realm&, Node& root, Function filter); virtual void visit_edges(Cell::Visitor&) override; diff --git a/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp b/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp index 3c5bd4f5ca..64c6778e16 100644 --- a/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp +++ b/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp @@ -4,29 +4,29 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include -#include namespace Web::DOM { -JS::NonnullGCPtr MutationObserver::create_with_global_object(HTML::Window& window, JS::GCPtr callback) +JS::NonnullGCPtr MutationObserver::construct_impl(JS::Realm& realm, JS::GCPtr callback) { - return *window.heap().allocate(window.realm(), window, callback); + return *realm.heap().allocate(realm, realm, callback); } // https://dom.spec.whatwg.org/#dom-mutationobserver-mutationobserver -MutationObserver::MutationObserver(HTML::Window& window, JS::GCPtr callback) - : PlatformObject(window.realm()) +MutationObserver::MutationObserver(JS::Realm& realm, JS::GCPtr callback) + : PlatformObject(realm) , m_callback(move(callback)) { - set_prototype(&window.cached_web_prototype("MutationObserver")); + set_prototype(&Bindings::cached_web_prototype(realm, "MutationObserver")); // 1. Set this’s callback to callback. // 2. Append this to this’s relevant agent’s mutation observers. - auto* agent_custom_data = verify_cast(window.vm().custom_data()); + auto* agent_custom_data = verify_cast(realm.vm().custom_data()); agent_custom_data->mutation_observers.append(*this); } diff --git a/Userland/Libraries/LibWeb/DOM/MutationObserver.h b/Userland/Libraries/LibWeb/DOM/MutationObserver.h index b6f86d7b61..3bc7a85d84 100644 --- a/Userland/Libraries/LibWeb/DOM/MutationObserver.h +++ b/Userland/Libraries/LibWeb/DOM/MutationObserver.h @@ -32,7 +32,7 @@ class MutationObserver final : public Bindings::PlatformObject { WEB_PLATFORM_OBJECT(MutationObserver, Bindings::PlatformObject); public: - static JS::NonnullGCPtr create_with_global_object(HTML::Window&, JS::GCPtr); + static JS::NonnullGCPtr construct_impl(JS::Realm&, JS::GCPtr); virtual ~MutationObserver() override; WebIDL::ExceptionOr observe(Node& target, MutationObserverInit options = {}); @@ -50,7 +50,7 @@ public: } private: - MutationObserver(HTML::Window&, JS::GCPtr); + MutationObserver(JS::Realm&, JS::GCPtr); virtual void visit_edges(Cell::Visitor&) override; diff --git a/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp b/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp index 3eee96fa9f..cd05247c19 100644 --- a/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp +++ b/Userland/Libraries/LibWeb/DOM/MutationRecord.cpp @@ -5,20 +5,20 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include -#include namespace Web::DOM { -JS::NonnullGCPtr 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::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(window.realm(), window, type, target, added_nodes, removed_nodes, previous_sibling, next_sibling, attribute_name, attribute_namespace, old_value); + return *realm.heap().allocate(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; diff --git a/Userland/Libraries/LibWeb/DOM/MutationRecord.h b/Userland/Libraries/LibWeb/DOM/MutationRecord.h index db2298c5e6..ad61a4835f 100644 --- a/Userland/Libraries/LibWeb/DOM/MutationRecord.h +++ b/Userland/Libraries/LibWeb/DOM/MutationRecord.h @@ -15,7 +15,7 @@ class MutationRecord : public Bindings::PlatformObject { WEB_PLATFORM_OBJECT(MutationRecord, Bindings::PlatformObject); public: - static JS::NonnullGCPtr 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 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; diff --git a/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp b/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp index f273a31ea5..05417be3ba 100644 --- a/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp +++ b/Userland/Libraries/LibWeb/DOM/NamedNodeMap.cpp @@ -19,7 +19,7 @@ JS::NonnullGCPtr 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 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 NamedNodeMap::set_attribute(Attr& attribute) { // 1. If attr’s 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 attr’s namespace, attr’s local name, and element. // FIXME: When getNamedItemNS is implemented, use that instead. diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index 1ff0fae8bb..8a0b55a969 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -315,24 +315,24 @@ WebIDL::ExceptionOr Node::ensure_pre_insertion_validity(JS::NonnullGCPtr(this) && !is(this) && !is(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(*node) && !is(*node) && !is(*node) && !is(*node) && !is(*node) && !is(*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(*node) && is(this)) || (is(*node) && !is(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(this)) { @@ -343,18 +343,18 @@ WebIDL::ExceptionOr Node::ensure_pre_insertion_validity(JS::NonnullGCPtr(*node).child_element_count(); if ((node_element_child_count > 1 || node->has_child_of_type()) || (node_element_child_count == 1 && (has_child_of_type() || is(child.ptr()) || (child && child->has_following_node_of_type_in_tree_order())))) { - return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion"); + return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion"); } } else if (is(*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() || is(child.ptr()) || (child && child->has_following_node_of_type_in_tree_order())) - return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion"); + return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion"); } else if (is(*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() || (child && child->has_preceding_node_of_type_in_tree_order()) || (!child && has_child_of_type())) - 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, JS::GCPtr 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, JS::GCPtr 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> Node::pre_remove(JS::NonnullGCPtrparent() != 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> 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> Node::replace_child(JS::NonnullGCPtr { // If parent is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException. if (!is(this) && !is(this) && !is(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’s 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(*node) && !is(*node) && !is(*node) && !is(*node) && !is(*node) && !is(*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(*node) && is(this)) || (is(*node) && !is(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(this)) { @@ -641,18 +641,18 @@ WebIDL::ExceptionOr> Node::replace_child(JS::NonnullGCPtr auto node_element_child_count = verify_cast(*node).child_element_count(); if ((node_element_child_count > 1 || node->has_child_of_type()) || (node_element_child_count == 1 && (first_child_of_type() != child || child->has_following_node_of_type_in_tree_order()))) { - return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion"); + return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion"); } } else if (is(*node)) { // Element // parent has an element child that is not child or a doctype is following child. if (first_child_of_type() != child || child->has_following_node_of_type_in_tree_order()) - return WebIDL::HierarchyRequestError::create(global_object(), "Invalid node type for insertion"); + return WebIDL::HierarchyRequestError::create(realm(), "Invalid node type for insertion"); } else if (is(*node)) { // DocumentType // parent has a doctype child that is not child, or an element is preceding child. if (first_child_of_type() != node || child->has_preceding_node_of_type_in_tree_order()) - 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> 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::clone_node(Document* document, bool clone_children) else if (is(this)) { // Document auto document_ = verify_cast(this); - auto document_copy = Document::create(Bindings::main_thread_internal_window_object(), document_->url()); + auto document_copy = Document::create(this->realm(), document_->url()); // Set copy’s encoding, content type, URL, origin, type, and mode to those of node. document_copy->set_encoding(document_->encoding()); @@ -796,7 +796,7 @@ WebIDL::ExceptionOr> Node::clone_node_binding(bool deep) { // 1. If this is a shadow root, then throw a "NotSupportedError" DOMException. if (is(*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 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) // 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 observer’s record queue. interested_observer.key->enqueue_record({}, move(record)); diff --git a/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp b/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp index db2cb941fa..712786ade6 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp +++ b/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp @@ -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 NodeIterator::filter(Node& node) { // 1. If traverser’s 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 node’s nodeType attribute value − 1. auto n = node.node_type() - 1; diff --git a/Userland/Libraries/LibWeb/DOM/NodeList.cpp b/Userland/Libraries/LibWeb/DOM/NodeList.cpp index f70b3890cf..ed866d2c63 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeList.cpp +++ b/Userland/Libraries/LibWeb/DOM/NodeList.cpp @@ -4,14 +4,14 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include -#include 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")) { } diff --git a/Userland/Libraries/LibWeb/DOM/NodeList.h b/Userland/Libraries/LibWeb/DOM/NodeList.h index 3027a17651..9e8327f30b 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeList.h +++ b/Userland/Libraries/LibWeb/DOM/NodeList.h @@ -25,7 +25,7 @@ public: virtual bool is_supported_property_index(u32) const override; protected: - explicit NodeList(HTML::Window&); + explicit NodeList(JS::Realm&); }; } diff --git a/Userland/Libraries/LibWeb/DOM/ParentNode.cpp b/Userland/Libraries/LibWeb/DOM/ParentNode.cpp index 24f82d4439..02916f82b7 100644 --- a/Userland/Libraries/LibWeb/DOM/ParentNode.cpp +++ b/Userland/Libraries/LibWeb/DOM/ParentNode.cpp @@ -22,7 +22,7 @@ WebIDL::ExceptionOr> 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> 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> ParentNode::query_selector_all(S return IterationDecision::Continue; }); - return StaticNodeList::create(window(), move(elements)); + return StaticNodeList::create(realm(), move(elements)); } JS::GCPtr ParentNode::first_element_child() diff --git a/Userland/Libraries/LibWeb/DOM/Position.h b/Userland/Libraries/LibWeb/DOM/Position.h index fd9847b8c4..a8405b66ab 100644 --- a/Userland/Libraries/LibWeb/DOM/Position.h +++ b/Userland/Libraries/LibWeb/DOM/Position.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include diff --git a/Userland/Libraries/LibWeb/DOM/Range.cpp b/Userland/Libraries/LibWeb/DOM/Range.cpp index 7c0ae951e0..f8f47f5d3c 100644 --- a/Userland/Libraries/LibWeb/DOM/Range.cpp +++ b/Userland/Libraries/LibWeb/DOM/Range.cpp @@ -6,6 +6,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -31,31 +32,32 @@ JS::NonnullGCPtr Range::create(HTML::Window& window) JS::NonnullGCPtr Range::create(Document& document) { - auto& window_object = document.window(); - return *window_object.heap().allocate(window_object.realm(), document); + auto& realm = document.realm(); + return *realm.heap().allocate(realm, document); } JS::NonnullGCPtr 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(window_object.realm(), start_container, start_offset, end_container, end_offset); + auto& realm = start_container.realm(); + return *realm.heap().allocate(realm, start_container, start_offset, end_container, end_offset); } -JS::NonnullGCPtr Range::create_with_global_object(HTML::Window& window) +JS::NonnullGCPtr Range::construct_impl(JS::Realm& realm) { + auto& window = verify_cast(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 Range::set_start_or_end(Node& node, u32 offset, StartO // 1. If node is a doctype, then throw an "InvalidNodeTypeError" DOMException. if (is(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 node’s 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 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, node’s index). return set_start_or_end(*parent, node.index(), StartOrEnd::Start); @@ -210,7 +212,7 @@ WebIDL::ExceptionOr 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, node’s index plus 1). return set_start_or_end(*parent, node.index() + 1, StartOrEnd::Start); @@ -224,7 +226,7 @@ WebIDL::ExceptionOr 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, node’s index). return set_start_or_end(*parent, node.index(), StartOrEnd::End); @@ -238,7 +240,7 @@ WebIDL::ExceptionOr 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, node’s index plus 1). return set_start_or_end(*parent, node.index() + 1, StartOrEnd::End); @@ -254,11 +256,11 @@ WebIDL::ExceptionOr 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 this’s root is not the same as sourceRange’s 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 this_point_node; u32 this_point_offset = 0; @@ -339,7 +341,7 @@ WebIDL::ExceptionOr 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 node’s index. auto index = node.index(); @@ -381,7 +383,7 @@ WebIDL::ExceptionOr Range::select_node_contents(Node const& node) { // 1. If node is a doctype, throw an "InvalidNodeTypeError" DOMException. if (is(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 Range::is_point_in_range(Node const& node, u32 offset) // 2. If node is a doctype, then throw an "InvalidNodeTypeError" DOMException. if (is(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 node’s 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 Range::compare_point(Node const& node, u32 offset) cons { // 1. If node’s root is different from this’s 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(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 node’s 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> 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(*child)) - return WebIDL::HierarchyRequestError::create(global_object(), "Contained child is a DocumentType"); + return WebIDL::HierarchyRequestError::create(realm(), "Contained child is a DocumentType"); } JS::GCPtr new_node; @@ -783,7 +785,7 @@ WebIDL::ExceptionOr Range::insert(JS::NonnullGCPtr node) if ((is(*m_start_container) || is(*m_start_container)) || (is(*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 Range::surround_contents(JS::NonnullGCPtr new_pa if (is(*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(*new_parent) || is(*new_parent) || is(*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> 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(*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: diff --git a/Userland/Libraries/LibWeb/DOM/Range.h b/Userland/Libraries/LibWeb/DOM/Range.h index 234c2bb810..2303ab4d15 100644 --- a/Userland/Libraries/LibWeb/DOM/Range.h +++ b/Userland/Libraries/LibWeb/DOM/Range.h @@ -19,10 +19,8 @@ public: static JS::NonnullGCPtr create(Document&); static JS::NonnullGCPtr create(HTML::Window&); static JS::NonnullGCPtr create(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset); - static JS::NonnullGCPtr create_with_global_object(HTML::Window&); + static JS::NonnullGCPtr 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& 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; diff --git a/Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp b/Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp index 052143aedd..339ba80f2b 100644 --- a/Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp +++ b/Userland/Libraries/LibWeb/DOM/StaticNodeList.cpp @@ -4,18 +4,18 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include -#include namespace Web::DOM { -JS::NonnullGCPtr StaticNodeList::create(HTML::Window& window, Vector> static_nodes) +JS::NonnullGCPtr StaticNodeList::create(JS::Realm& realm, Vector> static_nodes) { - return *window.heap().allocate(window.realm(), window, move(static_nodes)); + return *realm.heap().allocate(realm, realm, move(static_nodes)); } -StaticNodeList::StaticNodeList(HTML::Window& window, Vector> static_nodes) - : NodeList(window) +StaticNodeList::StaticNodeList(JS::Realm& realm, Vector> static_nodes) + : NodeList(realm) { for (auto& node : static_nodes) m_static_nodes.append(*node); diff --git a/Userland/Libraries/LibWeb/DOM/StaticNodeList.h b/Userland/Libraries/LibWeb/DOM/StaticNodeList.h index 842d03a8f9..d5ef8f896e 100644 --- a/Userland/Libraries/LibWeb/DOM/StaticNodeList.h +++ b/Userland/Libraries/LibWeb/DOM/StaticNodeList.h @@ -16,7 +16,7 @@ class StaticNodeList final : public NodeList { WEB_PLATFORM_OBJECT(StaticNodeList, NodeList); public: - static JS::NonnullGCPtr create(HTML::Window&, Vector>); + static JS::NonnullGCPtr create(JS::Realm&, Vector>); virtual ~StaticNodeList() override; @@ -26,7 +26,7 @@ public: virtual bool is_supported_property_index(u32) const override; private: - StaticNodeList(HTML::Window&, Vector>); + StaticNodeList(JS::Realm&, Vector>); virtual void visit_edges(Cell::Visitor&) override; diff --git a/Userland/Libraries/LibWeb/DOM/StaticRange.cpp b/Userland/Libraries/LibWeb/DOM/StaticRange.cpp index 68c0ada312..7cd142ff73 100644 --- a/Userland/Libraries/LibWeb/DOM/StaticRange.cpp +++ b/Userland/Libraries/LibWeb/DOM/StaticRange.cpp @@ -6,8 +6,8 @@ */ #include +#include #include -#include #include #include #include @@ -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::create_with_global_object(HTML::Window& window, StaticRangeInit& init) +WebIDL::ExceptionOr 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(*init.start_container) || is(*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(*init.end_container) || is(*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 this’s start to (init["startContainer"], init["startOffset"]) and end to (init["endContainer"], init["endOffset"]). - return window.heap().allocate(window.realm(), *init.start_container, init.start_offset, *init.end_container, init.end_offset); + return realm.heap().allocate(realm, *init.start_container, init.start_offset, *init.end_container, init.end_offset); } } diff --git a/Userland/Libraries/LibWeb/DOM/StaticRange.h b/Userland/Libraries/LibWeb/DOM/StaticRange.h index ec98ba31b0..e26f58701b 100644 --- a/Userland/Libraries/LibWeb/DOM/StaticRange.h +++ b/Userland/Libraries/LibWeb/DOM/StaticRange.h @@ -24,7 +24,7 @@ class StaticRange final : public AbstractRange { WEB_PLATFORM_OBJECT(StaticRange, JS::Object); public: - static WebIDL::ExceptionOr create_with_global_object(HTML::Window&, StaticRangeInit& init); + static WebIDL::ExceptionOr construct_impl(JS::Realm&, StaticRangeInit& init); StaticRange(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset); virtual ~StaticRange() override; diff --git a/Userland/Libraries/LibWeb/DOM/Text.cpp b/Userland/Libraries/LibWeb/DOM/Text.cpp index afc7c773b1..1002e664c9 100644 --- a/Userland/Libraries/LibWeb/DOM/Text.cpp +++ b/Userland/Libraries/LibWeb/DOM/Text.cpp @@ -4,9 +4,11 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include +#include #include #include @@ -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::create_with_global_object(HTML::Window& window, String const& data) +JS::NonnullGCPtr Text::construct_impl(JS::Realm& realm, String const& data) { - return *window.heap().allocate(window.realm(), window.associated_document(), data); + // The new Text(data) constructor steps are to set this’s data to data and this’s node document to current global object’s associated Document. + auto& window = verify_cast(HTML::current_global_object()); + return *realm.heap().allocate(realm, window.associated_document(), data); } void Text::set_owner_input_element(Badge, HTML::HTMLInputElement& input_element) @@ -50,7 +54,7 @@ WebIDL::ExceptionOr> 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; diff --git a/Userland/Libraries/LibWeb/DOM/Text.h b/Userland/Libraries/LibWeb/DOM/Text.h index 7980275c72..59a43a0cbf 100644 --- a/Userland/Libraries/LibWeb/DOM/Text.h +++ b/Userland/Libraries/LibWeb/DOM/Text.h @@ -18,7 +18,7 @@ class Text : public CharacterData { public: virtual ~Text() override = default; - static JS::NonnullGCPtr create_with_global_object(HTML::Window& window, String const& data); + static JS::NonnullGCPtr construct_impl(JS::Realm& window, String const& data); // ^Node virtual FlyString node_name() const override { return "#text"; } @@ -32,7 +32,7 @@ public: WebIDL::ExceptionOr> 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; diff --git a/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp b/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp index e01b6bd678..1f7edb50e1 100644 --- a/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp +++ b/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp @@ -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 TreeWalker::filter(Node& node) { // 1. If traverser’s 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 node’s nodeType attribute value − 1. auto n = node.node_type() - 1; diff --git a/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp b/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp index bacbcf35dd..1210f241ae 100644 --- a/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp +++ b/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.cpp b/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.cpp index 7dfe2a0987..80f431aaeb 100644 --- a/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.cpp +++ b/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.cpp @@ -20,15 +20,15 @@ namespace Web::DOMParsing { -JS::NonnullGCPtr XMLSerializer::create_with_global_object(HTML::Window& window) +JS::NonnullGCPtr XMLSerializer::construct_impl(JS::Realm& realm) { - return *window.heap().allocate(window.realm(), window); + return *realm.heap().allocate(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 serialize_element_attributes(DOM::Element const& element, HashMap>& namespace_prefix_map, u64& prefix_index, HashMap 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 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 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 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 serialize_element_attributes(DOM::Element con // https://w3c.github.io/DOM-Parsing/#xml-serializing-an-element-node static WebIDL::ExceptionOr serialize_element(DOM::Element const& element, Optional& namespace_, HashMap>& 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 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 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 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 "". @@ -788,7 +788,7 @@ static WebIDL::ExceptionOr 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 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: diff --git a/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.h b/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.h index be14dbe6c3..28748f3f19 100644 --- a/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.h +++ b/Userland/Libraries/LibWeb/DOMParsing/XMLSerializer.h @@ -14,14 +14,14 @@ class XMLSerializer final : public Bindings::PlatformObject { WEB_PLATFORM_OBJECT(XMLSerializer, Bindings::PlatformObject); public: - static JS::NonnullGCPtr create_with_global_object(HTML::Window&); + static JS::NonnullGCPtr construct_impl(JS::Realm&); virtual ~XMLSerializer() override; WebIDL::ExceptionOr serialize_to_string(JS::NonnullGCPtr root); private: - explicit XMLSerializer(HTML::Window&); + explicit XMLSerializer(JS::Realm&); }; enum class RequireWellFormed { diff --git a/Userland/Libraries/LibWeb/HTML/MessagePort.cpp b/Userland/Libraries/LibWeb/HTML/MessagePort.cpp index 7774931e9c..437a382ff7 100644 --- a/Userland/Libraries/LibWeb/HTML/MessagePort.cpp +++ b/Userland/Libraries/LibWeb/HTML/MessagePort.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace Web::HTML { diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h index c2f34b1466..dbb1377dc6 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h +++ b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include diff --git a/Userland/Libraries/LibWeb/WebIDL/DOMException.cpp b/Userland/Libraries/LibWeb/WebIDL/DOMException.cpp index d263398446..8553fda7f5 100644 --- a/Userland/Libraries/LibWeb/WebIDL/DOMException.cpp +++ b/Userland/Libraries/LibWeb/WebIDL/DOMException.cpp @@ -4,29 +4,27 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include namespace Web::WebIDL { -JS::NonnullGCPtr DOMException::create(JS::Object& global_object, FlyString const& name, FlyString const& message) +JS::NonnullGCPtr DOMException::create(JS::Realm& realm, FlyString const& name, FlyString const& message) { - auto& window = verify_cast(global_object); - return *window.heap().allocate(window.realm(), window, name, message); + return *realm.heap().allocate(realm, realm, name, message); } -JS::NonnullGCPtr DOMException::create_with_global_object(JS::Object& global_object, FlyString const& message, FlyString const& name) +JS::NonnullGCPtr DOMException::construct_impl(JS::Realm& realm, FlyString const& message, FlyString const& name) { - auto& window = verify_cast(global_object); - return *window.heap().allocate(window.realm(), window, name, message); + return *realm.heap().allocate(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; diff --git a/Userland/Libraries/LibWeb/WebIDL/DOMException.h b/Userland/Libraries/LibWeb/WebIDL/DOMException.h index 17742491f1..4189e93bc1 100644 --- a/Userland/Libraries/LibWeb/WebIDL/DOMException.h +++ b/Userland/Libraries/LibWeb/WebIDL/DOMException.h @@ -9,17 +9,18 @@ #include #include #include +#include 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 create(JS::Object& global_object, FlyString const& name, FlyString const& message); + static JS::NonnullGCPtr 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 create_with_global_object(JS::Object& global_object, FlyString const& message, FlyString const& name); - - static JS::NonnullGCPtr create(JS::Realm& realm, FlyString const& message); + static JS::NonnullGCPtr 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 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 create(JS::Realm& realm, FlyString const& message) \ + { \ + return DOMException::create(realm, #ErrorName, message); \ + } \ + static JS::NonnullGCPtr create(JS::Object const& global_object, FlyString const& message) \ + { \ + return create(HTML::relevant_realm(global_object), message); \ + } \ }; ENUMERATE_DOM_EXCEPTION_ERROR_NAMES #undef __ENUMERATE