aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-11-10 16:16:56 -0800
committerManish Goregaokar <manishsmail@gmail.com>2016-11-15 06:56:18 -0800
commit177d6fa4eefd347645de18bc58120340e16e23f7 (patch)
treebaecfa9af78df9b3d1947159b9e872dfdf0f5d62 /components
parent2220fcdc0bbb46b907a3a5ed974508c67ddb2890 (diff)
downloadservo-177d6fa4eefd347645de18bc58120340e16e23f7.tar.gz
servo-177d6fa4eefd347645de18bc58120340e16e23f7.zip
Support basic immutable CSSOM
Diffstat (limited to 'components')
-rw-r--r--components/script/dom/cssfontfacerule.rs50
-rw-r--r--components/script/dom/cssgroupingrule.rs30
-rw-r--r--components/script/dom/csskeyframesrule.rs50
-rw-r--r--components/script/dom/cssmediarule.rs51
-rw-r--r--components/script/dom/cssnamespacerule.rs50
-rw-r--r--components/script/dom/cssrule.rs103
-rw-r--r--components/script/dom/cssrulelist.rs67
-rw-r--r--components/script/dom/cssstylerule.rs50
-rw-r--r--components/script/dom/cssstylesheet.rs51
-rw-r--r--components/script/dom/cssviewportrule.rs50
-rw-r--r--components/script/dom/document.rs59
-rw-r--r--components/script/dom/htmllinkelement.rs15
-rw-r--r--components/script/dom/htmlmetaelement.rs19
-rw-r--r--components/script/dom/htmlstyleelement.rs17
-rw-r--r--components/script/dom/mod.rs10
-rw-r--r--components/script/dom/node.rs30
-rw-r--r--components/script/dom/stylesheet.rs2
-rw-r--r--components/script/dom/stylesheetlist.rs13
-rw-r--r--components/script/dom/webidls/CSSFontFaceRule.webidl17
-rw-r--r--components/script/dom/webidls/CSSGroupingRule.webidl12
-rw-r--r--components/script/dom/webidls/CSSKeyframesRule.webidl14
-rw-r--r--components/script/dom/webidls/CSSMediaRule.webidl9
-rw-r--r--components/script/dom/webidls/CSSNamespaceRule.webidl10
-rw-r--r--components/script/dom/webidls/CSSRule.webidl33
-rw-r--r--components/script/dom/webidls/CSSRuleList.webidl11
-rw-r--r--components/script/dom/webidls/CSSStyleRule.webidl10
-rw-r--r--components/script/dom/webidls/CSSStyleSheet.webidl12
-rw-r--r--components/script/dom/webidls/CSSViewportRule.webidl9
-rw-r--r--components/style/stylesheets.rs42
29 files changed, 857 insertions, 39 deletions
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<RwLock<FontFaceRule>>,
+}
+
+impl CSSFontFaceRule {
+ fn new_inherited(parent: &CSSStyleSheet, fontfacerule: Arc<RwLock<FontFaceRule>>) -> CSSFontFaceRule {
+ CSSFontFaceRule {
+ cssrule: CSSRule::new_inherited(parent),
+ fontfacerule: fontfacerule,
+ }
+ }
+
+ #[allow(unrooted_must_root)]
+ pub fn new(window: &Window, parent: &CSSStyleSheet,
+ fontfacerule: Arc<RwLock<FontFaceRule>>) -> Root<CSSFontFaceRule> {
+ 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<CSSGroupingRule> {
+ 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<RwLock<KeyframesRule>>,
+}
+
+impl CSSKeyframesRule {
+ fn new_inherited(parent: &CSSStyleSheet, keyframesrule: Arc<RwLock<KeyframesRule>>) -> CSSKeyframesRule {
+ CSSKeyframesRule {
+ cssrule: CSSRule::new_inherited(parent),
+ keyframesrule: keyframesrule,
+ }
+ }
+
+ #[allow(unrooted_must_root)]
+ pub fn new(window: &Window, parent: &CSSStyleSheet,
+ keyframesrule: Arc<RwLock<KeyframesRule>>) -> Root<CSSKeyframesRule> {
+ 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<RwLock<MediaRule>>,
+}
+
+impl CSSMediaRule {
+ fn new_inherited(parent: &CSSStyleSheet, mediarule: Arc<RwLock<MediaRule>>) -> CSSMediaRule {
+ CSSMediaRule {
+ cssrule: CSSGroupingRule::new_inherited(parent),
+ mediarule: mediarule,
+ }
+ }
+
+ #[allow(unrooted_must_root)]
+ pub fn new(window: &Window, parent: &CSSStyleSheet,
+ mediarule: Arc<RwLock<MediaRule>>) -> Root<CSSMediaRule> {
+ 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<RwLock<NamespaceRule>>,
+}
+
+impl CSSNamespaceRule {
+ fn new_inherited(parent: &CSSStyleSheet, namespacerule: Arc<RwLock<NamespaceRule>>) -> CSSNamespaceRule {
+ CSSNamespaceRule {
+ cssrule: CSSRule::new_inherited(parent),
+ namespacerule: namespacerule,
+ }
+ }
+
+ #[allow(unrooted_must_root)]
+ pub fn new(window: &Window, parent: &CSSStyleSheet,
+ namespacerule: Arc<RwLock<NamespaceRule>>) -> Root<CSSNamespaceRule> {
+ 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<JS<CSSStyleSheet>>,
+}
+
+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<CSSRule> {
+ reflect_dom_object(box CSSRule::new_inherited(parent),
+ window,
+ CSSRuleBinding::Wrap)
+ }
+
+ pub fn as_specific(&self) -> &SpecificCSSRule {
+ if let Some(rule) = self.downcast::<CSSStyleRule>() {
+ rule as &SpecificCSSRule
+ } else if let Some(rule) = self.downcast::<CSSFontFaceRule>() {
+ rule as &SpecificCSSRule
+ } else if let Some(rule) = self.downcast::<CSSKeyframesRule>() {
+ rule as &SpecificCSSRule
+ } else if let Some(rule) = self.downcast::<CSSMediaRule>() {
+ rule as &SpecificCSSRule
+ } else if let Some(rule) = self.downcast::<CSSNamespaceRule>() {
+ rule as &SpecificCSSRule
+ } else if let Some(rule) = self.downcast::<CSSViewportRule>() {
+ 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<CSSRule> {
+ // 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<Root<CSSStyleSheet>> {
+ 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..5975a5eb6d1
--- /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<CSSStyleSheet>,
+ #[ignore_heap_size_of = "Arc"]
+ rules: CssRules,
+ dom_rules: Vec<MutNullableHeap<JS<CSSRule>>>
+}
+
+impl CSSRuleList {
+ #[allow(unrooted_must_root)]
+ pub fn new_inherited(sheet: &CSSStyleSheet, rules: CssRules) -> CSSRuleList {
+ let dom_rules = rules.0.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<CSSRuleList> {
+ 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<Root<CSSRule>> {
+ self.dom_rules.get(idx as usize).map(|rule| {
+ rule.or_init(|| {
+ CSSRule::new_specific(self.global().as_window(),
+ &self.sheet,
+ self.rules.0[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<Root<CSSRule>> {
+ 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<RwLock<StyleRule>>,
+}
+
+impl CSSStyleRule {
+ fn new_inherited(parent: &CSSStyleSheet, stylerule: Arc<RwLock<StyleRule>>) -> CSSStyleRule {
+ CSSStyleRule {
+ cssrule: CSSRule::new_inherited(parent),
+ stylerule: stylerule,
+ }
+ }
+
+ #[allow(unrooted_must_root)]
+ pub fn new(window: &Window, parent: &CSSStyleSheet,
+ stylerule: Arc<RwLock<StyleRule>>) -> Root<CSSStyleRule> {
+ 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<JS<CSSRuleList>>,
+ #[ignore_heap_size_of = "Arc"]
+ style_stylesheet: Arc<StyleStyleSheet>,
+}
+
+impl CSSStyleSheet {
+ fn new_inherited(type_: DOMString, href: Option<DOMString>,
+ title: Option<DOMString>, stylesheet: Arc<StyleStyleSheet>) -> 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<DOMString>,
+ title: Option<DOMString>,
+ stylesheet: Arc<StyleStyleSheet>) -> Root<CSSStyleSheet> {
+ 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<CSSRuleList> {
+ 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<RwLock<ViewportRule>>,
+}
+
+impl CSSViewportRule {
+ fn new_inherited(parent: &CSSStyleSheet, viewportrule: Arc<RwLock<ViewportRule>>) -> CSSViewportRule {
+ CSSViewportRule {
+ cssrule: CSSRule::new_inherited(parent),
+ viewportrule: viewportrule,
+ }
+ }
+
+ #[allow(unrooted_must_root)]
+ pub fn new(window: &Window, parent: &CSSStyleSheet,
+ viewportrule: Arc<RwLock<ViewportRule>>) -> Root<CSSViewportRule> {
+ 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<Node>,
+pub struct StylesheetInDocument {
+ pub node: JS<Node>,
#[ignore_heap_size_of = "Arc"]
- stylesheet: Arc<Stylesheet>,
+ pub stylesheet: Arc<Stylesheet>,
}
// https://dom.spec.whatwg.org/#document
@@ -189,6 +186,7 @@ pub struct Document {
stylesheets: DOMRefCell<Option<Vec<StylesheetInDocument>>>,
/// Whether the list of stylesheets has changed since the last reflow was triggered.
stylesheets_changed_since_reflow: Cell<bool>,
+ stylesheet_list: MutNullableHeap<JS<StyleSheetList>>,
ready_state: Cell<DocumentReadyState>,
/// Whether the DOMContentLoaded event has already been dispatched.
domcontentloaded_dispatched: Cell<bool>,
@@ -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::<Node>()
+ .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<Arc<Stylesheet>> {
- {
- let mut stylesheets = self.stylesheets.borrow_mut();
- if stylesheets.is_none() {
- *stylesheets = Some(self.upcast::<Node>()
- .traverse_preorder()
- .filter_map(|node| {
- if let Some(node) = node.downcast::<HTMLStyleElement>() {
- node.get_stylesheet()
- } else if let Some(node) = node.downcast::<HTMLLinkElement>() {
- node.get_stylesheet()
- } else if let Some(node) = node.downcast::<HTMLMetaElement>() {
- 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<F, T>(&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<Document> {
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> {
- 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<JS<DOMTokenList>>,
#[ignore_heap_size_of = "Arc"]
stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>,
+ cssom_stylesheet: MutNullableHeap<JS<CSSStyleSheet>>,
/// https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts
parser_inserted: Cell<bool>,
@@ -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<Arc<Stylesheet>> {
self.stylesheet.borrow().clone()
}
+
+ pub fn get_cssom_stylesheet(&self) -> Option<Root<CSSStyleSheet>> {
+ 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<String> {
diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs
index 29135ee933a..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<Option<Arc<Stylesheet>>>,
+ cssom_stylesheet: MutNullableHeap<JS<CSSStyleSheet>>,
}
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<Root<CSSStyleSheet>> {
+ 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::<Element>();
if let Some(name) = element.get_attribute(&ns!(), &local_name!("name")).r() {
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<Option<Arc<Stylesheet>>>,
+ cssom_stylesheet: MutNullableHeap<JS<CSSStyleSheet>>,
}
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<Arc<Stylesheet>> {
self.stylesheet.borrow().clone()
}
+
+ pub fn get_cssom_stylesheet(&self) -> Option<Root<CSSStyleSheet>> {
+ 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::<Node>().remove_self();
Ok(())
}
+
+ pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
+ if let Some(node) = self.downcast::<HTMLStyleElement>() {
+ node.get_stylesheet()
+ } else if let Some(node) = self.downcast::<HTMLLinkElement>() {
+ node.get_stylesheet()
+ } else if let Some(node) = self.downcast::<HTMLMetaElement>() {
+ node.get_stylesheet()
+ } else {
+ None
+ }
+ }
+
+ pub fn get_cssom_stylesheet(&self) -> Option<Root<CSSStyleSheet>> {
+ if let Some(node) = self.downcast::<HTMLStyleElement>() {
+ node.get_cssom_stylesheet()
+ } else if let Some(node) = self.downcast::<HTMLLinkElement>() {
+ node.get_cssom_stylesheet()
+ } else if let Some(node) = self.downcast::<HTMLMetaElement>() {
+ 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<DOMString>, title: Option<DOMString>) -> StyleSheet {
+ pub fn new_inherited(type_: DOMString, href: Option<DOMString>, title: Option<DOMString>) -> 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<Root<StyleSheet>> {
- None
- //TODO Create a new StyleSheet object and return it
+ fn Item(&self, index: u32) -> Option<Root<StyleSheet>> {
+ // 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/CSSFontFaceRule.webidl b/components/script/dom/webidls/CSSFontFaceRule.webidl
new file mode 100644
index 00000000000..56f5f6338d2
--- /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,Worker)]
+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..fdf5f22fbcc
--- /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,Worker)]
+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..e2c9fe68058
--- /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,Worker)]
+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..4d83f8255d8
--- /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,Worker)]
+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..5ee1013a82b
--- /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,Worker)]
+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..1c1015c9fe4
--- /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,Worker)]
+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..9947ca8473b
--- /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,Worker)]
+interface CSSRuleList {
+ getter CSSRule? item(unsigned long index);
+ readonly attribute unsigned long length;
+};
diff --git a/components/script/dom/webidls/CSSStyleRule.webidl b/components/script/dom/webidls/CSSStyleRule.webidl
new file mode 100644
index 00000000000..acf2386cc18
--- /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,Worker)]
+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..e30663fc778
--- /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,Worker)]
+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..bea63540527
--- /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,Worker)]
+interface CSSViewportRule : CSSRule {
+ // readonly attribute CSSStyleDeclaration style;
+};
diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs
index 924851db5b6..7126ba0ee8c 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,7 +42,7 @@ pub enum Origin {
User,
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct CssRules(pub Arc<Vec<CssRule>>);
impl From<Vec<CssRule>> for CssRules {
@@ -67,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
@@ -129,6 +132,41 @@ pub struct StyleRule {
pub block: Arc<RwLock<PropertyDeclarationBlock>>,
}
+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<W>(&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<W>(&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<I: Iterator<Item=Vec<u8>>>(