LibWeb: Save more details about ASF presence in UnresolvedStyleValue

In the upcoming changes we would have to know specifically whether
`var()`, `attr()` or both are included in UnresolvedStyleValue.
This commit is contained in:
Aliaksandr Kalenik 2025-07-27 19:40:17 +02:00 committed by Andreas Kling
commit b1efd62ce6
Notes: github-actions[bot] 2025-07-30 09:07:37 +00:00
5 changed files with 44 additions and 41 deletions

View file

@ -393,7 +393,7 @@ Parser::ParseErrorOr<NonnullRefPtr<CSSStyleValue const>> Parser::parse_css_value
// FIXME: Stop removing whitespace here. It's less helpful than it seems.
Vector<ComponentValue> component_values;
bool contains_arbitrary_substitution_function = false;
SubstitutionFunctionsPresence substitution_presence;
bool const property_accepts_custom_ident = property_accepts_type(property_id, ValueType::CustomIdent);
while (unprocessed_tokens.has_next_token()) {
@ -412,12 +412,10 @@ Parser::ParseErrorOr<NonnullRefPtr<CSSStyleValue const>> Parser::parse_css_value
return ParseError::IncludesIgnoredVendorPrefix;
}
if (!contains_arbitrary_substitution_function) {
if (token.is_function() && token.function().contains_arbitrary_substitution_function())
contains_arbitrary_substitution_function = true;
else if (token.is_block() && token.block().contains_arbitrary_substitution_function())
contains_arbitrary_substitution_function = true;
}
if (token.is_function())
token.function().contains_arbitrary_substitution_function(substitution_presence);
else if (token.is_block())
token.block().contains_arbitrary_substitution_function(substitution_presence);
component_values.append(token);
}
@ -428,8 +426,8 @@ Parser::ParseErrorOr<NonnullRefPtr<CSSStyleValue const>> Parser::parse_css_value
return parsed_value.release_nonnull();
}
if (property_id == PropertyID::Custom || contains_arbitrary_substitution_function)
return UnresolvedStyleValue::create(move(component_values), contains_arbitrary_substitution_function, original_source_text);
if (property_id == PropertyID::Custom || substitution_presence.has_any())
return UnresolvedStyleValue::create(move(component_values), substitution_presence, original_source_text);
if (component_values.is_empty())
return ParseError::SyntaxError;

View file

@ -51,15 +51,14 @@ String SimpleBlock::original_source_text() const
return builder.to_string_without_validation();
}
bool SimpleBlock::contains_arbitrary_substitution_function() const
void SimpleBlock::contains_arbitrary_substitution_function(SubstitutionFunctionsPresence& presence) const
{
for (auto const& component_value : value) {
if (component_value.is_function() && component_value.function().contains_arbitrary_substitution_function())
return true;
if (component_value.is_block() && component_value.block().contains_arbitrary_substitution_function())
return true;
if (component_value.is_function())
component_value.function().contains_arbitrary_substitution_function(presence);
if (component_value.is_block())
component_value.block().contains_arbitrary_substitution_function(presence);
}
return false;
}
String Function::to_string() const
@ -86,17 +85,18 @@ String Function::original_source_text() const
return builder.to_string_without_validation();
}
bool Function::contains_arbitrary_substitution_function() const
void Function::contains_arbitrary_substitution_function(SubstitutionFunctionsPresence& presence) const
{
if (name.equals_ignoring_ascii_case("var"sv) || name.equals_ignoring_ascii_case("attr"sv))
return true;
if (name.equals_ignoring_ascii_case("var"sv))
presence.var = true;
else if (name.equals_ignoring_ascii_case("attr"sv))
presence.attr = true;
for (auto const& component_value : value) {
if (component_value.is_function() && component_value.function().contains_arbitrary_substitution_function())
return true;
if (component_value.is_block() && component_value.block().contains_arbitrary_substitution_function())
return true;
if (component_value.is_function())
component_value.function().contains_arbitrary_substitution_function(presence);
if (component_value.is_block())
component_value.block().contains_arbitrary_substitution_function(presence);
}
return false;
}
void AtRule::for_each(AtRuleVisitor&& visit_at_rule, QualifiedRuleVisitor&& visit_qualified_rule, DeclarationVisitor&& visit_declaration) const

View file

