LibWeb/CSS: Use ErrorReporter for property/descriptor parsing errors

This commit is contained in:
Sam Atkins 2025-07-23 11:05:39 +01:00
commit dc91688f18
Notes: github-actions[bot] 2025-08-04 09:51:59 +00:00
3 changed files with 71 additions and 20 deletions

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/CSS/Parser/ErrorReporter.h>
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
#include <LibWeb/CSS/StyleValues/FontSourceStyleValue.h>
@ -19,7 +20,10 @@ namespace Web::CSS::Parser {
Parser::ParseErrorOr<NonnullRefPtr<CSSStyleValue const>> Parser::parse_descriptor_value(AtRuleID at_rule_id, DescriptorID descriptor_id, TokenStream<ComponentValue>& unprocessed_tokens)
{
if (!at_rule_supports_descriptor(at_rule_id, descriptor_id)) {
dbgln_if(CSS_PARSER_DEBUG, "Unsupported descriptor '{}' in '{}'", to_string(descriptor_id), to_string(at_rule_id));
ErrorReporter::the().report(UnknownPropertyError {
.rule_name = to_string(at_rule_id),
.property_name = to_string(descriptor_id),
});
return ParseError::SyntaxError;
}
@ -212,10 +216,12 @@ Parser::ParseErrorOr<NonnullRefPtr<CSSStyleValue const>> Parser::parse_descripto
return parsed_style_value.release_nonnull();
}
if constexpr (CSS_PARSER_DEBUG) {
dbgln("Failed to parse descriptor '{}' in '{}'", to_string(descriptor_id), to_string(at_rule_id));
tokens.dump_all_tokens();
}
ErrorReporter::the().report(InvalidPropertyError {
.rule_name = to_string(at_rule_id),
.property_name = to_string(descriptor_id),
.value_string = tokens.dump_string(),
.description = "Failed to parse."_string,
});
return ParseError::SyntaxError;
}

View file

