diff --git a/Libraries/LibWeb/CSS/MediaQuery.cpp b/Libraries/LibWeb/CSS/MediaQuery.cpp index 801bd865c4a..afcff44b4fc 100644 --- a/Libraries/LibWeb/CSS/MediaQuery.cpp +++ b/Libraries/LibWeb/CSS/MediaQuery.cpp @@ -17,7 +17,10 @@ NonnullRefPtr MediaQuery::create_not_all() { auto media_query = new MediaQuery; media_query->m_negated = true; - media_query->m_media_type = MediaType::All; + media_query->m_media_type = { + .name = "all"_fly_string, + .known_type = KnownMediaType::All, + }; return adopt_ref(*media_query); } @@ -265,8 +268,12 @@ String MediaQuery::to_string() const if (m_negated) builder.append("not "sv); - if (m_negated || m_media_type != MediaType::All || !m_media_condition) { - builder.append(CSS::to_string(m_media_type)); + if (m_negated || m_media_type.known_type != KnownMediaType::All || !m_media_condition) { + if (m_media_type.known_type.has_value()) { + builder.append(CSS::to_string(m_media_type.known_type.value())); + } else { + builder.append(serialize_an_identifier(m_media_type.name.to_ascii_lowercase())); + } if (m_media_condition) builder.append(" and "sv); } @@ -280,28 +287,18 @@ String MediaQuery::to_string() const bool MediaQuery::evaluate(HTML::Window const& window) { - auto matches_media = [](MediaType media) -> MatchResult { - switch (media) { - case MediaType::All: + auto matches_media = [](MediaType const& media) -> MatchResult { + if (!media.known_type.has_value()) + return MatchResult::False; + switch (media.known_type.value()) { + case KnownMediaType::All: return MatchResult::True; - case MediaType::Print: + case KnownMediaType::Print: // FIXME: Enable for printing, when we have printing! return MatchResult::False; - case MediaType::Screen: + case KnownMediaType::Screen: // FIXME: Disable for printing, when we have printing! return MatchResult::True; - case MediaType::Unknown: - return MatchResult::False; - // Deprecated, must never match: - case MediaType::TTY: - case MediaType::TV: - case MediaType::Projection: - case MediaType::Handheld: - case MediaType::Braille: - case MediaType::Embossed: - case MediaType::Aural: - case MediaType::Speech: - return MatchResult::False; } VERIFY_NOT_REACHED(); }; @@ -330,60 +327,26 @@ String serialize_a_media_query_list(Vector> const& med return MUST(String::join(", "sv, media_queries)); } -MediaQuery::MediaType media_type_from_string(StringView name) +Optional media_type_from_string(StringView name) { if (name.equals_ignoring_ascii_case("all"sv)) - return MediaQuery::MediaType::All; - if (name.equals_ignoring_ascii_case("aural"sv)) - return MediaQuery::MediaType::Aural; - if (name.equals_ignoring_ascii_case("braille"sv)) - return MediaQuery::MediaType::Braille; - if (name.equals_ignoring_ascii_case("embossed"sv)) - return MediaQuery::MediaType::Embossed; - if (name.equals_ignoring_ascii_case("handheld"sv)) - return MediaQuery::MediaType::Handheld; + return MediaQuery::KnownMediaType::All; if (name.equals_ignoring_ascii_case("print"sv)) - return MediaQuery::MediaType::Print; - if (name.equals_ignoring_ascii_case("projection"sv)) - return MediaQuery::MediaType::Projection; + return MediaQuery::KnownMediaType::Print; if (name.equals_ignoring_ascii_case("screen"sv)) - return MediaQuery::MediaType::Screen; - if (name.equals_ignoring_ascii_case("speech"sv)) - return MediaQuery::MediaType::Speech; - if (name.equals_ignoring_ascii_case("tty"sv)) - return MediaQuery::MediaType::TTY; - if (name.equals_ignoring_ascii_case("tv"sv)) - return MediaQuery::MediaType::TV; - return MediaQuery::MediaType::Unknown; + return MediaQuery::KnownMediaType::Screen; + return {}; } -StringView to_string(MediaQuery::MediaType media_type) +StringView to_string(MediaQuery::KnownMediaType media_type) { switch (media_type) { - case MediaQuery::MediaType::All: + case MediaQuery::KnownMediaType::All: return "all"sv; - case MediaQuery::MediaType::Aural: - return "aural"sv; - case MediaQuery::MediaType::Braille: - return "braille"sv; - case MediaQuery::MediaType::Embossed: - return "embossed"sv; - case MediaQuery::MediaType::Handheld: - return "handheld"sv; - case MediaQuery::MediaType::Print: + case MediaQuery::KnownMediaType::Print: return "print"sv; - case MediaQuery::MediaType::Projection: - return "projection"sv; - case MediaQuery::MediaType::Screen: + case MediaQuery::KnownMediaType::Screen: return "screen"sv; - case MediaQuery::MediaType::Speech: - return "speech"sv; - case MediaQuery::MediaType::TTY: - return "tty"sv; - case MediaQuery::MediaType::TV: - return "tv"sv; - case MediaQuery::MediaType::Unknown: - return "unknown"sv; } VERIFY_NOT_REACHED(); } diff --git a/Libraries/LibWeb/CSS/MediaQuery.h b/Libraries/LibWeb/CSS/MediaQuery.h index e760c134ca1..aea69afd7f2 100644 --- a/Libraries/LibWeb/CSS/MediaQuery.h +++ b/Libraries/LibWeb/CSS/MediaQuery.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -189,21 +190,14 @@ public: ~MediaQuery() = default; // https://www.w3.org/TR/mediaqueries-4/#media-types - enum class MediaType { + enum class KnownMediaType : u8 { All, Print, Screen, - Unknown, - - // Deprecated, must never match: - TTY, - TV, - Projection, - Handheld, - Braille, - Embossed, - Aural, - Speech, + }; + struct MediaType { + FlyString name; + Optional known_type; }; static NonnullRefPtr create_not_all(); @@ -218,7 +212,7 @@ private: // https://www.w3.org/TR/mediaqueries-4/#mq-not bool m_negated { false }; - MediaType m_media_type { MediaType::All }; + MediaType m_media_type { .name = "all"_fly_string, .known_type = KnownMediaType::All }; OwnPtr m_media_condition { nullptr }; // Cached value, updated by evaluate() @@ -227,8 +221,8 @@ private: String serialize_a_media_query_list(Vector> const&); -MediaQuery::MediaType media_type_from_string(StringView); -StringView to_string(MediaQuery::MediaType); +Optional media_type_from_string(StringView); +StringView to_string(MediaQuery::KnownMediaType); } diff --git a/Libraries/LibWeb/CSS/Parser/MediaParsing.cpp b/Libraries/LibWeb/CSS/Parser/MediaParsing.cpp index e446d37693d..42e79a7ec88 100644 --- a/Libraries/LibWeb/CSS/Parser/MediaParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/MediaParsing.cpp @@ -112,13 +112,11 @@ NonnullRefPtr Parser::parse_media_query(TokenStream& // `` if (auto media_type = parse_media_type(tokens); media_type.has_value()) { - // https://drafts.csswg.org/mediaqueries-4/#error-handling - // An unknown must be treated as not matching. - if (media_type.value() == MediaQuery::MediaType::Unknown) - return invalid_media_query(); - media_query->m_media_type = media_type.value(); + media_query->m_media_type = media_type.release_value(); tokens.discard_whitespace(); } else { + // https://drafts.csswg.org/mediaqueries-4/#error-handling + // A media query that does not match the grammar in the previous section must be replaced by not all during parsing. return invalid_media_query(); } @@ -415,10 +413,19 @@ Optional Parser::parse_media_type(TokenStream`, https://www.w3.org/TR/mediaqueries-4/#typedef-mf-value diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/mediaqueries/match-media-parsing.txt b/Tests/LibWeb/Text/expected/wpt-import/css/mediaqueries/match-media-parsing.txt index 03af42c3672..7f169810d5f 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/mediaqueries/match-media-parsing.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/mediaqueries/match-media-parsing.txt @@ -2,8 +2,7 @@ Harness status: OK Found 34 tests -32 Pass -2 Fail +34 Pass Pass Test parsing '' with matchMedia Pass Test parsing ' ' with matchMedia Pass Test parsing 'all' with matchMedia @@ -19,12 +18,12 @@ Pass Test parsing ' ( color ' with matchMedia Pass Test parsing 'color)' with matchMedia Pass Test parsing ' color)' with matchMedia Pass Test parsing ' color ), ( color' with matchMedia -Fail Test parsing ' foo ' with matchMedia +Pass Test parsing ' foo ' with matchMedia Pass Test parsing ',' with matchMedia Pass Test parsing ' , ' with matchMedia Pass Test parsing ',,' with matchMedia Pass Test parsing ' , , ' with matchMedia -Fail Test parsing ' foo,' with matchMedia +Pass Test parsing ' foo,' with matchMedia Pass Test parsing '(min-resolution: 1x)' with matchMedia Pass Test parsing '(min-resolution: calc(1x))' with matchMedia Pass Test parsing '(resolution: 2x)' with matchMedia