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

Meta: Lazily initialize initial property values

This solves the longhands must be initialized before shorthands
problem by just initializing the value when it is first requested.

This will be needed for background-position-x/y which is a longhand
of a longhand, which otherwise breaks the longhands before shorthands
rule.
This commit is contained in:
MacDue 2023-04-02 22:46:22 +01:00 committed by Andreas Kling
parent 875c3d109f
commit de4ab4f69e

View file

@ -313,16 +313,16 @@ bool property_affects_stacking_context(PropertyID property_id)
NonnullRefPtr<StyleValue> property_initial_value(JS::Realm& context_realm, PropertyID property_id) NonnullRefPtr<StyleValue> property_initial_value(JS::Realm& context_realm, PropertyID property_id)
{ {
static Array<RefPtr<StyleValue>, to_underlying(last_property_id) + 1> initial_values; static Array<RefPtr<StyleValue>, to_underlying(last_property_id) + 1> initial_values;
static bool initialized = false; if (auto initial_value = initial_values[to_underlying(property_id)])
if (!initialized) { return initial_value.release_nonnull();
initialized = true;
Parser::ParsingContext parsing_context(context_realm);
)~~~");
// NOTE: Parsing a shorthand property requires that its longhands are already available here. // Lazily parse initial values as needed.
// So, we do this in two passes: First longhands, then shorthands. // This ensures the shorthands will always be able to get the initial values of their longhands.
// Probably we should build a dependency graph and then handle them in order, but this // This also now allows a longhand have its own longhand (like background-position-x).
// works for now! :^)
Parser::ParsingContext parsing_context(context_realm);
switch (property_id) {
)~~~");
auto output_initial_value_code = [&](auto& name, auto& object) { auto output_initial_value_code = [&](auto& name, auto& object) {
if (!object.has("initial"sv)) { if (!object.has("initial"sv)) {
@ -336,33 +336,27 @@ NonnullRefPtr<StyleValue> property_initial_value(JS::Realm& context_realm, Prope
auto member_generator = generator.fork(); auto member_generator = generator.fork();
member_generator.set("name:titlecase", title_casify(name)); member_generator.set("name:titlecase", title_casify(name));
member_generator.set("initial_value_string", initial_value_string); member_generator.set("initial_value_string", initial_value_string);
member_generator.append(R"~~~( member_generator.append(
R"~~~( case PropertyID::@name:titlecase@:
{ {
auto parsed_value = parse_css_value(parsing_context, "@initial_value_string@"sv, PropertyID::@name:titlecase@); auto parsed_value = parse_css_value(parsing_context, "@initial_value_string@"sv, PropertyID::@name:titlecase@);
VERIFY(!parsed_value.is_null()); VERIFY(!parsed_value.is_null());
initial_values[to_underlying(PropertyID::@name:titlecase@)] = parsed_value.release_nonnull(); auto initial_value = parsed_value.release_nonnull();
initial_values[to_underlying(PropertyID::@name:titlecase@)] = initial_value;
return initial_value;
} }
)~~~"); )~~~");
}; };
properties.for_each_member([&](auto& name, auto& value) { properties.for_each_member([&](auto& name, auto& value) {
VERIFY(value.is_object()); VERIFY(value.is_object());
if (value.as_object().has("longhands"sv))
return;
output_initial_value_code(name, value.as_object()); output_initial_value_code(name, value.as_object());
}); });
properties.for_each_member([&](auto& name, auto& value) { generator.append(
VERIFY(value.is_object()); R"~~~( default: VERIFY_NOT_REACHED();
if (!value.as_object().has("longhands"sv))
return;
output_initial_value_code(name, value.as_object());
});
generator.append(R"~~~(
} }
VERIFY_NOT_REACHED();
return *initial_values[to_underlying(property_id)];
} }
bool property_has_quirk(PropertyID property_id, Quirk quirk) bool property_has_quirk(PropertyID property_id, Quirk quirk)