Auto merge of #16378 - emilio:media-fixes, r=upsuper

stylo: A bunch of media query fixes.

<!-- 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/16378)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-04-12 10:00:26 -05:00 committed by GitHub
commit bb66bf81d5
16 changed files with 211 additions and 125 deletions

View file

@ -113,7 +113,7 @@ use style::data::StoredRestyleHint;
use style::dom::{ShowSubtree, ShowSubtreeDataAndPrimaryValues, TElement, TNode}; use style::dom::{ShowSubtree, ShowSubtreeDataAndPrimaryValues, TElement, TNode};
use style::error_reporting::StdoutErrorReporter; use style::error_reporting::StdoutErrorReporter;
use style::logical_geometry::LogicalPoint; use style::logical_geometry::LogicalPoint;
use style::media_queries::{Device, MediaType}; use style::media_queries::{Device, MediaList, MediaType};
use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION, STORE_OVERFLOW}; use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION, STORE_OVERFLOW};
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards}; use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards};
use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets}; use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets};
@ -1583,7 +1583,7 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
None, None,
None, None,
Origin::UserAgent, Origin::UserAgent,
Default::default(), MediaList::empty(),
shared_lock.clone(), shared_lock.clone(),
None, None,
&StdoutErrorReporter)) &StdoutErrorReporter))
@ -1598,7 +1598,7 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
} }
for &(ref contents, ref url) in &opts::get().user_stylesheets { for &(ref contents, ref url) in &opts::get().user_stylesheets {
user_or_user_agent_stylesheets.push(Stylesheet::from_bytes( user_or_user_agent_stylesheets.push(Stylesheet::from_bytes(
&contents, url.clone(), None, None, Origin::User, Default::default(), &contents, url.clone(), None, None, Origin::User, MediaList::empty(),
shared_lock.clone(), None, &StdoutErrorReporter)); shared_lock.clone(), None, &StdoutErrorReporter));
} }

View file

