1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:07:47 +00:00

LibWeb: Correct parsing of background-position 3-value syntax

There were two bugs here, one of which hid the other:
- Only one offset would have a value, but we dereferenced both.
- We consumed a token whether it was a valid offset or not.
This commit is contained in:
Sam Atkins 2023-12-04 15:32:45 +00:00 committed by Andreas Kling
parent 20da5b6153
commit ef48d967d4

View file

@ -2554,8 +2554,13 @@ RefPtr<PositionStyleValue> Parser::parse_position_value(TokenStream<ComponentVal
Optional<PositionEdge> vertical_edge; Optional<PositionEdge> vertical_edge;
Optional<LengthPercentage> vertical_offset; Optional<LengthPercentage> vertical_offset;
auto matches = [&]() {
return horizontal_edge.has_value() && vertical_edge.has_value()
&& horizontal_offset.has_value() != vertical_offset.has_value();
};
auto parse_horizontal = [&] { auto parse_horizontal = [&] {
// [ left | right ] <length-percentage> ] // [ left | right ] <length-percentage>?
auto transaction = tokens.begin_transaction(); auto transaction = tokens.begin_transaction();
tokens.skip_whitespace(); tokens.skip_whitespace();
auto edge = parse_position_edge(tokens.next_token()); auto edge = parse_position_edge(tokens.next_token());
@ -2564,16 +2569,17 @@ RefPtr<PositionStyleValue> Parser::parse_position_value(TokenStream<ComponentVal
horizontal_edge = move(edge); horizontal_edge = move(edge);
tokens.skip_whitespace(); tokens.skip_whitespace();
auto length_percentage = parse_length_percentage(tokens.next_token()); auto length_percentage = parse_length_percentage(tokens.peek_token());
if (length_percentage.has_value()) if (length_percentage.has_value()) {
(void)tokens.next_token(); // offset
horizontal_offset = move(length_percentage); horizontal_offset = move(length_percentage);
}
transaction.commit(); transaction.commit();
return true; return true;
}; };
auto parse_vertical = [&] { auto parse_vertical = [&] {
// [ top | bottom ] <length-percentage> ] // [ top | bottom ] <length-percentage>?
auto transaction = tokens.begin_transaction(); auto transaction = tokens.begin_transaction();
tokens.skip_whitespace(); tokens.skip_whitespace();
auto edge = parse_position_edge(tokens.next_token()); auto edge = parse_position_edge(tokens.next_token());
@ -2582,17 +2588,20 @@ RefPtr<PositionStyleValue> Parser::parse_position_value(TokenStream<ComponentVal
vertical_edge = move(edge); vertical_edge = move(edge);
tokens.skip_whitespace(); tokens.skip_whitespace();
auto length_percentage = parse_length_percentage(tokens.next_token()); auto length_percentage = parse_length_percentage(tokens.peek_token());
if (length_percentage.has_value()) if (length_percentage.has_value()) {
(void)tokens.next_token(); // offset
vertical_offset = move(length_percentage); vertical_offset = move(length_percentage);
}
transaction.commit(); transaction.commit();
return true; return true;
}; };
if (parse_horizontal() && parse_vertical()) { if (parse_horizontal() && parse_vertical() && matches()) {
transaction.commit(); transaction.commit();
return PositionStyleValue::create(EdgeStyleValue::create(*horizontal_edge, *horizontal_offset), EdgeStyleValue::create(*vertical_edge, *vertical_offset)); return PositionStyleValue::create(
EdgeStyleValue::create(*horizontal_edge, horizontal_offset.value_or(Length::make_px(0))),
EdgeStyleValue::create(*vertical_edge, vertical_offset.value_or(Length::make_px(0))));
} }
horizontal_edge.clear(); horizontal_edge.clear();
@ -2600,9 +2609,11 @@ RefPtr<PositionStyleValue> Parser::parse_position_value(TokenStream<ComponentVal
vertical_edge.clear(); vertical_edge.clear();
vertical_offset.clear(); vertical_offset.clear();
if (parse_vertical() && parse_horizontal()) { if (parse_vertical() && parse_horizontal() && matches()) {
transaction.commit(); transaction.commit();
return PositionStyleValue::create(EdgeStyleValue::create(*horizontal_edge, *horizontal_offset), EdgeStyleValue::create(*vertical_edge, *vertical_offset)); return PositionStyleValue::create(
EdgeStyleValue::create(*horizontal_edge, horizontal_offset.value_or(Length::make_px(0))),
EdgeStyleValue::create(*vertical_edge, vertical_offset.value_or(Length::make_px(0))));
} }
return nullptr; return nullptr;