diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index c908719eb6..d5393b0410 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -264,6 +264,7 @@ set(SOURCES HTML/HTMLDialogElement.cpp HTML/HTMLDirectoryElement.cpp HTML/HTMLDivElement.cpp + HTML/HTMLDocument.cpp HTML/HTMLElement.cpp HTML/HTMLEmbedElement.cpp HTML/HTMLFieldSetElement.cpp diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index e3154c4dd3..c413a7b309 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -243,7 +244,7 @@ WebIDL::ExceptionOr> Document::create_and_initialize( // 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 = TRY(Document::create(window->realm())); + auto document = TRY(HTML::HTMLDocument::create(window->realm())); document->m_type = type; document->m_content_type = move(content_type); document->set_origin(navigation_params.origin); @@ -2658,7 +2659,7 @@ JS::NonnullGCPtr Document::appropriate_template_contents_owner_do // 1. If doc does not yet have an associated inert template document, then: if (!m_associated_inert_template_document) { // 1. Let new doc be a new Document (whose browsing context is null). This is "a Document created by this algorithm" for the purposes of the step above. - auto new_document = DOM::Document::create(realm()).release_value_but_fixme_should_propagate_errors(); + auto new_document = HTML::HTMLDocument::create(realm()).release_value_but_fixme_should_propagate_errors(); new_document->m_created_for_appropriate_template_contents = true; // 2. If doc is an HTML document, mark new doc as an HTML document also. diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp index b1e1b6d8dc..2b370ea4de 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -203,7 +204,7 @@ JS::NonnullGCPtr BrowsingContext::create_a_new_browsing_context // load timing info is loadTimingInfo, // FIXME: navigation id is null, // and which is ready for post-load tasks. - auto document = DOM::Document::create(window->realm()).release_value_but_fixme_should_propagate_errors(); + auto document = HTML::HTMLDocument::create(window->realm()).release_value_but_fixme_should_propagate_errors(); // Non-standard document->set_window(*window); @@ -361,7 +362,7 @@ WebIDL::ExceptionOr BrowsingContext verify_cast(Bindings::host_defined_environment_settings_object(window->realm())).cross_origin_isolated_capability() == CanUseCrossOriginIsolatedAPIs::Yes); // 14. Let document be a new Document, with: - auto document = TRY(DOM::Document::create(window->realm())); + auto document = TRY(HTML::HTMLDocument::create(window->realm())); // Non-standard document->set_window(*window); diff --git a/Userland/Libraries/LibWeb/HTML/DOMParser.cpp b/Userland/Libraries/LibWeb/HTML/DOMParser.cpp index 9f4c655038..e107866e6c 100644 --- a/Userland/Libraries/LibWeb/HTML/DOMParser.cpp +++ b/Userland/Libraries/LibWeb/HTML/DOMParser.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -37,13 +38,14 @@ JS::ThrowCompletionOr DOMParser::initialize(JS::Realm& realm) JS::NonnullGCPtr DOMParser::parse_from_string(DeprecatedString const& string, Bindings::DOMParserSupportedType type) { // 1. Let document be a new Document, whose content type is type and url is this's relevant global object's associated Document's URL. - auto document = DOM::Document::create(realm(), verify_cast(relevant_global_object(*this)).associated_document().url()).release_value_but_fixme_should_propagate_errors(); - document->set_content_type(Bindings::idl_enum_to_deprecated_string(type)); + JS::GCPtr document; // 2. Switch on type: if (type == Bindings::DOMParserSupportedType::Text_Html) { // -> "text/html" // 1. Set document's type to "html". + document = HTML::HTMLDocument::create(realm(), verify_cast(relevant_global_object(*this)).associated_document().url()).release_value_but_fixme_should_propagate_errors(); + document->set_content_type(Bindings::idl_enum_to_deprecated_string(type)); document->set_document_type(DOM::Document::Type::HTML); // 2. Create an HTML parser parser, associated with document. @@ -56,6 +58,8 @@ JS::NonnullGCPtr DOMParser::parse_from_string(DeprecatedString co parser->run("about:blank"sv); } else { // -> Otherwise + document = DOM::Document::create(realm(), verify_cast(relevant_global_object(*this)).associated_document().url()).release_value_but_fixme_should_propagate_errors(); + document->set_content_type(Bindings::idl_enum_to_deprecated_string(type)); // 1. Create an XML parser parse, associated with document, and with XML scripting support disabled. XML::Parser parser(string, { .resolve_external_resource = resolve_xml_resource }); @@ -76,7 +80,7 @@ JS::NonnullGCPtr DOMParser::parse_from_string(DeprecatedString co } // 3. Return document. - return document; + return *document; } } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDocument.cpp b/Userland/Libraries/LibWeb/HTML/HTMLDocument.cpp new file mode 100644 index 0000000000..4c862a7e83 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/HTMLDocument.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Web::HTML { + +HTMLDocument::HTMLDocument(JS::Realm& realm, AK::URL const& url) + : Document(realm, url) +{ +} + +HTMLDocument::~HTMLDocument() = default; + +WebIDL::ExceptionOr> HTMLDocument::construct_impl(JS::Realm& realm) +{ + return HTMLDocument::create(realm); +} + +WebIDL::ExceptionOr> HTMLDocument::create(JS::Realm& realm, AK::URL const& url) +{ + return MUST_OR_THROW_OOM(realm.heap().allocate(realm, realm, url)); +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDocument.h b/Userland/Libraries/LibWeb/HTML/HTMLDocument.h new file mode 100644 index 0000000000..45bf05324e --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/HTMLDocument.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::HTML { + +// NOTE: This class is not currently in the specifications but it *is* implemented by all major browsers. +// There is discussion about bringing it back: +// https://github.com/whatwg/html/issues/4792 +// https://github.com/whatwg/dom/issues/221 +class HTMLDocument final : public DOM::Document { + JS_CELL(HTMLDocument, DOM::Document); + +public: + virtual ~HTMLDocument() override; + + static WebIDL::ExceptionOr> create(JS::Realm&, AK::URL const& url = "about:blank"sv); + WebIDL::ExceptionOr> construct_impl(JS::Realm&); + +private: + HTMLDocument(JS::Realm&, AK::URL const&); +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDocument.idl b/Userland/Libraries/LibWeb/HTML/HTMLDocument.idl new file mode 100644 index 0000000000..8d6cd7fafa --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/HTMLDocument.idl @@ -0,0 +1,6 @@ +#import + +[Exposed=Window] +interface HTMLDocument : Document { +}; + diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index d6a58a010f..73f6466de8 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -96,6 +96,7 @@ libweb_js_bindings(HTML/HTMLDetailsElement) libweb_js_bindings(HTML/HTMLDialogElement) libweb_js_bindings(HTML/HTMLDirectoryElement) libweb_js_bindings(HTML/HTMLDivElement) +libweb_js_bindings(HTML/HTMLDocument) libweb_js_bindings(HTML/HTMLDListElement) libweb_js_bindings(HTML/HTMLElement) libweb_js_bindings(HTML/HTMLEmbedElement)