Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions Libraries/LibWeb/DOM/Attr.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2021, Tim Flynn <[email protected]>
* Copyright (c) 2023, Luke Wilde <[email protected]>
* Copyright (c) 2025, Miguel Sacristán Izcue <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
Expand All @@ -13,6 +14,7 @@
#include <LibWeb/DOM/MutationType.h>
#include <LibWeb/DOM/StaticNodeList.h>
#include <LibWeb/HTML/CustomElements/CustomElementReactionNames.h>
#include <LibWeb/TrustedTypes/TrustedTypePolicy.h>

namespace Web::DOM {

Expand Down Expand Up @@ -69,17 +71,43 @@ void Attr::set_owner_element(Element* owner_element)
m_owner_element = owner_element;
}

// https://dom.spec.whatwg.org/#set-an-existing-attribute-value
void Attr::set_value(String value)
// FIXME: Trusted Types integration with DOM is still under review https://github.com/whatwg/dom/pull/1268
// https://whatpr.org/dom/1268.html#set-an-existing-attribute-value
WebIDL::ExceptionOr<void> Attr::set_value(String value)
{
// 1. If attribute’s element is null, then set attribute’s value to value.
if (!owner_element()) {
m_value = move(value);
}
// 2. Otherwise, change attribute to value.
// 2. Otherwise:
else {
change_attribute(move(value));
// 1. Let element be attribute’s element.
auto const* element = owner_element();

// 2. Let verifiedValue be the result of calling get Trusted Types-compliant attribute value with
// attribute’s local name, attribute’s namespace, element, and value.
auto const verified_value = TRY(TrustedTypes::get_trusted_types_compliant_attribute_value(
local_name(),
namespace_uri().has_value() ? Utf16String::from_utf8(namespace_uri().value()) : Optional<Utf16String>(),
*element,
Utf16String::from_utf8(value)));

// 3. If attribute’s element is null, then set attribute’s value to verifiedValue, and return.
if (!owner_element()) {
m_value = verified_value.to_utf8_but_should_be_ported_to_utf16();
return {};
}

// 4. If attribute’s element is not element, then return.
if (owner_element() != element) {
return {};
}

// 5. Change attribute to verifiedValue.
change_attribute(verified_value.to_utf8_but_should_be_ported_to_utf16());
}

return {};
}

// https://dom.spec.whatwg.org/#concept-element-attributes-change
Expand Down
2 changes: 1 addition & 1 deletion Libraries/LibWeb/DOM/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class WEB_API Attr final : public Node {
FlyString const& lowercase_name() const { return m_lowercase_name; }

String const& value() const { return m_value; }
void set_value(String value);
WebIDL::ExceptionOr<void> set_value(String value);
void change_attribute(String value);

Element* owner_element();
Expand Down
56 changes: 41 additions & 15 deletions Libraries/LibWeb/DOM/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@
#include <LibWeb/SVG/SVGStyleElement.h>
#include <LibWeb/SVG/SVGTitleElement.h>
#include <LibWeb/Selection/Selection.h>
#include <LibWeb/TrustedTypes/RequireTrustedTypesForDirective.h>
#include <LibWeb/TrustedTypes/TrustedTypePolicy.h>
#include <LibWeb/UIEvents/CompositionEvent.h>
#include <LibWeb/UIEvents/EventNames.h>
#include <LibWeb/UIEvents/FocusEvent.h>
Expand Down Expand Up @@ -644,41 +646,56 @@ GC::Ptr<Selection::Selection> Document::get_selection() const
}

// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-write
WebIDL::ExceptionOr<void> Document::write(Vector<String> const& text)
WebIDL::ExceptionOr<void> Document::write(Vector<TrustedTypes::TrustedHTMLOrString> const& text)
{
// The document.write(...text) method steps are to run the document write steps with this, text, false, and "Document write".
return run_the_document_write_steps(text, AddLineFeed::No, TrustedTypes::InjectionSink::Documentwrite);
}

// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-writeln
WebIDL::ExceptionOr<void> Document::writeln(Vector<String> const& text)
WebIDL::ExceptionOr<void> Document::writeln(Vector<TrustedTypes::TrustedHTMLOrString> const& text)
{
// The document.writeln(...text) method steps are to run the document write steps with this, text, true, and "Document writeln".
return run_the_document_write_steps(text, AddLineFeed::Yes, TrustedTypes::InjectionSink::Documentwriteln);
}

// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#document-write-steps
WebIDL::ExceptionOr<void> Document::run_the_document_write_steps(Vector<String> const& text, AddLineFeed line_feed, TrustedTypes::InjectionSink sink)
WebIDL::ExceptionOr<void> Document::run_the_document_write_steps(Vector<TrustedTypes::TrustedHTMLOrString> const& text, AddLineFeed line_feed, TrustedTypes::InjectionSink sink)
{
// 1. Let string be the empty string.
StringBuilder string;

// 2. Let isTrusted be false if text contains a string; otherwise true.
// FIXME: We currently only accept strings. Revisit this once we support the TrustedHTML type.
auto is_trusted = true;
for (auto const& value : text) {
if (value.has<Utf16String>()) {
is_trusted = false;
break;
}
}

// 3. For each value of text:
for (auto const& value : text) {
// FIXME: 1. If value is a TrustedHTML object, then append value's associated data to string.

// 2. Otherwise, append value to string.
string.append(value);
string.append(value.visit(
// 1. If value is a TrustedHTML object, then append value's associated data to string.
[](GC::Root<TrustedTypes::TrustedHTML> const& value) { return value->to_string(); },
// 2. Otherwise, append value to string.
[](Utf16String const& value) { return value; })
.to_utf8_but_should_be_ported_to_utf16());
}

// FIXME: 4. If isTrusted is false, set string to the result of invoking the Get Trusted Type compliant string algorithm
// 4. If isTrusted is false, set string to the result of invoking the Get Trusted Type compliant string algorithm
// with TrustedHTML, this's relevant global object, string, sink, and "script".
(void)is_trusted;
(void)sink;
if (!is_trusted) {
auto const new_string = TRY(TrustedTypes::get_trusted_type_compliant_string(
TrustedTypes::TrustedTypeName::TrustedHTML,
relevant_global_object(*this),
Utf16String::from_utf8(MUST(string.to_string())),
sink,
TrustedTypes::Script.to_string()));
string.clear();
string.append(new_string.to_utf8_but_should_be_ported_to_utf16());
}

// 5. If lineFeed is true, append U+000A LINE FEED to string.
if (line_feed == AddLineFeed::Yes)
Expand Down Expand Up @@ -6345,10 +6362,19 @@ void Document::parse_html_from_a_string(StringView html)
}

// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-parsehtmlunsafe
GC::Ref<Document> Document::parse_html_unsafe(JS::VM& vm, StringView html)
WebIDL::ExceptionOr<GC::Root<DOM::Document>> Document::parse_html_unsafe(JS::VM& vm, TrustedTypes::TrustedHTMLOrString const& html)
{
auto& realm = *vm.current_realm();
// FIXME: 1. Let compliantHTML to the result of invoking the Get Trusted Type compliant string algorithm with TrustedHTML, this's relevant global object, html, "Document parseHTMLUnsafe", and "script".

// FIXME: update description once https://github.com/whatwg/html/issues/11778 gets solved
// 1. Let compliantHTML to the result of invoking the Get Trusted Type compliant string algorithm with
// TrustedHTML, this's relevant global object, html, "Document parseHTMLUnsafe", and "script".
auto const compliant_html = TRY(TrustedTypes::get_trusted_type_compliant_string(
TrustedTypes::TrustedTypeName::TrustedHTML,
HTML::current_principal_global_object(),
html,
TrustedTypes::InjectionSink::DocumentparseHTMLUnsafe,
TrustedTypes::Script.to_string()));

// 2. Let document be a new Document, whose content type is "text/html".
auto document = Document::create_for_fragment_parsing(realm);
Expand All @@ -6357,8 +6383,8 @@ GC::Ref<Document> Document::parse_html_unsafe(JS::VM& vm, StringView html)
// 3. Set document's allow declarative shadow roots to true.
document->set_allow_declarative_shadow_roots(true);

// 4. Parse HTML from a string given document and compliantHTML. // FIXME: Use compliantHTML.
document->parse_html_from_a_string(html);
// 4. Parse HTML from a string given document and compliantHTML.
document->parse_html_from_a_string(compliant_html.to_utf8_but_should_be_ported_to_utf16());

// AD-HOC: Setting the origin to match that of the associated document matches the behavior of existing browsers.
auto& associated_document = as<HTML::Window>(realm.global_object()).associated_document();
Expand Down
8 changes: 4 additions & 4 deletions Libraries/LibWeb/DOM/Document.h
Original file line number Diff line number Diff line change
Expand Up @@ -472,8 +472,8 @@ class WEB_API Document

void set_window(HTML::Window&);

WebIDL::ExceptionOr<void> write(Vector<String> const& strings);
WebIDL::ExceptionOr<void> writeln(Vector<String> const& strings);
WebIDL::ExceptionOr<void> write(Vector<TrustedTypes::TrustedHTMLOrString> const& text);
WebIDL::ExceptionOr<void> writeln(Vector<TrustedTypes::TrustedHTMLOrString> const& text);

WebIDL::ExceptionOr<Document*> open(Optional<String> const& = {}, Optional<String> const& = {});
WebIDL::ExceptionOr<GC::Ptr<HTML::WindowProxy>> open(StringView url, StringView name, StringView features);
Expand Down Expand Up @@ -828,7 +828,7 @@ class WEB_API Document
Vector<GC::Root<Range>> find_matching_text(String const&, CaseSensitivity);

void parse_html_from_a_string(StringView);
static GC::Ref<Document> parse_html_unsafe(JS::VM&, StringView);
static WebIDL::ExceptionOr<GC::Root<DOM::Document>> parse_html_unsafe(JS::VM&, TrustedTypes::TrustedHTMLOrString const&);

void set_console_client(GC::Ptr<JS::ConsoleClient> console_client) { m_console_client = console_client; }
GC::Ptr<JS::ConsoleClient> console_client() const { return m_console_client; }
Expand Down Expand Up @@ -972,7 +972,7 @@ class WEB_API Document
Yes,
No,
};
WebIDL::ExceptionOr<void> run_the_document_write_steps(Vector<String> const& text, AddLineFeed line_feed, TrustedTypes::InjectionSink sink);
WebIDL::ExceptionOr<void> run_the_document_write_steps(Vector<TrustedTypes::TrustedHTMLOrString> const& text, AddLineFeed line_feed, TrustedTypes::InjectionSink sink);

