Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSSOM: Make Stylesheet fields have their own synchronization #14232

Merged
merged 5 commits into from Nov 22, 2016
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -24,7 +24,6 @@ lazy_static = "0.2"
log = "0.3.5"
msg = {path = "../msg"}
net_traits = {path = "../net_traits"}
style_traits = {path = "../style_traits"}
parking_lot = {version = "0.3.3", features = ["nightly"]}
plugins = {path = "../plugins"}
profile_traits = {path = "../profile_traits"}
@@ -42,7 +42,6 @@ extern crate selectors;
extern crate serde_json;
extern crate servo_url;
extern crate style;
extern crate style_traits;
extern crate util;
extern crate webrender_traits;

@@ -1055,7 +1054,7 @@ impl LayoutThread {
.send(ConstellationMsg::ViewportConstrained(self.id, constraints))
.unwrap();
}
if data.document_stylesheets.iter().any(|sheet| sheet.dirty_on_viewport_size_change) {
if data.document_stylesheets.iter().any(|sheet| sheet.dirty_on_viewport_size_change()) {
let mut iter = node.traverse_preorder();

let mut next = iter.next();
@@ -1531,6 +1530,7 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
None,
None,
Origin::UserAgent,
Default::default(),
Box::new(StdoutErrorReporter),
ParserContextExtraData::default()))
}
@@ -1543,8 +1543,8 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
}
for &(ref contents, ref url) in &opts::get().user_stylesheets {
user_or_user_agent_stylesheets.push(Stylesheet::from_bytes(
&contents, url.clone(), None, None, Origin::User, Box::new(StdoutErrorReporter),
ParserContextExtraData::default()));
&contents, url.clone(), None, None, Origin::User, Default::default(),
Box::new(StdoutErrorReporter), ParserContextExtraData::default()));
}

let quirks_mode_stylesheet = try!(parse_ua_stylesheet("quirks-mode.css"));
@@ -370,12 +370,10 @@ impl FetchResponseListener for StylesheetContext {

let win = window_from_node(&*elem);

let mut sheet = Stylesheet::from_bytes(&data, final_url, protocol_encoding_label,
Some(environment_encoding), Origin::Author,
win.css_error_reporter(),
ParserContextExtraData::default());
sheet.set_media(self.media.take().unwrap());
let sheet = Arc::new(sheet);
let sheet = Arc::new(Stylesheet::from_bytes(
&data, final_url, protocol_encoding_label, Some(environment_encoding),
Origin::Author, self.media.take().unwrap(), win.css_error_reporter(),
ParserContextExtraData::default()));

let win = window_from_node(&*elem);
win.layout_chan().send(Msg::AddStylesheet(sheet.clone())).unwrap();
@@ -21,6 +21,7 @@ use html5ever_atoms::LocalName;
use parking_lot::RwLock;
use std::ascii::AsciiExt;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use style::attr::AttrValue;
use style::str::HTML_SPACE_CHARACTERS;
use style::stylesheets::{Stylesheet, CssRule, Origin};
@@ -101,7 +102,7 @@ impl HTMLMetaElement {
media: Default::default(),
// Viewport constraints are always recomputed on resize; they don't need to
// force all styles to be recomputed.
dirty_on_viewport_size_change: false,
dirty_on_viewport_size_change: AtomicBool::new(false),
}));
let doc = document_from_node(self);
doc.invalidate_stylesheets();
@@ -65,10 +65,9 @@ impl HTMLStyleElement {
};

let data = node.GetTextContent().expect("Element.textContent must be a string");
let mut sheet = Stylesheet::from_str(&data, url, Origin::Author, win.css_error_reporter(),
ParserContextExtraData::default());
let mut css_parser = CssParser::new(&mq_str);
sheet.set_media(parse_media_query_list(&mut css_parser));
let mq = parse_media_query_list(&mut CssParser::new(&mq_str));
let sheet = Stylesheet::from_str(&data, url, Origin::Author, mq, win.css_error_reporter(),
ParserContextExtraData::default());
let sheet = Arc::new(sheet);