@ -15,7 +15,7 @@ use dom::window::Window;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use std::sync::Arc; use std::sync::Arc;
use style::shared_lock::Locked; use style::shared_lock::Locked;
use style::stylesheets::{CssRules, KeyframesRule, RulesMutateError}; use style::stylesheets::{CssRules, CssRulesHelpers, KeyframesRule, RulesMutateError};
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe_no_jsmanaged_fields!(RulesSource); unsafe_no_jsmanaged_fields!(RulesSource);
@ -90,15 +90,13 @@ impl CSSRuleList {
let index = idx as usize; let index = idx as usize;
let parent_stylesheet = self.parent_stylesheet.style_stylesheet(); let parent_stylesheet = self.parent_stylesheet.style_stylesheet();
let new_rule = { let new_rule =
let mut guard = parent_stylesheet.shared_lock.write(); css_rules.insert_rule(&parent_stylesheet.shared_lock,
// FIXME We should probably pass in a proper StylesheetLoader. rule,
// See servo/servo#16240 parent_stylesheet,
css_rules.write_with(&mut guard).insert_rule(rule, parent_stylesheet, index,
index, nested, None)? nested,
// Drop `guard` here, None)?;
// CSSRule::new_specific re-acquires the lock for @support and @media.
};
let parent_stylesheet = &*self.parent_stylesheet; let parent_stylesheet = &*self.parent_stylesheet;
let dom_rule = CSSRule::new_specific(&window, parent_stylesheet, new_rule); let dom_rule = CSSRule::new_specific(&window, parent_stylesheet, new_rule);

View file

@ -24,6 +24,7 @@ use std::ascii::AsciiExt;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use style::attr::AttrValue; use style::attr::AttrValue;
use style::media_queries::MediaList;
use style::str::HTML_SPACE_CHARACTERS; use style::str::HTML_SPACE_CHARACTERS;
use style::stylesheets::{Stylesheet, CssRule, CssRules, Origin}; use style::stylesheets::{Stylesheet, CssRule, CssRules, Origin};
use style::viewport::ViewportRule; use style::viewport::ViewportRule;
@ -107,7 +108,7 @@ impl HTMLMetaElement {
shared_lock: shared_lock.clone(), shared_lock: shared_lock.clone(),
url_data: window_from_node(self).get_url(), url_data: window_from_node(self).get_url(),
namespaces: Default::default(), namespaces: Default::default(),
media: Arc::new(shared_lock.wrap(Default::default())), media: Arc::new(shared_lock.wrap(MediaList::empty())),
// Viewport constraints are always recomputed on resize; they don't need to // Viewport constraints are always recomputed on resize; they don't need to
// force all styles to be recomputed. // force all styles to be recomputed.
dirty_on_viewport_size_change: AtomicBool::new(false), dirty_on_viewport_size_change: AtomicBool::new(false),

View file

@ -86,8 +86,9 @@ impl HTMLStyleElement {
let context = CssParserContext::new_for_cssom(&url, let context = CssParserContext::new_for_cssom(&url,
win.css_error_reporter(), win.css_error_reporter(),
Some(CssRuleType::Media)); Some(CssRuleType::Media));
let mq = parse_media_query_list(&context, &mut CssParser::new(&mq_str));
let shared_lock = node.owner_doc().style_shared_lock().clone(); let shared_lock = node.owner_doc().style_shared_lock().clone();
let mq = Arc::new(shared_lock.wrap(
parse_media_query_list(&context, &mut CssParser::new(&mq_str))));
let loader = StylesheetLoader::for_element(self.upcast()); let loader = StylesheetLoader::for_element(self.upcast());
let sheet = Stylesheet::from_str(&data, win.get_url(), Origin::Author, mq, let sheet = Stylesheet::from_str(&data, win.get_url(), Origin::Author, mq,
shared_lock, Some(&loader), shared_lock, Some(&loader),

View file

@ -67,7 +67,7 @@ impl MediaListMethods for MediaList {
// Step 2 // Step 2
if value.is_empty() { if value.is_empty() {
// Step 1 // Step 1
*media_queries = StyleMediaList::default(); *media_queries = StyleMediaList::empty();
return; return;
} }
// Step 3 // Step 3

View file

@ -271,15 +271,15 @@ impl<'a> StylesheetLoader<'a> {
impl<'a> StyleStylesheetLoader for StylesheetLoader<'a> { impl<'a> StyleStylesheetLoader for StylesheetLoader<'a> {
fn request_stylesheet( fn request_stylesheet(
&self, &self,
media: MediaList, media: Arc<StyleLocked<MediaList>>,
make_import: &mut FnMut(MediaList) -> ImportRule, make_import: &mut FnMut(Arc<StyleLocked<MediaList>>) -> ImportRule,
make_arc: &mut FnMut(ImportRule) -> Arc<StyleLocked<ImportRule>>, make_arc: &mut FnMut(ImportRule) -> Arc<StyleLocked<ImportRule>>,
) -> Arc<StyleLocked<ImportRule>> { ) -> Arc<StyleLocked<ImportRule>> {
let import = make_import(media); let import = make_import(media);
let url = import.url.url().expect("Invalid urls shouldn't enter the loader").clone(); let url = import.url.url().expect("Invalid urls shouldn't enter the loader").clone();
//TODO (mrnayak) : Whether we should use the original loader's CORS setting? // TODO (mrnayak) : Whether we should use the original loader's CORS
//Fix this when spec has more details. // setting? Fix this when spec has more details.
let source = StylesheetContextSource::Import(import.stylesheet.clone()); let source = StylesheetContextSource::Import(import.stylesheet.clone());
self.load(source, url, None, "".to_owned()); self.load(source, url, None, "".to_owned());

View file

@ -12,6 +12,7 @@ use media_queries::MediaList;
use self::encoding::{EncodingRef, DecoderTrap}; use self::encoding::{EncodingRef, DecoderTrap};
use shared_lock::SharedRwLock; use shared_lock::SharedRwLock;
use std::str; use std::str;
use std::sync::Arc;
use stylesheets::{Stylesheet, StylesheetLoader, Origin, UrlExtraData}; use stylesheets::{Stylesheet, StylesheetLoader, Origin, UrlExtraData};
struct RustEncoding; struct RustEncoding;
@ -62,7 +63,7 @@ impl Stylesheet {
Stylesheet::from_str(&string, Stylesheet::from_str(&string,
url_data, url_data,
origin, origin,
media, Arc::new(shared_lock.wrap(media)),
shared_lock, shared_lock,
stylesheet_loader, stylesheet_loader,
error_reporter) error_reporter)

View file

@ -463,7 +463,7 @@ extern "C" {
child_sheet: RawServoStyleSheetBorrowed, child_sheet: RawServoStyleSheetBorrowed,
base_url_data: *mut RawGeckoURLExtraData, base_url_data: *mut RawGeckoURLExtraData,
url_bytes: *const u8, url_length: u32, url_bytes: *const u8, url_length: u32,
media_bytes: *const u8, media_length: u32); media_list: RawServoMediaListStrong);
} }
extern "C" { extern "C" {
pub fn Gecko_MaybeCreateStyleChildrenIterator(node: RawGeckoNodeBorrowed) pub fn Gecko_MaybeCreateStyleChildrenIterator(node: RawGeckoNodeBorrowed)
@ -1461,6 +1461,8 @@ extern "C" {
*mut ServoStyleSheet, *mut ServoStyleSheet,
data: *const nsACString, data: *const nsACString,
parsing_mode: SheetParsingMode, parsing_mode: SheetParsingMode,
media_list:
*const RawServoMediaList,
extra_data: extra_data:
*mut RawGeckoURLExtraData) *mut RawGeckoURLExtraData)
-> RawServoStyleSheetStrong; -> RawServoStyleSheetStrong;
@ -1914,6 +1916,17 @@ extern "C" {
pub fn Servo_DeclarationBlock_SetTextDecorationColorOverride(declarations: pub fn Servo_DeclarationBlock_SetTextDecorationColorOverride(declarations:
RawServoDeclarationBlockBorrowed); RawServoDeclarationBlockBorrowed);
} }
extern "C" {
pub fn Servo_MediaList_Create() -> RawServoMediaListStrong;
}
extern "C" {
pub fn Servo_MediaList_DeepClone(list: RawServoMediaListBorrowed)
-> RawServoMediaListStrong;
}
extern "C" {
pub fn Servo_MediaList_Matches(list: RawServoMediaListBorrowed,
set: RawServoStyleSetBorrowed) -> bool;
}
extern "C" { extern "C" {
pub fn Servo_MediaList_GetText(list: RawServoMediaListBorrowed, pub fn Servo_MediaList_GetText(list: RawServoMediaListBorrowed,
result: *mut nsAString); result: *mut nsAString);

View file

@ -20,7 +20,7 @@ pub use servo::media_queries::{Device, Expression};
pub use gecko::media_queries::{Device, Expression}; pub use gecko::media_queries::{Device, Expression};
/// A type that encapsulates a media query list. /// A type that encapsulates a media query list.
#[derive(Debug)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct MediaList { pub struct MediaList {
/// The list of media queries. /// The list of media queries.
@ -35,8 +35,9 @@ impl ToCss for MediaList {
} }
} }
impl Default for MediaList { impl MediaList {
fn default() -> MediaList { /// Create an empty MediaList.
pub fn empty() -> Self {
MediaList { media_queries: vec![] } MediaList { media_queries: vec![] }
} }
} }
@ -251,7 +252,7 @@ impl MediaQuery {
/// https://drafts.csswg.org/mediaqueries/#error-handling /// https://drafts.csswg.org/mediaqueries/#error-handling
pub fn parse_media_query_list(context: &ParserContext, input: &mut Parser) -> MediaList { pub fn parse_media_query_list(context: &ParserContext, input: &mut Parser) -> MediaList {
if input.is_exhausted() { if input.is_exhausted() {
return Default::default() return MediaList::empty()
} }
let mut media_queries = vec![]; let mut media_queries = vec![];

View file

@ -135,53 +135,6 @@ impl CssRules {
}) })
} }
/// https://drafts.csswg.org/cssom/#insert-a-css-rule
pub fn insert_rule(&mut self,
rule: &str,
parent_stylesheet: &Stylesheet,
index: usize,
nested: bool,
loader: Option<&StylesheetLoader>)
-> Result<CssRule, RulesMutateError> {
// Step 1, 2
if index > self.0.len() {
return Err(RulesMutateError::IndexSize);
}
// Computes the parser state at the given index
let state = if nested {
None
} else if index == 0 {
Some(State::Start)
} else {
self.0.get(index - 1).map(CssRule::rule_state)
};
// Step 3, 4
// XXXManishearth should we also store the namespace map?
let (new_rule, new_state) =
try!(CssRule::parse(&rule, parent_stylesheet, state, loader));
// Step 5
// Computes the maximum allowed parser state at a given index.
let rev_state = self.0.get(index).map_or(State::Body, CssRule::rule_state);
if new_state > rev_state {
// We inserted a rule too early, e.g. inserting
// a regular style rule before @namespace rules
return Err(RulesMutateError::HierarchyRequest);
}
// Step 6
if let CssRule::Namespace(..) = new_rule {
if !self.only_ns_or_import() {
return Err(RulesMutateError::InvalidState);
}
}
self.0.insert(index, new_rule.clone());
Ok(new_rule)
}
/// https://drafts.csswg.org/cssom/#remove-a-css-rule /// https://drafts.csswg.org/cssom/#remove-a-css-rule
pub fn remove_rule(&mut self, index: usize) -> Result<(), RulesMutateError> { pub fn remove_rule(&mut self, index: usize) -> Result<(), RulesMutateError> {
// Step 1, 2 // Step 1, 2
@ -207,6 +160,86 @@ impl CssRules {
} }
} }
/// A trait to implement helpers for `Arc<Locked<CssRules>>`.
pub trait CssRulesHelpers {
/// https://drafts.csswg.org/cssom/#insert-a-css-rule
///
/// Written in this funky way because parsing an @import rule may cause us
/// to clone a stylesheet from the same document due to caching in the CSS
/// loader.
///
/// TODO(emilio): We could also pass the write guard down into the loader
/// instead, but that seems overkill.
fn insert_rule(&self,
lock: &SharedRwLock,
rule: &str,
parent_stylesheet: &Stylesheet,
index: usize,
nested: bool,
loader: Option<&StylesheetLoader>)
-> Result<CssRule, RulesMutateError>;
}
impl CssRulesHelpers for Arc<Locked<CssRules>> {
fn insert_rule(&self,
lock: &SharedRwLock,
rule: &str,
parent_stylesheet: &Stylesheet,
index: usize,
nested: bool,
loader: Option<&StylesheetLoader>)
-> Result<CssRule, RulesMutateError> {
let state = {
let read_guard = lock.read();
let rules = self.read_with(&read_guard);
// Step 1, 2
if index > rules.0.len() {
return Err(RulesMutateError::IndexSize);
}
// Computes the parser state at the given index
if nested {
None
} else if index == 0 {
Some(State::Start)
} else {
rules.0.get(index - 1).map(CssRule::rule_state)
}
};
// Step 3, 4
// XXXManishearth should we also store the namespace map?
let (new_rule, new_state) =
try!(CssRule::parse(&rule, parent_stylesheet, state, loader));
{
let mut write_guard = lock.write();
let mut rules = self.write_with(&mut write_guard);
// Step 5
// Computes the maximum allowed parser state at a given index.
let rev_state = rules.0.get(index).map_or(State::Body, CssRule::rule_state);
if new_state > rev_state {
// We inserted a rule too early, e.g. inserting
// a regular style rule before @namespace rules
return Err(RulesMutateError::HierarchyRequest);
}
// Step 6
if let CssRule::Namespace(..) = new_rule {
if !rules.only_ns_or_import() {
return Err(RulesMutateError::InvalidState);
}
}
rules.0.insert(index, new_rule.clone());
}
Ok(new_rule)
}
}
/// The structure servo uses to represent a stylesheet. /// The structure servo uses to represent a stylesheet.
#[derive(Debug)] #[derive(Debug)]
pub struct Stylesheet { pub struct Stylesheet {
@ -690,7 +723,7 @@ impl Stylesheet {
pub fn from_str(css: &str, pub fn from_str(css: &str,
url_data: UrlExtraData, url_data: UrlExtraData,
origin: Origin, origin: Origin,
media: MediaList, media: Arc<Locked<MediaList>>,
shared_lock: SharedRwLock, shared_lock: SharedRwLock,
stylesheet_loader: Option<&StylesheetLoader>, stylesheet_loader: Option<&StylesheetLoader>,
error_reporter: &ParseErrorReporter) -> Stylesheet { error_reporter: &ParseErrorReporter) -> Stylesheet {
@ -704,7 +737,7 @@ impl Stylesheet {
url_data: url_data, url_data: url_data,
namespaces: RwLock::new(namespaces), namespaces: RwLock::new(namespaces),
rules: CssRules::new(rules, &shared_lock), rules: CssRules::new(rules, &shared_lock),
media: Arc::new(shared_lock.wrap(media)), media: media,
shared_lock: shared_lock, shared_lock: shared_lock,
dirty_on_viewport_size_change: AtomicBool::new(dirty_on_viewport_size_change), dirty_on_viewport_size_change: AtomicBool::new(dirty_on_viewport_size_change),
disabled: AtomicBool::new(false), disabled: AtomicBool::new(false),
@ -825,8 +858,8 @@ pub trait StylesheetLoader {
/// before theyre locked, while keeping the trait object-safe. /// before theyre locked, while keeping the trait object-safe.
fn request_stylesheet( fn request_stylesheet(
&self, &self,
media: MediaList, media: Arc<Locked<MediaList>>,
make_import: &mut FnMut(MediaList) -> ImportRule, make_import: &mut FnMut(Arc<Locked<MediaList>>) -> ImportRule,
make_arc: &mut FnMut(ImportRule) -> Arc<Locked<ImportRule>>, make_arc: &mut FnMut(ImportRule) -> Arc<Locked<ImportRule>>,
) -> Arc<Locked<ImportRule>>; ) -> Arc<Locked<ImportRule>>;
} }
@ -836,8 +869,8 @@ struct NoOpLoader;
impl StylesheetLoader for NoOpLoader { impl StylesheetLoader for NoOpLoader {
fn request_stylesheet( fn request_stylesheet(
&self, &self,
media: MediaList, media: Arc<Locked<MediaList>>,
make_import: &mut FnMut(MediaList) -> ImportRule, make_import: &mut FnMut(Arc<Locked<MediaList>>) -> ImportRule,
make_arc: &mut FnMut(ImportRule) -> Arc<Locked<ImportRule>>, make_arc: &mut FnMut(ImportRule) -> Arc<Locked<ImportRule>>,
) -> Arc<Locked<ImportRule>> { ) -> Arc<Locked<ImportRule>> {
make_arc(make_import(media)) make_arc(make_import(media))
@ -906,6 +939,7 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
let specified_url = SpecifiedUrl::parse_from_string(url_string, &self.context)?; let specified_url = SpecifiedUrl::parse_from_string(url_string, &self.context)?;
let media = parse_media_query_list(&self.context, input); let media = parse_media_query_list(&self.context, input);
let media = Arc::new(self.shared_lock.wrap(media));
let noop_loader = NoOpLoader; let noop_loader = NoOpLoader;
let loader = if !specified_url.is_invalid() { let loader = if !specified_url.is_invalid() {
@ -920,7 +954,7 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
url: specified_url.take().unwrap(), url: specified_url.take().unwrap(),
stylesheet: Arc::new(Stylesheet { stylesheet: Arc::new(Stylesheet {
rules: CssRules::new(Vec::new(), self.shared_lock), rules: CssRules::new(Vec::new(), self.shared_lock),
media: Arc::new(self.shared_lock.wrap(media)), media: media,
shared_lock: self.shared_lock.clone(), shared_lock: self.shared_lock.clone(),
origin: self.context.stylesheet_origin, origin: self.context.stylesheet_origin,
url_data: self.context.url_data.clone(), url_data: self.context.url_data.clone(),

View file

@ -30,7 +30,7 @@ use style::gecko::wrapper::GeckoElement;
use style::gecko_bindings::bindings; use style::gecko_bindings::bindings;
use style::gecko_bindings::bindings::{RawGeckoKeyframeListBorrowed, RawGeckoKeyframeListBorrowedMut}; use style::gecko_bindings::bindings::{RawGeckoKeyframeListBorrowed, RawGeckoKeyframeListBorrowedMut};
use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong}; use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
use style::gecko_bindings::bindings::{RawServoMediaListBorrowed, RawServoMediaListStrong}; use style::gecko_bindings::bindings::{RawServoMediaList, RawServoMediaListBorrowed, RawServoMediaListStrong};
use style::gecko_bindings::bindings::{RawServoMediaRule, RawServoMediaRuleBorrowed}; use style::gecko_bindings::bindings::{RawServoMediaRule, RawServoMediaRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoNamespaceRule, RawServoNamespaceRuleBorrowed}; use style::gecko_bindings::bindings::{RawServoNamespaceRule, RawServoNamespaceRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoPageRule, RawServoPageRuleBorrowed}; use style::gecko_bindings::bindings::{RawServoPageRule, RawServoPageRuleBorrowed};
@ -83,8 +83,9 @@ use style::selector_parser::PseudoElementCascadeType;
use style::sequential; use style::sequential;
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked}; use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked};
use style::string_cache::Atom; use style::string_cache::Atom;
use style::stylesheets::{CssRule, CssRules, CssRuleType, ImportRule, MediaRule, NamespaceRule, PageRule}; use style::stylesheets::{CssRule, CssRules, CssRuleType, CssRulesHelpers};
use style::stylesheets::{Origin, Stylesheet, StyleRule}; use style::stylesheets::{ImportRule, MediaRule, NamespaceRule, Origin};
use style::stylesheets::{PageRule, Stylesheet, StyleRule};
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader; use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::supports::parse_condition_or_declaration; use style::supports::parse_condition_or_declaration;
use style::thread_state; use style::thread_state;
@ -494,7 +495,8 @@ pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyl
let shared_lock = global_style_data.shared_lock.clone(); let shared_lock = global_style_data.shared_lock.clone();
Arc::new(Stylesheet::from_str( Arc::new(Stylesheet::from_str(
"", unsafe { dummy_url_data() }.clone(), origin, "", unsafe { dummy_url_data() }.clone(), origin,
Default::default(), shared_lock, None, &StdoutErrorReporter) Arc::new(shared_lock.wrap(MediaList::empty())),
shared_lock, None, &StdoutErrorReporter)
).into_strong() ).into_strong()
} }
@ -503,6 +505,7 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(loader: *mut Loader,
stylesheet: *mut ServoStyleSheet, stylesheet: *mut ServoStyleSheet,
data: *const nsACString, data: *const nsACString,
mode: SheetParsingMode, mode: SheetParsingMode,
media_list: *const RawServoMediaList,
extra_data: *mut URLExtraData) extra_data: *mut URLExtraData)
-> RawServoStyleSheetStrong { -> RawServoStyleSheetStrong {
let global_style_data = &*GLOBAL_STYLE_DATA; let global_style_data = &*GLOBAL_STYLE_DATA;
@ -528,8 +531,14 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(loader: *mut Loader,
}; };
let shared_lock = global_style_data.shared_lock.clone(); let shared_lock = global_style_data.shared_lock.clone();
let media = if media_list.is_null() {
Arc::new(shared_lock.wrap(MediaList::empty()))
} else {
Locked::<MediaList>::as_arc(unsafe { &&*media_list }).clone()
};
Arc::new(Stylesheet::from_str( Arc::new(Stylesheet::from_str(
input, url_data.clone(), origin, Default::default(), input, url_data.clone(), origin, media,
shared_lock, loader, &StdoutErrorReporter) shared_lock, loader, &StdoutErrorReporter)
).into_strong() ).into_strong()
} }
@ -698,15 +707,20 @@ pub extern "C" fn Servo_CssRules_InsertRule(rules: ServoCssRulesBorrowed,
}; };
let loader = loader.as_ref().map(|loader| loader as &StyleStylesheetLoader); let loader = loader.as_ref().map(|loader| loader as &StyleStylesheetLoader);
let rule = unsafe { rule.as_ref().unwrap().as_str_unchecked() }; let rule = unsafe { rule.as_ref().unwrap().as_str_unchecked() };
write_locked_arc(rules, |rules: &mut CssRules| {
match rules.insert_rule(rule, sheet, index as usize, nested, loader) { let global_style_data = &*GLOBAL_STYLE_DATA;
Ok(new_rule) => { match Locked::<CssRules>::as_arc(&rules).insert_rule(&global_style_data.shared_lock,
*unsafe { rule_type.as_mut().unwrap() } = new_rule.rule_type() as u16; rule,
nsresult::NS_OK sheet,
} index as usize,
Err(err) => err.into() nested,
loader) {
Ok(new_rule) => {
*unsafe { rule_type.as_mut().unwrap() } = new_rule.rule_type() as u16;
nsresult::NS_OK
} }
}) Err(err) => err.into(),
}
} }
#[no_mangle] #[no_mangle]
@ -1192,6 +1206,31 @@ pub extern "C" fn Servo_DeclarationBlock_RemovePropertyById(declarations: RawSer
remove_property(declarations, get_property_id_from_nscsspropertyid!(property, ())) remove_property(declarations, get_property_id_from_nscsspropertyid!(property, ()))
} }
#[no_mangle]
pub extern "C" fn Servo_MediaList_Create() -> RawServoMediaListStrong {
let global_style_data = &*GLOBAL_STYLE_DATA;
Arc::new(global_style_data.shared_lock.wrap(MediaList::empty())).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_MediaList_DeepClone(list: RawServoMediaListBorrowed) -> RawServoMediaListStrong {
let global_style_data = &*GLOBAL_STYLE_DATA;
read_locked_arc(list, |list: &MediaList| {
Arc::new(global_style_data.shared_lock.wrap(list.clone()))
.into_strong()
})
}
#[no_mangle]
pub extern "C" fn Servo_MediaList_Matches(list: RawServoMediaListBorrowed,
raw_data: RawServoStyleSetBorrowed)
-> bool {
let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
read_locked_arc(list, |list: &MediaList| {
list.evaluate(&per_doc_data.stylist.device)
})
}
#[no_mangle] #[no_mangle]
pub extern "C" fn Servo_MediaList_GetText(list: RawServoMediaListBorrowed, result: *mut nsAString) { pub extern "C" fn Servo_MediaList_GetText(list: RawServoMediaListBorrowed, result: *mut nsAString) {
read_locked_arc(list, |list: &MediaList| { read_locked_arc(list, |list: &MediaList| {

View file

@ -5,11 +5,10 @@
use std::sync::Arc; use std::sync::Arc;
use style::gecko_bindings::bindings::Gecko_LoadStyleSheet; use style::gecko_bindings::bindings::Gecko_LoadStyleSheet;
use style::gecko_bindings::structs::{Loader, ServoStyleSheet}; use style::gecko_bindings::structs::{Loader, ServoStyleSheet};
use style::gecko_bindings::sugar::ownership::HasArcFFI; use style::gecko_bindings::sugar::ownership::{HasArcFFI, FFIArcHelpers};
use style::media_queries::MediaList; use style::media_queries::MediaList;
use style::shared_lock::Locked; use style::shared_lock::Locked;
use style::stylesheets::{ImportRule, Stylesheet, StylesheetLoader as StyleStylesheetLoader}; use style::stylesheets::{ImportRule, Stylesheet, StylesheetLoader as StyleStylesheetLoader};
use style_traits::ToCss;
pub struct StylesheetLoader(*mut Loader, *mut ServoStyleSheet); pub struct StylesheetLoader(*mut Loader, *mut ServoStyleSheet);
@ -22,21 +21,11 @@ impl StylesheetLoader {
impl StyleStylesheetLoader for StylesheetLoader { impl StyleStylesheetLoader for StylesheetLoader {
fn request_stylesheet( fn request_stylesheet(
&self, &self,
media: MediaList, media: Arc<Locked<MediaList>>,
make_import: &mut FnMut(MediaList) -> ImportRule, make_import: &mut FnMut(Arc<Locked<MediaList>>) -> ImportRule,
make_arc: &mut FnMut(ImportRule) -> Arc<Locked<ImportRule>>, make_arc: &mut FnMut(ImportRule) -> Arc<Locked<ImportRule>>,
) -> Arc<Locked<ImportRule>> { ) -> Arc<Locked<ImportRule>> {
// TODO(emilio): We probably want to share media representation with let import = make_import(media.clone());
// Gecko in Stylo.
//
// This also allows us to get rid of a bunch of extra work to evaluate
// and ensure parity, and shouldn't be much Gecko work given we always
// evaluate them on the main thread.
//
// Meanwhile, this works.
let media_string = media.to_css_string();
let import = make_import(media);
// After we get this raw pointer ImportRule will be moved into a lock and Arc // After we get this raw pointer ImportRule will be moved into a lock and Arc
// and so the Arc<Url> pointer inside will also move, // and so the Arc<Url> pointer inside will also move,
@ -52,8 +41,7 @@ impl StyleStylesheetLoader for StylesheetLoader {
base_url_data, base_url_data,
spec_bytes, spec_bytes,
spec_len as u32, spec_len as u32,
media_string.as_bytes().as_ptr(), media.into_strong())
media_string.len() as u32);
} }
make_arc(import) make_arc(import)
} }

View file

@ -6,6 +6,7 @@ use cssparser::{Parser, SourcePosition};
use euclid::size::TypedSize2D; use euclid::size::TypedSize2D;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::sync::Arc;
use style::Atom; use style::Atom;
use style::error_reporting::ParseErrorReporter; use style::error_reporting::ParseErrorReporter;
use style::media_queries::*; use style::media_queries::*;
@ -28,8 +29,10 @@ fn test_media_rule<F>(css: &str, callback: F)
{ {
let url = ServoUrl::parse("http://localhost").unwrap(); let url = ServoUrl::parse("http://localhost").unwrap();
let css_str = css.to_owned(); let css_str = css.to_owned();
let lock = SharedRwLock::new();
let media_list = Arc::new(lock.wrap(MediaList::empty()));
let stylesheet = Stylesheet::from_str( let stylesheet = Stylesheet::from_str(
css, url, Origin::Author, Default::default(), SharedRwLock::new(), css, url, Origin::Author, media_list, lock,
None, &CSSErrorReporterTest); None, &CSSErrorReporterTest);
let mut rule_count = 0; let mut rule_count = 0;
let guard = stylesheet.shared_lock.read(); let guard = stylesheet.shared_lock.read();
@ -55,8 +58,10 @@ fn media_queries<F>(guard: &SharedRwLockReadGuard, rules: &[CssRule], f: &mut F)
fn media_query_test(device: &Device, css: &str, expected_rule_count: usize) { fn media_query_test(device: &Device, css: &str, expected_rule_count: usize) {
let url = ServoUrl::parse("http://localhost").unwrap(); let url = ServoUrl::parse("http://localhost").unwrap();
let lock = SharedRwLock::new();
let media_list = Arc::new(lock.wrap(MediaList::empty()));
let ss = Stylesheet::from_str( let ss = Stylesheet::from_str(
css, url, Origin::Author, Default::default(), SharedRwLock::new(), css, url, Origin::Author, media_list, lock,
None, &CSSErrorReporterTest); None, &CSSErrorReporterTest);
let mut rule_count = 0; let mut rule_count = 0;
ss.effective_style_rules(device, &ss.shared_lock.read(), |_| rule_count += 1); ss.effective_style_rules(device, &ss.shared_lock.read(), |_| rule_count += 1);

View file

@ -42,13 +42,14 @@ impl<'a> Drop for AutoGCRuleTree<'a> {
} }
fn parse_rules(css: &str) -> Vec<(StyleSource, CascadeLevel)> { fn parse_rules(css: &str) -> Vec<(StyleSource, CascadeLevel)> {
let lock = SharedRwLock::new();
let media = Arc::new(lock.wrap(MediaList::empty()));
let s = Stylesheet::from_str(css, let s = Stylesheet::from_str(css,
ServoUrl::parse("http://localhost").unwrap(), ServoUrl::parse("http://localhost").unwrap(),
Origin::Author, Origin::Author,
MediaList { media,
media_queries: vec![], lock,
},
SharedRwLock::new(),
None, None,
&ErrorringErrorReporter); &ErrorringErrorReporter);
let guard = s.shared_lock.read(); let guard = s.shared_lock.read();

View file

@ -15,6 +15,7 @@ use std::sync::Mutex;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use style::error_reporting::ParseErrorReporter; use style::error_reporting::ParseErrorReporter;
use style::keyframes::{Keyframe, KeyframeSelector, KeyframePercentage}; use style::keyframes::{Keyframe, KeyframeSelector, KeyframePercentage};
use style::media_queries::MediaList;
use style::properties::Importance; use style::properties::Importance;
use style::properties::{CSSWideKeyword, DeclaredValueOwned, PropertyDeclaration, PropertyDeclarationBlock}; use style::properties::{CSSWideKeyword, DeclaredValueOwned, PropertyDeclaration, PropertyDeclarationBlock};
use style::properties::longhands; use style::properties::longhands;
@ -61,14 +62,15 @@ fn test_parse_stylesheet() {
} }
}"; }";
let url = ServoUrl::parse("about::test").unwrap(); let url = ServoUrl::parse("about::test").unwrap();
let stylesheet = Stylesheet::from_str(css, url.clone(), Origin::UserAgent, Default::default(), let lock = SharedRwLock::new();
SharedRwLock::new(), None, let media = Arc::new(lock.wrap(MediaList::empty()));
&CSSErrorReporterTest); let stylesheet = Stylesheet::from_str(css, url.clone(), Origin::UserAgent, media, lock,
None, &CSSErrorReporterTest);
let mut namespaces = Namespaces::default(); let mut namespaces = Namespaces::default();
namespaces.default = Some(ns!(html)); namespaces.default = Some(ns!(html));
let expected = Stylesheet { let expected = Stylesheet {
origin: Origin::UserAgent, origin: Origin::UserAgent,
media: Arc::new(stylesheet.shared_lock.wrap(Default::default())), media: Arc::new(stylesheet.shared_lock.wrap(MediaList::empty())),
shared_lock: stylesheet.shared_lock.clone(), shared_lock: stylesheet.shared_lock.clone(),
namespaces: RwLock::new(namespaces), namespaces: RwLock::new(namespaces),
url_data: url, url_data: url,
@ -323,9 +325,10 @@ fn test_report_error_stylesheet() {
let errors = error_reporter.errors.clone(); let errors = error_reporter.errors.clone();
Stylesheet::from_str(css, url.clone(), Origin::UserAgent, Default::default(), let lock = SharedRwLock::new();
SharedRwLock::new(), None, let media = Arc::new(lock.wrap(MediaList::empty()));
&error_reporter); Stylesheet::from_str(css, url.clone(), Origin::UserAgent, media, lock,
None, &error_reporter);
let mut errors = errors.lock().unwrap(); let mut errors = errors.lock().unwrap();

View file

@ -7,7 +7,8 @@ use euclid::size::TypedSize2D;
use media_queries::CSSErrorReporterTest; use media_queries::CSSErrorReporterTest;
use servo_config::prefs::{PREFS, PrefValue}; use servo_config::prefs::{PREFS, PrefValue};
use servo_url::ServoUrl; use servo_url::ServoUrl;
use style::media_queries::{Device, MediaType}; use std::sync::Arc;
use style::media_queries::{Device, MediaList, MediaType};
use style::parser::{Parse, ParserContext}; use style::parser::{Parse, ParserContext};
use style::shared_lock::SharedRwLock; use style::shared_lock::SharedRwLock;
use style::stylesheets::{CssRuleType, Stylesheet, Origin}; use style::stylesheets::{CssRuleType, Stylesheet, Origin};
@ -27,7 +28,7 @@ macro_rules! stylesheet {
$css, $css,
ServoUrl::parse("http://localhost").unwrap(), ServoUrl::parse("http://localhost").unwrap(),
Origin::$origin, Origin::$origin,
Default::default(), Arc::new($shared_lock.wrap(MediaList::empty())),
$shared_lock, $shared_lock,
None, None,
&$error_reporter &$error_reporter