LibWeb: Add method for whether tree-counting function is allowed

Some contexts (e.g. descriptors, media conditions) don't allow tree
counting functions, this commit adds an easy way to check if the current
value context is one of those.
This commit is contained in:
Callum Law 2025-09-30 15:12:52 +13:00 committed by Tim Ledbetter
commit fd31fbd84b
Notes: github-actions[bot] 2025-10-20 15:13:55 +00:00
5 changed files with 27 additions and 1 deletions

View file

@ -458,6 +458,8 @@ Optional<MediaFeatureValue> Parser::parse_media_feature_value(MediaFeatureID med
{ {
auto transaction = tokens.begin_transaction(); auto transaction = tokens.begin_transaction();
auto value = [this](MediaFeatureID media_feature, TokenStream<ComponentValue>& tokens) -> Optional<MediaFeatureValue> { auto value = [this](MediaFeatureID media_feature, TokenStream<ComponentValue>& tokens) -> Optional<MediaFeatureValue> {
auto context_guard = push_temporary_value_parsing_context(SpecialContext::MediaCondition);
// One branch for each member of the MediaFeatureValueType enum: // One branch for each member of the MediaFeatureValueType enum:
// Identifiers // Identifiers
if (tokens.next_token().is(Token::Type::Ident)) { if (tokens.next_token().is(Token::Type::Ident)) {

View file

@ -1694,6 +1694,21 @@ bool Parser::context_allows_quirky_length() const
return unitless_length_allowed; return unitless_length_allowed;
} }
bool Parser::context_allows_tree_counting_functions() const
{
for (auto context : m_value_context) {
if (context.has<DescriptorContext>())
return false;
if (auto const* special_context = context.get_pointer<SpecialContext>(); special_context && first_is_one_of(*special_context, SpecialContext::DOMMatrixInitString, SpecialContext::MediaCondition))
return false;
// TODO: Handle other contexts where tree counting functions are not allowed
}
return true;
}
Vector<ComponentValue> Parser::parse_as_list_of_component_values() Vector<ComponentValue> Parser::parse_as_list_of_component_values()
{ {
return parse_a_list_of_component_values(m_token_stream); return parse_a_list_of_component_values(m_token_stream);

View file

@ -77,6 +77,8 @@ struct DescriptorContext {
enum SpecialContext : u8 { enum SpecialContext : u8 {
AngularColorStopList, AngularColorStopList,
CubicBezierFunctionXCoordinate, CubicBezierFunctionXCoordinate,
DOMMatrixInitString,
MediaCondition,
ShadowBlurRadius, ShadowBlurRadius,
StepsIntervalsJumpNone, StepsIntervalsJumpNone,
StepsIntervalsNormal, StepsIntervalsNormal,
@ -583,6 +585,7 @@ private:
return ScopeGuard { [&] { m_value_context.take_last(); } }; return ScopeGuard { [&] { m_value_context.take_last(); } };
} }
bool context_allows_quirky_length() const; bool context_allows_quirky_length() const;
bool context_allows_tree_counting_functions() const;
Vector<RuleContext> m_rule_context; Vector<RuleContext> m_rule_context;
HashTable<FlyString> m_declared_namespaces; HashTable<FlyString> m_declared_namespaces;

View file

@ -4142,6 +4142,9 @@ RefPtr<CalculatedStyleValue const> Parser::parse_calculated_value(ComponentValue
case SpecialContext::TranslateZArgument: case SpecialContext::TranslateZArgument:
// Percentages are disallowed for the Z axis // Percentages are disallowed for the Z axis
return CalculationContext {}; return CalculationContext {};
case SpecialContext::DOMMatrixInitString:
case SpecialContext::MediaCondition:
return {};
} }
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
}); });

View file

@ -949,7 +949,10 @@ WebIDL::ExceptionOr<ParsedMatrix> parse_dom_matrix_init_string(JS::Realm& realm,
// 2. Parse transformList into parsedValue given the grammar for the CSS transform property. // 2. Parse transformList into parsedValue given the grammar for the CSS transform property.
// The result will be a <transform-list>, the keyword none, or failure. // The result will be a <transform-list>, the keyword none, or failure.
// If parsedValue is failure, or any <transform-function> has <length> values without absolute length units, or any keyword other than none is used, then return failure. [CSS3-SYNTAX] [CSS3-TRANSFORMS] // If parsedValue is failure, or any <transform-function> has <length> values without absolute length units, or any keyword other than none is used, then return failure. [CSS3-SYNTAX] [CSS3-TRANSFORMS]
auto transform_style_value = parse_css_value(CSS::Parser::ParsingParams {}, transform_list, CSS::PropertyID::Transform); CSS::Parser::ParsingParams parsing_params {};
parsing_params.value_context = { CSS::Parser::SpecialContext::DOMMatrixInitString };
auto transform_style_value = parse_css_value(parsing_params, transform_list, CSS::PropertyID::Transform);
if (!transform_style_value || (transform_style_value->is_keyword() && transform_style_value->to_keyword() != CSS::Keyword::None) || transform_style_value->is_unresolved()) if (!transform_style_value || (transform_style_value->is_keyword() && transform_style_value->to_keyword() != CSS::Keyword::None) || transform_style_value->is_unresolved())
return WebIDL::SyntaxError::create(realm, "Failed to parse CSS transform string."_utf16); return WebIDL::SyntaxError::create(realm, "Failed to parse CSS transform string."_utf16);
auto parsed_value = CSS::ComputedProperties::transformations_for_style_value(*transform_style_value); auto parsed_value = CSS::ComputedProperties::transformations_for_style_value(*transform_style_value);