diff --git a/Libraries/LibWeb/CSS/MediaList.cpp b/Libraries/LibWeb/CSS/MediaList.cpp index 394b44f2faa..2bce5d162f7 100644 --- a/Libraries/LibWeb/CSS/MediaList.cpp +++ b/Libraries/LibWeb/CSS/MediaList.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,12 @@ void MediaList::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(MediaList); } +void MediaList::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_associated_style_sheet); +} + // https://www.w3.org/TR/cssom-1/#dom-medialist-mediatext String MediaList::media_text() const { @@ -42,6 +49,11 @@ String MediaList::media_text() const // https://www.w3.org/TR/cssom-1/#dom-medialist-mediatext void MediaList::set_media_text(StringView text) { + ScopeGuard guard = [&] { + if (m_associated_style_sheet) + as(*m_associated_style_sheet).invalidate_owners(DOM::StyleInvalidationReason::MediaListSetMediaText); + }; + m_media.clear(); if (text.is_empty()) return; @@ -76,6 +88,9 @@ void MediaList::append_medium(StringView medium) // 4. Append m to the collection of media queries. m_media.append(m.release_nonnull()); + + if (m_associated_style_sheet) + as(*m_associated_style_sheet).invalidate_owners(DOM::StyleInvalidationReason::MediaListAppendMedium); } // https://www.w3.org/TR/cssom-1/#dom-medialist-deletemedium @@ -84,9 +99,13 @@ void MediaList::delete_medium(StringView medium) auto m = parse_media_query(Parser::ParsingParams { realm() }, medium); if (!m) return; - m_media.remove_all_matching([&](auto& existing) -> bool { + bool was_removed = m_media.remove_all_matching([&](auto& existing) -> bool { return m->to_string() == existing->to_string(); }); + if (was_removed) { + if (m_associated_style_sheet) + as(*m_associated_style_sheet).invalidate_owners(DOM::StyleInvalidationReason::MediaListDeleteMedium); + } // FIXME: If nothing was removed, then throw a NotFoundError exception. } diff --git a/Libraries/LibWeb/CSS/MediaList.h b/Libraries/LibWeb/CSS/MediaList.h index 48365abc519..b7bcdf06692 100644 --- a/Libraries/LibWeb/CSS/MediaList.h +++ b/Libraries/LibWeb/CSS/MediaList.h @@ -36,11 +36,15 @@ public: bool evaluate(HTML::Window const&); bool matches() const; + void set_associated_style_sheet(GC::Ref style_sheet) { m_associated_style_sheet = style_sheet; } + private: MediaList(JS::Realm&, Vector>&&); virtual void initialize(JS::Realm&) override; + virtual void visit_edges(Visitor&) override; + GC::Ptr m_associated_style_sheet; Vector> m_media; }; diff --git a/Libraries/LibWeb/CSS/StyleSheet.cpp b/Libraries/LibWeb/CSS/StyleSheet.cpp index aed8c04b784..2d908e00c15 100644 --- a/Libraries/LibWeb/CSS/StyleSheet.cpp +++ b/Libraries/LibWeb/CSS/StyleSheet.cpp @@ -16,6 +16,7 @@ StyleSheet::StyleSheet(JS::Realm& realm, MediaList& media) : PlatformObject(realm) , m_media(media) { + m_media->set_associated_style_sheet(*this); } void StyleSheet::visit_edges(Cell::Visitor& visitor) diff --git a/Libraries/LibWeb/DOM/Node.h b/Libraries/LibWeb/DOM/Node.h index e1e7874db70..c5d6c48d879 100644 --- a/Libraries/LibWeb/DOM/Node.h +++ b/Libraries/LibWeb/DOM/Node.h @@ -68,6 +68,9 @@ enum class ShouldComputeRole { X(HTMLOptionElementSelectedChange) \ X(HTMLSelectElementSetIsOpen) \ X(Hover) \ + X(MediaListSetMediaText) \ + X(MediaListAppendMedium) \ + X(MediaListDeleteMedium) \ X(MediaQueryChangedMatchState) \ X(NavigableSetViewportSize) \ X(NodeInsertBefore) \ diff --git a/Libraries/LibWeb/HTML/HTMLLinkElement.cpp b/Libraries/LibWeb/HTML/HTMLLinkElement.cpp index 435787982d4..35a6c68a240 100644 --- a/Libraries/LibWeb/HTML/HTMLLinkElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLLinkElement.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -125,6 +126,18 @@ GC::Ref HTMLLinkElement::sizes() return *m_sizes; } +void HTMLLinkElement::set_media(String media) +{ + (void)set_attribute(HTML::AttributeNames::media, media); + if (auto sheet = m_loaded_style_sheet) + sheet->set_media(media); +} + +String HTMLLinkElement::media() const +{ + return attribute(HTML::AttributeNames::media).value_or(String {}); +} + bool HTMLLinkElement::has_loaded_icon() const { return m_relationship & Relationship::Icon && resource() && resource()->is_loaded() && resource()->has_encoded_data(); diff --git a/Libraries/LibWeb/HTML/HTMLLinkElement.h b/Libraries/LibWeb/HTML/HTMLLinkElement.h index 675e712585c..ca13885a51a 100644 --- a/Libraries/LibWeb/HTML/HTMLLinkElement.h +++ b/Libraries/LibWeb/HTML/HTMLLinkElement.h @@ -45,6 +45,9 @@ public: void set_parser_document(Badge, GC::Ref); + void set_media(String); + String media() const; + private: HTMLLinkElement(DOM::Document&, DOM::QualifiedName); diff --git a/Libraries/LibWeb/HTML/HTMLLinkElement.idl b/Libraries/LibWeb/HTML/HTMLLinkElement.idl index 05fc7800ec0..71d12a6af6e 100644 --- a/Libraries/LibWeb/HTML/HTMLLinkElement.idl +++ b/Libraries/LibWeb/HTML/HTMLLinkElement.idl @@ -42,7 +42,7 @@ interface HTMLLinkElement : HTMLElement { [CEReactions, Reflect] attribute DOMString rel; [CEReactions, Reflect, Enumerated=PotentialDestination] attribute DOMString as; [SameObject, PutForwards=value] readonly attribute DOMTokenList relList; - [CEReactions, Reflect] attribute DOMString media; + [CEReactions] attribute DOMString media; [CEReactions, Reflect] attribute DOMString integrity; [CEReactions, Reflect] attribute DOMString hreflang; [CEReactions, Reflect] attribute DOMString type; diff --git a/Libraries/LibWeb/HTML/HTMLStyleElement.cpp b/Libraries/LibWeb/HTML/HTMLStyleElement.cpp index 2763b6e2c64..7a33feb92fe 100644 --- a/Libraries/LibWeb/HTML/HTMLStyleElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLStyleElement.cpp @@ -7,6 +7,8 @@ */ #include +#include +#include #include namespace Web::HTML { @@ -77,6 +79,18 @@ void HTMLStyleElement::set_disabled(bool disabled) sheet()->set_disabled(disabled); } +String HTMLStyleElement::media() const +{ + return attribute(HTML::AttributeNames::media).value_or(String {}); +} + +void HTMLStyleElement::set_media(String media) +{ + (void)set_attribute(HTML::AttributeNames::media, media); + if (auto sheet = m_style_element_utils.sheet()) + sheet->set_media(media); +} + // https://www.w3.org/TR/cssom/#dom-linkstyle-sheet CSS::CSSStyleSheet* HTMLStyleElement::sheet() { diff --git a/Libraries/LibWeb/HTML/HTMLStyleElement.h b/Libraries/LibWeb/HTML/HTMLStyleElement.h index 314541ddcbe..ab159ca83a7 100644 --- a/Libraries/LibWeb/HTML/HTMLStyleElement.h +++ b/Libraries/LibWeb/HTML/HTMLStyleElement.h @@ -26,6 +26,9 @@ public: bool disabled(); void set_disabled(bool disabled); + [[nodiscard]] String media() const; + void set_media(String); + CSS::CSSStyleSheet* sheet(); CSS::CSSStyleSheet const* sheet() const; diff --git a/Libraries/LibWeb/HTML/HTMLStyleElement.idl b/Libraries/LibWeb/HTML/HTMLStyleElement.idl index 2ff7d2de755..9ffe4fd69ac 100644 --- a/Libraries/LibWeb/HTML/HTMLStyleElement.idl +++ b/Libraries/LibWeb/HTML/HTMLStyleElement.idl @@ -8,7 +8,7 @@ interface HTMLStyleElement : HTMLElement { [HTMLConstructor] constructor(); attribute boolean disabled; - [Reflect, CEReactions] attribute DOMString media; + [CEReactions] attribute DOMString media; [FIXME, SameObject, PutForwards=value] readonly attribute DOMTokenList blocking; // Obsolete diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/semantics/document-metadata/the-style-element/style_media.txt b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/document-metadata/the-style-element/style_media.txt new file mode 100644 index 00000000000..f6dd1d553d9 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/document-metadata/the-style-element/style_media.txt @@ -0,0 +1,6 @@ +Harness status: OK + +Found 1 tests + +1 Pass +Pass The style information must be applied to the environment specified by the media attribute \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/html/semantics/document-metadata/the-style-element/style_media.html b/Tests/LibWeb/Text/input/wpt-import/html/semantics/document-metadata/the-style-element/style_media.html new file mode 100644 index 00000000000..0c70586aaea --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/html/semantics/document-metadata/the-style-element/style_media.html @@ -0,0 +1,40 @@ + + + + + HTML Test: The style information must be applied to the environment specified by the media attribute + + + + + + + + + +
+
+ + +