win.layout_chan().send(Msg::AddStylesheet(sheet.clone())).unwrap();
@@ -22,6 +22,7 @@ use servo_url::ServoUrl;
use std::cell::Cell;
use std::fmt;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use style_traits::ToCss;
use viewport::ViewportRule;

@@ -57,9 +58,9 @@ pub struct Stylesheet {
/// cascading order)
pub rules: CssRules,
/// List of media associated with the Stylesheet.
pub media: MediaList,
pub media: Arc<RwLock<MediaList>>,
pub origin: Origin,
pub dirty_on_viewport_size_change: bool,
pub dirty_on_viewport_size_change: AtomicBool,
}


@@ -170,35 +171,21 @@ impl ToCss for StyleRule {


impl Stylesheet {
pub fn from_bytes_iter<I: Iterator<Item=Vec<u8>>>(
input: I, base_url: ServoUrl, protocol_encoding_label: Option<&str>,
environment_encoding: Option<EncodingRef>, origin: Origin,
error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData) -> Stylesheet {
let mut bytes = vec![];
// TODO: incremental decoding and tokenization/parsing
for chunk in input {
bytes.extend_from_slice(&chunk)
}
Stylesheet::from_bytes(&bytes, base_url, protocol_encoding_label,
environment_encoding, origin, error_reporter,
extra_data)
}

pub fn from_bytes(bytes: &[u8],
base_url: ServoUrl,
protocol_encoding_label: Option<&str>,
environment_encoding: Option<EncodingRef>,
origin: Origin, error_reporter: Box<ParseErrorReporter + Send>,
origin: Origin,
media: MediaList,
error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData)
-> Stylesheet {
// TODO: bytes.as_slice could be bytes.container_as_bytes()
let (string, _) = decode_stylesheet_bytes(
bytes, protocol_encoding_label, environment_encoding);
Stylesheet::from_str(&string, base_url, origin, error_reporter, extra_data)
Stylesheet::from_str(&string, base_url, origin, media, error_reporter, extra_data)
}

pub fn from_str(css: &str, base_url: ServoUrl, origin: Origin,
pub fn from_str(css: &str, base_url: ServoUrl, origin: Origin, media: MediaList,
error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData) -> Stylesheet {
let rule_parser = TopLevelRuleParser {
@@ -228,23 +215,36 @@ impl Stylesheet {
Stylesheet {
origin: origin,
rules: rules.into(),
media: Default::default(),
dirty_on_viewport_size_change:
input.seen_viewport_percentages(),
media: Arc::new(RwLock::new(media)),
dirty_on_viewport_size_change: AtomicBool::new(input.seen_viewport_percentages()),
}
}

/// Set the MediaList associated with the style-sheet.
pub fn set_media(&mut self, media: MediaList) {
self.media = media;
pub fn dirty_on_viewport_size_change(&self) -> bool {
self.dirty_on_viewport_size_change.load(Ordering::SeqCst)
}

/// When CSSOM inserts a rule or declaration into this stylesheet, it needs to call this method
/// with the return value of `cssparser::Parser::seen_viewport_percentages`.
///
/// FIXME: actually make these calls
///
/// Note: when *removing* a rule or declaration that contains a viewport percentage,
/// to keep the flag accurate we’d need to iterator through the rest of the stylesheet to
/// check for *other* such values.
///
/// Instead, we conservatively assume there might be some.
/// Restyling will some some more work than necessary, but give correct results.
pub fn inserted_has_viewport_percentages(&self, has_viewport_percentages: bool) {
self.dirty_on_viewport_size_change.fetch_or(has_viewport_percentages, Ordering::SeqCst);
}

/// Returns whether the style-sheet applies for the current device depending
/// on the associated MediaList.
///
/// Always true if no associated MediaList exists.
pub fn is_effective_for_device(&self, device: &Device) -> bool {
self.media.evaluate(device)
self.media.read().evaluate(device)
}

/// Return an iterator over the effective rules within the style-sheet, as

Some generated files are not rendered by default. Learn more.

@@ -174,8 +174,8 @@ pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyl
SheetParsingMode::eUserSheetFeatures => Origin::User,
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
};
let sheet = Arc::new(Stylesheet::from_str("", url, origin, Box::new(StdoutErrorReporter),
extra_data));
let sheet = Arc::new(Stylesheet::from_str(
"", url, origin, Default::default(), Box::new(StdoutErrorReporter), extra_data));
unsafe {
transmute(sheet)
}
@@ -204,8 +204,8 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(data: *const nsACString,
referrer: Some(GeckoArcURI::new(referrer)),
principal: Some(GeckoArcPrincipal::new(principal)),
}};
let sheet = Arc::new(Stylesheet::from_str(input, url, origin, Box::new(StdoutErrorReporter),
extra_data));
let sheet = Arc::new(Stylesheet::from_str(
input, url, origin, Default::default(), Box::new(StdoutErrorReporter), extra_data));
unsafe {
transmute(sheet)
}

Some generated files are not rendered by default. Learn more.

@@ -26,8 +26,9 @@ impl ParseErrorReporter for CSSErrorReporterTest {

fn test_media_rule<F>(css: &str, callback: F) where F: Fn(&MediaList, &str) {
let url = ServoUrl::parse("http://localhost").unwrap();
let stylesheet = Stylesheet::from_str(css, url, Origin::Author, Box::new(CSSErrorReporterTest),
ParserContextExtraData::default());
let stylesheet = Stylesheet::from_str(
css, url, Origin::Author, Default::default(),
Box::new(CSSErrorReporterTest), ParserContextExtraData::default());
let mut rule_count = 0;
media_queries(&stylesheet.rules.0.read(), &mut |mq| {
rule_count += 1;
@@ -49,8 +50,9 @@ fn media_queries<F>(rules: &[CssRule], f: &mut F) where F: FnMut(&MediaList) {

fn media_query_test(device: &Device, css: &str, expected_rule_count: usize) {
let url = ServoUrl::parse("http://localhost").unwrap();
let ss = Stylesheet::from_str(css, url, Origin::Author, Box::new(CSSErrorReporterTest),
ParserContextExtraData::default());
let ss = Stylesheet::from_str(
css, url, Origin::Author, Default::default(),
Box::new(CSSErrorReporterTest), ParserContextExtraData::default());
let mut rule_count = 0;
ss.effective_style_rules(device, |_| rule_count += 1);
assert!(rule_count == expected_rule_count, css.to_owned());
@@ -12,6 +12,7 @@ use servo_url::ServoUrl;
use std::borrow::ToOwned;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::atomic::AtomicBool;
use style::error_reporting::ParseErrorReporter;
use style::keyframes::{Keyframe, KeyframeSelector, KeyframePercentage};
use style::parser::ParserContextExtraData;
@@ -49,13 +50,13 @@ fn test_parse_stylesheet() {
}
}";
let url = ServoUrl::parse("about::test").unwrap();
let stylesheet = Stylesheet::from_str(css, url, Origin::UserAgent,
let stylesheet = Stylesheet::from_str(css, url, Origin::UserAgent, Default::default(),
Box::new(CSSErrorReporterTest),
ParserContextExtraData::default());
let expected = Stylesheet {
origin: Origin::UserAgent,
media: Default::default(),
dirty_on_viewport_size_change: false,
dirty_on_viewport_size_change: AtomicBool::new(false),
rules: vec![
CssRule::Namespace(Arc::new(RwLock::new(NamespaceRule {
prefix: None,
@@ -320,7 +321,7 @@ fn test_report_error_stylesheet() {

let errors = error_reporter.errors.clone();

Stylesheet::from_str(css, url, Origin::UserAgent, error_reporter,
Stylesheet::from_str(css, url, Origin::UserAgent, Default::default(), error_reporter,
ParserContextExtraData::default());

let mut errors = errors.lock().unwrap();
@@ -23,6 +23,7 @@ macro_rules! stylesheet {
$css,
ServoUrl::parse("http://localhost").unwrap(),
Origin::$origin,
Default::default(),
$error_reporter,
ParserContextExtraData::default()
))
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.