aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/cssfontfacerule.rs4
-rw-r--r--components/script/dom/cssgroupingrule.rs49
-rw-r--r--components/script/dom/csskeyframerule.rs50
-rw-r--r--components/script/dom/csskeyframesrule.rs84
-rw-r--r--components/script/dom/cssmediarule.rs7
-rw-r--r--components/script/dom/cssnamespacerule.rs19
-rw-r--r--components/script/dom/cssrule.rs30
-rw-r--r--components/script/dom/cssrulelist.rs221
-rw-r--r--components/script/dom/cssstylerule.rs4
-rw-r--r--components/script/dom/cssstylesheet.rs26
-rw-r--r--components/script/dom/cssviewportrule.rs4
-rw-r--r--components/script/dom/htmllinkelement.rs6
-rw-r--r--components/script/dom/htmlstyleelement.rs9
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/webidls/CSSGroupingRule.webidl6
-rw-r--r--components/script/dom/webidls/CSSKeyframeRule.webidl10
-rw-r--r--components/script/dom/webidls/CSSKeyframesRule.webidl8
-rw-r--r--components/script/dom/webidls/CSSNamespaceRule.webidl4
-rw-r--r--components/script/dom/webidls/CSSStyleSheet.webidl4
-rw-r--r--components/script/dom/webidls/HTMLLinkElement.webidl2
-rw-r--r--components/script/dom/webidls/HTMLStyleElement.webidl2
-rw-r--r--components/script/dom/webidls/StyleSheet.webidl6
22 files changed, 499 insertions, 57 deletions
diff --git a/components/script/dom/cssfontfacerule.rs b/components/script/dom/cssfontfacerule.rs
index 18371c89c45..60022b7ba8f 100644
--- a/components/script/dom/cssfontfacerule.rs
+++ b/components/script/dom/cssfontfacerule.rs
@@ -22,7 +22,7 @@ pub struct CSSFontFaceRule {
}
impl CSSFontFaceRule {
- fn new_inherited(parent: &CSSStyleSheet, fontfacerule: Arc<RwLock<FontFaceRule>>) -> CSSFontFaceRule {
+ fn new_inherited(parent: Option<&CSSStyleSheet>, fontfacerule: Arc<RwLock<FontFaceRule>>) -> CSSFontFaceRule {
CSSFontFaceRule {
cssrule: CSSRule::new_inherited(parent),
fontfacerule: fontfacerule,
@@ -30,7 +30,7 @@ impl CSSFontFaceRule {
}
#[allow(unrooted_must_root)]
- pub fn new(window: &Window, parent: &CSSStyleSheet,
+ pub fn new(window: &Window, parent: Option<&CSSStyleSheet>,
fontfacerule: Arc<RwLock<FontFaceRule>>) -> Root<CSSFontFaceRule> {
reflect_dom_object(box CSSFontFaceRule::new_inherited(parent, fontfacerule),
window,
diff --git a/components/script/dom/cssgroupingrule.rs b/components/script/dom/cssgroupingrule.rs
index 3558686ea74..cd55cd358b6 100644
--- a/components/script/dom/cssgroupingrule.rs
+++ b/components/script/dom/cssgroupingrule.rs
@@ -3,28 +3,67 @@
* 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::bindings::codegen::Bindings::CSSGroupingRuleBinding::CSSGroupingRuleMethods;
+use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleBinding::CSSRuleMethods;
+use dom::bindings::error::{ErrorResult, Fallible};
+use dom::bindings::inheritance::Castable;
+use dom::bindings::js::{JS, MutNullableHeap, Root};
+use dom::bindings::reflector::{Reflectable, reflect_dom_object};
+use dom::bindings::str::DOMString;
use dom::cssrule::CSSRule;
+use dom::cssrulelist::{CSSRuleList, RulesSource};
use dom::cssstylesheet::CSSStyleSheet;
use dom::window::Window;
+use style::stylesheets::CssRules as StyleCssRules;
#[dom_struct]
pub struct CSSGroupingRule {
cssrule: CSSRule,
+ #[ignore_heap_size_of = "Arc"]
+ rules: StyleCssRules,
+ rulelist: MutNullableHeap<JS<CSSRuleList>>,
}
impl CSSGroupingRule {
- pub fn new_inherited(parent: &CSSStyleSheet) -> CSSGroupingRule {
+ pub fn new_inherited(parent: Option<&CSSStyleSheet>,
+ rules: StyleCssRules) -> CSSGroupingRule {
CSSGroupingRule {
cssrule: CSSRule::new_inherited(parent),
+ rules: rules,
+ rulelist: MutNullableHeap::new(None),
}
}
#[allow(unrooted_must_root)]
- pub fn new(window: &Window, parent: &CSSStyleSheet) -> Root<CSSGroupingRule> {
- reflect_dom_object(box CSSGroupingRule::new_inherited(parent),
+ pub fn new(window: &Window, parent: Option<&CSSStyleSheet>, rules: StyleCssRules) -> Root<CSSGroupingRule> {
+ reflect_dom_object(box CSSGroupingRule::new_inherited(parent, rules),
window,
CSSGroupingRuleBinding::Wrap)
}
+
+ fn rulelist(&self) -> Root<CSSRuleList> {
+ let sheet = self.upcast::<CSSRule>().GetParentStyleSheet();
+ let sheet = sheet.as_ref().map(|s| &**s);
+ self.rulelist.or_init(|| CSSRuleList::new(self.global().as_window(),
+ sheet,
+ RulesSource::Rules(self.rules.clone())))
+ }
+}
+
+impl CSSGroupingRuleMethods for CSSGroupingRule {
+ // https://drafts.csswg.org/cssom/#dom-cssgroupingrule-cssrules
+ fn CssRules(&self) -> Root<CSSRuleList> {
+ // XXXManishearth check origin clean flag
+ self.rulelist()
+ }
+
+ // https://drafts.csswg.org/cssom/#dom-cssgroupingrule-insertrule
+ fn InsertRule(&self, rule: DOMString, index: u32) -> Fallible<u32> {
+ self.rulelist().insert_rule(&rule, index, /* nested */ true)
+ }
+
+ // https://drafts.csswg.org/cssom/#dom-cssgroupingrule-deleterule
+ fn DeleteRule(&self, index: u32) -> ErrorResult {
+ self.rulelist().remove_rule(index)
+ }
}
diff --git a/components/script/dom/csskeyframerule.rs b/components/script/dom/csskeyframerule.rs
new file mode 100644
index 00000000000..e09099e1135
--- /dev/null
+++ b/components/script/dom/csskeyframerule.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::CSSKeyframeRuleBinding;
+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::keyframes::Keyframe;
+use style_traits::ToCss;
+
+#[dom_struct]
+pub struct CSSKeyframeRule {
+ cssrule: CSSRule,
+ #[ignore_heap_size_of = "Arc"]
+ keyframerule: Arc<RwLock<Keyframe>>,
+}
+
+impl CSSKeyframeRule {
+ fn new_inherited(parent: Option<&CSSStyleSheet>, keyframerule: Arc<RwLock<Keyframe>>) -> CSSKeyframeRule {
+ CSSKeyframeRule {
+ cssrule: CSSRule::new_inherited(parent),
+ keyframerule: keyframerule,
+ }
+ }
+
+ #[allow(unrooted_must_root)]
+ pub fn new(window: &Window, parent: Option<&CSSStyleSheet>,
+ keyframerule: Arc<RwLock<Keyframe>>) -> Root<CSSKeyframeRule> {
+ reflect_dom_object(box CSSKeyframeRule::new_inherited(parent, keyframerule),
+ window,
+ CSSKeyframeRuleBinding::Wrap)
+ }
+}
+
+impl SpecificCSSRule for CSSKeyframeRule {
+ fn ty(&self) -> u16 {
+ use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleConstants;
+ CSSRuleConstants::KEYFRAME_RULE
+ }
+
+ fn get_css(&self) -> DOMString {
+ self.keyframerule.read().to_css_string().into()
+ }
+}
diff --git a/components/script/dom/csskeyframesrule.rs b/components/script/dom/csskeyframesrule.rs
index 138c8b20558..b7baf6b85a9 100644
--- a/components/script/dom/csskeyframesrule.rs
+++ b/components/script/dom/csskeyframesrule.rs
@@ -2,16 +2,25 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use cssparser::Parser;
use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding;
-use dom::bindings::js::Root;
-use dom::bindings::reflector::reflect_dom_object;
+use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding::CSSKeyframesRuleMethods;
+use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleMethods;
+use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
+use dom::bindings::inheritance::Castable;
+use dom::bindings::js::{JS, MutNullableHeap, Root};
+use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::bindings::str::DOMString;
+use dom::csskeyframerule::CSSKeyframeRule;
use dom::cssrule::{CSSRule, SpecificCSSRule};
+use dom::cssrulelist::{CSSRuleList, RulesSource};
use dom::cssstylesheet::CSSStyleSheet;
use dom::window::Window;
use parking_lot::RwLock;
use std::sync::Arc;
-use style::stylesheets::KeyframesRule;
+use style::keyframes::{Keyframe, KeyframeSelector};
+use style::parser::ParserContextExtraData;
+use style::stylesheets::{KeyframesRule, Origin};
use style_traits::ToCss;
#[dom_struct]
@@ -19,23 +28,84 @@ pub struct CSSKeyframesRule {
cssrule: CSSRule,
#[ignore_heap_size_of = "Arc"]
keyframesrule: Arc<RwLock<KeyframesRule>>,
+ rulelist: MutNullableHeap<JS<CSSRuleList>>,
}
impl CSSKeyframesRule {
- fn new_inherited(parent: &CSSStyleSheet, keyframesrule: Arc<RwLock<KeyframesRule>>) -> CSSKeyframesRule {
+ fn new_inherited(parent: Option<&CSSStyleSheet>, keyframesrule: Arc<RwLock<KeyframesRule>>) -> CSSKeyframesRule {
CSSKeyframesRule {
cssrule: CSSRule::new_inherited(parent),
keyframesrule: keyframesrule,
+ rulelist: MutNullableHeap::new(None),
}
}
#[allow(unrooted_must_root)]
- pub fn new(window: &Window, parent: &CSSStyleSheet,
+ pub fn new(window: &Window, parent: Option<&CSSStyleSheet>,
keyframesrule: Arc<RwLock<KeyframesRule>>) -> Root<CSSKeyframesRule> {
reflect_dom_object(box CSSKeyframesRule::new_inherited(parent, keyframesrule),
window,
CSSKeyframesRuleBinding::Wrap)
}
+
+ fn rulelist(&self) -> Root<CSSRuleList> {
+ self.rulelist.or_init(|| {
+ let sheet = self.upcast::<CSSRule>().GetParentStyleSheet();
+ let sheet = sheet.as_ref().map(|s| &**s);
+ CSSRuleList::new(self.global().as_window(),
+ sheet,
+ RulesSource::Keyframes(self.keyframesrule.clone()))
+ })
+ }
+
+ /// Given a keyframe selector, finds the index of the first corresponding rule if any
+ fn find_rule(&self, selector: &str) -> Option<usize> {
+ let mut input = Parser::new(selector);
+ if let Ok(sel) = KeyframeSelector::parse(&mut input) {
+ // This finds the *last* element matching a selector
+ // because that's the rule that applies. Thus, rposition
+ self.keyframesrule.read()
+ .keyframes.iter().rposition(|frame| {
+ frame.read().selector == sel
+ })
+ } else {
+ None
+ }
+ }
+}
+
+impl CSSKeyframesRuleMethods for CSSKeyframesRule {
+ // https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-cssrules
+ fn CssRules(&self) -> Root<CSSRuleList> {
+ self.rulelist()
+ }
+
+ // https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-appendrule
+ fn AppendRule(&self, rule: DOMString) {
+ let global = self.global();
+ let window = global.as_window();
+ let doc = window.Document();
+ let rule = Keyframe::parse(&rule, Origin::Author, doc.url().clone(),
+ ParserContextExtraData::default());
+ if let Ok(rule) = rule {
+ self.keyframesrule.write().keyframes.push(rule);
+ self.rulelist().append_lazy_dom_rule();
+ }
+ }
+
+ // https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-deleterule
+ fn DeleteRule(&self, selector: DOMString) {
+ if let Some(idx) = self.find_rule(&selector) {
+ let _ = self.rulelist().remove_rule(idx as u32);
+ }
+ }
+
+ // https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-findrule
+ fn FindRule(&self, selector: DOMString) -> Option<Root<CSSKeyframeRule>> {
+ self.find_rule(&selector).and_then(|idx| {
+ self.rulelist().item(idx as u32)
+ }).and_then(Root::downcast)
+ }
}
impl SpecificCSSRule for CSSKeyframesRule {
@@ -47,4 +117,8 @@ impl SpecificCSSRule for CSSKeyframesRule {
fn get_css(&self) -> DOMString {
self.keyframesrule.read().to_css_string().into()
}
+
+ fn deparent_children(&self) {
+ self.rulelist.get().map(|list| list.deparent_all());
+ }
}
diff --git a/components/script/dom/cssmediarule.rs b/components/script/dom/cssmediarule.rs
index a8d8649b31f..67933fccd3b 100644
--- a/components/script/dom/cssmediarule.rs
+++ b/components/script/dom/cssmediarule.rs
@@ -23,15 +23,16 @@ pub struct CSSMediaRule {
}
impl CSSMediaRule {
- fn new_inherited(parent: &CSSStyleSheet, mediarule: Arc<RwLock<MediaRule>>) -> CSSMediaRule {
+ fn new_inherited(parent: Option<&CSSStyleSheet>, mediarule: Arc<RwLock<MediaRule>>) -> CSSMediaRule {
+ let list = mediarule.read().rules.clone();
CSSMediaRule {
- cssrule: CSSGroupingRule::new_inherited(parent),
+ cssrule: CSSGroupingRule::new_inherited(parent, list),
mediarule: mediarule,
}
}
#[allow(unrooted_must_root)]
- pub fn new(window: &Window, parent: &CSSStyleSheet,
+ pub fn new(window: &Window, parent: Option<&CSSStyleSheet>,
mediarule: Arc<RwLock<MediaRule>>) -> Root<CSSMediaRule> {
reflect_dom_object(box CSSMediaRule::new_inherited(parent, mediarule),
window,
diff --git a/components/script/dom/cssnamespacerule.rs b/components/script/dom/cssnamespacerule.rs
index 04c4431df77..4e93eea2e1f 100644
--- a/components/script/dom/cssnamespacerule.rs
+++ b/components/script/dom/cssnamespacerule.rs
@@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::Bindings::CSSNamespaceRuleBinding;
+use dom::bindings::codegen::Bindings::CSSNamespaceRuleBinding::CSSNamespaceRuleMethods;
use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
@@ -22,7 +23,7 @@ pub struct CSSNamespaceRule {
}
impl CSSNamespaceRule {
- fn new_inherited(parent: &CSSStyleSheet, namespacerule: Arc<RwLock<NamespaceRule>>) -> CSSNamespaceRule {
+ fn new_inherited(parent: Option<&CSSStyleSheet>, namespacerule: Arc<RwLock<NamespaceRule>>) -> CSSNamespaceRule {
CSSNamespaceRule {
cssrule: CSSRule::new_inherited(parent),
namespacerule: namespacerule,
@@ -30,7 +31,7 @@ impl CSSNamespaceRule {
}
#[allow(unrooted_must_root)]
- pub fn new(window: &Window, parent: &CSSStyleSheet,
+ pub fn new(window: &Window, parent: Option<&CSSStyleSheet>,
namespacerule: Arc<RwLock<NamespaceRule>>) -> Root<CSSNamespaceRule> {
reflect_dom_object(box CSSNamespaceRule::new_inherited(parent, namespacerule),
window,
@@ -38,6 +39,20 @@ impl CSSNamespaceRule {
}
}
+impl CSSNamespaceRuleMethods for CSSNamespaceRule {
+ // https://drafts.csswg.org/cssom/#dom-cssnamespacerule-prefix
+ fn Prefix(&self) -> DOMString {
+ self.namespacerule.read().prefix
+ .as_ref().map(|s| s.to_string().into())
+ .unwrap_or(DOMString::new())
+ }
+
+ // https://drafts.csswg.org/cssom/#dom-cssnamespacerule-namespaceuri
+ fn NamespaceURI(&self) -> DOMString {
+ (*self.namespacerule.read().url).into()
+ }
+}
+
impl SpecificCSSRule for CSSNamespaceRule {
fn ty(&self) -> u16 {
use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleConstants;
diff --git a/components/script/dom/cssrule.rs b/components/script/dom/cssrule.rs
index e46738bb1b4..ca1e52b77f0 100644
--- a/components/script/dom/cssrule.rs
+++ b/components/script/dom/cssrule.rs
@@ -9,6 +9,7 @@ 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::csskeyframerule::CSSKeyframeRule;
use dom::csskeyframesrule::CSSKeyframesRule;
use dom::cssmediarule::CSSMediaRule;
use dom::cssnamespacerule::CSSNamespaceRule;
@@ -27,15 +28,15 @@ pub struct CSSRule {
impl CSSRule {
#[allow(unrooted_must_root)]
- pub fn new_inherited(parent: &CSSStyleSheet) -> CSSRule {
+ pub fn new_inherited(parent: Option<&CSSStyleSheet>) -> CSSRule {
CSSRule {
reflector_: Reflector::new(),
- parent: MutNullableHeap::new(Some(parent)),
+ parent: MutNullableHeap::new(parent),
}
}
#[allow(unrooted_must_root)]
- pub fn new(window: &Window, parent: &CSSStyleSheet) -> Root<CSSRule> {
+ pub fn new(window: &Window, parent: Option<&CSSStyleSheet>) -> Root<CSSRule> {
reflect_dom_object(box CSSRule::new_inherited(parent),
window,
CSSRuleBinding::Wrap)
@@ -54,6 +55,8 @@ impl CSSRule {
rule as &SpecificCSSRule
} else if let Some(rule) = self.downcast::<CSSViewportRule>() {
rule as &SpecificCSSRule
+ } else if let Some(rule) = self.downcast::<CSSKeyframeRule>() {
+ rule as &SpecificCSSRule
} else {
unreachable!()
}
@@ -61,7 +64,7 @@ impl CSSRule {
// 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,
+ pub fn new_specific(window: &Window, parent: Option<&CSSStyleSheet>,
rule: StyleCssRule) -> Root<CSSRule> {
// be sure to update the match in as_specific when this is updated
match rule {
@@ -73,6 +76,21 @@ impl CSSRule {
StyleCssRule::Viewport(s) => Root::upcast(CSSViewportRule::new(window, parent, s)),
}
}
+
+ /// Sets owner sheet/rule to null
+ pub fn detach(&self) {
+ self.deparent();
+ // should set parent rule to None when we add parent rule support
+ }
+
+ /// Sets owner sheet to null (and does the same for all children)
+ pub fn deparent(&self) {
+ self.parent.set(None);
+ // https://github.com/w3c/csswg-drafts/issues/722
+ // Spec doesn't ask us to do this, but it makes sense
+ // and browsers implement this behavior
+ self.as_specific().deparent_children();
+ }
}
impl CSSRuleMethods for CSSRule {
@@ -100,4 +118,8 @@ impl CSSRuleMethods for CSSRule {
pub trait SpecificCSSRule {
fn ty(&self) -> u16;
fn get_css(&self) -> DOMString;
+ /// Remove CSSStyleSheet parent from all transitive children
+ fn deparent_children(&self) {
+ // most CSSRules do nothing here
+ }
}
diff --git a/components/script/dom/cssrulelist.rs b/components/script/dom/cssrulelist.rs
index 1c383403a00..deb6b93e8b1 100644
--- a/components/script/dom/cssrulelist.rs
+++ b/components/script/dom/cssrulelist.rs
@@ -2,61 +2,248 @@
* 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::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CSSRuleListBinding;
use dom::bindings::codegen::Bindings::CSSRuleListBinding::CSSRuleListMethods;
+use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
+use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
+use dom::csskeyframerule::CSSKeyframeRule;
use dom::cssrule::CSSRule;
use dom::cssstylesheet::CSSStyleSheet;
use dom::window::Window;
-use style::stylesheets::CssRules;
+use parking_lot::RwLock;
+use std::sync::Arc;
+use style::parser::ParserContextExtraData;
+use style::stylesheets::{CssRules, KeyframesRule, Origin};
+use style::stylesheets::CssRule as StyleCssRule;
+no_jsmanaged_fields!(RulesSource);
no_jsmanaged_fields!(CssRules);
#[dom_struct]
pub struct CSSRuleList {
reflector_: Reflector,
- sheet: JS<CSSStyleSheet>,
+ sheet: MutNullableHeap<JS<CSSStyleSheet>>,
#[ignore_heap_size_of = "Arc"]
- rules: CssRules,
- dom_rules: Vec<MutNullableHeap<JS<CSSRule>>>
+ rules: RulesSource,
+ dom_rules: DOMRefCell<Vec<MutNullableHeap<JS<CSSRule>>>>
+}
+
+pub enum RulesSource {
+ Rules(CssRules),
+ Keyframes(Arc<RwLock<KeyframesRule>>),
}
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();
+ pub fn new_inherited(sheet: Option<&CSSStyleSheet>, rules: RulesSource) -> CSSRuleList {
+ let dom_rules = match rules {
+ RulesSource::Rules(ref rules) => {
+ rules.0.read().iter().map(|_| MutNullableHeap::new(None)).collect()
+ }
+ RulesSource::Keyframes(ref rules) => {
+ rules.read().keyframes.iter().map(|_| MutNullableHeap::new(None)).collect()
+ }
+ };
+
CSSRuleList {
reflector_: Reflector::new(),
- sheet: JS::from_ref(sheet),
+ sheet: MutNullableHeap::new(sheet),
rules: rules,
- dom_rules: dom_rules,
+ dom_rules: DOMRefCell::new(dom_rules),
}
}
#[allow(unrooted_must_root)]
- pub fn new(window: &Window, sheet: &CSSStyleSheet, rules: CssRules) -> Root<CSSRuleList> {
+ pub fn new(window: &Window, sheet: Option<&CSSStyleSheet>,
+ rules: RulesSource) -> Root<CSSRuleList> {
reflect_dom_object(box CSSRuleList::new_inherited(sheet, rules),
window,
CSSRuleListBinding::Wrap)
}
+
+ /// https://drafts.csswg.org/cssom/#insert-a-css-rule
+ ///
+ /// Should only be called for CssRules-backed rules. Use append_lazy_rule
+ /// for keyframes-backed rules.
+ pub fn insert_rule(&self, rule: &str, idx: u32, nested: bool) -> Fallible<u32> {
+ use style::stylesheets::SingleRuleParseError;
+ /// Insert an item into a vector, appending if it is out of bounds
+ fn insert<T>(vec: &mut Vec<T>, index: usize, item: T) {
+ if index >= vec.len() {
+ vec.push(item);
+ } else {
+ vec.insert(index, item);
+ }
+ }
+
+ let css_rules = if let RulesSource::Rules(ref rules) = self.rules {
+ rules
+ } else {
+ panic!("Called insert_rule on non-CssRule-backed CSSRuleList");
+ };
+
+ let global = self.global();
+ let window = global.as_window();
+ let doc = window.Document();
+ let index = idx as usize;
+
+
+ let new_rule = {
+ let rules = css_rules.0.read();
+ let state = if nested {
+ None
+ } else {
+ Some(CssRules::state_at_index(&rules, index))
+ };
+
+ let rev_state = CssRules::state_at_index_rev(&rules, index);
+
+ // Step 1, 2
+ // XXXManishearth get url from correct location
+ // XXXManishearth should we also store the namespace map?
+ let parse_result = StyleCssRule::parse(&rule, Origin::Author,
+ doc.url().clone(),
+ ParserContextExtraData::default(),
+ state);
+
+ if let Err(SingleRuleParseError::Syntax) = parse_result {
+ return Err(Error::Syntax)
+ }
+
+ // Step 3, 4
+ if index > rules.len() {
+ return Err(Error::IndexSize);
+ }
+
+ let (new_rule, new_state) = try!(parse_result.map_err(|_| Error::HierarchyRequest));
+
+ if new_state > rev_state {
+ // We inserted a rule too early, e.g. inserting
+ // a regular style rule before @namespace rules
+ return Err((Error::HierarchyRequest));
+ }
+
+ // Step 6
+ if let StyleCssRule::Namespace(..) = new_rule {
+ if !CssRules::only_ns_or_import(&rules) {
+ return Err(Error::InvalidState);
+ }
+ }
+
+ new_rule
+ };
+
+ insert(&mut css_rules.0.write(), index, new_rule.clone());
+ let sheet = self.sheet.get();
+ let sheet = sheet.as_ref().map(|sheet| &**sheet);
+ let dom_rule = CSSRule::new_specific(&window, sheet, new_rule);
+ insert(&mut self.dom_rules.borrow_mut(),
+ index, MutNullableHeap::new(Some(&*dom_rule)));
+ Ok((idx))
+ }
+
+ // https://drafts.csswg.org/cssom/#remove-a-css-rule
+ // https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-deleterule
+ // In case of a keyframe rule, index must be valid.
+ pub fn remove_rule(&self, index: u32) -> ErrorResult {
+ let index = index as usize;
+
+ match self.rules {
+ RulesSource::Rules(ref css_rules) => {
+ // https://drafts.csswg.org/cssom/#remove-a-css-rule
+ {
+ let rules = css_rules.0.read();
+
+ // Step 1, 2
+ if index >= rules.len() {
+ return Err(Error::IndexSize);
+ }
+
+ // Step 3
+ let ref rule = rules[index];
+
+ // Step 4
+ if let StyleCssRule::Namespace(..) = *rule {
+ if !CssRules::only_ns_or_import(&rules) {
+ return Err(Error::InvalidState);
+ }
+ }
+ }
+
+ // Step 5, 6
+ let mut dom_rules = self.dom_rules.borrow_mut();
+ css_rules.0.write().remove(index);
+ dom_rules[index].get().map(|r| r.detach());
+ dom_rules.remove(index);
+ Ok(())
+ }
+ RulesSource::Keyframes(ref kf) => {
+ // https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-deleterule
+ let mut dom_rules = self.dom_rules.borrow_mut();
+ dom_rules[index].get().map(|r| r.detach());
+ dom_rules.remove(index);
+ kf.write().keyframes.remove(index);
+ Ok(())
+ }
+ }
+ }
+
+ // Remove parent stylesheets from all children
+ pub fn deparent_all(&self) {
+ for rule in self.dom_rules.borrow().iter() {
+ rule.get().map(|r| Root::upcast(r).deparent());
+ }
+ }
+
+ pub fn item(&self, idx: u32) -> Option<Root<CSSRule>> {
+ self.dom_rules.borrow().get(idx as usize).map(|rule| {
+ rule.or_init(|| {
+ let sheet = self.sheet.get();
+ let sheet = sheet.as_ref().map(|sheet| &**sheet);
+ match self.rules {
+ RulesSource::Rules(ref rules) => {
+ CSSRule::new_specific(self.global().as_window(),
+ sheet,
+ rules.0.read()[idx as usize].clone())
+ }
+ RulesSource::Keyframes(ref rules) => {
+ Root::upcast(CSSKeyframeRule::new(self.global().as_window(),
+ sheet,
+ rules.read()
+ .keyframes[idx as usize]
+ .clone()))
+ }
+ }
+
+ })
+ })
+ }
+
+ /// Add a rule to the list of DOM rules. This list is lazy,
+ /// so we just append a placeholder.
+ ///
+ /// Should only be called for keyframes-backed rules, use insert_rule
+ /// for CssRules-backed rules
+ pub fn append_lazy_dom_rule(&self) {
+ if let RulesSource::Rules(..) = self.rules {
+ panic!("Can only call append_lazy_rule with keyframes-backed CSSRules");
+ }
+ self.dom_rules.borrow_mut().push(MutNullableHeap::new(None));
+ }
}
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.read()[idx as usize].clone())
- })
- })
+ self.item(idx)
}
// https://drafts.csswg.org/cssom/#dom-cssrulelist-length
fn Length(&self) -> u32 {
- self.dom_rules.len() as u32
+ self.dom_rules.borrow().len() as u32
}
// check-tidy: no specs after this line
diff --git a/components/script/dom/cssstylerule.rs b/components/script/dom/cssstylerule.rs
index 30726018ca9..7d776655147 100644
--- a/components/script/dom/cssstylerule.rs
+++ b/components/script/dom/cssstylerule.rs
@@ -22,7 +22,7 @@ pub struct CSSStyleRule {
}
impl CSSStyleRule {
- fn new_inherited(parent: &CSSStyleSheet, stylerule: Arc<RwLock<StyleRule>>) -> CSSStyleRule {
+ fn new_inherited(parent: Option<&CSSStyleSheet>, stylerule: Arc<RwLock<StyleRule>>) -> CSSStyleRule {
CSSStyleRule {
cssrule: CSSRule::new_inherited(parent),
stylerule: stylerule,
@@ -30,7 +30,7 @@ impl CSSStyleRule {
}
#[allow(unrooted_must_root)]
- pub fn new(window: &Window, parent: &CSSStyleSheet,
+ pub fn new(window: &Window, parent: Option<&CSSStyleSheet>,
stylerule: Arc<RwLock<StyleRule>>) -> Root<CSSStyleRule> {
reflect_dom_object(box CSSStyleRule::new_inherited(parent, stylerule),
window,
diff --git a/components/script/dom/cssstylesheet.rs b/components/script/dom/cssstylesheet.rs
index d5a9342a75a..2e2ac45d867 100644
--- a/components/script/dom/cssstylesheet.rs
+++ b/components/script/dom/cssstylesheet.rs
@@ -4,10 +4,11 @@
use dom::bindings::codegen::Bindings::CSSStyleSheetBinding;
use dom::bindings::codegen::Bindings::CSSStyleSheetBinding::CSSStyleSheetMethods;
+use dom::bindings::error::{ErrorResult, Fallible};
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::cssrulelist::{CSSRuleList, RulesSource};
use dom::stylesheet::StyleSheet;
use dom::window::Window;
use std::sync::Arc;
@@ -40,12 +41,33 @@ impl CSSStyleSheet {
window,
CSSStyleSheetBinding::Wrap)
}
+
+ fn rulelist(&self) -> Root<CSSRuleList> {
+ self.rulelist.or_init(|| CSSRuleList::new(self.global().as_window(),
+ Some(self),
+ RulesSource::Rules(self.style_stylesheet
+ .rules.clone())))
+ }
}
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()))
+ // XXXManishearth check origin clean flag
+ // https://github.com/servo/servo/issues/14327
+ self.rulelist()
+ }
+
+ // https://drafts.csswg.org/cssom/#dom-cssstylesheet-insertrule
+ fn InsertRule(&self, rule: DOMString, index: u32) -> Fallible<u32> {
+ // XXXManishearth check origin clean flag
+ self.rulelist().insert_rule(&rule, index, /* nested */ false)
+ }
+
+ // https://drafts.csswg.org/cssom/#dom-cssstylesheet-deleterule
+ fn DeleteRule(&self, index: u32) -> ErrorResult {
+ // XXXManishearth check origin clean flag
+ self.rulelist().remove_rule(index)
}
}
diff --git a/components/script/dom/cssviewportrule.rs b/components/script/dom/cssviewportrule.rs
index f534c535a64..b324b0c64f5 100644
--- a/components/script/dom/cssviewportrule.rs
+++ b/components/script/dom/cssviewportrule.rs
@@ -22,7 +22,7 @@ pub struct CSSViewportRule {
}
impl CSSViewportRule {
- fn new_inherited(parent: &CSSStyleSheet, viewportrule: Arc<RwLock<ViewportRule>>) -> CSSViewportRule {
+ fn new_inherited(parent: Option<&CSSStyleSheet>, viewportrule: Arc<RwLock<ViewportRule>>) -> CSSViewportRule {
CSSViewportRule {
cssrule: CSSRule::new_inherited(parent),
viewportrule: viewportrule,
@@ -30,7 +30,7 @@ impl CSSViewportRule {
}
#[allow(unrooted_must_root)]
- pub fn new(window: &Window, parent: &CSSStyleSheet,
+ pub fn new(window: &Window, parent: Option<&CSSStyleSheet>,
viewportrule: Arc<RwLock<ViewportRule>>) -> Root<CSSViewportRule> {
reflect_dom_object(box CSSViewportRule::new_inherited(parent, viewportrule),
window,
diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs
index d1f6d8e957f..f311d022470 100644
--- a/components/script/dom/htmllinkelement.rs
+++ b/components/script/dom/htmllinkelement.rs
@@ -22,6 +22,7 @@ use dom::eventtarget::EventTarget;
use dom::globalscope::GlobalScope;
use dom::htmlelement::HTMLElement;
use dom::node::{Node, document_from_node, window_from_node};
+use dom::stylesheet::StyleSheet as DOMStyleSheet;
use dom::virtualmethods::VirtualMethods;
use encoding::EncodingRef;
use encoding::all::UTF_8;
@@ -452,4 +453,9 @@ impl HTMLLinkElementMethods for HTMLLinkElement {
// https://html.spec.whatwg.org/multipage/#dom-link-target
make_setter!(SetTarget, "target");
+
+ // https://drafts.csswg.org/cssom/#dom-linkstyle-sheet
+ fn GetSheet(&self) -> Option<Root<DOMStyleSheet>> {
+ self.get_cssom_stylesheet().map(Root::upcast)
+ }
}
diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs
index d65153bee31..6a20bf06cdd 100644
--- a/components/script/dom/htmlstyleelement.rs
+++ b/components/script/dom/htmlstyleelement.rs
@@ -5,6 +5,7 @@
use cssparser::Parser as CssParser;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::HTMLStyleElementBinding;
+use dom::bindings::codegen::Bindings::HTMLStyleElementBinding::HTMLStyleElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, MutNullableHeap, Root};
@@ -14,6 +15,7 @@ use dom::document::Document;
use dom::element::Element;
use dom::htmlelement::HTMLElement;
use dom::node::{ChildrenMutation, Node, document_from_node, window_from_node};
+use dom::stylesheet::StyleSheet as DOMStyleSheet;
use dom::virtualmethods::VirtualMethods;
use html5ever_atoms::LocalName;
use script_layout_interface::message::Msg;
@@ -117,3 +119,10 @@ impl VirtualMethods for HTMLStyleElement {
}
}
}
+
+impl HTMLStyleElementMethods for HTMLStyleElement {
+ // https://drafts.csswg.org/cssom/#dom-linkstyle-sheet
+ fn GetSheet(&self) -> Option<Root<DOMStyleSheet>> {
+ self.get_cssom_stylesheet().map(Root::upcast)
+ }
+}
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index 05ec1963a20..23209d89e07 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -244,6 +244,7 @@ pub mod crypto;
pub mod css;
pub mod cssfontfacerule;
pub mod cssgroupingrule;
+pub mod csskeyframerule;
pub mod csskeyframesrule;
pub mod cssmediarule;
pub mod cssnamespacerule;
diff --git a/components/script/dom/webidls/CSSGroupingRule.webidl b/components/script/dom/webidls/CSSGroupingRule.webidl
index 6a317191ff6..9f8347a17d5 100644
--- a/components/script/dom/webidls/CSSGroupingRule.webidl
+++ b/components/script/dom/webidls/CSSGroupingRule.webidl
@@ -5,8 +5,8 @@
// 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);
+ [SameObject] readonly attribute CSSRuleList cssRules;
+ [Throws] unsigned long insertRule(DOMString rule, unsigned long index);
+ [Throws] void deleteRule(unsigned long index);
};
diff --git a/components/script/dom/webidls/CSSKeyframeRule.webidl b/components/script/dom/webidls/CSSKeyframeRule.webidl
new file mode 100644
index 00000000000..5458440be6d
--- /dev/null
+++ b/components/script/dom/webidls/CSSKeyframeRule.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/css-animations/#interface-csskeyframerule
+[Exposed=Window]
+interface CSSKeyframeRule : CSSRule {
+ // attribute DOMString keyText;
+ // readonly attribute CSSStyleDeclaration style;
+};
diff --git a/components/script/dom/webidls/CSSKeyframesRule.webidl b/components/script/dom/webidls/CSSKeyframesRule.webidl
index db152d72850..34d45e1a357 100644
--- a/components/script/dom/webidls/CSSKeyframesRule.webidl
+++ b/components/script/dom/webidls/CSSKeyframesRule.webidl
@@ -6,9 +6,9 @@
[Exposed=Window]
interface CSSKeyframesRule : CSSRule {
// attribute DOMString name;
- // readonly attribute CSSRuleList cssRules;
+ readonly attribute CSSRuleList cssRules;
- // void appendRule(DOMString rule);
- // void deleteRule(DOMString select);
- // CSSKeyframeRule? findRule(DOMString select);
+ void appendRule(DOMString rule);
+ void deleteRule(DOMString select);
+ CSSKeyframeRule? findRule(DOMString select);
};
diff --git a/components/script/dom/webidls/CSSNamespaceRule.webidl b/components/script/dom/webidls/CSSNamespaceRule.webidl
index a8d6b61548f..aa1ce87e289 100644
--- a/components/script/dom/webidls/CSSNamespaceRule.webidl
+++ b/components/script/dom/webidls/CSSNamespaceRule.webidl
@@ -5,6 +5,6 @@
// https://drafts.csswg.org/cssom/#the-cssnamespacerule-interface
[Exposed=Window]
interface CSSNamespaceRule : CSSRule {
- // readonly attribute DOMString namespaceURI;
- // readonly attribute DOMString prefix;
+ readonly attribute DOMString namespaceURI;
+ readonly attribute DOMString prefix;
};
diff --git a/components/script/dom/webidls/CSSStyleSheet.webidl b/components/script/dom/webidls/CSSStyleSheet.webidl
index 99ab3234705..6fba0cf983a 100644
--- a/components/script/dom/webidls/CSSStyleSheet.webidl
+++ b/components/script/dom/webidls/CSSStyleSheet.webidl
@@ -7,6 +7,6 @@
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);
+ [Throws] unsigned long insertRule(DOMString rule, unsigned long index);
+ [Throws] void deleteRule(unsigned long index);
};
diff --git a/components/script/dom/webidls/HTMLLinkElement.webidl b/components/script/dom/webidls/HTMLLinkElement.webidl
index 8c1bf496590..e7bec059efe 100644
--- a/components/script/dom/webidls/HTMLLinkElement.webidl
+++ b/components/script/dom/webidls/HTMLLinkElement.webidl
@@ -15,7 +15,7 @@ interface HTMLLinkElement : HTMLElement {
// also has obsolete members
};
-//HTMLLinkElement implements LinkStyle;
+HTMLLinkElement implements LinkStyle;
// https://html.spec.whatwg.org/multipage/#HTMLLinkElement-partial
partial interface HTMLLinkElement {
diff --git a/components/script/dom/webidls/HTMLStyleElement.webidl b/components/script/dom/webidls/HTMLStyleElement.webidl
index dd766f41d22..78926c2c1a8 100644
--- a/components/script/dom/webidls/HTMLStyleElement.webidl
+++ b/components/script/dom/webidls/HTMLStyleElement.webidl
@@ -8,4 +8,4 @@ interface HTMLStyleElement : HTMLElement {
// attribute DOMString type;
// attribute boolean scoped;
};
-//HTMLStyleElement implements LinkStyle;
+HTMLStyleElement implements LinkStyle;
diff --git a/components/script/dom/webidls/StyleSheet.webidl b/components/script/dom/webidls/StyleSheet.webidl
index a63e2a41f01..336bc6b282c 100644
--- a/components/script/dom/webidls/StyleSheet.webidl
+++ b/components/script/dom/webidls/StyleSheet.webidl
@@ -15,3 +15,9 @@ interface StyleSheet {
// [SameObject, PutForwards=mediaText] readonly attribute MediaList media;
// attribute boolean disabled;
};
+
+// https://drafts.csswg.org/cssom/#the-linkstyle-interface
+[NoInterfaceObject]
+interface LinkStyle {
+ readonly attribute StyleSheet? sheet;
+};