1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-10 18:10:56 +09:00

LibWeb/CSS: Parse nested declarations in insert_a_css_rule()

The spec algorithm changed at some point to support nested declarations,
but I only just noticed. The subtest regression is one we were passing
incorrectly.
This commit is contained in:
Sam Atkins 2025-04-14 15:36:42 +01:00
parent fa8bbfa6a5
commit 3d1665cc80
Notes: github-actions[bot] 2025-04-23 10:40:15 +00:00
4 changed files with 40 additions and 20 deletions

View file

@ -41,10 +41,14 @@ void CSSGroupingRule::clear_caches()
rule->clear_caches(); rule->clear_caches();
} }
// https://drafts.csswg.org/cssom/#dom-cssgroupingrule-insertrule
WebIDL::ExceptionOr<u32> CSSGroupingRule::insert_rule(StringView rule, u32 index) WebIDL::ExceptionOr<u32> CSSGroupingRule::insert_rule(StringView rule, u32 index)
{ {
TRY(m_rules->insert_a_css_rule(rule, index)); // The insertRule(rule, index) method must return the result of invoking insert a CSS rule rule into the child CSS
// NOTE: The spec doesn't say where to set the parent rule, so we'll do it here. // rules at index, with the nested flag set.
TRY(m_rules->insert_a_css_rule(rule, index, CSSRuleList::Nested::Yes));
// AD-HOC: The spec doesn't say where to set the parent rule, so we'll do it here.
m_rules->item(index)->set_parent_rule(this); m_rules->item(index)->set_parent_rule(this);
return index; return index;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org> * Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -11,6 +11,7 @@
#include <LibWeb/CSS/CSSKeyframesRule.h> #include <LibWeb/CSS/CSSKeyframesRule.h>
#include <LibWeb/CSS/CSSLayerBlockRule.h> #include <LibWeb/CSS/CSSLayerBlockRule.h>
#include <LibWeb/CSS/CSSMediaRule.h> #include <LibWeb/CSS/CSSMediaRule.h>
#include <LibWeb/CSS/CSSNestedDeclarations.h>
#include <LibWeb/CSS/CSSRule.h> #include <LibWeb/CSS/CSSRule.h>
#include <LibWeb/CSS/CSSRuleList.h> #include <LibWeb/CSS/CSSRuleList.h>
#include <LibWeb/CSS/CSSSupportsRule.h> #include <LibWeb/CSS/CSSSupportsRule.h>
@ -52,8 +53,8 @@ void CSSRuleList::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_rules); visitor.visit(m_rules);
} }
// https://www.w3.org/TR/cssom/#insert-a-css-rule // https://drafts.csswg.org/cssom/#insert-a-css-rule
WebIDL::ExceptionOr<unsigned> CSSRuleList::insert_a_css_rule(Variant<StringView, CSSRule*> rule, u32 index) WebIDL::ExceptionOr<unsigned> CSSRuleList::insert_a_css_rule(Variant<StringView, CSSRule*> rule, u32 index, Nested nested)
{ {
// 1. Set length to the number of items in list. // 1. Set length to the number of items in list.
auto length = m_rules.size(); auto length = m_rules.size();
@ -69,24 +70,37 @@ WebIDL::ExceptionOr<unsigned> CSSRuleList::insert_a_css_rule(Variant<StringView,
CSSRule* new_rule = nullptr; CSSRule* new_rule = nullptr;
if (rule.has<StringView>()) { if (rule.has<StringView>()) {
new_rule = parse_css_rule( new_rule = parse_css_rule(
CSS::Parser::ParsingParams { realm() }, Parser::ParsingParams { realm() },
rule.get<StringView>()); rule.get<StringView>());
} else { } else {
new_rule = rule.get<CSSRule*>(); new_rule = rule.get<CSSRule*>();
} }
// 4. If new rule is a syntax error, throw a SyntaxError exception. // 4. If new rule is a syntax error, and nested is set, perform the following substeps:
if (!new_rule && nested == Nested::Yes) {
// - Set declarations to the results of performing parse a CSS declaration block, on argument rule.
auto declarations = parse_css_property_declaration_block(Parser::ParsingParams { realm() }, rule.get<StringView>());
// - If declarations is empty, throw a SyntaxError exception.
if (declarations.custom_properties.is_empty() && declarations.properties.is_empty())
return WebIDL::SyntaxError::create(realm(), "Unable to parse CSS declarations block."_string);
// - Otherwise, set new rule to a new nested declarations rule with declarations as it contents.
new_rule = CSSNestedDeclarations::create(realm(), CSSStyleProperties::create(realm(), move(declarations.properties), move(declarations.custom_properties)));
}
// 5. If new rule is a syntax error, throw a SyntaxError exception.
if (!new_rule) if (!new_rule)
return WebIDL::SyntaxError::create(realm(), "Unable to parse CSS rule."_string); return WebIDL::SyntaxError::create(realm(), "Unable to parse CSS rule."_string);
// FIXME: 5. If new rule cannot be inserted into list at the zero-index position index due to constraints specified by CSS, then throw a HierarchyRequestError exception. [CSS21] // FIXME: 6. If new rule cannot be inserted into list at the zero-index position index due to constraints specified by CSS, then throw a HierarchyRequestError exception. [CSS21]
// FIXME: 6. If new rule is an @namespace at-rule, and list contains anything other than @import at-rules, and @namespace at-rules, throw an InvalidStateError exception. // FIXME: 7. If new rule is an @namespace at-rule, and list contains anything other than @import at-rules, and @namespace at-rules, throw an InvalidStateError exception.
// 7. Insert new rule into list at the zero-indexed position index. // 8. Insert new rule into list at the zero-indexed position index.
m_rules.insert(index, *new_rule); m_rules.insert(index, *new_rule);
// 8. Return index. // 9. Return index.
if (on_change) if (on_change)
on_change(); on_change();
return index; return index;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org> * Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org> * Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2023, Luke Wilde <lukew@serenityos.org> * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
* *
@ -9,8 +9,6 @@
#pragma once #pragma once
#include <AK/Function.h> #include <AK/Function.h>
#include <AK/Iterator.h>
#include <AK/RefPtr.h>
#include <LibWeb/Bindings/PlatformObject.h> #include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/CSS/CSSRule.h> #include <LibWeb/CSS/CSSRule.h>
#include <LibWeb/Forward.h> #include <LibWeb/Forward.h>
@ -55,7 +53,11 @@ public:
virtual Optional<JS::Value> item_value(size_t index) const override; virtual Optional<JS::Value> item_value(size_t index) const override;
WebIDL::ExceptionOr<void> remove_a_css_rule(u32 index); WebIDL::ExceptionOr<void> remove_a_css_rule(u32 index);
WebIDL::ExceptionOr<unsigned> insert_a_css_rule(Variant<StringView, CSSRule*>, u32 index); enum class Nested {
No,
Yes,
};
WebIDL::ExceptionOr<unsigned> insert_a_css_rule(Variant<StringView, CSSRule*>, u32 index, Nested = Nested::No);
void for_each_effective_rule(TraversalOrder, Function<void(CSSRule const&)> const& callback) const; void for_each_effective_rule(TraversalOrder, Function<void(CSSRule const&)> const& callback) const;
// Returns whether the match state of any media queries changed after evaluation. // Returns whether the match state of any media queries changed after evaluation.

View file

@ -2,17 +2,17 @@ Harness status: OK
Found 12 tests Found 12 tests
6 Pass 7 Pass
6 Fail 5 Fail
Fail Trailing declarations Fail Trailing declarations
Fail Mixed declarations Fail Mixed declarations
Fail CSSNestedDeclarations.style Fail CSSNestedDeclarations.style
Pass Nested group rule Pass Nested group rule
Pass Nested @scope rule Pass Nested @scope rule
Fail Inner rule starting with an ident Fail Inner rule starting with an ident
Fail Inserting a CSSNestedDeclaration rule into style rule Pass Inserting a CSSNestedDeclaration rule into style rule
Fail Inserting a CSSNestedDeclaration rule into nested group rule Pass Inserting a CSSNestedDeclaration rule into nested group rule
Pass Attempting to insert a CSSNestedDeclaration rule into top-level @media rule Fail Attempting to insert a CSSNestedDeclaration rule into top-level @media rule
Pass Attempting to insert a CSSNestedDeclaration rule into a stylesheet Pass Attempting to insert a CSSNestedDeclaration rule into a stylesheet
Pass Attempting to insert a CSSNestedDeclaration rule, empty block Pass Attempting to insert a CSSNestedDeclaration rule, empty block
Pass Attempting to insert a CSSNestedDeclaration rule, all invalid declarations Pass Attempting to insert a CSSNestedDeclaration rule, all invalid declarations