mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-08 06:09:58 +00:00
LibWeb/CSS: Stop copying the input in parse_css_value()
Now that we don't strip out whitespace, this method was copying the input TokenStream into a Vector, and then creating new TokenStreams from that. So, stop doing that and use the input TokenStream instead.
This commit is contained in:
parent
2bbf578737
commit
427d7fabd7
Notes:
github-actions[bot]
2025-11-03 11:25:06 +00:00
Author: https://github.com/AtkinsSJ
Commit: 427d7fabd7
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6646
Reviewed-by: https://github.com/tcl3
1 changed files with 47 additions and 43 deletions
|
|
@ -459,18 +459,18 @@ Optional<Parser::PropertyAndValue> Parser::parse_css_value_for_properties(Readon
|
|||
return OptionalNone {};
|
||||
}
|
||||
|
||||
Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_css_value(PropertyID property_id, TokenStream<ComponentValue>& unprocessed_tokens, Optional<String> original_source_text)
|
||||
Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_css_value(PropertyID property_id, TokenStream<ComponentValue>& tokens, Optional<String> original_source_text)
|
||||
{
|
||||
auto context_guard = push_temporary_value_parsing_context(property_id);
|
||||
|
||||
Vector<ComponentValue> component_values;
|
||||
SubstitutionFunctionsPresence substitution_presence;
|
||||
|
||||
while (unprocessed_tokens.has_next_token()) {
|
||||
auto const& token = unprocessed_tokens.consume_a_token();
|
||||
tokens.mark();
|
||||
while (tokens.has_next_token()) {
|
||||
auto const& token = tokens.consume_a_token();
|
||||
|
||||
if (token.is(Token::Type::Semicolon)) {
|
||||
unprocessed_tokens.reconsume_current_input_token();
|
||||
tokens.reconsume_current_input_token();
|
||||
return ParseError::SyntaxError;
|
||||
}
|
||||
|
||||
|
|
@ -478,25 +478,9 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_css_value(Pr
|
|||
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);
|
||||
}
|
||||
tokens.restore_a_mark();
|
||||
|
||||
if (component_values.size() == 1) {
|
||||
auto tokens = TokenStream { component_values };
|
||||
if (auto parsed_value = parse_builtin_value(tokens))
|
||||
return parsed_value.release_nonnull();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
auto tokens = TokenStream { component_values };
|
||||
|
||||
// Special-case property handling
|
||||
auto parse_all_as = [](auto& tokens, auto&& callback) -> ParseErrorOr<NonnullRefPtr<StyleValue const>> {
|
||||
tokens.discard_whitespace();
|
||||
auto parsed_value = callback(tokens);
|
||||
|
|
@ -506,6 +490,28 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_css_value(Pr
|
|||
return ParseError::SyntaxError;
|
||||
};
|
||||
|
||||
{
|
||||
auto builtin_transaction = tokens.begin_transaction();
|
||||
auto builtin = parse_all_as(tokens, [this](auto& tokens) { return parse_builtin_value(tokens); });
|
||||
if (!builtin.is_error()) {
|
||||
builtin_transaction.commit();
|
||||
return builtin.release_value();
|
||||
}
|
||||
}
|
||||
|
||||
if (property_id == PropertyID::Custom || substitution_presence.has_any()) {
|
||||
Vector<ComponentValue> component_values;
|
||||
while (tokens.has_next_token()) {
|
||||
component_values.append(tokens.consume_a_token());
|
||||
}
|
||||
return UnresolvedStyleValue::create(move(component_values), substitution_presence, original_source_text);
|
||||
}
|
||||
|
||||
tokens.discard_whitespace();
|
||||
if (!tokens.has_next_token())
|
||||
return ParseError::SyntaxError;
|
||||
|
||||
// Special-case property handling
|
||||
switch (property_id) {
|
||||
case PropertyID::All:
|
||||
// NOTE: The 'all' property, unlike some other shorthands, doesn't support directly listing sub-property
|
||||
|
|
@ -754,41 +760,39 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_css_value(Pr
|
|||
return ParseError::SyntaxError;
|
||||
}
|
||||
|
||||
// If there's only 1 ComponentValue, we can only produce a single StyleValue.
|
||||
if (component_values.size() == 1) {
|
||||
auto stream = TokenStream { component_values };
|
||||
if (auto parsed_value = parse_css_value_for_property(property_id, stream))
|
||||
return parsed_value.release_nonnull();
|
||||
} else {
|
||||
{
|
||||
auto transaction = tokens.begin_transaction();
|
||||
StyleValueVector parsed_values;
|
||||
auto stream = TokenStream { component_values };
|
||||
while (auto parsed_value = parse_css_value_for_property(property_id, stream)) {
|
||||
while (auto parsed_value = parse_css_value_for_property(property_id, tokens)) {
|
||||
parsed_values.append(parsed_value.release_nonnull());
|
||||
if (!stream.has_next_token())
|
||||
tokens.discard_whitespace();
|
||||
if (!tokens.has_next_token())
|
||||
break;
|
||||
}
|
||||
|
||||
if (!stream.has_next_token()) {
|
||||
// Some types (such as <ratio>) can be made from multiple ComponentValues, so if we only made 1 StyleValue, return it directly.
|
||||
if (parsed_values.size() == 1)
|
||||
tokens.discard_whitespace();
|
||||
if (!tokens.has_next_token()) {
|
||||
if (parsed_values.size() == 1) {
|
||||
transaction.commit();
|
||||
return *parsed_values.take_first();
|
||||
}
|
||||
|
||||
if (!parsed_values.is_empty() && parsed_values.size() <= property_maximum_value_count(property_id))
|
||||
if (!parsed_values.is_empty() && parsed_values.size() <= property_maximum_value_count(property_id)) {
|
||||
transaction.commit();
|
||||
return StyleValueList::create(move(parsed_values), StyleValueList::Separator::Space);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We have multiple values, but the property claims to accept only a single one, check if it's a shorthand property.
|
||||
// We have more values than the property claims to allow. Check if it's a shorthand.
|
||||
auto unassigned_properties = longhands_for_shorthand(property_id);
|
||||
if (unassigned_properties.is_empty())
|
||||
return ParseError::SyntaxError;
|
||||
|
||||
auto stream = TokenStream { component_values };
|
||||
|
||||
OrderedHashMap<UnderlyingType<PropertyID>, Vector<ValueComparingNonnullRefPtr<StyleValue const>>> assigned_values;
|
||||
|
||||
while (stream.has_next_token() && !unassigned_properties.is_empty()) {
|
||||
auto property_and_value = parse_css_value_for_properties(unassigned_properties, stream);
|
||||
while (tokens.has_next_token() && !unassigned_properties.is_empty()) {
|
||||
auto property_and_value = parse_css_value_for_properties(unassigned_properties, tokens);
|
||||
if (property_and_value.has_value()) {
|
||||
auto property = property_and_value->property;
|
||||
auto value = property_and_value->style_value;
|
||||
|
|
@ -804,7 +808,7 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_css_value(Pr
|
|||
|
||||
// No property matched, so we're done.
|
||||
if constexpr (CSS_PARSER_DEBUG) {
|
||||
dbgln("No property (from {} properties) matched {}", unassigned_properties.size(), stream.next_token().to_debug_string());
|
||||
dbgln("No property (from {} properties) matched {}", unassigned_properties.size(), tokens.next_token().to_debug_string());
|
||||
for (auto id : unassigned_properties)
|
||||
dbgln(" {}", string_from_property_id(id));
|
||||
}
|
||||
|
|
@ -814,8 +818,8 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_css_value(Pr
|
|||
for (auto& property : unassigned_properties)
|
||||
assigned_values.ensure(to_underlying(property)).append(property_initial_value(property));
|
||||
|
||||
stream.discard_whitespace();
|
||||
if (stream.has_next_token())
|
||||
tokens.discard_whitespace();
|
||||
if (tokens.has_next_token())
|
||||
return ParseError::SyntaxError;
|
||||
|
||||
Vector<PropertyID> longhand_properties;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue