LibWeb: Parse @keyframes name as logical string, not token text

The @keyframes parser was storing the keyframes name via
Token::to_string(), which keeps a string token in its quoted,
serialized form. That meant @keyframes "foo" was stored as
"\"foo\"" while animation-name: "foo" resolved to "foo",
and the two never matched.

Store the unquoted string or identifier value so the @keyframes name
and the animation-name reference compare on the same string.
This commit is contained in:
Andreas Kling
2026-04-21 20:48:11 +02:00
committed by Andreas Kling
parent a941b8a2a1
commit e4800b2498
Notes: github-actions[bot] 2026-04-22 19:00:23 +00:00
3 changed files with 28 additions and 1 deletions

View File

@@ -515,7 +515,9 @@ GC::Ptr<CSSKeyframesRule> Parser::convert_to_keyframes_rule(AtRule const& rule)
return {};
}
auto name = name_token.to_string();
// Store the logical keyframes name instead of the serialized token text so @keyframes "foo" and
// animation-name: "foo" compare on the same value.
auto name = name_token.is(Token::Type::String) ? name_token.string() : name_token.ident();
GC::RootVector<GC::Ref<CSSRule>> keyframes(realm().heap());
rule.for_each_as_qualified_rule_list([&](auto& qualified_rule) {

View File

@@ -0,0 +1,2 @@
opacity before keyframes: 1
opacity after keyframes: 0.25

View File

@@ -0,0 +1,23 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<style id="test-style">
#target {
animation-name: "123fade";
animation-duration: 1s;
animation-fill-mode: both;
}
</style>
<div id="target">target</div>
<script>
asyncTest(async done => {
const target = document.getElementById("target");
const styleSheet = document.getElementById("test-style").sheet;
println(`opacity before keyframes: ${getComputedStyle(target).opacity}`);
styleSheet.insertRule('@keyframes "123fade" { from { opacity: 0.25; } to { opacity: 0.25; } }', styleSheet.cssRules.length);
await animationFrame();
println(`opacity after keyframes: ${getComputedStyle(target).opacity}`);
done();
});
</script>