1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 04:58:13 +00:00

LibWeb: Add HTMLDocument class

This class is currently not in the spec, but it *is* still in all the
major browser engines. For compatibility reasons, let's do what other
engines do.

There is discussion about bringing HTMLDocument back into specs:
- https://github.com/whatwg/html/issues/4792
- https://github.com/whatwg/dom/issues/221
This commit is contained in:
Andreas Kling 2023-06-21 13:53:09 +02:00
parent 40e7f64433
commit 8f927eaa68
8 changed files with 79 additions and 7 deletions

View file

@ -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

View file

@ -49,6 +49,7 @@
#include <LibWeb/HTML/HTMLAreaElement.h>
#include <LibWeb/HTML/HTMLBaseElement.h>
#include <LibWeb/HTML/HTMLBodyElement.h>
#include <LibWeb/HTML/HTMLDocument.h>
#include <LibWeb/HTML/HTMLEmbedElement.h>
#include <LibWeb/HTML/HTMLFormElement.h>
#include <LibWeb/HTML/HTMLFrameSetElement.h>
@ -243,7 +244,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Document>> 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<DOM::Document> 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.

View file

@ -16,6 +16,7 @@
#include <LibWeb/HTML/CrossOrigin/CrossOriginOpenerPolicy.h>
#include <LibWeb/HTML/EventLoop/EventLoop.h>
#include <LibWeb/HTML/HTMLAnchorElement.h>
#include <LibWeb/HTML/HTMLDocument.h>
#include <LibWeb/HTML/HTMLInputElement.h>
#include <LibWeb/HTML/NavigableContainer.h>
#include <LibWeb/HTML/RemoteBrowsingContext.h>
@ -203,7 +204,7 @@ JS::NonnullGCPtr<BrowsingContext> 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::BrowsingContextAndDocument> BrowsingContext
verify_cast<WindowEnvironmentSettingsObject>(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);

View file

@ -7,6 +7,7 @@
#include <LibWeb/Bindings/DOMParserPrototype.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/HTML/DOMParser.h>
#include <LibWeb/HTML/HTMLDocument.h>
#include <LibWeb/HTML/Parser/HTMLParser.h>
#include <LibWeb/HTML/Scripting/Environments.h>
#include <LibWeb/XML/XMLDocumentBuilder.h>
@ -37,13 +38,14 @@ JS::ThrowCompletionOr<void> DOMParser::initialize(JS::Realm& realm)
JS::NonnullGCPtr<DOM::Document> 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<HTML::Window>(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<DOM::Document> 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<HTML::Window>(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<DOM::Document> DOMParser::parse_from_string(DeprecatedString co
parser->run("about:blank"sv);
} else {
// -> Otherwise
document = DOM::Document::create(realm(), verify_cast<HTML::Window>(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<DOM::Document> DOMParser::parse_from_string(DeprecatedString co
}
// 3. Return document.
return document;
return *document;
}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/HTML/HTMLDocument.h>
namespace Web::HTML {
HTMLDocument::HTMLDocument(JS::Realm& realm, AK::URL const& url)
: Document(realm, url)
{
}
HTMLDocument::~HTMLDocument() = default;
WebIDL::ExceptionOr<JS::NonnullGCPtr<HTMLDocument>> HTMLDocument::construct_impl(JS::Realm& realm)
{
return HTMLDocument::create(realm);
}
WebIDL::ExceptionOr<JS::NonnullGCPtr<HTMLDocument>> HTMLDocument::create(JS::Realm& realm, AK::URL const& url)
{
return MUST_OR_THROW_OOM(realm.heap().allocate<HTMLDocument>(realm, realm, url));
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/DOM/Document.h>
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<JS::NonnullGCPtr<HTMLDocument>> create(JS::Realm&, AK::URL const& url = "about:blank"sv);
WebIDL::ExceptionOr<JS::NonnullGCPtr<HTMLDocument>> construct_impl(JS::Realm&);
private:
HTMLDocument(JS::Realm&, AK::URL const&);
};
}

View file

@ -0,0 +1,6 @@
#import <DOM/Document.idl>
[Exposed=Window]
interface HTMLDocument : Document {
};

View file

@ -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)