void queue_intersection_observer_task();
void queue_an_intersection_observer_entry(IntersectionObserver::IntersectionObserver&, HighResolutionTime::DOMHighResTimeStamp time, GC::Ref<Geometry::DOMRectReadOnly> root_bounds, GC::Ref<Geometry::DOMRectReadOnly> bounding_client_rect, GC::Ref<Geometry::DOMRectReadOnly> intersection_rect, bool is_intersecting, double intersection_ratio, GC::Ref<Element> target);
Expand Down
10 changes: 4 additions & 6 deletions Libraries/LibWeb/DOM/Document.idl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#import <HTML/HTMLScriptElement.idl>
#import <HTML/Location.idl>
#import <Selection/Selection.idl>
#import <TrustedTypes/TrustedHTML.idl>
#import <ViewTransition/ViewTransition.idl>
#import <XPath/XPathResult.idl>
#import <XPath/XPathExpression.idl>
Expand Down Expand Up @@ -56,13 +57,10 @@ interface Document : Node {
[CEReactions] Document open(optional DOMString unused1, optional DOMString unused2);
WindowProxy? open(USVString url, DOMString name, DOMString features);
[CEReactions] undefined close();
// FIXME: [CEReactions] undefined write((TrustedHTML or DOMString)... text);
[CEReactions] undefined write(DOMString... text);
// FIXME: [CEReactions] undefined writeln((TrustedHTML or DOMString)... text);
[CEReactions] undefined writeln(DOMString... text);
[CEReactions] undefined write((TrustedHTML or Utf16DOMString)... text);
[CEReactions] undefined writeln((TrustedHTML or Utf16DOMString)... text);

// FIXME: static Document parseHTMLUnsafe((TrustedHTML or DOMString) html);
static Document parseHTMLUnsafe(DOMString html);
static Document parseHTMLUnsafe((TrustedHTML or Utf16DOMString) html);

attribute DOMString cookie;

Expand Down
4 changes: 2 additions & 2 deletions Libraries/LibWeb/DOM/DocumentLoading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ static WebIDL::ExceptionOr<GC::Ref<DOM::Document>> load_media_document(HTML::Nav
};

auto style_element = TRY(DOM::create_element(document, HTML::TagNames::style, Namespace::HTML));
style_element->set_text_content(R"~~~(
MUST(style_element->set_text_content(R"~~~(
:root {
background-color: #222;
}
Expand All @@ -310,7 +310,7 @@ static WebIDL::ExceptionOr<GC::Ref<DOM::Document>> load_media_document(HTML::Nav
img {
background-color: #fff;
}
)~~~"_utf16);
)~~~"_utf16));
TRY(document->head()->append_child(style_element));

auto url_string = document->url_string();
Expand Down
Loading
Loading