From 29d7aa9fc9de76491d0f400526f53699176c3c07 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Fri, 9 Aug 2024 13:36:11 +0100 Subject: [PATCH] LibWeb/CSS: Parse url() functions with TokenStream --- .../Libraries/LibWeb/CSS/Parser/Parser.cpp | 42 +++++++++---------- Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 2 +- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 05f3d2dcc6b..b6bbbe9d15d 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -1157,14 +1157,17 @@ ElementInlineCSSStyleDeclaration* Parser::parse_as_style_attribute(DOM::Element& return ElementInlineCSSStyleDeclaration::create(element, move(properties), move(custom_properties)); } -Optional Parser::parse_url_function(ComponentValue const& component_value) +Optional Parser::parse_url_function(TokenStream& tokens) { - // FIXME: Handle list of media queries. https://www.w3.org/TR/css-cascade-3/#conditional-import + auto transaction = tokens.begin_transaction(); + auto& component_value = tokens.next_token(); auto convert_string_to_url = [&](StringView url_string) -> Optional { auto url = m_context.complete_url(url_string); - if (url.is_valid()) + if (url.is_valid()) { + transaction.commit(); return url; + } return {}; }; @@ -1192,10 +1195,9 @@ Optional Parser::parse_url_function(ComponentValue const& component_va RefPtr Parser::parse_url_value(TokenStream& tokens) { - auto url = parse_url_function(tokens.peek_token()); + auto url = parse_url_function(tokens); if (!url.has_value()) return nullptr; - (void)tokens.next_token(); return URLStyleValue::create(*url); } @@ -1332,16 +1334,12 @@ JS::GCPtr Parser::convert_to_import_rule(Rule& rule) TokenStream tokens { rule.prelude() }; tokens.skip_whitespace(); - Optional url; - auto& url_token = tokens.next_token(); - if (url_token.is(Token::Type::String)) { - url = m_context.complete_url(url_token.token().string()); - } else { - url = parse_url_function(url_token); - } + Optional url = parse_url_function(tokens); + if (!url.has_value() && tokens.peek_token().is(Token::Type::String)) + url = m_context.complete_url(tokens.next_token().token().string()); if (!url.has_value()) { - dbgln_if(CSS_PARSER_DEBUG, "Failed to parse @import rule: Unable to parse `{}` as URL.", url_token.to_debug_string()); + dbgln_if(CSS_PARSER_DEBUG, "Failed to parse @import rule: Unable to parse `{}` as URL.", tokens.peek_token().to_debug_string()); return {}; } @@ -1497,13 +1495,12 @@ JS::GCPtr Parser::convert_to_namespace_rule(Rule& rule) } FlyString namespace_uri; - auto& url_token = tokens.next_token(); - if (url_token.is(Token::Type::String)) { - namespace_uri = url_token.token().string(); - } else if (auto url = parse_url_function(url_token); url.has_value()) { + if (auto url = parse_url_function(tokens); url.has_value()) { namespace_uri = MUST(url.value().to_string()); + } else if (auto& url_token = tokens.next_token(); url_token.is(Token::Type::String)) { + namespace_uri = url_token.token().string(); } else { - dbgln_if(CSS_PARSER_DEBUG, "Failed to parse @namespace rule: Unable to parse `{}` as URL.", url_token.to_debug_string()); + dbgln_if(CSS_PARSER_DEBUG, "Failed to parse @namespace rule: Unable to parse `{}` as URL.", tokens.peek_token().to_debug_string()); return {}; } @@ -3203,12 +3200,13 @@ RefPtr Parser::parse_string_value(TokenStream& token RefPtr Parser::parse_image_value(TokenStream& tokens) { auto transaction = tokens.begin_transaction(); - auto& token = tokens.next_token(); - if (auto url = parse_url_function(token); url.has_value()) { + if (auto url = parse_url_function(tokens); url.has_value()) { transaction.commit(); return ImageStyleValue::create(url.value()); } + + auto& token = tokens.next_token(); if (auto linear_gradient = parse_linear_gradient_function(token)) { transaction.commit(); return linear_gradient; @@ -5266,11 +5264,10 @@ Vector Parser::parse_font_face_src(TokenStream& compo for (auto const& source_token_list : list_of_source_token_lists) { TokenStream source_tokens { source_token_list }; source_tokens.skip_whitespace(); - auto const& first = source_tokens.next_token(); // [ format()]? // FIXME: Implement optional tech() function from CSS-Fonts-4. - if (auto maybe_url = parse_url_function(first); maybe_url.has_value()) { + if (auto maybe_url = parse_url_function(source_tokens); maybe_url.has_value()) { auto url = maybe_url.release_value(); if (!url.is_valid()) { continue; @@ -5326,6 +5323,7 @@ Vector Parser::parse_font_face_src(TokenStream& compo continue; } + auto const& first = source_tokens.next_token(); if (first.is_function("local"sv)) { if (first.function().values().is_empty()) { continue; diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index a750493e5d1..cf3e7f65cf0 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -261,7 +261,7 @@ private: Optional parse_repeat(Vector const&); Optional parse_track_sizing_function(ComponentValue const&); - Optional parse_url_function(ComponentValue const&); + Optional parse_url_function(TokenStream&); RefPtr parse_url_value(TokenStream&); RefPtr parse_basic_shape_value(TokenStream&);