From f29c18292908f1cea00505341f4611f07ef0276b Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Thu, 3 Apr 2025 08:56:47 -0700 Subject: [PATCH] script: Implement deprecated CSSStyleSheet members (#36313) Implements `rules`, `addRule()` and `removeRule()` for `CSSStyleSheet`. https://drafts.csswg.org/cssom/#legacy-css-style-sheet-members This is part of #36162 Testing: - `/css/css-cascade/at-scope-parsing.html` - `/css/css-conditional/at-supports-whitespace.html` - `/css/css-nesting/invalidation-004.html` - `/css/css-nesting/parsing.html` - `/css/css-nesting/serialize-group-rules-with-decls.html` - `/css/css-syntax/custom-property-rule-ambiguity.html` - `/css/css-syntax/invalid-nested-rules.html` - `/css/css-syntax/trailing-braces.html` - `/css/css-syntax/var-with-blocks.html` - `/css/css-transitions/parsing/starting-style-parsing.html` - `/css/cssom/CSSStyleSheet.html` - `/css/cssom/idlharness.html` - `/css/cssom/insertRule-across-context.html` Signed-off-by: Oriol Brufau --- components/script/dom/cssstylesheet.rs | 49 ++++++++++- .../webidls/CSSStyleSheet.webidl | 11 +++ .../css/css-cascade/at-scope-parsing.html.ini | 84 ------------------- .../at-supports-whitespace.html.ini | 48 ----------- .../css/css-nesting/invalidation-004.html.ini | 3 - .../wpt/meta/css/css-nesting/parsing.html.ini | 2 - .../serialize-group-rules-with-decls.html.ini | 45 ---------- .../custom-property-rule-ambiguity.html.ini | 12 --- .../css-syntax/invalid-nested-rules.html.ini | 3 - .../css/css-syntax/trailing-braces.html.ini | 3 - .../css/css-syntax/var-with-blocks.html.ini | 42 ---------- .../parsing/starting-style-parsing.html.ini | 12 --- .../wpt/meta/css/cssom/CSSStyleSheet.html.ini | 25 ------ tests/wpt/meta/css/cssom/idlharness.html.ini | 24 ------ .../cssom/insertRule-across-context.html.ini | 3 - 15 files changed, 57 insertions(+), 309 deletions(-) delete mode 100644 tests/wpt/meta/css/css-conditional/at-supports-whitespace.html.ini delete mode 100644 tests/wpt/meta/css/css-nesting/invalidation-004.html.ini delete mode 100644 tests/wpt/meta/css/css-nesting/parsing.html.ini delete mode 100644 tests/wpt/meta/css/css-nesting/serialize-group-rules-with-decls.html.ini delete mode 100644 tests/wpt/meta/css/css-syntax/custom-property-rule-ambiguity.html.ini delete mode 100644 tests/wpt/meta/css/css-syntax/invalid-nested-rules.html.ini delete mode 100644 tests/wpt/meta/css/css-syntax/trailing-braces.html.ini delete mode 100644 tests/wpt/meta/css/css-syntax/var-with-blocks.html.ini delete mode 100644 tests/wpt/meta/css/cssom/CSSStyleSheet.html.ini diff --git a/components/script/dom/cssstylesheet.rs b/components/script/dom/cssstylesheet.rs index e5d802eb532..12358f97028 100644 --- a/components/script/dom/cssstylesheet.rs +++ b/components/script/dom/cssstylesheet.rs @@ -10,6 +10,7 @@ use style::shared_lock::SharedRwLock; use style::stylesheets::{CssRuleTypes, Stylesheet as StyleStyleSheet}; use crate::dom::bindings::codegen::Bindings::CSSStyleSheetBinding::CSSStyleSheetMethods; +use crate::dom::bindings::codegen::GenericBindings::CSSRuleListBinding::CSSRuleList_Binding::CSSRuleListMethods; use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object}; use crate::dom::bindings::root::{DomRoot, MutNullableDom}; @@ -125,7 +126,7 @@ impl CSSStyleSheet { } impl CSSStyleSheetMethods for CSSStyleSheet { - // https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssrules + /// fn GetCssRules(&self) -> Fallible> { if !self.origin_clean.get() { return Err(Error::Security); @@ -133,7 +134,7 @@ impl CSSStyleSheetMethods for CSSStyleSheet { Ok(self.rulelist()) } - // https://drafts.csswg.org/cssom/#dom-cssstylesheet-insertrule + /// fn InsertRule(&self, rule: DOMString, index: u32) -> Fallible { if !self.origin_clean.get() { return Err(Error::Security); @@ -142,11 +143,53 @@ impl CSSStyleSheetMethods for CSSStyleSheet { .insert_rule(&rule, index, CssRuleTypes::default(), None, CanGc::note()) } - // https://drafts.csswg.org/cssom/#dom-cssstylesheet-deleterule + /// fn DeleteRule(&self, index: u32) -> ErrorResult { if !self.origin_clean.get() { return Err(Error::Security); } self.rulelist().remove_rule(index) } + + /// + fn GetRules(&self) -> Fallible> { + self.GetCssRules() + } + + /// + fn RemoveRule(&self, index: u32) -> ErrorResult { + self.DeleteRule(index) + } + + /// + fn AddRule( + &self, + selector: DOMString, + block: DOMString, + optional_index: Option, + ) -> Fallible { + // > 1. Let *rule* be an empty string. + // > 2. Append *selector* to *rule*. + let mut rule = selector; + + // > 3. Append " { " to *rule*. + // > 4. If *block* is not empty, append *block*, followed by a space, to *rule*. + // > 5. Append "}" to *rule*. + if block.is_empty() { + rule.push_str(" { }"); + } else { + rule.push_str(" { "); + rule.push_str(block.str()); + rule.push_str(" } "); + }; + + // > 6. Let *index* be *optionalIndex* if provided, or the number of CSS rules in the stylesheet otherwise. + let index = optional_index.unwrap_or_else(|| self.rulelist().Length()); + + // > 7. Call `insertRule()`, with *rule* and *index* as arguments. + self.InsertRule(rule, index)?; + + // > 8. Return -1. + Ok(-1) + } } diff --git a/components/script_bindings/webidls/CSSStyleSheet.webidl b/components/script_bindings/webidls/CSSStyleSheet.webidl index 0133eefd8a1..701a5637eb2 100644 --- a/components/script_bindings/webidls/CSSStyleSheet.webidl +++ b/components/script_bindings/webidls/CSSStyleSheet.webidl @@ -10,3 +10,14 @@ interface CSSStyleSheet : StyleSheet { [Throws] unsigned long insertRule(DOMString rule, optional unsigned long index = 0); [Throws] undefined deleteRule(unsigned long index); }; + +// https://drafts.csswg.org/cssom/#legacy-css-style-sheet-members +partial interface CSSStyleSheet { + [Throws, SameObject] readonly attribute CSSRuleList rules; + [Throws] long addRule( + optional DOMString selector = "undefined", + optional DOMString style = "undefined", + optional unsigned long index + ); + [Throws] undefined removeRule(optional unsigned long index = 0); +}; diff --git a/tests/wpt/meta/css/css-cascade/at-scope-parsing.html.ini b/tests/wpt/meta/css/css-cascade/at-scope-parsing.html.ini index b0d1c3d93e8..55c14a67536 100644 --- a/tests/wpt/meta/css/css-cascade/at-scope-parsing.html.ini +++ b/tests/wpt/meta/css/css-cascade/at-scope-parsing.html.ini @@ -76,87 +76,3 @@ [@scope (> &) to (>>) is valid] expected: FAIL - - [@scope div is not valid] - expected: FAIL - - [@scope (.a) unknown (.c) is not valid] - expected: FAIL - - [@scope (.a) to unknown (.c) is not valid] - expected: FAIL - - [@scope (.a) 1px (.c) is not valid] - expected: FAIL - - [@scope (.a) to unknown(c) is not valid] - expected: FAIL - - [@scope unknown(.a) is not valid] - expected: FAIL - - [@scope 1px is not valid] - expected: FAIL - - [@scope creep is not valid] - expected: FAIL - - [@scope ))) is not valid] - expected: FAIL - - [@scope ( is not valid] - expected: FAIL - - [@scope ( {} is not valid] - expected: FAIL - - [@scope to is not valid] - expected: FAIL - - [@scope } is not valid] - expected: FAIL - - [@scope (.a is not valid] - expected: FAIL - - [@scope (.a to (.b) is not valid] - expected: FAIL - - [@scope ( to (.b) is not valid] - expected: FAIL - - [@scope (.a) from (.c) is not valid] - expected: FAIL - - [@scope (.c <> .d) is not valid] - expected: FAIL - - [@scope (.a, .c <> .d) is not valid] - expected: FAIL - - [@scope (.a <> .b, .c) is not valid] - expected: FAIL - - [@scope (div::before) is not valid] - expected: FAIL - - [@scope (div::after) is not valid] - expected: FAIL - - [@scope (slotted(div)) is not valid] - expected: FAIL - - [@scope (.a) to (div::before) is not valid] - expected: FAIL - - [@scope (> &) to (>>) is not valid] - expected: FAIL - - [@scope () is not valid] - expected: FAIL - - [@scope to () is not valid] - expected: FAIL - - [@scope () to () is not valid] - expected: FAIL diff --git a/tests/wpt/meta/css/css-conditional/at-supports-whitespace.html.ini b/tests/wpt/meta/css/css-conditional/at-supports-whitespace.html.ini deleted file mode 100644 index f6785bccb2c..00000000000 --- a/tests/wpt/meta/css/css-conditional/at-supports-whitespace.html.ini +++ /dev/null @@ -1,48 +0,0 @@ -[at-supports-whitespace.html] - [@supports ((a)) {}] - expected: FAIL - - [@supports ((a) ) {}] - expected: FAIL - - [@supports ( (a)) {}] - expected: FAIL - - [@supports ( (a) ) {}] - expected: FAIL - - [@supports (not (a)) {}] - expected: FAIL - - [@supports (not (a) ) {}] - expected: FAIL - - [@supports ( not (a)) {}] - expected: FAIL - - [@supports ( not (a) ) {}] - expected: FAIL - - [@supports ((a) and (b)) {}] - expected: FAIL - - [@supports ((a) and (b) ) {}] - expected: FAIL - - [@supports ( (a) and (b)) {}] - expected: FAIL - - [@supports ( (a) and (b) ) {}] - expected: FAIL - - [@supports ((a) or (b)) {}] - expected: FAIL - - [@supports ((a) or (b) ) {}] - expected: FAIL - - [@supports ( (a) or (b)) {}] - expected: FAIL - - [@supports ( (a) or (b) ) {}] - expected: FAIL diff --git a/tests/wpt/meta/css/css-nesting/invalidation-004.html.ini b/tests/wpt/meta/css/css-nesting/invalidation-004.html.ini deleted file mode 100644 index 13b64ab6de9..00000000000 --- a/tests/wpt/meta/css/css-nesting/invalidation-004.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[invalidation-004.html] - [CSS Selectors nested invalidation through @media by selectorText] - expected: FAIL diff --git a/tests/wpt/meta/css/css-nesting/parsing.html.ini b/tests/wpt/meta/css/css-nesting/parsing.html.ini deleted file mode 100644 index 24cf7d970e3..00000000000 --- a/tests/wpt/meta/css/css-nesting/parsing.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[parsing.html] - expected: ERROR diff --git a/tests/wpt/meta/css/css-nesting/serialize-group-rules-with-decls.html.ini b/tests/wpt/meta/css/css-nesting/serialize-group-rules-with-decls.html.ini deleted file mode 100644 index 64a205e15f5..00000000000 --- a/tests/wpt/meta/css/css-nesting/serialize-group-rules-with-decls.html.ini +++ /dev/null @@ -1,45 +0,0 @@ -[serialize-group-rules-with-decls.html] - [Declarations are serialized on one line, rules on two.] - expected: FAIL - - [Mixed declarations/rules are on two lines.] - expected: FAIL - - [Implicit rule is serialized] - expected: FAIL - - [Implicit rule not removed] - expected: FAIL - - [Implicit + empty hover rule] - expected: FAIL - - [Implicit like rule not in first position] - expected: FAIL - - [Two implicit-like rules] - expected: FAIL - - [Implicit like rule after decls] - expected: FAIL - - [Implicit like rule after decls, missing closing braces] - expected: FAIL - - [Implicit like rule with other selectors] - expected: FAIL - - [Implicit-like rule in style rule] - expected: FAIL - - [Empty conditional rule] - expected: FAIL - - [Empty style rule] - expected: FAIL - - [Empty conditional inside style rule] - expected: FAIL - - [Empty style inside conditional] - expected: FAIL diff --git a/tests/wpt/meta/css/css-syntax/custom-property-rule-ambiguity.html.ini b/tests/wpt/meta/css/css-syntax/custom-property-rule-ambiguity.html.ini deleted file mode 100644 index d0ceac7c522..00000000000 --- a/tests/wpt/meta/css/css-syntax/custom-property-rule-ambiguity.html.ini +++ /dev/null @@ -1,12 +0,0 @@ -[custom-property-rule-ambiguity.html] - [Rule that looks like a custom property declaration is ignored] - expected: FAIL - - [Rule that looks like an invalid custom property declaration is ignored] - expected: FAIL - - [Nested rule that looks like a custom property declaration] - expected: FAIL - - [Nested rule that looks like an invalid custom property declaration] - expected: FAIL diff --git a/tests/wpt/meta/css/css-syntax/invalid-nested-rules.html.ini b/tests/wpt/meta/css/css-syntax/invalid-nested-rules.html.ini deleted file mode 100644 index d311978e78c..00000000000 --- a/tests/wpt/meta/css/css-syntax/invalid-nested-rules.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[invalid-nested-rules.html] - [Continues parsing after block on invalid rule error] - expected: FAIL diff --git a/tests/wpt/meta/css/css-syntax/trailing-braces.html.ini b/tests/wpt/meta/css/css-syntax/trailing-braces.html.ini deleted file mode 100644 index b2950bf88b1..00000000000 --- a/tests/wpt/meta/css/css-syntax/trailing-braces.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[trailing-braces.html] - [Trailing braces are not valid] - expected: FAIL diff --git a/tests/wpt/meta/css/css-syntax/var-with-blocks.html.ini b/tests/wpt/meta/css/css-syntax/var-with-blocks.html.ini deleted file mode 100644 index 59a5b3aca44..00000000000 --- a/tests/wpt/meta/css/css-syntax/var-with-blocks.html.ini +++ /dev/null @@ -1,42 +0,0 @@ -[var-with-blocks.html] - [Plain var()] - expected: FAIL - - [Whole-value block with var()] - expected: FAIL - - [Whole-value block with var() (spaces)] - expected: FAIL - - [Trailing block, leading var()] - expected: FAIL - - [Leading block, trailing var()] - expected: FAIL - - [In-block var() with trailing token] - expected: FAIL - - [In-block var() with leading token] - expected: FAIL - - [Plain var() (custom property)] - expected: FAIL - - [Whole-value block with var() (custom property)] - expected: FAIL - - [Whole-value block with var() (spaces, custom property)] - expected: FAIL - - [Trailing block, leading var() (custom property)] - expected: FAIL - - [Leading block, trailing var() (custom property)] - expected: FAIL - - [In-block var() with trailing token (custom property)] - expected: FAIL - - [In-block var() with leading token (custom property)] - expected: FAIL diff --git a/tests/wpt/meta/css/css-transitions/parsing/starting-style-parsing.html.ini b/tests/wpt/meta/css/css-transitions/parsing/starting-style-parsing.html.ini index bbaf0376001..1b1e0430b62 100644 --- a/tests/wpt/meta/css/css-transitions/parsing/starting-style-parsing.html.ini +++ b/tests/wpt/meta/css/css-transitions/parsing/starting-style-parsing.html.ini @@ -1,15 +1,3 @@ [starting-style-parsing.html] [@starting-style is valid] expected: FAIL - - [@starting-style div is not valid] - expected: FAIL - - [@starting-style () is not valid] - expected: FAIL - - [@starting-style ( {} is not valid] - expected: FAIL - - [@starting-style } is not valid] - expected: FAIL diff --git a/tests/wpt/meta/css/cssom/CSSStyleSheet.html.ini b/tests/wpt/meta/css/cssom/CSSStyleSheet.html.ini deleted file mode 100644 index a23f10e20df..00000000000 --- a/tests/wpt/meta/css/cssom/CSSStyleSheet.html.ini +++ /dev/null @@ -1,25 +0,0 @@ -[CSSStyleSheet.html] - [addRule with no argument adds "undefined" selector] - expected: FAIL - - [removeRule on empty style sheet throws] - expected: FAIL - - [cssRules and rules are the same object] - expected: FAIL - - [addRule with index greater than length throws] - expected: FAIL - - [addRule with #foo selectors] - expected: FAIL - - [removeRule(1)] - expected: FAIL - - [removeRule with no argument removes first rule] - expected: FAIL - - [addRule with @media rule] - expected: FAIL - diff --git a/tests/wpt/meta/css/cssom/idlharness.html.ini b/tests/wpt/meta/css/cssom/idlharness.html.ini index 1a49cc5deb2..3a9e207afdb 100644 --- a/tests/wpt/meta/css/cssom/idlharness.html.ini +++ b/tests/wpt/meta/css/cssom/idlharness.html.ini @@ -53,9 +53,6 @@ [SVGStyleElement interface: attribute sheet] expected: FAIL - [CSSStyleSheet interface: attribute rules] - expected: FAIL - [CSSStyleDeclaration interface: sheet.cssRules[2\].cssRules[0\].style must inherit property "setProperty(CSSOMString, CSSOMString, optional CSSOMString)" with the proper type] expected: FAIL @@ -101,9 +98,6 @@ [CSSStyleDeclaration interface: svg_element.style must inherit property "cssFloat" with the proper type] expected: FAIL - [CSSStyleSheet interface: calling addRule(optional DOMString, optional DOMString, optional unsigned long) on sheet with too few arguments must throw TypeError] - expected: FAIL - [CSSStyleDeclaration must be primary interface of sheet.cssRules[2\].cssRules[0\].style] expected: FAIL @@ -161,9 +155,6 @@ [CSSPageRule interface: existence and properties of interface prototype object's @@unscopables property] expected: FAIL - [CSSStyleSheet interface: operation addRule(optional DOMString, optional DOMString, optional unsigned long)] - expected: FAIL - [CSSRule interface: sheet.cssRules[1\] must inherit property "parentRule" with the proper type] expected: FAIL @@ -173,9 +164,6 @@ [CSSPageRule interface: existence and properties of interface object] expected: FAIL - [CSSStyleSheet interface: sheet must inherit property "rules" with the proper type] - expected: FAIL - [CSSPageRule must be primary interface of sheet.cssRules[2\]] expected: FAIL @@ -230,9 +218,6 @@ [CSSPageRule interface: sheet.cssRules[2\] must inherit property "selectorText" with the proper type] expected: FAIL - [CSSStyleSheet interface: sheet must inherit property "addRule(optional DOMString, optional DOMString, optional unsigned long)" with the proper type] - expected: FAIL - [CSSMarginRule interface: existence and properties of interface prototype object's @@unscopables property] expected: FAIL @@ -284,9 +269,6 @@ [CSSStyleDeclaration interface: sheet.cssRules[2\].style must inherit property "cssText" with the proper type] expected: FAIL - [CSSStyleSheet interface: operation removeRule(optional unsigned long)] - expected: FAIL - [Stringification of sheet.cssRules[4\]] expected: FAIL @@ -347,9 +329,6 @@ [CSSRule interface: sheet.cssRules[4\] must inherit property "cssText" with the proper type] expected: FAIL - [CSSStyleSheet interface: sheet must inherit property "removeRule(optional unsigned long)" with the proper type] - expected: FAIL - [CSSMarginRule interface: existence and properties of interface prototype object's "constructor" property] expected: FAIL @@ -407,9 +386,6 @@ [CSSMarginRule interface: attribute style] expected: FAIL - [CSSStyleSheet interface: calling removeRule(optional unsigned long) on sheet with too few arguments must throw TypeError] - expected: FAIL - [CSSStyleDeclaration interface: sheet.cssRules[2\].style must inherit property "getPropertyValue(CSSOMString)" with the proper type] expected: FAIL diff --git a/tests/wpt/meta/css/cssom/insertRule-across-context.html.ini b/tests/wpt/meta/css/cssom/insertRule-across-context.html.ini index 83f82072f63..bbf010a5559 100644 --- a/tests/wpt/meta/css/cssom/insertRule-across-context.html.ini +++ b/tests/wpt/meta/css/cssom/insertRule-across-context.html.ini @@ -1,6 +1,3 @@ [insertRule-across-context.html] - [The constructor of inserted rule object must be from iframe] - expected: FAIL - [The constructor of inserted rule object must be from iframe for new CSSStyleSheet()] expected: FAIL