mirror of
https://github.com/servo/servo.git
synced 2025-08-10 07:55:33 +01:00
Auto merge of #14190 - Manishearth:cssom, r=SimonSapin
Immutable CSSOM This PR is intended to add basic support for all CSSOM interfaces, with the ability to index `document.styleSheets` and css rule lists, and serializing individual css rules. Handling individual interface methods for CSSRule subclasses can probably be done with easy/medium bugs. Mutation safety isn't dealt with here; if the css rule list is mutated the CSSOM will be in an inconsistent state. I intend to deal with this via zero sized tokens, see https://groups.google.com/forum/#!topic/mozilla.dev.servo/AnxJoVmtMXQ . I'll handle that when I start making the CSSOM mutable. (Getting the immutable bit landed first opens this up for easy bugs) This doesn't really change style aside from adding an extra arc in the CSS rule list as discussed in the linked thread. So far this same design can be used by stylo as well when the time comes. f? @SimonSapin @emilio cc @upsuper part of #11420 Todo: - [x] Stubs for rest of the CSSRule subclasses - [x] <s>ToCSS impls for CSSRules.</s> May make into easy bugs and stub out in this PR https://github.com/servo/servo/issues/14195 - [x] Cache CSSStyleSheet on the relevant node <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/14190) <!-- Reviewable:end -->
This commit is contained in:
commit
afc60bee28
57 changed files with 915 additions and 209 deletions
|
@ -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;
|
||||
|
|
|
@ -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<RwLock<Vec<CssRule>>>);
|
||||
|
||||
impl From<Vec<CssRule>> for CssRules {
|
||||
fn from(other: Vec<CssRule>) -> 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<CssRule>,
|
||||
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<RwLock<MediaList>>,
|
||||
pub rules: Vec<CssRule>,
|
||||
pub rules: CssRules,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -121,6 +133,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>>>(
|
||||
|
@ -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<F>(&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<CssRule> {
|
||||
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<CssRul
|
|||
}
|
||||
}
|
||||
}
|
||||
rules
|
||||
rules.into()
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue