From ed962be0fa4271c0e7d1df864f2f71133dc5e1d3 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Mon, 9 Aug 2021 16:02:26 +0100 Subject: [PATCH] LibWeb: Make 'auto' be both a Length and Identifier in CSS I had accidentally parsed it in `parse_builtin_or_dynamic_value()` instead of `parse_length()` before, which was confusing, so now it's parsed along with other Lengths. Whether it should be a Length is up for debate, and has been tripping me up a few times, but a lot of code expects it to be one. For now, an 'auto' Length value (or any other value which overloads `is_auto()`) also claims to be a `ValueID::Auto` identifier. --- Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 9 +++++++-- Userland/Libraries/LibWeb/CSS/StyleValue.h | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 91bbaad40f..ccce9c5bff 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -1407,8 +1407,6 @@ RefPtr Parser::parse_builtin_or_dynamic_value(ParsingContext const& return InheritStyleValue::create(); if (ident.equals_ignoring_case("initial")) return InitialStyleValue::create(); - if (ident.equals_ignoring_case("auto")) - return LengthStyleValue::create(Length::make_auto()); // FIXME: Implement `unset` keyword } @@ -1493,6 +1491,8 @@ Optional Parser::parse_length(ParsingContext const& context, StyleCompon type = Length::Type::Percentage; auto value_string = component_value.token().m_value.string_view(); numeric_value = try_parse_float(value_string); + } else if (component_value.is(Token::Type::Ident) && component_value.token().ident().equals_ignoring_case("auto")) { + return Length::make_auto(); } if (!numeric_value.has_value()) @@ -1507,7 +1507,12 @@ RefPtr Parser::parse_length_value(ParsingContext const& context, Sty // 1) We're in quirks mode, and it's an integer. // 2) It's a 0. // We handle case 1 here. Case 2 is handled by NumericStyleValue pretending to be a LengthStyleValue if it is 0. + + // FIXME: "auto" is also treated as a Length, and most of the time that is how it is used, but not always. + // Possibly it should always be an Identifier, and then quietly converted to a Length when needed, like 0 above. + // Right now, it instead is quietly converted to an Identifier when needed. if (component_value.is(Token::Type::Dimension) || component_value.is(Token::Type::Percentage) + || (component_value.is(Token::Type::Ident) && component_value.token().ident().equals_ignoring_case("auto"sv)) || (context.in_quirks_mode() && component_value.is(Token::Type::Number) && component_value.token().m_value.string_view() != "0"sv)) { auto length = parse_length(context, component_value); if (length.has_value()) diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 8790379ee7..c02be1f858 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -236,7 +236,7 @@ public: bool is_inherit() const { return type() == Type::Inherit; } bool is_initial() const { return type() == Type::Initial; } bool is_color() const { return type() == Type::Color; } - bool is_identifier() const { return type() == Type::Identifier; } + bool is_identifier() const { return type() == Type::Identifier || is_auto(); } bool is_image() const { return type() == Type::Image; } bool is_string() const { return type() == Type::String; } virtual bool is_length() const { return type() == Type::Length; } @@ -638,6 +638,8 @@ inline CSS::ValueID StyleValue::to_identifier() const { if (is_identifier()) return static_cast(*this).id(); + if (is_auto()) + return CSS::ValueID::Auto; return CSS::ValueID::Invalid; } }