diff --git a/components/script/dom/cssfontfacerule.rs b/components/script/dom/cssfontfacerule.rs new file mode 100644 index 00000000000..88dcaf4603f --- /dev/null +++ b/components/script/dom/cssfontfacerule.rs @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 dom::bindings::codegen::Bindings::CSSFontFaceRuleBinding; +use dom::bindings::js::Root; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::str::DOMString; +use dom::cssrule::{CSSRule, SpecificCSSRule}; +use dom::cssstylesheet::CSSStyleSheet; +use dom::window::Window; +use parking_lot::RwLock; +use std::sync::Arc; +use style::font_face::FontFaceRule; + +#[dom_struct] +pub struct CSSFontFaceRule { + cssrule: CSSRule, + #[ignore_heap_size_of = "Arc"] + fontfacerule: Arc>, +} + +impl CSSFontFaceRule { + fn new_inherited(parent: &CSSStyleSheet, fontfacerule: Arc>) -> CSSFontFaceRule { + CSSFontFaceRule { + cssrule: CSSRule::new_inherited(parent), + fontfacerule: fontfacerule, + } + } + + #[allow(unrooted_must_root)] + pub fn new(window: &Window, parent: &CSSStyleSheet, + fontfacerule: Arc>) -> Root { + reflect_dom_object(box CSSFontFaceRule::new_inherited(parent, fontfacerule), + window, + CSSFontFaceRuleBinding::Wrap) + } +} + +impl SpecificCSSRule for CSSFontFaceRule { + fn ty(&self) -> u16 { + use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleConstants; + CSSRuleConstants::FONT_FACE_RULE + } + + fn get_css(&self) -> DOMString { + // self.fontfacerule.read().to_css_string().into() + "".into() + } +} diff --git a/components/script/dom/cssgroupingrule.rs b/components/script/dom/cssgroupingrule.rs new file mode 100644 index 00000000000..3558686ea74 --- /dev/null +++ b/components/script/dom/cssgroupingrule.rs @@ -0,0 +1,30 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 dom::bindings::codegen::Bindings::CSSGroupingRuleBinding; +use dom::bindings::js::Root; +use dom::bindings::reflector::reflect_dom_object; +use dom::cssrule::CSSRule; +use dom::cssstylesheet::CSSStyleSheet; +use dom::window::Window; + +#[dom_struct] +pub struct CSSGroupingRule { + cssrule: CSSRule, +} + +impl CSSGroupingRule { + pub fn new_inherited(parent: &CSSStyleSheet) -> CSSGroupingRule { + CSSGroupingRule { + cssrule: CSSRule::new_inherited(parent), + } + } + + #[allow(unrooted_must_root)] + pub fn new(window: &Window, parent: &CSSStyleSheet) -> Root { + reflect_dom_object(box CSSGroupingRule::new_inherited(parent), + window, + CSSGroupingRuleBinding::Wrap) + } +} diff --git a/components/script/dom/csskeyframesrule.rs b/components/script/dom/csskeyframesrule.rs new file mode 100644 index 00000000000..3fced7751d6 --- /dev/null +++ b/components/script/dom/csskeyframesrule.rs @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding; +use dom::bindings::js::Root; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::str::DOMString; +use dom::cssrule::{CSSRule, SpecificCSSRule}; +use dom::cssstylesheet::CSSStyleSheet; +use dom::window::Window; +use parking_lot::RwLock; +use std::sync::Arc; +use style::stylesheets::KeyframesRule; + +#[dom_struct] +pub struct CSSKeyframesRule { + cssrule: CSSRule, + #[ignore_heap_size_of = "Arc"] + keyframesrule: Arc>, +} + +impl CSSKeyframesRule { + fn new_inherited(parent: &CSSStyleSheet, keyframesrule: Arc>) -> CSSKeyframesRule { + CSSKeyframesRule { + cssrule: CSSRule::new_inherited(parent), + keyframesrule: keyframesrule, + } + } + + #[allow(unrooted_must_root)] + pub fn new(window: &Window, parent: &CSSStyleSheet, + keyframesrule: Arc>) -> Root { + reflect_dom_object(box CSSKeyframesRule::new_inherited(parent, keyframesrule), + window, + CSSKeyframesRuleBinding::Wrap) + } +} + +impl SpecificCSSRule for CSSKeyframesRule { + fn ty(&self) -> u16 { + use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleConstants; + CSSRuleConstants::KEYFRAMES_RULE + } + + fn get_css(&self) -> DOMString { + // self.keyframesrule.read().to_css_string().into() + "".into() + } +} diff --git a/components/script/dom/cssmediarule.rs b/components/script/dom/cssmediarule.rs new file mode 100644 index 00000000000..dc4f3e586ba --- /dev/null +++ b/components/script/dom/cssmediarule.rs @@ -0,0 +1,51 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 dom::bindings::codegen::Bindings::CSSMediaRuleBinding; +use dom::bindings::js::Root; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::str::DOMString; +use dom::cssgroupingrule::CSSGroupingRule; +use dom::cssrule::SpecificCSSRule; +use dom::cssstylesheet::CSSStyleSheet; +use dom::window::Window; +use parking_lot::RwLock; +use std::sync::Arc; +use style::stylesheets::MediaRule; + +#[dom_struct] +pub struct CSSMediaRule { + cssrule: CSSGroupingRule, + #[ignore_heap_size_of = "Arc"] + mediarule: Arc>, +} + +impl CSSMediaRule { + fn new_inherited(parent: &CSSStyleSheet, mediarule: Arc>) -> CSSMediaRule { + CSSMediaRule { + cssrule: CSSGroupingRule::new_inherited(parent), + mediarule: mediarule, + } + } + + #[allow(unrooted_must_root)] + pub fn new(window: &Window, parent: &CSSStyleSheet, + mediarule: Arc>) -> Root { + reflect_dom_object(box CSSMediaRule::new_inherited(parent, mediarule), + window, + CSSMediaRuleBinding::Wrap) + } +} + +impl SpecificCSSRule for CSSMediaRule { + fn ty(&self) -> u16 { + use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleConstants; + CSSRuleConstants::MEDIA_RULE + } + + fn get_css(&self) -> DOMString { + // self.mediarule.read().to_css_string().into() + "".into() + } +} diff --git a/components/script/dom/cssnamespacerule.rs b/components/script/dom/cssnamespacerule.rs new file mode 100644 index 00000000000..2c0866c5dbe --- /dev/null +++ b/components/script/dom/cssnamespacerule.rs @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 dom::bindings::codegen::Bindings::CSSNamespaceRuleBinding; +use dom::bindings::js::Root; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::str::DOMString; +use dom::cssrule::{CSSRule, SpecificCSSRule}; +use dom::cssstylesheet::CSSStyleSheet; +use dom::window::Window; +use parking_lot::RwLock; +use std::sync::Arc; +use style::stylesheets::NamespaceRule; + +#[dom_struct] +pub struct CSSNamespaceRule { + cssrule: CSSRule, + #[ignore_heap_size_of = "Arc"] + namespacerule: Arc>, +} + +impl CSSNamespaceRule { + fn new_inherited(parent: &CSSStyleSheet, namespacerule: Arc>) -> CSSNamespaceRule { + CSSNamespaceRule { + cssrule: CSSRule::new_inherited(parent), + namespacerule: namespacerule, + } + } + + #[allow(unrooted_must_root)] + pub fn new(window: &Window, parent: &CSSStyleSheet, + namespacerule: Arc>) -> Root { + reflect_dom_object(box CSSNamespaceRule::new_inherited(parent, namespacerule), + window, + CSSNamespaceRuleBinding::Wrap) + } +} + +impl SpecificCSSRule for CSSNamespaceRule { + fn ty(&self) -> u16 { + use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleConstants; + CSSRuleConstants::NAMESPACE_RULE + } + + fn get_css(&self) -> DOMString { + // self.namespacerule.read().to_css_string().into() + "".into() + } +} diff --git a/components/script/dom/cssrule.rs b/components/script/dom/cssrule.rs new file mode 100644 index 00000000000..e46738bb1b4 --- /dev/null +++ b/components/script/dom/cssrule.rs @@ -0,0 +1,103 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 dom::bindings::codegen::Bindings::CSSRuleBinding; +use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleMethods; +use dom::bindings::inheritance::Castable; +use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::str::DOMString; +use dom::cssfontfacerule::CSSFontFaceRule; +use dom::csskeyframesrule::CSSKeyframesRule; +use dom::cssmediarule::CSSMediaRule; +use dom::cssnamespacerule::CSSNamespaceRule; +use dom::cssstylerule::CSSStyleRule; +use dom::cssstylesheet::CSSStyleSheet; +use dom::cssviewportrule::CSSViewportRule; +use dom::window::Window; +use style::stylesheets::CssRule as StyleCssRule; + + +#[dom_struct] +pub struct CSSRule { + reflector_: Reflector, + parent: MutNullableHeap>, +} + +impl CSSRule { + #[allow(unrooted_must_root)] + pub fn new_inherited(parent: &CSSStyleSheet) -> CSSRule { + CSSRule { + reflector_: Reflector::new(), + parent: MutNullableHeap::new(Some(parent)), + } + } + + #[allow(unrooted_must_root)] + pub fn new(window: &Window, parent: &CSSStyleSheet) -> Root { + reflect_dom_object(box CSSRule::new_inherited(parent), + window, + CSSRuleBinding::Wrap) + } + + pub fn as_specific(&self) -> &SpecificCSSRule { + if let Some(rule) = self.downcast::() { + rule as &SpecificCSSRule + } else if let Some(rule) = self.downcast::() { + rule as &SpecificCSSRule + } else if let Some(rule) = self.downcast::() { + rule as &SpecificCSSRule + } else if let Some(rule) = self.downcast::() { + rule as &SpecificCSSRule + } else if let Some(rule) = self.downcast::() { + rule as &SpecificCSSRule + } else if let Some(rule) = self.downcast::() { + rule as &SpecificCSSRule + } else { + unreachable!() + } + } + + // Given a StyleCssRule, create a new instance of a derived class of + // CSSRule based on which rule it is + pub fn new_specific(window: &Window, parent: &CSSStyleSheet, + rule: StyleCssRule) -> Root { + // be sure to update the match in as_specific when this is updated + match rule { + StyleCssRule::Style(s) => Root::upcast(CSSStyleRule::new(window, parent, s)), + StyleCssRule::FontFace(s) => Root::upcast(CSSFontFaceRule::new(window, parent, s)), + StyleCssRule::Keyframes(s) => Root::upcast(CSSKeyframesRule::new(window, parent, s)), + StyleCssRule::Media(s) => Root::upcast(CSSMediaRule::new(window, parent, s)), + StyleCssRule::Namespace(s) => Root::upcast(CSSNamespaceRule::new(window, parent, s)), + StyleCssRule::Viewport(s) => Root::upcast(CSSViewportRule::new(window, parent, s)), + } + } +} + +impl CSSRuleMethods for CSSRule { + // https://drafts.csswg.org/cssom/#dom-cssrule-type + fn Type(&self) -> u16 { + self.as_specific().ty() + } + + // https://drafts.csswg.org/cssom/#dom-cssrule-parentstylesheet + fn GetParentStyleSheet(&self) -> Option> { + self.parent.get() + } + + // https://drafts.csswg.org/cssom/#dom-cssrule-csstext + fn CssText(&self) -> DOMString { + self.as_specific().get_css() + } + + // https://drafts.csswg.org/cssom/#dom-cssrule-csstext + fn SetCssText(&self, _: DOMString) { + // do nothing + } +} + +pub trait SpecificCSSRule { + fn ty(&self) -> u16; + fn get_css(&self) -> DOMString; +} diff --git a/components/script/dom/cssrulelist.rs b/components/script/dom/cssrulelist.rs new file mode 100644 index 00000000000..1c383403a00 --- /dev/null +++ b/components/script/dom/cssrulelist.rs @@ -0,0 +1,67 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 dom::bindings::codegen::Bindings::CSSRuleListBinding; +use dom::bindings::codegen::Bindings::CSSRuleListBinding::CSSRuleListMethods; +use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; +use dom::cssrule::CSSRule; +use dom::cssstylesheet::CSSStyleSheet; +use dom::window::Window; +use style::stylesheets::CssRules; + +no_jsmanaged_fields!(CssRules); + +#[dom_struct] +pub struct CSSRuleList { + reflector_: Reflector, + sheet: JS, + #[ignore_heap_size_of = "Arc"] + rules: CssRules, + dom_rules: Vec>> +} + +impl CSSRuleList { + #[allow(unrooted_must_root)] + pub fn new_inherited(sheet: &CSSStyleSheet, rules: CssRules) -> CSSRuleList { + let dom_rules = rules.0.read().iter().map(|_| MutNullableHeap::new(None)).collect(); + CSSRuleList { + reflector_: Reflector::new(), + sheet: JS::from_ref(sheet), + rules: rules, + dom_rules: dom_rules, + } + } + + #[allow(unrooted_must_root)] + pub fn new(window: &Window, sheet: &CSSStyleSheet, rules: CssRules) -> Root { + reflect_dom_object(box CSSRuleList::new_inherited(sheet, rules), + window, + CSSRuleListBinding::Wrap) + } +} + +impl CSSRuleListMethods for CSSRuleList { + // https://drafts.csswg.org/cssom/#ref-for-dom-cssrulelist-item-1 + fn Item(&self, idx: u32) -> Option> { + self.dom_rules.get(idx as usize).map(|rule| { + rule.or_init(|| { + CSSRule::new_specific(self.global().as_window(), + &self.sheet, + self.rules.0.read()[idx as usize].clone()) + }) + }) + } + + // https://drafts.csswg.org/cssom/#dom-cssrulelist-length + fn Length(&self) -> u32 { + self.dom_rules.len() as u32 + } + + // check-tidy: no specs after this line + fn IndexedGetter(&self, index: u32) -> Option> { + self.Item(index) + } +} + diff --git a/components/script/dom/cssstylerule.rs b/components/script/dom/cssstylerule.rs new file mode 100644 index 00000000000..30726018ca9 --- /dev/null +++ b/components/script/dom/cssstylerule.rs @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 dom::bindings::codegen::Bindings::CSSStyleRuleBinding; +use dom::bindings::js::Root; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::str::DOMString; +use dom::cssrule::{CSSRule, SpecificCSSRule}; +use dom::cssstylesheet::CSSStyleSheet; +use dom::window::Window; +use parking_lot::RwLock; +use std::sync::Arc; +use style::stylesheets::StyleRule; +use style_traits::ToCss; + +#[dom_struct] +pub struct CSSStyleRule { + cssrule: CSSRule, + #[ignore_heap_size_of = "Arc"] + stylerule: Arc>, +} + +impl CSSStyleRule { + fn new_inherited(parent: &CSSStyleSheet, stylerule: Arc>) -> CSSStyleRule { + CSSStyleRule { + cssrule: CSSRule::new_inherited(parent), + stylerule: stylerule, + } + } + + #[allow(unrooted_must_root)] + pub fn new(window: &Window, parent: &CSSStyleSheet, + stylerule: Arc>) -> Root { + reflect_dom_object(box CSSStyleRule::new_inherited(parent, stylerule), + window, + CSSStyleRuleBinding::Wrap) + } +} + +impl SpecificCSSRule for CSSStyleRule { + fn ty(&self) -> u16 { + use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleConstants; + CSSRuleConstants::STYLE_RULE + } + + fn get_css(&self) -> DOMString { + self.stylerule.read().to_css_string().into() + } +} diff --git a/components/script/dom/cssstylesheet.rs b/components/script/dom/cssstylesheet.rs new file mode 100644 index 00000000000..d5a9342a75a --- /dev/null +++ b/components/script/dom/cssstylesheet.rs @@ -0,0 +1,51 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 dom::bindings::codegen::Bindings::CSSStyleSheetBinding; +use dom::bindings::codegen::Bindings::CSSStyleSheetBinding::CSSStyleSheetMethods; +use dom::bindings::js::{JS, Root, MutNullableHeap}; +use dom::bindings::reflector::{reflect_dom_object, Reflectable}; +use dom::bindings::str::DOMString; +use dom::cssrulelist::CSSRuleList; +use dom::stylesheet::StyleSheet; +use dom::window::Window; +use std::sync::Arc; +use style::stylesheets::Stylesheet as StyleStyleSheet; + +#[dom_struct] +pub struct CSSStyleSheet { + stylesheet: StyleSheet, + rulelist: MutNullableHeap>, + #[ignore_heap_size_of = "Arc"] + style_stylesheet: Arc, +} + +impl CSSStyleSheet { + fn new_inherited(type_: DOMString, href: Option, + title: Option, stylesheet: Arc) -> CSSStyleSheet { + CSSStyleSheet { + stylesheet: StyleSheet::new_inherited(type_, href, title), + rulelist: MutNullableHeap::new(None), + style_stylesheet: stylesheet, + } + } + + #[allow(unrooted_must_root)] + pub fn new(window: &Window, type_: DOMString, + href: Option, + title: Option, + stylesheet: Arc) -> Root { + reflect_dom_object(box CSSStyleSheet::new_inherited(type_, href, title, stylesheet), + window, + CSSStyleSheetBinding::Wrap) + } +} + +impl CSSStyleSheetMethods for CSSStyleSheet { + // https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssrules + fn CssRules(&self) -> Root { + self.rulelist.or_init(|| CSSRuleList::new(self.global().as_window(), self, self.style_stylesheet.rules.clone())) + } +} + diff --git a/components/script/dom/cssviewportrule.rs b/components/script/dom/cssviewportrule.rs new file mode 100644 index 00000000000..89f1ada597d --- /dev/null +++ b/components/script/dom/cssviewportrule.rs @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 dom::bindings::codegen::Bindings::CSSViewportRuleBinding; +use dom::bindings::js::Root; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::str::DOMString; +use dom::cssrule::{CSSRule, SpecificCSSRule}; +use dom::cssstylesheet::CSSStyleSheet; +use dom::window::Window; +use parking_lot::RwLock; +use std::sync::Arc; +use style::viewport::ViewportRule; + +#[dom_struct] +pub struct CSSViewportRule { + cssrule: CSSRule, + #[ignore_heap_size_of = "Arc"] + viewportrule: Arc>, +} + +impl CSSViewportRule { + fn new_inherited(parent: &CSSStyleSheet, viewportrule: Arc>) -> CSSViewportRule { + CSSViewportRule { + cssrule: CSSRule::new_inherited(parent), + viewportrule: viewportrule, + } + } + + #[allow(unrooted_must_root)] + pub fn new(window: &Window, parent: &CSSStyleSheet, + viewportrule: Arc>) -> Root { + reflect_dom_object(box CSSViewportRule::new_inherited(parent, viewportrule), + window, + CSSViewportRuleBinding::Wrap) + } +} + +impl SpecificCSSRule for CSSViewportRule { + fn ty(&self) -> u16 { + use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleConstants; + CSSRuleConstants::VIEWPORT_RULE + } + + fn get_css(&self) -> DOMString { + // self.viewportrule.read().to_css_string().into() + "".into() + } +} diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 5b1f4cfe404..56b7b17b0ca 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -59,10 +59,7 @@ use dom::htmlheadelement::HTMLHeadElement; use dom::htmlhtmlelement::HTMLHtmlElement; use dom::htmliframeelement::HTMLIFrameElement; use dom::htmlimageelement::HTMLImageElement; -use dom::htmllinkelement::HTMLLinkElement; -use dom::htmlmetaelement::HTMLMetaElement; use dom::htmlscriptelement::HTMLScriptElement; -use dom::htmlstyleelement::HTMLStyleElement; use dom::htmltitleelement::HTMLTitleElement; use dom::keyboardevent::KeyboardEvent; use dom::location::Location; @@ -152,10 +149,10 @@ enum ParserBlockedByScript { #[derive(JSTraceable, HeapSizeOf)] #[must_root] -struct StylesheetInDocument { - node: JS, +pub struct StylesheetInDocument { + pub node: JS, #[ignore_heap_size_of = "Arc"] - stylesheet: Arc, + pub stylesheet: Arc, } // https://dom.spec.whatwg.org/#document @@ -189,6 +186,7 @@ pub struct Document { stylesheets: DOMRefCell>>, /// Whether the list of stylesheets has changed since the last reflow was triggered. stylesheets_changed_since_reflow: Cell, + stylesheet_list: MutNullableHeap>, ready_state: Cell, /// Whether the DOMContentLoaded event has already been dispatched. domcontentloaded_dispatched: Cell, @@ -1811,6 +1809,7 @@ impl Document { applets: Default::default(), stylesheets: DOMRefCell::new(None), stylesheets_changed_since_reflow: Cell::new(false), + stylesheet_list: MutNullableHeap::new(None), ready_state: Cell::new(ready_state), domcontentloaded_dispatched: Cell::new(domcontentloaded_dispatched), possibly_focused: Default::default(), @@ -1910,35 +1909,37 @@ impl Document { self.GetDocumentElement().and_then(Root::downcast) } + // Ensure that the stylesheets vector is populated + fn ensure_stylesheets(&self) { + let mut stylesheets = self.stylesheets.borrow_mut(); + if stylesheets.is_none() { + *stylesheets = Some(self.upcast::() + .traverse_preorder() + .filter_map(|node| { + node.get_stylesheet() + .map(|stylesheet| StylesheetInDocument { + node: JS::from_ref(&*node), + stylesheet: stylesheet, + }) + }) + .collect()); + }; + } + /// Returns the list of stylesheets associated with nodes in the document. pub fn stylesheets(&self) -> Vec> { - { - let mut stylesheets = self.stylesheets.borrow_mut(); - if stylesheets.is_none() { - *stylesheets = Some(self.upcast::() - .traverse_preorder() - .filter_map(|node| { - if let Some(node) = node.downcast::() { - node.get_stylesheet() - } else if let Some(node) = node.downcast::() { - node.get_stylesheet() - } else if let Some(node) = node.downcast::() { - node.get_stylesheet() - } else { - None - }.map(|stylesheet| StylesheetInDocument { - node: JS::from_ref(&*node), - stylesheet: stylesheet - }) - }) - .collect()); - }; - } + self.ensure_stylesheets(); self.stylesheets.borrow().as_ref().unwrap().iter() .map(|s| s.stylesheet.clone()) .collect() } + pub fn with_style_sheets_in_document(&self, mut f: F) -> T + where F: FnMut(&[StylesheetInDocument]) -> T { + self.ensure_stylesheets(); + f(&self.stylesheets.borrow().as_ref().unwrap()) + } + /// https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document pub fn appropriate_template_contents_owner_document(&self) -> Root { self.appropriate_template_contents_owner_document.or_init(|| { @@ -2038,7 +2039,7 @@ impl Element { impl DocumentMethods for Document { // https://drafts.csswg.org/cssom/#dom-document-stylesheets fn StyleSheets(&self) -> Root { - StyleSheetList::new(&self.window, JS::from_ref(&self)) + self.stylesheet_list.or_init(|| StyleSheetList::new(&self.window, JS::from_ref(&self))) } // https://dom.spec.whatwg.org/#dom-document-implementation diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 5df64f62ca0..17c9514287e 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -14,6 +14,7 @@ use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::Reflectable; use dom::bindings::str::DOMString; +use dom::cssstylesheet::CSSStyleSheet; use dom::document::Document; use dom::domtokenlist::DOMTokenList; use dom::element::{AttributeMutation, Element, ElementCreator}; @@ -56,6 +57,7 @@ pub struct HTMLLinkElement { rel_list: MutNullableHeap>, #[ignore_heap_size_of = "Arc"] stylesheet: DOMRefCell>>, + cssom_stylesheet: MutNullableHeap>, /// https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts parser_inserted: Cell, @@ -69,6 +71,7 @@ impl HTMLLinkElement { rel_list: Default::default(), parser_inserted: Cell::new(creator == ElementCreator::ParserCreated), stylesheet: DOMRefCell::new(None), + cssom_stylesheet: MutNullableHeap::new(None), } } @@ -85,6 +88,18 @@ impl HTMLLinkElement { pub fn get_stylesheet(&self) -> Option> { self.stylesheet.borrow().clone() } + + pub fn get_cssom_stylesheet(&self) -> Option> { + self.get_stylesheet().map(|sheet| { + self.cssom_stylesheet.or_init(|| { + CSSStyleSheet::new(&window_from_node(self), + "text/css".into(), + None, // todo handle location + None, // todo handle title + sheet) + }) + }) + } } fn get_attr(element: &Element, local_name: &LocalName) -> Option { diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs index 82855472589..c948dde4ab8 100644 --- a/components/script/dom/htmlmetaelement.rs +++ b/components/script/dom/htmlmetaelement.rs @@ -8,13 +8,14 @@ use dom::bindings::codegen::Bindings::HTMLMetaElementBinding; use dom::bindings::codegen::Bindings::HTMLMetaElementBinding::HTMLMetaElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{Root, RootedReference}; +use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; use dom::bindings::str::DOMString; +use dom::cssstylesheet::CSSStyleSheet; use dom::document::Document; use dom::element::{AttributeMutation, Element}; use dom::htmlelement::HTMLElement; use dom::htmlheadelement::HTMLHeadElement; -use dom::node::{Node, UnbindContext, document_from_node}; +use dom::node::{Node, UnbindContext, document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; use html5ever_atoms::LocalName; use parking_lot::RwLock; @@ -30,6 +31,7 @@ pub struct HTMLMetaElement { htmlelement: HTMLElement, #[ignore_heap_size_of = "Arc"] stylesheet: DOMRefCell>>, + cssom_stylesheet: MutNullableHeap>, } impl HTMLMetaElement { @@ -39,6 +41,7 @@ impl HTMLMetaElement { HTMLMetaElement { htmlelement: HTMLElement::new_inherited(local_name, prefix, document), stylesheet: DOMRefCell::new(None), + cssom_stylesheet: MutNullableHeap::new(None), } } @@ -55,6 +58,18 @@ impl HTMLMetaElement { self.stylesheet.borrow().clone() } + pub fn get_cssom_stylesheet(&self) -> Option> { + self.get_stylesheet().map(|sheet| { + self.cssom_stylesheet.or_init(|| { + CSSStyleSheet::new(&window_from_node(self), + "text/css".into(), + None, // todo handle location + None, // todo handle title + sheet) + }) + }) + } + fn process_attributes(&self) { let element = self.upcast::(); if let Some(name) = element.get_attribute(&ns!(), &local_name!("name")).r() { @@ -81,7 +96,7 @@ impl HTMLMetaElement { if !content.is_empty() { if let Some(translated_rule) = ViewportRule::from_meta(&**content) { *self.stylesheet.borrow_mut() = Some(Arc::new(Stylesheet { - rules: vec![CssRule::Viewport(Arc::new(RwLock::new(translated_rule)))], + rules: vec![CssRule::Viewport(Arc::new(RwLock::new(translated_rule)))].into(), origin: Origin::Author, media: Default::default(), // Viewport constraints are always recomputed on resize; they don't need to diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 8c1bc031dc0..577e290a3ea 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -7,8 +7,9 @@ use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::HTMLStyleElementBinding; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::Root; +use dom::bindings::js::{JS, MutNullableHeap, Root}; use dom::bindings::str::DOMString; +use dom::cssstylesheet::CSSStyleSheet; use dom::document::Document; use dom::element::Element; use dom::htmlelement::HTMLElement; @@ -26,6 +27,7 @@ pub struct HTMLStyleElement { htmlelement: HTMLElement, #[ignore_heap_size_of = "Arc"] stylesheet: DOMRefCell>>, + cssom_stylesheet: MutNullableHeap>, } impl HTMLStyleElement { @@ -35,6 +37,7 @@ impl HTMLStyleElement { HTMLStyleElement { htmlelement: HTMLElement::new_inherited(local_name, prefix, document), stylesheet: DOMRefCell::new(None), + cssom_stylesheet: MutNullableHeap::new(None), } } @@ -77,6 +80,18 @@ impl HTMLStyleElement { pub fn get_stylesheet(&self) -> Option> { self.stylesheet.borrow().clone() } + + pub fn get_cssom_stylesheet(&self) -> Option> { + self.get_stylesheet().map(|sheet| { + self.cssom_stylesheet.or_init(|| { + CSSStyleSheet::new(&window_from_node(self), + "text/css".into(), + None, // todo handle location + None, // todo handle title + sheet) + }) + }) + } } impl VirtualMethods for HTMLStyleElement { diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index d419d41ec61..05ec1963a20 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -242,7 +242,17 @@ pub mod comment; pub mod console; pub mod crypto; pub mod css; +pub mod cssfontfacerule; +pub mod cssgroupingrule; +pub mod csskeyframesrule; +pub mod cssmediarule; +pub mod cssnamespacerule; +pub mod cssrule; +pub mod cssrulelist; pub mod cssstyledeclaration; +pub mod cssstylerule; +pub mod cssstylesheet; +pub mod cssviewportrule; pub mod customevent; pub mod dedicatedworkerglobalscope; pub mod document; diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 0f510719640..37e0548fa13 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -30,6 +30,7 @@ use dom::bindings::reflector::{Reflectable, reflect_dom_object}; use dom::bindings::str::{DOMString, USVString}; use dom::bindings::xmlname::namespace_from_domstring; use dom::characterdata::{CharacterData, LayoutCharacterDataHelpers}; +use dom::cssstylesheet::CSSStyleSheet; use dom::document::{Document, DocumentSource, IsHTMLDocument}; use dom::documentfragment::DocumentFragment; use dom::documenttype::DocumentType; @@ -43,6 +44,9 @@ use dom::htmlelement::HTMLElement; use dom::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementLayoutMethods}; use dom::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers}; use dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers}; +use dom::htmllinkelement::HTMLLinkElement; +use dom::htmlmetaelement::HTMLMetaElement; +use dom::htmlstyleelement::HTMLStyleElement; use dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaElementHelpers}; use dom::nodelist::NodeList; use dom::processinginstruction::ProcessingInstruction; @@ -76,8 +80,10 @@ use std::default::Default; use std::iter; use std::mem; use std::ops::Range; +use std::sync::Arc; use style::dom::OpaqueNode; use style::selector_impl::ServoSelectorImpl; +use style::stylesheets::Stylesheet; use style::thread_state; use url::Url; use uuid::Uuid; @@ -901,6 +907,30 @@ impl Node { element.upcast::().remove_self(); Ok(()) } + + pub fn get_stylesheet(&self) -> Option> { + if let Some(node) = self.downcast::() { + node.get_stylesheet() + } else if let Some(node) = self.downcast::() { + node.get_stylesheet() + } else if let Some(node) = self.downcast::() { + node.get_stylesheet() + } else { + None + } + } + + pub fn get_cssom_stylesheet(&self) -> Option> { + if let Some(node) = self.downcast::() { + node.get_cssom_stylesheet() + } else if let Some(node) = self.downcast::() { + node.get_cssom_stylesheet() + } else if let Some(node) = self.downcast::() { + node.get_cssom_stylesheet() + } else { + None + } + } } diff --git a/components/script/dom/stylesheet.rs b/components/script/dom/stylesheet.rs index 02c96623800..7def8f1ba6c 100644 --- a/components/script/dom/stylesheet.rs +++ b/components/script/dom/stylesheet.rs @@ -20,7 +20,7 @@ pub struct StyleSheet { impl StyleSheet { #[allow(unrooted_must_root)] - fn new_inherited(type_: DOMString, href: Option, title: Option) -> StyleSheet { + pub fn new_inherited(type_: DOMString, href: Option, title: Option) -> StyleSheet { StyleSheet { reflector_: Reflector::new(), type_: type_, diff --git a/components/script/dom/stylesheetlist.rs b/components/script/dom/stylesheetlist.rs index a4541fc9bb4..b028e7f2b73 100644 --- a/components/script/dom/stylesheetlist.rs +++ b/components/script/dom/stylesheetlist.rs @@ -35,13 +35,18 @@ impl StyleSheetList { impl StyleSheetListMethods for StyleSheetList { // https://drafts.csswg.org/cssom/#dom-stylesheetlist-length fn Length(&self) -> u32 { - self.document.stylesheets().len() as u32 + self.document.with_style_sheets_in_document(|s| s.len() as u32) } // https://drafts.csswg.org/cssom/#dom-stylesheetlist-item - fn Item(&self, _index: u32) -> Option> { - None - //TODO Create a new StyleSheet object and return it + fn Item(&self, index: u32) -> Option> { + // XXXManishearth this doesn't handle the origin clean flag + // and is a cors vulnerability + self.document.with_style_sheets_in_document(|sheets| { + sheets.get(index as usize) + .and_then(|sheet| sheet.node.get_cssom_stylesheet()) + .map(Root::upcast) + }) } // check-tidy: no specs after this line diff --git a/components/script/dom/webidls/CSS.webidl b/components/script/dom/webidls/CSS.webidl index 54458060909..438c6814ccb 100644 --- a/components/script/dom/webidls/CSS.webidl +++ b/components/script/dom/webidls/CSS.webidl @@ -6,7 +6,7 @@ * http://dev.w3.org/csswg/cssom/#the-css-interface */ -[Abstract, Exposed=(Window,Worker)] +[Abstract, Exposed=Window] interface CSS { [Throws] static DOMString escape(DOMString ident); diff --git a/components/script/dom/webidls/CSSFontFaceRule.webidl b/components/script/dom/webidls/CSSFontFaceRule.webidl new file mode 100644 index 00000000000..3749a79a818 --- /dev/null +++ b/components/script/dom/webidls/CSSFontFaceRule.webidl @@ -0,0 +1,17 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +// https://drafts.csswg.org/css-fonts/#cssfontfacerule +[Exposed=Window] +interface CSSFontFaceRule : CSSRule { + // attribute DOMString family; + // attribute DOMString src; + // attribute DOMString style; + // attribute DOMString weight; + // attribute DOMString stretch; + // attribute DOMString unicodeRange; + // attribute DOMString variant; + // attribute DOMString featureSettings; +}; + diff --git a/components/script/dom/webidls/CSSGroupingRule.webidl b/components/script/dom/webidls/CSSGroupingRule.webidl new file mode 100644 index 00000000000..6a317191ff6 --- /dev/null +++ b/components/script/dom/webidls/CSSGroupingRule.webidl @@ -0,0 +1,12 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +// https://drafts.csswg.org/cssom/#the-cssgroupingrule-interface +[Exposed=Window] +interface CSSGroupingRule : CSSRule { + // [SameObject] readonly attribute CSSRuleList cssRules; + // unsigned long insertRule(DOMString rule, unsigned long index); + // void deleteRule(unsigned long index); +}; + diff --git a/components/script/dom/webidls/CSSKeyframesRule.webidl b/components/script/dom/webidls/CSSKeyframesRule.webidl new file mode 100644 index 00000000000..db152d72850 --- /dev/null +++ b/components/script/dom/webidls/CSSKeyframesRule.webidl @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +// https://drafts.csswg.org/css-animations/#interface-csskeyframesrule +[Exposed=Window] +interface CSSKeyframesRule : CSSRule { + // attribute DOMString name; + // readonly attribute CSSRuleList cssRules; + + // void appendRule(DOMString rule); + // void deleteRule(DOMString select); + // CSSKeyframeRule? findRule(DOMString select); +}; diff --git a/components/script/dom/webidls/CSSMediaRule.webidl b/components/script/dom/webidls/CSSMediaRule.webidl new file mode 100644 index 00000000000..e2b89dee723 --- /dev/null +++ b/components/script/dom/webidls/CSSMediaRule.webidl @@ -0,0 +1,9 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +// https://drafts.csswg.org/cssom/#the-cssmediarule-interface +[Exposed=Window] +interface CSSMediaRule : CSSGroupingRule { + // [SameObject, PutForwards=mediaText] readonly attribute MediaList media; +}; diff --git a/components/script/dom/webidls/CSSNamespaceRule.webidl b/components/script/dom/webidls/CSSNamespaceRule.webidl new file mode 100644 index 00000000000..a8d6b61548f --- /dev/null +++ b/components/script/dom/webidls/CSSNamespaceRule.webidl @@ -0,0 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +// https://drafts.csswg.org/cssom/#the-cssnamespacerule-interface +[Exposed=Window] +interface CSSNamespaceRule : CSSRule { + // readonly attribute DOMString namespaceURI; + // readonly attribute DOMString prefix; +}; diff --git a/components/script/dom/webidls/CSSRule.webidl b/components/script/dom/webidls/CSSRule.webidl new file mode 100644 index 00000000000..462943430e6 --- /dev/null +++ b/components/script/dom/webidls/CSSRule.webidl @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +// https://drafts.csswg.org/cssom/#the-cssrule-interface +[Exposed=Window] +interface CSSRule { + const unsigned short STYLE_RULE = 1; + const unsigned short CHARSET_RULE = 2; // historical + const unsigned short IMPORT_RULE = 3; + const unsigned short MEDIA_RULE = 4; + const unsigned short FONT_FACE_RULE = 5; + const unsigned short PAGE_RULE = 6; + const unsigned short MARGIN_RULE = 9; + const unsigned short NAMESPACE_RULE = 10; + + readonly attribute unsigned short type; + attribute DOMString cssText; + // readonly attribute CSSRule? parentRule; + readonly attribute CSSStyleSheet? parentStyleSheet; +}; + +// https://drafts.csswg.org/css-animations/#interface-cssrule-idl +partial interface CSSRule { + const unsigned short KEYFRAMES_RULE = 7; + const unsigned short KEYFRAME_RULE = 8; +}; + +// https://drafts.csswg.org/css-device-adapt/#css-rule-interface +partial interface CSSRule { + const unsigned short VIEWPORT_RULE = 15; +}; + diff --git a/components/script/dom/webidls/CSSRuleList.webidl b/components/script/dom/webidls/CSSRuleList.webidl new file mode 100644 index 00000000000..8ee12004a26 --- /dev/null +++ b/components/script/dom/webidls/CSSRuleList.webidl @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +// https://drafts.csswg.org/cssom/#cssrulelist +// [LegacyArrayClass] +[Exposed=Window] +interface CSSRuleList { + getter CSSRule? item(unsigned long index); + readonly attribute unsigned long length; +}; diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl index 3424e5593a6..0f0b483d0b1 100644 --- a/components/script/dom/webidls/CSSStyleDeclaration.webidl +++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl @@ -8,7 +8,7 @@ * Copyright © 2013 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. */ -[Exposed=(Window,Worker)] +[Exposed=(Window, Worker)] interface CSSStyleDeclaration { [SetterThrows] attribute DOMString cssText; diff --git a/components/script/dom/webidls/CSSStyleRule.webidl b/components/script/dom/webidls/CSSStyleRule.webidl new file mode 100644 index 00000000000..faee525e7ff --- /dev/null +++ b/components/script/dom/webidls/CSSStyleRule.webidl @@ -0,0 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +// https://drafts.csswg.org/cssom/#the-cssstylerule-interface +[Exposed=Window] +interface CSSStyleRule : CSSRule { + // attribute DOMString selectorText; + // [SameObject, PutForwards=cssText] readonly attribute CSSStyleDeclaration style; +}; diff --git a/components/script/dom/webidls/CSSStyleSheet.webidl b/components/script/dom/webidls/CSSStyleSheet.webidl new file mode 100644 index 00000000000..99ab3234705 --- /dev/null +++ b/components/script/dom/webidls/CSSStyleSheet.webidl @@ -0,0 +1,12 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +// https://drafts.csswg.org/cssom/#the-cssstylesheet-interface +[Exposed=Window] +interface CSSStyleSheet : StyleSheet { + // readonly attribute CSSRule? ownerRule; + [SameObject] readonly attribute CSSRuleList cssRules; + // unsigned long insertRule(DOMString rule, unsigned long index); + // void deleteRule(unsigned long index); +}; diff --git a/components/script/dom/webidls/CSSViewportRule.webidl b/components/script/dom/webidls/CSSViewportRule.webidl new file mode 100644 index 00000000000..b1b73eb9c50 --- /dev/null +++ b/components/script/dom/webidls/CSSViewportRule.webidl @@ -0,0 +1,9 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +// https://drafts.csswg.org/css-device-adapt/#css-viewport-rule-interface +[Exposed=Window] +interface CSSViewportRule : CSSRule { + // readonly attribute CSSStyleDeclaration style; +}; diff --git a/components/script/dom/webidls/StyleSheet.webidl b/components/script/dom/webidls/StyleSheet.webidl index b4f8bf94fae..a63e2a41f01 100644 --- a/components/script/dom/webidls/StyleSheet.webidl +++ b/components/script/dom/webidls/StyleSheet.webidl @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://drafts.csswg.org/cssom/#the-stylesheet-interface -[Exposed=(Window,Worker)] +[Exposed=Window] interface StyleSheet { readonly attribute DOMString type_; readonly attribute DOMString? href; diff --git a/components/script/dom/webidls/StyleSheetList.webidl b/components/script/dom/webidls/StyleSheetList.webidl index 26ad1f72c3d..20360eb4ba4 100644 --- a/components/script/dom/webidls/StyleSheetList.webidl +++ b/components/script/dom/webidls/StyleSheetList.webidl @@ -4,7 +4,7 @@ // https://drafts.csswg.org/cssom/#the-stylesheetlist-interface // [ArrayClass] -[Exposed=(Window,Worker)] +[Exposed=Window] interface StyleSheetList { getter StyleSheet? item(unsigned long index); readonly attribute unsigned long length; diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs index 1f955c0a0de..c574c097a5a 100644 --- a/components/style/selector_matching.rs +++ b/components/style/selector_matching.rs @@ -388,7 +388,7 @@ impl Stylist { false } self.is_device_dirty |= stylesheets.iter().any(|stylesheet| { - mq_eval_changed(&stylesheet.rules, &self.device, &device) + mq_eval_changed(&stylesheet.rules.0.read(), &self.device, &device) }); self.device = device; diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 2d82653f06d..1538e9e0f25 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -7,6 +7,7 @@ use {Atom, Prefix, Namespace}; use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, decode_stylesheet_bytes}; use cssparser::{AtRuleType, RuleListParser, Token}; +use cssparser::ToCss as ParserToCss; use encoding::EncodingRef; use error_reporting::ParseErrorReporter; use font_face::{FontFaceRule, parse_font_face_block}; @@ -18,7 +19,9 @@ use properties::{PropertyDeclarationBlock, parse_property_declaration_list}; use selector_impl::TheSelectorImpl; use selectors::parser::{Selector, parse_selector_list}; use std::cell::Cell; +use std::fmt; use std::sync::Arc; +use style_traits::ToCss; use url::Url; use viewport::ViewportRule; @@ -39,12 +42,20 @@ pub enum Origin { User, } +#[derive(Debug, Clone)] +pub struct CssRules(pub Arc>>); + +impl From> for CssRules { + fn from(other: Vec) -> Self { + CssRules(Arc::new(RwLock::new(other))) + } +} #[derive(Debug)] pub struct Stylesheet { /// List of rules in the order they were found (important for /// cascading order) - pub rules: Vec, + pub rules: CssRules, /// List of media associated with the Stylesheet. pub media: MediaList, pub origin: Origin, @@ -59,7 +70,7 @@ pub struct UserAgentStylesheets { } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum CssRule { // No Charset here, CSSCharsetRule has been removed from CSSOM // https://drafts.csswg.org/cssom/#changes-from-5-december-2013 @@ -89,7 +100,8 @@ impl CssRule { CssRule::Media(ref lock) => { let media_rule = lock.read(); let mq = media_rule.media_queries.read(); - f(&media_rule.rules, Some(&mq)) + let rules = media_rule.rules.0.read(); + f(&rules, Some(&mq)) } } } @@ -112,7 +124,7 @@ pub struct KeyframesRule { #[derive(Debug)] pub struct MediaRule { pub media_queries: Arc>, - pub rules: Vec, + pub rules: CssRules, } #[derive(Debug)] @@ -121,6 +133,41 @@ pub struct StyleRule { pub block: Arc>, } +impl StyleRule { + /// Serialize the group of selectors for this rule. + /// + /// https://drafts.csswg.org/cssom/#serialize-a-group-of-selectors + pub fn selectors_to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + let mut iter = self.selectors.iter(); + try!(iter.next().unwrap().to_css(dest)); + for selector in iter { + try!(write!(dest, ", ")); + try!(selector.to_css(dest)); + } + Ok(()) + } +} + +impl ToCss for StyleRule { + // https://drafts.csswg.org/cssom/#serialize-a-css-rule CSSStyleRule + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + // Step 1 + try!(self.selectors_to_css(dest)); + // Step 2 + try!(dest.write_str(" { ")); + // Step 3 + let declaration_block = self.block.read(); + try!(declaration_block.to_css(dest)); + // Step 4 + if declaration_block.declarations.len() > 0 { + try!(write!(dest, " ")); + } + // Step 5 + try!(dest.write_str("}")); + Ok(()) + } +} + impl Stylesheet { pub fn from_bytes_iter>>( @@ -180,7 +227,7 @@ impl Stylesheet { Stylesheet { origin: origin, - rules: rules, + rules: rules.into(), media: Default::default(), dirty_on_viewport_size_change: input.seen_viewport_percentages(), @@ -208,7 +255,7 @@ impl Stylesheet { /// examined. #[inline] pub fn effective_rules(&self, device: &Device, mut f: F) where F: FnMut(&CssRule) { - effective_rules(&self.rules, device, &mut f); + effective_rules(&self.rules.0.read(), device, &mut f); } } @@ -251,7 +298,7 @@ rule_filter! { effective_keyframes_rules(Keyframes => KeyframesRule), } -fn parse_nested_rules(context: &ParserContext, input: &mut Parser) -> Vec { +fn parse_nested_rules(context: &ParserContext, input: &mut Parser) -> CssRules { let mut iter = RuleListParser::new_for_nested_rule(input, NestedRuleParser { context: context }); let mut rules = Vec::new(); @@ -265,7 +312,7 @@ fn parse_nested_rules(context: &ParserContext, input: &mut Parser) -> Vec bool { - !Stylesheet::as_arc(&raw_sheet).rules.is_empty() + !Stylesheet::as_arc(&raw_sheet).rules.0.read().is_empty() } #[no_mangle] diff --git a/python/tidy/servo_tidy/tidy.py b/python/tidy/servo_tidy/tidy.py index bfb40bccd91..005a1bed24a 100644 --- a/python/tidy/servo_tidy/tidy.py +++ b/python/tidy/servo_tidy/tidy.py @@ -63,7 +63,7 @@ WEBIDL_STANDARDS = [ "//dvcs.w3.org/hg", "//dom.spec.whatwg.org", "//domparsing.spec.whatwg.org", - "//drafts.csswg.org/cssom", + "//drafts.csswg.org", "//drafts.fxtf.org", "//encoding.spec.whatwg.org", "//fetch.spec.whatwg.org", diff --git a/tests/unit/style/media_queries.rs b/tests/unit/style/media_queries.rs index 04d0903a1b9..59628128082 100644 --- a/tests/unit/style/media_queries.rs +++ b/tests/unit/style/media_queries.rs @@ -29,7 +29,7 @@ fn test_media_rule(css: &str, callback: F) where F: Fn(&MediaList, &str) { let stylesheet = Stylesheet::from_str(css, url, Origin::Author, Box::new(CSSErrorReporterTest), ParserContextExtraData::default()); let mut rule_count = 0; - media_queries(&stylesheet.rules, &mut |mq| { + media_queries(&stylesheet.rules.0.read(), &mut |mq| { rule_count += 1; callback(mq, css); }); diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 7791fb14b9b..2efd471b99f 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -256,7 +256,7 @@ fn test_parse_stylesheet() { ] }))) - ], + ].into(), }; assert_eq!(format!("{:#?}", stylesheet), format!("{:#?}", expected)); diff --git a/tests/wpt/harness/test/metadata/testharness/firefox/subdir/test_pref_reset.html.ini b/tests/wpt/harness/test/metadata/testharness/firefox/subdir/test_pref_reset.html.ini index 6c9198d9bbf..de0043c5149 100644 --- a/tests/wpt/harness/test/metadata/testharness/firefox/subdir/test_pref_reset.html.ini +++ b/tests/wpt/harness/test/metadata/testharness/firefox/subdir/test_pref_reset.html.ini @@ -1,2 +1,3 @@ [test_pref_reset.html] + type: testharness prefs: [@Reset] diff --git a/tests/wpt/harness/test/metadata/testharness/firefox/test_pref_set.html.ini b/tests/wpt/harness/test/metadata/testharness/firefox/test_pref_set.html.ini index bc9bfb9c413..ca005cd7558 100644 --- a/tests/wpt/harness/test/metadata/testharness/firefox/test_pref_set.html.ini +++ b/tests/wpt/harness/test/metadata/testharness/firefox/test_pref_set.html.ini @@ -1,3 +1,4 @@ [test_pref_set.html] + type: testharness prefs: ["browser.display.foreground_color:#00FF00", "browser.display.background_color:#000000"] diff --git a/tests/wpt/harness/test/metadata/testharness/subdir/testharness_1.html.ini b/tests/wpt/harness/test/metadata/testharness/subdir/testharness_1.html.ini index db9393987b6..8be3d47e852 100644 --- a/tests/wpt/harness/test/metadata/testharness/subdir/testharness_1.html.ini +++ b/tests/wpt/harness/test/metadata/testharness/subdir/testharness_1.html.ini @@ -1,2 +1,3 @@ [testharness_1.html] + type: testharness disabled: @False \ No newline at end of file diff --git a/tests/wpt/harness/test/metadata/testharness/tags/testharness_0.html.ini b/tests/wpt/harness/test/metadata/testharness/tags/testharness_0.html.ini index fe8ffa48dd0..7fa297c7cea 100644 --- a/tests/wpt/harness/test/metadata/testharness/tags/testharness_0.html.ini +++ b/tests/wpt/harness/test/metadata/testharness/tags/testharness_0.html.ini @@ -1,4 +1,5 @@ tags: [file-tag] [testharness_0.html] + type: testharness tags: [test-tag] diff --git a/tests/wpt/harness/test/metadata/testharness/tags/testharness_1.html.ini b/tests/wpt/harness/test/metadata/testharness/tags/testharness_1.html.ini index d6006a1551c..ecc07664f42 100644 --- a/tests/wpt/harness/test/metadata/testharness/tags/testharness_1.html.ini +++ b/tests/wpt/harness/test/metadata/testharness/tags/testharness_1.html.ini @@ -1,2 +1,3 @@ [testharness_0.html] + type: testharness tags: [test-1-tag] diff --git a/tests/wpt/harness/test/metadata/testharness/tags/testharness_2.html.ini b/tests/wpt/harness/test/metadata/testharness/tags/testharness_2.html.ini index 25fbf55362d..d95e28832cc 100644 --- a/tests/wpt/harness/test/metadata/testharness/tags/testharness_2.html.ini +++ b/tests/wpt/harness/test/metadata/testharness/tags/testharness_2.html.ini @@ -1,4 +1,5 @@ tags: [file-tag] [testharness_2.html] + type: testharness tags: [test-2-tag, @Reset] diff --git a/tests/wpt/metadata-css/css-transitions-1_dev/html/changing-while-transition.htm.ini b/tests/wpt/metadata-css/css-transitions-1_dev/html/changing-while-transition.htm.ini index e1464721388..4e9f379b7f9 100644 --- a/tests/wpt/metadata-css/css-transitions-1_dev/html/changing-while-transition.htm.ini +++ b/tests/wpt/metadata-css/css-transitions-1_dev/html/changing-while-transition.htm.ini @@ -2,6 +2,7 @@ type: testharness [changing transition-property / values] expected: FAIL + [changing transition-duration / values] expected: FAIL diff --git a/tests/wpt/metadata-css/css21_dev/html4/color-applies-to-014.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/color-applies-to-014.htm.ini index a3379e753de..d3bb209de34 100644 --- a/tests/wpt/metadata-css/css21_dev/html4/color-applies-to-014.htm.ini +++ b/tests/wpt/metadata-css/css21_dev/html4/color-applies-to-014.htm.ini @@ -1,2 +1,3 @@ [color-applies-to-014.htm] - disabled: https://github.com/servo/servo/pull/13870#issuecomment-255507790 + type: reftest + disabled: https://github.com/servo/servo/pull/13870 diff --git a/tests/wpt/metadata-css/cssom-1_dev/html/index-003.htm.ini b/tests/wpt/metadata-css/cssom-1_dev/html/index-003.htm.ini index b23072d78f6..e6f60a1c5f5 100644 --- a/tests/wpt/metadata-css/cssom-1_dev/html/index-003.htm.ini +++ b/tests/wpt/metadata-css/cssom-1_dev/html/index-003.htm.ini @@ -1,3 +1,8 @@ [index-003.htm] type: testharness - expected: ERROR + [@import rule is expected to be @import url("main.css")] + expected: FAIL + + [page rule is expected to be @page :first] + 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 78d6184cd70..02c46f56ee4 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,24 +117,9 @@ [StyleSheet interface: attribute disabled] expected: FAIL - [CSSStyleSheet interface: existence and properties of interface object] - expected: FAIL - - [CSSStyleSheet interface object length] - expected: FAIL - - [CSSStyleSheet interface: existence and properties of interface prototype object] - expected: FAIL - - [CSSStyleSheet interface: existence and properties of interface prototype object's "constructor" property] - expected: FAIL - [CSSStyleSheet interface: attribute ownerRule] expected: FAIL - [CSSStyleSheet interface: attribute cssRules] - expected: FAIL - [CSSStyleSheet interface: operation insertRule(DOMString,unsigned long)] expected: FAIL @@ -189,24 +174,9 @@ [StyleSheetList interface: existence and properties of interface prototype object] expected: FAIL - [CSSRuleList interface: existence and properties of interface object] - expected: FAIL - - [CSSRuleList interface object length] - expected: FAIL - [CSSRuleList interface: existence and properties of interface prototype object] expected: FAIL - [CSSRuleList interface: existence and properties of interface prototype object's "constructor" property] - expected: FAIL - - [CSSRuleList interface: operation item(unsigned long)] - expected: FAIL - - [CSSRuleList interface: attribute length] - expected: FAIL - [CSSRuleList must be primary interface of style_element.sheet.cssRules] expected: FAIL @@ -222,90 +192,9 @@ [CSSRuleList interface: style_element.sheet.cssRules must inherit property "length" with the proper type (1)] expected: FAIL - [CSSRule interface: existence and properties of interface object] - expected: FAIL - - [CSSRule interface object length] - expected: FAIL - - [CSSRule interface: existence and properties of interface prototype object] - expected: FAIL - - [CSSRule interface: existence and properties of interface prototype object's "constructor" property] - expected: FAIL - - [CSSRule interface: constant STYLE_RULE on interface object] - expected: FAIL - - [CSSRule interface: constant STYLE_RULE on interface prototype object] - expected: FAIL - - [CSSRule interface: constant CHARSET_RULE on interface object] - expected: FAIL - - [CSSRule interface: constant CHARSET_RULE on interface prototype object] - expected: FAIL - - [CSSRule interface: constant IMPORT_RULE on interface object] - expected: FAIL - - [CSSRule interface: constant IMPORT_RULE on interface prototype object] - expected: FAIL - - [CSSRule interface: constant MEDIA_RULE on interface object] - expected: FAIL - - [CSSRule interface: constant MEDIA_RULE on interface prototype object] - expected: FAIL - - [CSSRule interface: constant FONT_FACE_RULE on interface object] - expected: FAIL - - [CSSRule interface: constant FONT_FACE_RULE on interface prototype object] - expected: FAIL - - [CSSRule interface: constant PAGE_RULE on interface object] - expected: FAIL - - [CSSRule interface: constant PAGE_RULE on interface prototype object] - expected: FAIL - - [CSSRule interface: constant MARGIN_RULE on interface object] - expected: FAIL - - [CSSRule interface: constant MARGIN_RULE on interface prototype object] - expected: FAIL - - [CSSRule interface: constant NAMESPACE_RULE on interface object] - expected: FAIL - - [CSSRule interface: constant NAMESPACE_RULE on interface prototype object] - expected: FAIL - - [CSSRule interface: attribute type] - expected: FAIL - - [CSSRule interface: attribute cssText] - expected: FAIL - [CSSRule interface: attribute parentRule] expected: FAIL - [CSSRule interface: attribute parentStyleSheet] - expected: FAIL - - [CSSStyleRule interface: existence and properties of interface object] - expected: FAIL - - [CSSStyleRule interface object length] - expected: FAIL - - [CSSStyleRule interface: existence and properties of interface prototype object] - expected: FAIL - - [CSSStyleRule interface: existence and properties of interface prototype object's "constructor" property] - expected: FAIL - [CSSStyleRule interface: attribute selectorText] expected: FAIL @@ -381,18 +270,6 @@ [CSSImportRule interface: attribute styleSheet] expected: FAIL - [CSSGroupingRule interface: existence and properties of interface object] - expected: FAIL - - [CSSGroupingRule interface object length] - expected: FAIL - - [CSSGroupingRule interface: existence and properties of interface prototype object] - expected: FAIL - - [CSSGroupingRule interface: existence and properties of interface prototype object's "constructor" property] - expected: FAIL - [CSSGroupingRule interface: attribute cssRules] expected: FAIL @@ -402,18 +279,6 @@ [CSSGroupingRule interface: operation deleteRule(unsigned long)] expected: FAIL - [CSSMediaRule interface: existence and properties of interface object] - expected: FAIL - - [CSSMediaRule interface object length] - expected: FAIL - - [CSSMediaRule interface: existence and properties of interface prototype object] - expected: FAIL - - [CSSMediaRule interface: existence and properties of interface prototype object's "constructor" property] - expected: FAIL - [CSSMediaRule interface: attribute media] expected: FAIL @@ -453,18 +318,6 @@ [CSSMarginRule interface: attribute style] expected: FAIL - [CSSNamespaceRule interface: existence and properties of interface object] - expected: FAIL - - [CSSNamespaceRule interface object length] - expected: FAIL - - [CSSNamespaceRule interface: existence and properties of interface prototype object] - expected: FAIL - - [CSSNamespaceRule interface: existence and properties of interface prototype object's "constructor" property] - expected: FAIL - [CSSNamespaceRule interface: attribute namespaceURI] expected: FAIL diff --git a/tests/wpt/metadata-css/geometry-1_dev/html/DOMMatrix-003.htm.ini b/tests/wpt/metadata-css/geometry-1_dev/html/DOMMatrix-003.htm.ini index f48899ab692..29e6f751307 100644 --- a/tests/wpt/metadata-css/geometry-1_dev/html/DOMMatrix-003.htm.ini +++ b/tests/wpt/metadata-css/geometry-1_dev/html/DOMMatrix-003.htm.ini @@ -17,3 +17,4 @@ [test skewY()] expected: FAIL + diff --git a/tests/wpt/metadata-css/geometry-1_dev/xhtml1/DOMMatrix-001.xht.ini b/tests/wpt/metadata-css/geometry-1_dev/xhtml1/DOMMatrix-001.xht.ini index 52c1a3c5a0a..f1551700aef 100644 --- a/tests/wpt/metadata-css/geometry-1_dev/xhtml1/DOMMatrix-001.xht.ini +++ b/tests/wpt/metadata-css/geometry-1_dev/xhtml1/DOMMatrix-001.xht.ini @@ -1,6 +1,5 @@ [DOMMatrix-001.xht] type: testharness - [testConstructor1] expected: FAIL diff --git a/tests/wpt/metadata-css/geometry-1_dev/xhtml1/DOMMatrix-003.xht.ini b/tests/wpt/metadata-css/geometry-1_dev/xhtml1/DOMMatrix-003.xht.ini index b32671d9bc0..6dff066e704 100644 --- a/tests/wpt/metadata-css/geometry-1_dev/xhtml1/DOMMatrix-003.xht.ini +++ b/tests/wpt/metadata-css/geometry-1_dev/xhtml1/DOMMatrix-003.xht.ini @@ -17,3 +17,4 @@ [test skewY()] expected: FAIL + diff --git a/tests/wpt/metadata-css/geometry-1_dev/xhtml1print/DOMMatrix-001.xht.ini b/tests/wpt/metadata-css/geometry-1_dev/xhtml1print/DOMMatrix-001.xht.ini index 52c1a3c5a0a..f1551700aef 100644 --- a/tests/wpt/metadata-css/geometry-1_dev/xhtml1print/DOMMatrix-001.xht.ini +++ b/tests/wpt/metadata-css/geometry-1_dev/xhtml1print/DOMMatrix-001.xht.ini @@ -1,6 +1,5 @@ [DOMMatrix-001.xht] type: testharness - [testConstructor1] expected: FAIL diff --git a/tests/wpt/metadata-css/geometry-1_dev/xhtml1print/DOMMatrix-003.xht.ini b/tests/wpt/metadata-css/geometry-1_dev/xhtml1print/DOMMatrix-003.xht.ini index b32671d9bc0..6dff066e704 100644 --- a/tests/wpt/metadata-css/geometry-1_dev/xhtml1print/DOMMatrix-003.xht.ini +++ b/tests/wpt/metadata-css/geometry-1_dev/xhtml1print/DOMMatrix-003.xht.ini @@ -17,3 +17,4 @@ [test skewY()] expected: FAIL + diff --git a/tests/wpt/mozilla/meta/css/animations/basic-transition.html.ini b/tests/wpt/mozilla/meta/css/animations/basic-transition.html.ini index 8d564f4e839..269b3cd3710 100644 --- a/tests/wpt/mozilla/meta/css/animations/basic-transition.html.ini +++ b/tests/wpt/mozilla/meta/css/animations/basic-transition.html.ini @@ -1,2 +1,3 @@ [basic-transition.html] + type: reftest disabled: https://github.com/servo/servo/issues/13865 diff --git a/tests/wpt/mozilla/meta/css/inline_block_opacity_change.html.ini b/tests/wpt/mozilla/meta/css/inline_block_opacity_change.html.ini new file mode 100644 index 00000000000..e77c99740ec --- /dev/null +++ b/tests/wpt/mozilla/meta/css/inline_block_opacity_change.html.ini @@ -0,0 +1,4 @@ +[inline_block_opacity_change.html] + type: reftest + expected: PASS + disabled: https://github.com/servo/servo/issues/13360 diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.html b/tests/wpt/mozilla/tests/mozilla/interfaces.html index 51c0b2cae63..debc89bf675 100644 --- a/tests/wpt/mozilla/tests/mozilla/interfaces.html +++ b/tests/wpt/mozilla/tests/mozilla/interfaces.html @@ -20,7 +20,17 @@ test_interfaces([ "CharacterData", "CloseEvent", "CSS", + "CSSFontFaceRule", + "CSSGroupingRule", + "CSSKeyframesRule", + "CSSMediaRule", + "CSSNamespaceRule", + "CSSRule", + "CSSRuleList", "CSSStyleDeclaration", + "CSSStyleRule", + "CSSStyleSheet", + "CSSViewportRule", "DOMMatrix", "DOMMatrixReadOnly", "DOMPoint", diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js b/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js index bc46462be50..15c6e2d60c6 100644 --- a/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js +++ b/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js @@ -10,7 +10,6 @@ test_interfaces([ "BeforeUnloadEvent", "Blob", "CloseEvent", - "CSS", "CSSStyleDeclaration", "DOMPoint", "DOMPointReadOnly", @@ -50,8 +49,6 @@ test_interfaces([ "Screen", "Storage", "StorageEvent", - "StyleSheet", - "StyleSheetList", "TextDecoder", "TextEncoder", "URL",