diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs index 8e17e50a8fa..572550b2bc9 100644 --- a/components/script/dom/cssstyledeclaration.rs +++ b/components/script/dom/cssstyledeclaration.rs @@ -104,6 +104,8 @@ impl CSSStyleOwner { f(&mut *pdb.write_with(&mut guard), &mut changed) }; if changed { + // If this is changed, see also + // CSSStyleRule::SetSelectorText, which does the same thing. rule.global().as_window().Document().invalidate_stylesheets(); } result diff --git a/components/script/dom/cssstylerule.rs b/components/script/dom/cssstylerule.rs index 607f2cfb816..f9df3afc2ad 100644 --- a/components/script/dom/cssstylerule.rs +++ b/components/script/dom/cssstylerule.rs @@ -2,7 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use cssparser::{Parser as CssParser, ParserInput as CssParserInput}; +use cssparser::ToCss; use dom::bindings::codegen::Bindings::CSSStyleRuleBinding::{self, CSSStyleRuleMethods}; +use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, reflect_dom_object}; @@ -12,9 +15,12 @@ use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration, CSSSt use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; +use selectors::parser::SelectorList; +use std::mem; +use style::selector_parser::SelectorParser; use style::shared_lock::{Locked, ToCssWithGuard}; use style::stylearc::Arc; -use style::stylesheets::StyleRule; +use style::stylesheets::{StyleRule, Origin}; #[dom_struct] pub struct CSSStyleRule { @@ -71,4 +77,33 @@ impl CSSStyleRuleMethods for CSSStyleRule { ) }) } + + // https://drafts.csswg.org/cssom/#dom-cssstylerule-selectortext + fn SelectorText(&self) -> DOMString { + let guard = self.cssrule.shared_lock().read(); + let stylerule = self.stylerule.read_with(&guard); + return DOMString::from_string(stylerule.selectors.to_css_string()); + } + + // https://drafts.csswg.org/cssom/#dom-cssstylerule-selectortext + fn SetSelectorText(&self, value: DOMString) { + // It's not clear from the spec if we should use the stylesheet's namespaces. + // https://github.com/w3c/csswg-drafts/issues/1511 + let namespaces = self.cssrule.parent_stylesheet().style_stylesheet().contents.namespaces.read(); + let parser = SelectorParser { + stylesheet_origin: Origin::Author, + namespaces: &namespaces, + }; + let mut css_parser = CssParserInput::new(&*value); + let mut css_parser = CssParser::new(&mut css_parser); + if let Ok(mut s) = SelectorList::parse(&parser, &mut css_parser) { + // This mirrors what we do in CSSStyleOwner::mutate_associated_block. + let mut guard = self.cssrule.shared_lock().write(); + let mut stylerule = self.stylerule.write_with(&mut guard); + mem::swap(&mut stylerule.selectors, &mut s); + // It seems like we will want to avoid having to invalidate all + // stylesheets eventually! + self.global().as_window().Document().invalidate_stylesheets(); + } + } } diff --git a/components/script/dom/webidls/CSSStyleRule.webidl b/components/script/dom/webidls/CSSStyleRule.webidl index 145650a916c..8b85b863bb2 100644 --- a/components/script/dom/webidls/CSSStyleRule.webidl +++ b/components/script/dom/webidls/CSSStyleRule.webidl @@ -5,6 +5,6 @@ // https://drafts.csswg.org/cssom/#the-cssstylerule-interface [Exposed=Window] interface CSSStyleRule : CSSRule { - // attribute DOMString selectorText; + attribute DOMString selectorText; [SameObject, PutForwards=cssText] readonly attribute CSSStyleDeclaration style; }; diff --git a/components/selectors/attr.rs b/components/selectors/attr.rs index da208c94b1f..b71be2cca73 100644 --- a/components/selectors/attr.rs +++ b/components/selectors/attr.rs @@ -78,13 +78,15 @@ pub enum AttrSelectorOperator { impl ToCss for AttrSelectorOperator { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + // https://drafts.csswg.org/cssom/#serializing-selectors + // See "attribute selector". dest.write_str(match *self { - AttrSelectorOperator::Equal => " = ", - AttrSelectorOperator::Includes => " ~= ", - AttrSelectorOperator::DashMatch => " |= ", - AttrSelectorOperator::Prefix => " ^= ", - AttrSelectorOperator::Substring => " *= ", - AttrSelectorOperator::Suffix => " $= ", + AttrSelectorOperator::Equal => "=", + AttrSelectorOperator::Includes => "~=", + AttrSelectorOperator::DashMatch => "|=", + AttrSelectorOperator::Prefix => "^=", + AttrSelectorOperator::Substring => "*=", + AttrSelectorOperator::Suffix => "$=", }) } } diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index 676c1946822..022e3a06647 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -1934,7 +1934,7 @@ pub mod tests { ].into_boxed_slice()) ), specificity(0, 0, 1)) )))); - assert_eq!(parse("[attr |= \"foo\"]"), Ok(SelectorList::from_vec(vec!( + assert_eq!(parse("[attr|=\"foo\"]"), Ok(SelectorList::from_vec(vec!( Selector::from_vec(vec!( Component::AttributeInNoNamespace { local_name: DummyAtom::from("attr"), @@ -1993,7 +1993,7 @@ pub mod tests { parser.default_ns = None; assert!(parse(":not(#provel.old)").is_err()); assert!(parse(":not(#provel > old)").is_err()); - assert!(parse("table[rules]:not([rules = \"none\"]):not([rules = \"\"])").is_ok()); + assert!(parse("table[rules]:not([rules=\"none\"]):not([rules=\"\"])").is_ok()); assert_eq!(parse(":not(#provel)"), Ok(SelectorList::from_vec(vec!( Selector::from_vec(vec!(Component::Negation(vec!( Component::ID(DummyAtom::from("provel")), diff --git a/tests/unit/style/parsing/selectors.rs b/tests/unit/style/parsing/selectors.rs index 4f9d931197b..15611dd093c 100644 --- a/tests/unit/style/parsing/selectors.rs +++ b/tests/unit/style/parsing/selectors.rs @@ -23,5 +23,5 @@ fn test_selectors() { assert_roundtrip!(parse_selector, "div"); assert_roundtrip!(parse_selector, "svg|circle"); assert_roundtrip!(parse_selector, "p:before", "p::before"); - assert_roundtrip!(parse_selector, "[border = \"0\"]:-servo-nonzero-border ~ ::-servo-details-summary"); + assert_roundtrip!(parse_selector, "[border=\"0\"]:-servo-nonzero-border ~ ::-servo-details-summary"); } diff --git a/tests/wpt/metadata-css/cssom-1_dev/html/cssstylerule.htm.ini b/tests/wpt/metadata-css/cssom-1_dev/html/cssstylerule.htm.ini index 70d0be16aa7..8ce322a482b 100644 --- a/tests/wpt/metadata-css/cssom-1_dev/html/cssstylerule.htm.ini +++ b/tests/wpt/metadata-css/cssom-1_dev/html/cssstylerule.htm.ini @@ -15,6 +15,3 @@ [StyleRule_properties] expected: FAIL - [StyleRule_properties_values] - expected: FAIL - diff --git a/tests/wpt/metadata-css/cssom-1_dev/html/interfaces.htm.ini b/tests/wpt/metadata-css/cssom-1_dev/html/interfaces.htm.ini index 5b782cc150e..53dc0324df2 100644 --- a/tests/wpt/metadata-css/cssom-1_dev/html/interfaces.htm.ini +++ b/tests/wpt/metadata-css/cssom-1_dev/html/interfaces.htm.ini @@ -117,12 +117,6 @@ [CSSRule interface: attribute parentRule] expected: FAIL - [CSSStyleRule interface: attribute selectorText] - expected: FAIL - - [CSSStyleRule interface: style_element.sheet.cssRules[0\] must inherit property "selectorText" with the proper type (0)] - expected: FAIL - [CSSRule interface: style_element.sheet.cssRules[0\] must inherit property "parentRule" with the proper type (10)] expected: FAIL diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index 58ee872a951..45a49991d1e 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -160103,6 +160103,18 @@ {} ] ], + "cssom/selectorText-modification-restyle-001.html": [ + [ + "/cssom/selectorText-modification-restyle-001.html", + [ + [ + "/cssom/selectorText-modification-restyle-001-ref.html", + "==" + ] + ], + {} + ] + ], "html/dom/elements/global-attributes/dir_auto-EN-L.html": [ [ "/html/dom/elements/global-attributes/dir_auto-EN-L.html", @@ -274610,6 +274622,11 @@ {} ] ], + "cssom/selectorText-modification-restyle-001-ref.html": [ + [ + {} + ] + ], "cssom/stylesheet-same-origin.css": [ [ {} @@ -553977,6 +553994,14 @@ "002777c7c598eb1131ab625365ee3fe08650e830", "testharness" ], + "cssom/selectorText-modification-restyle-001-ref.html": [ + "4fbe124f09131f30e5c68154774246e5cd15b14a", + "support" + ], + "cssom/selectorText-modification-restyle-001.html": [ + "ac5a5414dd849151c3ca6348c90c0f4e80a09b75", + "reftest" + ], "cssom/serialization-CSSDeclaration-with-important.html": [ "ecc8b95fb2d71cacee271f4fea2fc16f35cdba57", "testharness" diff --git a/tests/wpt/metadata/cssom/CSSStyleRule.html.ini b/tests/wpt/metadata/cssom/CSSStyleRule.html.ini index 4b0ba813427..5cdf89a296a 100644 --- a/tests/wpt/metadata/cssom/CSSStyleRule.html.ini +++ b/tests/wpt/metadata/cssom/CSSStyleRule.html.ini @@ -9,9 +9,3 @@ [Values of CSSRule attributes] expected: FAIL - [Values of CSSStyleRule attributes] - expected: FAIL - - [Existence and type of CSSStyleRule attributes] - expected: FAIL - diff --git a/tests/wpt/metadata/cssom/interfaces.html.ini b/tests/wpt/metadata/cssom/interfaces.html.ini index 532de09173f..0b9d9c1b706 100644 --- a/tests/wpt/metadata/cssom/interfaces.html.ini +++ b/tests/wpt/metadata/cssom/interfaces.html.ini @@ -54,12 +54,6 @@ [CSSRule interface: attribute parentRule] expected: FAIL - [CSSStyleRule interface: attribute selectorText] - expected: FAIL - - [CSSStyleRule interface: style_element.sheet.cssRules[0\] must inherit property "selectorText" with the proper type (0)] - expected: FAIL - [CSSRule interface: style_element.sheet.cssRules[0\] must inherit property "parentRule" with the proper type (10)] expected: FAIL diff --git a/tests/wpt/metadata/selectors/attribute-selectors/attribute-case/cssom.html.ini b/tests/wpt/metadata/selectors/attribute-selectors/attribute-case/cssom.html.ini deleted file mode 100644 index 4b2a69d99a6..00000000000 --- a/tests/wpt/metadata/selectors/attribute-selectors/attribute-case/cssom.html.ini +++ /dev/null @@ -1,68 +0,0 @@ -[cssom.html] - type: testharness - [[foo="bar"\] /* sanity check */ getting CSSRule#cssText] - expected: FAIL - - [[foo="bar"\] /* sanity check */ getting CSSStyleRule#selectorText] - expected: FAIL - - [[foo="bar"\] /* sanity check */ setting CSSStyleRule#selectorText] - expected: FAIL - - [[foo="bar"\] /* sanity check */ getting CSSRule#cssText in @media] - expected: FAIL - - [[foo="bar"\] /* sanity check */ getting CSSStyleRule#selectorText in @media] - expected: FAIL - - [[foo="bar"\] /* sanity check */ setting CSSStyleRule#selectorText in @media] - expected: FAIL - - [[foo="bar" i\] getting CSSRule#cssText] - expected: FAIL - - [[foo="bar" i\] getting CSSStyleRule#selectorText] - expected: FAIL - - [[foo="bar" i\] getting CSSRule#cssText in @media] - expected: FAIL - - [[foo="bar" i\] getting CSSStyleRule#selectorText in @media] - expected: FAIL - - [[foo="bar" /**/ i\] getting CSSRule#cssText] - expected: FAIL - - [[foo="bar" /**/ i\] getting CSSStyleRule#selectorText] - expected: FAIL - - [[foo="bar" /**/ i\] setting CSSStyleRule#selectorText] - expected: FAIL - - [[foo="bar" /**/ i\] getting CSSRule#cssText in @media] - expected: FAIL - - [[foo="bar" /**/ i\] getting CSSStyleRule#selectorText in @media] - expected: FAIL - - [[foo="bar" /**/ i\] setting CSSStyleRule#selectorText in @media] - expected: FAIL - - [[foo="bar"/**/i\] getting CSSRule#cssText] - expected: FAIL - - [[foo="bar"/**/i\] getting CSSStyleRule#selectorText] - expected: FAIL - - [[foo="bar"/**/i\] setting CSSStyleRule#selectorText] - expected: FAIL - - [[foo="bar"/**/i\] getting CSSRule#cssText in @media] - expected: FAIL - - [[foo="bar"/**/i\] getting CSSStyleRule#selectorText in @media] - expected: FAIL - - [[foo="bar"/**/i\] setting CSSStyleRule#selectorText in @media] - expected: FAIL - diff --git a/tests/wpt/web-platform-tests/cssom/selectorText-modification-restyle-001-ref.html b/tests/wpt/web-platform-tests/cssom/selectorText-modification-restyle-001-ref.html new file mode 100644 index 00000000000..74e58074708 --- /dev/null +++ b/tests/wpt/web-platform-tests/cssom/selectorText-modification-restyle-001-ref.html @@ -0,0 +1,13 @@ + + +(Ref #1) CSSOM - CSSStyleRule.selectorText Modification Restyle - Reference #1 + + + + +
I should be green.
+ diff --git a/tests/wpt/web-platform-tests/cssom/selectorText-modification-restyle-001.html b/tests/wpt/web-platform-tests/cssom/selectorText-modification-restyle-001.html new file mode 100644 index 00000000000..681d32f1865 --- /dev/null +++ b/tests/wpt/web-platform-tests/cssom/selectorText-modification-restyle-001.html @@ -0,0 +1,21 @@ + + +(Test #1) CSSOM - CSSStyleRule.selectorText Modification Restyle - Test #1 + + + + + +
I should be green.
+ +