@ -1624,7 +1624,7 @@ Optional<StyleProperty> Parser::convert_to_style_property(Declaration const& dec
} else if (has_ignored_vendor_prefix(property_name)) {
return {};
} else {
dbgln_if(CSS_PARSER_DEBUG, "Unrecognized CSS property '{}'", property_name);
ErrorReporter::the().report(UnknownPropertyError { .property_name = property_name });
return {};
}
}
@ -1633,10 +1633,11 @@ Optional<StyleProperty> Parser::convert_to_style_property(Declaration const& dec
auto value = parse_css_value(property_id.value(), value_token_stream, declaration.original_text);
if (value.is_error()) {
if (value.error() == ParseError::SyntaxError) {
dbgln_if(CSS_PARSER_DEBUG, "Unable to parse value for CSS property '{}'.", property_name);
if constexpr (CSS_PARSER_DEBUG) {
value_token_stream.dump_all_tokens();
}
ErrorReporter::the().report(InvalidPropertyError {
.property_name = property_name,
.value_string = value_token_stream.dump_string(),
.description = "Failed to parse."_string,
});
}
return {};
}

View file

@ -2798,20 +2798,40 @@ RefPtr<CSSStyleValue const> Parser::parse_font_language_override_value(TokenStre
auto string_value = string->string_value();
tokens.discard_whitespace();
if (tokens.has_next_token()) {
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: Failed to parse font-language-override: unexpected trailing tokens");
ErrorReporter::the().report(InvalidPropertyError {
.rule_name = "style"_fly_string,
.property_name = "font-language-override"_fly_string,
.value_string = tokens.dump_string(),
.description = "Unexpected trailing tokens"_string,
});
return nullptr;
}
auto length = string_value.bytes().size();
if (length == 0) {
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: Failed to parse font-language-override: <string> value is empty");
ErrorReporter::the().report(InvalidPropertyError {
.rule_name = "style"_fly_string,
.property_name = "font-language-override"_fly_string,
.value_string = tokens.dump_string(),
.description = "<string> value is empty"_string,
});
return nullptr;
}
if (!string_value.is_ascii()) {
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: Failed to parse font-language-override: <string> value \"{}\" contains non-ascii characters", string_value);
ErrorReporter::the().report(InvalidPropertyError {
.rule_name = "style"_fly_string,
.property_name = "font-language-override"_fly_string,
.value_string = tokens.dump_string(),
.description = MUST(String::formatted("<string> value \"{}\" contains non-ascii characters", string_value)),
});
return nullptr;
}
if (length > 4) {
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: Failed to parse font-language-override: <string> value \"{}\" is too long", string_value);
ErrorReporter::the().report(InvalidPropertyError {
.rule_name = "style"_fly_string,
.property_name = "font-language-override"_fly_string,
.value_string = tokens.dump_string(),
.description = MUST(String::formatted("<string> value \"{}\" is too long", string_value)),
});
return nullptr;
}
transaction.commit();
@ -3227,7 +3247,11 @@ RefPtr<CSSStyleValue const> Parser::parse_font_variant_alternates_value(TokenStr
if (auto historical_forms = parse_all_as_single_keyword_value(tokens, Keyword::HistoricalForms))
return historical_forms;
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: @font-variant-alternate: parsing {} not implemented.", tokens.next_token().to_debug_string());
ErrorReporter::the().report(InvalidPropertyError {
.property_name = "font-variant-alternates"_fly_string,
.value_string = tokens.next_token().to_string(),
.description = "Invalid or not yet implemented"_string,
});
return nullptr;
}
@ -4168,7 +4192,11 @@ RefPtr<CSSStyleValue const> Parser::parse_transition_value(TokenStream<Component
transition.delay = move(time);
break;
default:
dbgln_if(CSS_PARSER_DEBUG, "Transition property has more than two time values");
ErrorReporter::the().report(InvalidPropertyError {
.property_name = "transition"_fly_string,
.value_string = tokens.dump_string(),
.description = "Contains more than two time values"_string,
});
return {};
}
time_value_count++;
@ -4177,7 +4205,11 @@ RefPtr<CSSStyleValue const> Parser::parse_transition_value(TokenStream<Component
if (auto easing = parse_easing_value(tokens)) {
if (transition.easing) {
dbgln_if(CSS_PARSER_DEBUG, "Transition property has multiple easing values");
ErrorReporter::the().report(InvalidPropertyError {
.property_name = "transition"_fly_string,
.value_string = tokens.dump_string(),
.description = "Contains multiple easing values"_string,
});
return {};
}
@ -4197,7 +4229,11 @@ RefPtr<CSSStyleValue const> Parser::parse_transition_value(TokenStream<Component
auto transition_keyword = parse_keyword_value(tokens);
VERIFY(transition_keyword->to_keyword() == Keyword::All);
if (transition.property_name) {
dbgln_if(CSS_PARSER_DEBUG, "Transition property has multiple property identifiers");
ErrorReporter::the().report(InvalidPropertyError {
.property_name = "transition"_fly_string,
.value_string = tokens.dump_string(),
.description = "Contains multiple property identifiers"_string,
});
return {};
}
transition.property_name = transition_keyword.release_nonnull();
@ -4206,7 +4242,11 @@ RefPtr<CSSStyleValue const> Parser::parse_transition_value(TokenStream<Component
if (auto transition_property = parse_custom_ident_value(tokens, { { "all"sv, "none"sv } })) {
if (transition.property_name) {
dbgln_if(CSS_PARSER_DEBUG, "Transition property has multiple property identifiers");
ErrorReporter::the().report(InvalidPropertyError {
.property_name = "transition"_fly_string,
.value_string = tokens.dump_string(),
.description = "Contains multiple property identifiers"_string,
});
return {};
}
@ -4217,7 +4257,11 @@ RefPtr<CSSStyleValue const> Parser::parse_transition_value(TokenStream<Component
}
}
dbgln_if(CSS_PARSER_DEBUG, "Transition property has unexpected token \"{}\"", tokens.next_token().to_string());
ErrorReporter::the().report(InvalidPropertyError {
.property_name = "transition"_fly_string,
.value_string = tokens.dump_string(),
.description = MUST(String::formatted("Unexpected token \"{}\"", tokens.next_token().to_string())),
});
return {};
}