mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-20 11:36:10 +00:00
LibWeb: Invalidate style (and rule cache) on MediaList changes
This makes dynamic changes to a style sheet's media attribute actually take effect immediately.
This commit is contained in:
parent
80c0a16597
commit
6606eecce5
Notes:
github-actions[bot]
2025-03-04 18:08:34 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/6606eecce51 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3798
12 changed files with 109 additions and 3 deletions
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/Bindings/MediaListPrototype.h>
|
||||
#include <LibWeb/CSS/CSSStyleSheet.h>
|
||||
#include <LibWeb/CSS/MediaList.h>
|
||||
#include <LibWeb/CSS/Parser/Parser.h>
|
||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||
|
@ -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<CSS::CSSStyleSheet>(*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<CSS::CSSStyleSheet>(*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<CSS::CSSStyleSheet>(*m_associated_style_sheet).invalidate_owners(DOM::StyleInvalidationReason::MediaListDeleteMedium);
|
||||
}
|
||||
// FIXME: If nothing was removed, then throw a NotFoundError exception.
|
||||
}
|
||||
|
||||
|
|
|
@ -36,11 +36,15 @@ public:
|
|||
bool evaluate(HTML::Window const&);
|
||||
bool matches() const;
|
||||
|
||||
void set_associated_style_sheet(GC::Ref<StyleSheet> style_sheet) { m_associated_style_sheet = style_sheet; }
|
||||
|
||||
private:
|
||||
MediaList(JS::Realm&, Vector<NonnullRefPtr<MediaQuery>>&&);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Visitor&) override;
|
||||
|
||||
GC::Ptr<StyleSheet> m_associated_style_sheet;
|
||||
Vector<NonnullRefPtr<MediaQuery>> m_media;
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <LibWeb/Bindings/HTMLLinkElementPrototype.h>
|
||||
#include <LibWeb/Bindings/PrincipalHostDefined.h>
|
||||
#include <LibWeb/CSS/Parser/Parser.h>
|
||||
#include <LibWeb/CSS/StyleComputer.h>
|
||||
#include <LibWeb/DOM/DOMTokenList.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/Event.h>
|
||||
|
@ -125,6 +126,18 @@ GC::Ref<DOM::DOMTokenList> 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();
|
||||
|
|
|
@ -45,6 +45,9 @@ public:
|
|||
|
||||
void set_parser_document(Badge<HTMLParser>, GC::Ref<DOM::Document>);
|
||||
|
||||
void set_media(String);
|
||||
String media() const;
|
||||
|
||||
private:
|
||||
HTMLLinkElement(DOM::Document&, DOM::QualifiedName);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
*/
|
||||
|
||||
#include <LibWeb/Bindings/HTMLStyleElementPrototype.h>
|
||||
#include <LibWeb/CSS/StyleComputer.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/HTML/HTMLStyleElement.h>
|
||||
|
||||
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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>HTML Test: The style information must be applied to the environment specified by the media attribute</title>
|
||||
<link rel="author" title="Intel" href="http://www.intel.com/">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-style-media">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-style-element">
|
||||
<script src="../../../../resources/testharness.js"></script>
|
||||
<script src="../../../../resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
#test {
|
||||
width: 100px;
|
||||
}
|
||||
</style>
|
||||
<style id="style">
|
||||
#test {
|
||||
width: 50px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<div id="test"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var testElement = document.getElementById("test");
|
||||
var style = document.getElementById("style");
|
||||
var width1, width2;
|
||||
|
||||
width1 = window.getComputedStyle(testElement)["width"];
|
||||
assert_equals(width1, "50px", "The style should be applied.");
|
||||
|
||||
style.media = "print";
|
||||
width2 = window.getComputedStyle(testElement)["width"];
|
||||
assert_equals(width2, "100px", "The style should not be applied.");
|
||||
}, "The style information must be applied to the environment specified by the media attribute");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Reference in a new issue