@ -61,6 +61,13 @@ struct Declaration {
String to_string() const;
};
struct SubstitutionFunctionsPresence {
bool attr { false };
bool var { false };
bool has_any() const { return attr || var; }
};
// https://drafts.csswg.org/css-syntax/#simple-block
struct SimpleBlock {
Token token;
@ -73,7 +80,7 @@ struct SimpleBlock {
String to_string() const;
String original_source_text() const;
bool contains_arbitrary_substitution_function() const;
void contains_arbitrary_substitution_function(SubstitutionFunctionsPresence&) const;
};
// https://drafts.csswg.org/css-syntax/#function
@ -85,7 +92,7 @@ struct Function {
String to_string() const;
String original_source_text() const;
bool contains_arbitrary_substitution_function() const;
void contains_arbitrary_substitution_function(SubstitutionFunctionsPresence&) const;
};
// https://drafts.csswg.org/css-variables/#guaranteed-invalid-value

View file

@ -13,27 +13,25 @@
namespace Web::CSS {
ValueComparingNonnullRefPtr<UnresolvedStyleValue const> UnresolvedStyleValue::create(Vector<Parser::ComponentValue>&& values, Optional<bool> contains_arbitrary_substitution_function, Optional<String> original_source_text)
ValueComparingNonnullRefPtr<UnresolvedStyleValue const> UnresolvedStyleValue::create(Vector<Parser::ComponentValue>&& values, Optional<Parser::SubstitutionFunctionsPresence> substitution_presence, Optional<String> original_source_text)
{
if (!contains_arbitrary_substitution_function.has_value()) {
bool found_asf = false;
if (!substitution_presence.has_value()) {
substitution_presence = Parser::SubstitutionFunctionsPresence {};
for (auto const& value : values) {
if ((value.is_function() && value.function().contains_arbitrary_substitution_function())
|| (value.is_block() && value.block().contains_arbitrary_substitution_function())) {
found_asf = true;
break;
}
if (value.is_function())
value.function().contains_arbitrary_substitution_function(*substitution_presence);
if (value.is_block())
value.block().contains_arbitrary_substitution_function(*substitution_presence);
}
contains_arbitrary_substitution_function = found_asf;
}
return adopt_ref(*new (nothrow) UnresolvedStyleValue(move(values), contains_arbitrary_substitution_function.value(), move(original_source_text)));
return adopt_ref(*new (nothrow) UnresolvedStyleValue(move(values), *substitution_presence, move(original_source_text)));
}
UnresolvedStyleValue::UnresolvedStyleValue(Vector<Parser::ComponentValue>&& values, bool contains_arbitrary_substitution_function, Optional<String> original_source_text)
UnresolvedStyleValue::UnresolvedStyleValue(Vector<Parser::ComponentValue>&& values, Parser::SubstitutionFunctionsPresence substitution_presence, Optional<String> original_source_text)
: CSSStyleValue(Type::Unresolved)
, m_values(move(values))
, m_contains_arbitrary_substitution_function(contains_arbitrary_substitution_function)
, m_substitution_functions_presence(substitution_presence)
, m_original_source_text(move(original_source_text))
{
}

View file

@ -17,22 +17,22 @@ namespace Web::CSS {
class UnresolvedStyleValue final : public CSSStyleValue {
public:
static ValueComparingNonnullRefPtr<UnresolvedStyleValue const> create(Vector<Parser::ComponentValue>&& values, Optional<bool> contains_arbitrary_substitution_function = {}, Optional<String> original_source_text = {});
static ValueComparingNonnullRefPtr<UnresolvedStyleValue const> create(Vector<Parser::ComponentValue>&& values, Optional<Parser::SubstitutionFunctionsPresence> = {}, Optional<String> original_source_text = {});
virtual ~UnresolvedStyleValue() override = default;
virtual String to_string(SerializationMode) const override;
virtual Vector<Parser::ComponentValue> tokenize() const override { return m_values; }
Vector<Parser::ComponentValue> const& values() const { return m_values; }
bool contains_arbitrary_substitution_function() const { return m_contains_arbitrary_substitution_function; }
bool contains_arbitrary_substitution_function() const { return m_substitution_functions_presence.has_any(); }
virtual bool equals(CSSStyleValue const& other) const override;
private:
UnresolvedStyleValue(Vector<Parser::ComponentValue>&& values, bool contains_arbitrary_substitution_function, Optional<String> original_source_text);
UnresolvedStyleValue(Vector<Parser::ComponentValue>&& values, Parser::SubstitutionFunctionsPresence, Optional<String> original_source_text);
Vector<Parser::ComponentValue> m_values;
bool m_contains_arbitrary_substitution_function { false };
Parser::SubstitutionFunctionsPresence m_substitution_functions_presence {};
Optional<String> m_original_source_text;
};