style: Add a way to update an empty stylesheet for @import.

We'll update the empty stylesheet we've created when instantiating the
ImportRule when the stylesheet finishes loading.
This commit is contained in:
Emilio Cobos Álvarez 2016-12-16 12:11:42 +01:00
parent a42cfae153
commit ca93a2dcec
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 92 additions and 33 deletions

View file

@ -297,4 +297,8 @@ impl MediaList {
}
})
}
pub fn is_empty(&self) -> bool {
self.media_queries.is_empty()
}
}

View file

@ -56,6 +56,12 @@ pub struct Namespaces {
#[derive(Debug)]
pub struct CssRules(pub Vec<CssRule>);
impl CssRules {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
pub enum RulesMutateError {
Syntax,
IndexSize,
@ -106,8 +112,9 @@ impl CssRules {
// Step 3, 4
// XXXManishearth should we also store the namespace map?
let (new_rule, new_state) = try!(CssRule::parse(&rule, parent_stylesheet,
ParserContextExtraData::default(), state));
let (new_rule, new_state) =
try!(CssRule::parse(&rule, parent_stylesheet,
ParserContextExtraData::default(), state));
// Step 5
// Computes the maximum allowed parser state at a given index.
@ -464,54 +471,102 @@ impl Stylesheet {
environment_encoding: Option<EncodingRef>,
origin: Origin,
media: MediaList,
stylesheet_loader: Option<&StylesheetLoader>,
error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData)
-> Stylesheet {
let (string, _) = decode_stylesheet_bytes(
bytes, protocol_encoding_label, environment_encoding);
Stylesheet::from_str(&string, base_url, origin, media, error_reporter, extra_data)
Stylesheet::from_str(&string,
base_url,
origin,
media,
stylesheet_loader,
error_reporter,
extra_data)
}
pub fn from_str(css: &str, base_url: ServoUrl, origin: Origin, media: MediaList,
error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData) -> Stylesheet {
let mut namespaces = Namespaces::default();
let mut rules = vec![];
let dirty_on_viewport_size_change;
pub fn update_from_bytes(existing: &Stylesheet,
bytes: &[u8],
protocol_encoding_label: Option<&str>,
environment_encoding: Option<EncodingRef>,
stylesheet_loader: Option<&StylesheetLoader>,
error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData) {
assert!(existing.rules.read().is_empty());
let (string, _) = decode_stylesheet_bytes(
bytes, protocol_encoding_label, environment_encoding);
Self::update_from_str(existing,
&string,
stylesheet_loader,
error_reporter,
extra_data)
}
pub fn update_from_str(existing: &Stylesheet,
css: &str,
stylesheet_loader: Option<&StylesheetLoader>,
error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData) {
let mut rules = existing.rules.write();
let mut namespaces = existing.namespaces.write();
assert!(rules.is_empty());
let mut input = Parser::new(css);
let rule_parser = TopLevelRuleParser {
stylesheet_origin: existing.origin,
namespaces: &mut namespaces,
loader: stylesheet_loader,
context: ParserContext::new_with_extra_data(existing.origin,
&existing.base_url,
error_reporter,
extra_data),
state: Cell::new(State::Start),
};
input.look_for_viewport_percentages();
{
let rule_parser = TopLevelRuleParser {
stylesheet_origin: origin,
namespaces: &mut namespaces,
context: ParserContext::new_with_extra_data(origin, &base_url, error_reporter, extra_data),
state: Cell::new(State::Start),
};
let mut input = Parser::new(css);
input.look_for_viewport_percentages();
{
let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser);
while let Some(result) = iter.next() {
match result {
Ok(rule) => rules.push(rule),
Err(range) => {
let pos = range.start;
let message = format!("Invalid rule: '{}'", iter.input.slice(range));
log_css_error(iter.input, pos, &*message, &iter.parser.context);
}
let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser);
while let Some(result) = iter.next() {
match result {
Ok(rule) => rules.0.push(rule),
Err(range) => {
let pos = range.start;
let message = format!("Invalid rule: '{}'", iter.input.slice(range));
log_css_error(iter.input, pos, &*message, &iter.parser.context);
}
}
}
dirty_on_viewport_size_change = input.seen_viewport_percentages();
}
Stylesheet {
existing.dirty_on_viewport_size_change
.store(input.seen_viewport_percentages(), Ordering::Release);
}
pub fn from_str(css: &str, base_url: ServoUrl, origin: Origin,
media: MediaList,
stylesheet_loader: Option<&StylesheetLoader>,
error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData) -> Stylesheet {
let s = Stylesheet {
origin: origin,
base_url: base_url,
namespaces: RwLock::new(namespaces),
rules: CssRules::new(rules),
namespaces: RwLock::new(Namespaces::default()),
rules: CssRules::new(vec![]),
media: Arc::new(RwLock::new(media)),
dirty_on_viewport_size_change: AtomicBool::new(dirty_on_viewport_size_change),
dirty_on_viewport_size_change: AtomicBool::new(false),
disabled: AtomicBool::new(false),
}
};
Self::update_from_str(&s,
css,
stylesheet_loader,
error_reporter,
extra_data);
s
}
pub fn dirty_on_viewport_size_change(&self) -> bool {