Add an extra data field to ParserContext.

This will be used for passing Gecko-specific information through
the CSS parser in stylo.
This commit is contained in:
Cameron McCormack 2016-05-19 11:58:31 +10:00
parent a636b7127e
commit bb85f5faf0
10 changed files with 91 additions and 27 deletions

View file

@ -15,6 +15,7 @@ use std::ascii::AsciiExt;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::Ref; use std::cell::Ref;
use string_cache::Atom; use string_cache::Atom;
use style::parser::ParserContextExtraData;
use style::properties::{PropertyDeclaration, Shorthand}; use style::properties::{PropertyDeclaration, Shorthand};
use style::properties::{is_supported_property, parse_one_declaration}; use style::properties::{is_supported_property, parse_one_declaration};
use style::selector_impl::PseudoElement; use style::selector_impl::PseudoElement;
@ -239,7 +240,9 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
// Step 6 // Step 6
let window = window_from_node(&*self.owner); let window = window_from_node(&*self.owner);
let declarations = parse_one_declaration(&property, &value, &window.get_url(), window.css_error_reporter()); let declarations =
parse_one_declaration(&property, &value, &window.get_url(), window.css_error_reporter(),
ParserContextExtraData::default());
// Step 7 // Step 7
let declarations = if let Ok(declarations) = declarations { let declarations = if let Ok(declarations) = declarations {

View file

@ -85,6 +85,7 @@ use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace, QualName}; use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace, QualName};
use style::element_state::*; use style::element_state::*;
use style::parser::ParserContextExtraData;
use style::properties::DeclaredValue; use style::properties::DeclaredValue;
use style::properties::longhands::{self, background_image, border_spacing, font_family, overflow_x, font_size}; use style::properties::longhands::{self, background_image, border_spacing, font_family, overflow_x, font_size};
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute}; use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
@ -1977,7 +1978,8 @@ impl VirtualMethods for Element {
*self.style_attribute.borrow_mut() = *self.style_attribute.borrow_mut() =
mutation.new_value(attr).map(|value| { mutation.new_value(attr).map(|value| {
let win = window_from_node(self); let win = window_from_node(self);
parse_style_attribute(&value, &doc.base_url(), win.css_error_reporter()) parse_style_attribute(&value, &doc.base_url(), win.css_error_reporter(),
ParserContextExtraData::default())
}); });
if node.is_in_doc() { if node.is_in_doc() {
node.dirty(NodeDamage::NodeStyleDamaged); node.dirty(NodeDamage::NodeStyleDamaged);

View file

@ -37,6 +37,7 @@ use std::mem;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use string_cache::Atom; use string_cache::Atom;
use style::media_queries::{MediaQueryList, parse_media_query_list}; use style::media_queries::{MediaQueryList, parse_media_query_list};
use style::parser::ParserContextExtraData;
use style::servo::Stylesheet; use style::servo::Stylesheet;
use style::stylesheets::Origin; use style::stylesheets::Origin;
use url::Url; use url::Url;
@ -306,7 +307,8 @@ impl AsyncResponseListener for StylesheetContext {
let mut sheet = Stylesheet::from_bytes(&data, final_url, protocol_encoding_label, let mut sheet = Stylesheet::from_bytes(&data, final_url, protocol_encoding_label,
Some(environment_encoding), Origin::Author, Some(environment_encoding), Origin::Author,
win.css_error_reporter()); win.css_error_reporter(),
ParserContextExtraData::default());
let media = self.media.take().unwrap(); let media = self.media.take().unwrap();
sheet.set_media(Some(media)); sheet.set_media(Some(media));
let sheet = Arc::new(sheet); let sheet = Arc::new(sheet);

View file

@ -17,6 +17,7 @@ use layout_interface::{LayoutChan, Msg};
use std::sync::Arc; use std::sync::Arc;
use string_cache::Atom; use string_cache::Atom;
use style::media_queries::parse_media_query_list; use style::media_queries::parse_media_query_list;
use style::parser::ParserContextExtraData;
use style::servo::Stylesheet; use style::servo::Stylesheet;
use style::stylesheets::Origin; use style::stylesheets::Origin;
use util::str::DOMString; use util::str::DOMString;
@ -60,7 +61,8 @@ impl HTMLStyleElement {
}; };
let data = node.GetTextContent().expect("Element.textContent must be a string"); 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()); let mut sheet = Stylesheet::from_str(&data, url, Origin::Author, win.css_error_reporter(),
ParserContextExtraData::default());
let mut css_parser = CssParser::new(&mq_str); let mut css_parser = CssParser::new(&mq_str);
let media = parse_media_query_list(&mut css_parser); let media = parse_media_query_list(&mut css_parser);
sheet.set_media(Some(media)); sheet.set_media(Some(media));

View file

@ -9,16 +9,38 @@ use selectors::parser::ParserContext as SelectorParserContext;
use stylesheets::Origin; use stylesheets::Origin;
use url::Url; use url::Url;
#[cfg(not(feature = "gecko"))]
pub struct ParserContextExtraData;
#[cfg(feature = "gecko")]
pub struct ParserContextExtraData {
}
impl ParserContextExtraData {
#[cfg(not(feature = "gecko"))]
pub fn default() -> ParserContextExtraData {
ParserContextExtraData
}
#[cfg(feature = "gecko")]
pub fn default() -> ParserContextExtraData {
ParserContextExtraData { }
}
}
pub struct ParserContext<'a> { pub struct ParserContext<'a> {
pub stylesheet_origin: Origin, pub stylesheet_origin: Origin,
pub base_url: &'a Url, pub base_url: &'a Url,
pub selector_context: SelectorParserContext, pub selector_context: SelectorParserContext,
pub error_reporter: Box<ParseErrorReporter + Send>, pub error_reporter: Box<ParseErrorReporter + Send>,
pub extra_data: ParserContextExtraData,
} }
impl<'a> ParserContext<'a> { impl<'a> ParserContext<'a> {
pub fn new(stylesheet_origin: Origin, base_url: &'a Url, error_reporter: Box<ParseErrorReporter + Send>) pub fn new_with_extra_data(stylesheet_origin: Origin, base_url: &'a Url,
-> ParserContext<'a> { error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData)
-> ParserContext<'a> {
let mut selector_context = SelectorParserContext::new(); let mut selector_context = SelectorParserContext::new();
selector_context.in_user_agent_stylesheet = stylesheet_origin == Origin::UserAgent; selector_context.in_user_agent_stylesheet = stylesheet_origin == Origin::UserAgent;
ParserContext { ParserContext {
@ -26,8 +48,15 @@ impl<'a> ParserContext<'a> {
base_url: base_url, base_url: base_url,
selector_context: selector_context, selector_context: selector_context,
error_reporter: error_reporter, error_reporter: error_reporter,
extra_data: extra_data,
} }
} }
pub fn new(stylesheet_origin: Origin, base_url: &'a Url, error_reporter: Box<ParseErrorReporter + Send>)
-> ParserContext<'a> {
let extra_data = ParserContextExtraData::default();
ParserContext::new_with_extra_data(stylesheet_origin, base_url, error_reporter, extra_data)
}
} }

View file

@ -29,7 +29,7 @@ use euclid::size::Size2D;
use string_cache::Atom; use string_cache::Atom;
use computed_values; use computed_values;
use logical_geometry::{LogicalMargin, PhysicalSide, WritingMode}; use logical_geometry::{LogicalMargin, PhysicalSide, WritingMode};
use parser::{ParserContext, log_css_error}; use parser::{ParserContext, ParserContextExtraData, log_css_error};
use selectors::matching::DeclarationBlock; use selectors::matching::DeclarationBlock;
use stylesheets::Origin; use stylesheets::Origin;
use values::AuExtensionMethods; use values::AuExtensionMethods;
@ -185,13 +185,18 @@ mod property_bit_field {
if let DeclaredValue::WithVariables { if let DeclaredValue::WithVariables {
ref css, first_token_type, ref base_url, from_shorthand ref css, first_token_type, ref base_url, from_shorthand
} = *value { } = *value {
// FIXME(heycam): A ParserContextExtraData should be built from data
// stored in the WithVariables, in case variable expansion results in
// a url() value.
let extra_data = ParserContextExtraData::default();
substitute_variables_${property.ident}_slow(css, substitute_variables_${property.ident}_slow(css,
first_token_type, first_token_type,
base_url, base_url,
from_shorthand, from_shorthand,
custom_properties, custom_properties,
f, f,
error_reporter); error_reporter,
extra_data);
} else { } else {
f(value); f(value);
} }
@ -206,7 +211,8 @@ mod property_bit_field {
from_shorthand: Option<Shorthand>, from_shorthand: Option<Shorthand>,
custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>, custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>,
f: F, f: F,
error_reporter: &mut StdBox<ParseErrorReporter + Send>) error_reporter: &mut StdBox<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData)
where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) { where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) {
f(& f(&
::custom_properties::substitute(css, first_token_type, custom_properties) ::custom_properties::substitute(css, first_token_type, custom_properties)
@ -215,8 +221,9 @@ mod property_bit_field {
// //
// FIXME(pcwalton): Cloning the error reporter is slow! But so are custom // FIXME(pcwalton): Cloning the error reporter is slow! But so are custom
// properties, so whatever... // properties, so whatever...
let context = ParserContext::new( let context = ParserContext::new_with_extra_data(
::stylesheets::Origin::Author, base_url, (*error_reporter).clone()); ::stylesheets::Origin::Author, base_url, (*error_reporter).clone(),
extra_data);
Parser::new(&css).parse_entirely(|input| { Parser::new(&css).parse_entirely(|input| {
match from_shorthand { match from_shorthand {
None => { None => {
@ -256,15 +263,17 @@ pub struct PropertyDeclarationBlock {
pub normal: Arc<Vec<PropertyDeclaration>>, pub normal: Arc<Vec<PropertyDeclaration>>,
} }
pub fn parse_style_attribute(input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>) pub fn parse_style_attribute(input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData)
-> PropertyDeclarationBlock { -> PropertyDeclarationBlock {
let context = ParserContext::new(Origin::Author, base_url, error_reporter); let context = ParserContext::new_with_extra_data(Origin::Author, base_url, error_reporter, extra_data);
parse_property_declaration_list(&context, &mut Parser::new(input)) parse_property_declaration_list(&context, &mut Parser::new(input))
} }
pub fn parse_one_declaration(name: &str, input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>) pub fn parse_one_declaration(name: &str, input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData)
-> Result<Vec<PropertyDeclaration>, ()> { -> Result<Vec<PropertyDeclaration>, ()> {
let context = ParserContext::new(Origin::Author, base_url, error_reporter); let context = ParserContext::new_with_extra_data(Origin::Author, base_url, error_reporter, extra_data);
let mut results = vec![]; let mut results = vec![];
match PropertyDeclaration::parse(name, &context, &mut Parser::new(input), &mut results) { match PropertyDeclaration::parse(name, &context, &mut Parser::new(input), &mut results) {
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => Ok(results), PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => Ok(results),

View file

@ -9,6 +9,7 @@ use dom::PresentationalHintsSynthetizer;
use element_state::*; use element_state::*;
use error_reporting::StdoutErrorReporter; use error_reporting::StdoutErrorReporter;
use media_queries::{Device, MediaType}; use media_queries::{Device, MediaType};
use parser::ParserContextExtraData;
use properties::{self, PropertyDeclaration, PropertyDeclarationBlock}; use properties::{self, PropertyDeclaration, PropertyDeclarationBlock};
use restyle_hints::{ElementSnapshot, RestyleHint, DependencySet}; use restyle_hints::{ElementSnapshot, RestyleHint, DependencySet};
use selector_impl::{SelectorImplExt, ServoSelectorImpl}; use selector_impl::{SelectorImplExt, ServoSelectorImpl};
@ -46,7 +47,8 @@ lazy_static! {
None, None,
None, None,
Origin::UserAgent, Origin::UserAgent,
box StdoutErrorReporter); box StdoutErrorReporter,
ParserContextExtraData::default());
stylesheets.push(ua_stylesheet); stylesheets.push(ua_stylesheet);
} }
Err(..) => { Err(..) => {
@ -57,7 +59,8 @@ lazy_static! {
} }
for &(ref contents, ref url) in &opts::get().user_stylesheets { for &(ref contents, ref url) in &opts::get().user_stylesheets {
stylesheets.push(Stylesheet::from_bytes( stylesheets.push(Stylesheet::from_bytes(
&contents, url.clone(), None, None, Origin::User, box StdoutErrorReporter)); &contents, url.clone(), None, None, Origin::User, box StdoutErrorReporter,
ParserContextExtraData::default()));
} }
stylesheets stylesheets
}; };
@ -73,7 +76,8 @@ lazy_static! {
None, None,
None, None,
Origin::UserAgent, Origin::UserAgent,
box StdoutErrorReporter) box StdoutErrorReporter,
ParserContextExtraData::default())
}, },
Err(..) => { Err(..) => {
error!("Stylist failed to load 'quirks-mode.css'!"); error!("Stylist failed to load 'quirks-mode.css'!");

View file

@ -8,7 +8,7 @@ use encoding::EncodingRef;
use error_reporting::ParseErrorReporter; use error_reporting::ParseErrorReporter;
use font_face::{FontFaceRule, parse_font_face_block}; use font_face::{FontFaceRule, parse_font_face_block};
use media_queries::{Device, MediaQueryList, parse_media_query_list}; use media_queries::{Device, MediaQueryList, parse_media_query_list};
use parser::{ParserContext, log_css_error}; use parser::{ParserContext, ParserContextExtraData, log_css_error};
use properties::{PropertyDeclarationBlock, parse_property_declaration_list}; use properties::{PropertyDeclarationBlock, parse_property_declaration_list};
use selectors::parser::{Selector, SelectorImpl, parse_selector_list}; use selectors::parser::{Selector, SelectorImpl, parse_selector_list};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -83,32 +83,37 @@ impl<Impl: SelectorImpl> Stylesheet<Impl> {
pub fn from_bytes_iter<I: Iterator<Item=Vec<u8>>>( pub fn from_bytes_iter<I: Iterator<Item=Vec<u8>>>(
input: I, base_url: Url, protocol_encoding_label: Option<&str>, input: I, base_url: Url, protocol_encoding_label: Option<&str>,
environment_encoding: Option<EncodingRef>, origin: Origin, environment_encoding: Option<EncodingRef>, origin: Origin,
error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet<Impl> { error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData) -> Stylesheet<Impl> {
let mut bytes = vec![]; let mut bytes = vec![];
// TODO: incremental decoding and tokenization/parsing // TODO: incremental decoding and tokenization/parsing
for chunk in input { for chunk in input {
bytes.extend_from_slice(&chunk) bytes.extend_from_slice(&chunk)
} }
Stylesheet::from_bytes(&bytes, base_url, protocol_encoding_label, Stylesheet::from_bytes(&bytes, base_url, protocol_encoding_label,
environment_encoding, origin, error_reporter) environment_encoding, origin, error_reporter,
extra_data)
} }
pub fn from_bytes(bytes: &[u8], pub fn from_bytes(bytes: &[u8],
base_url: Url, base_url: Url,
protocol_encoding_label: Option<&str>, protocol_encoding_label: Option<&str>,
environment_encoding: Option<EncodingRef>, environment_encoding: Option<EncodingRef>,
origin: Origin, error_reporter: Box<ParseErrorReporter + Send>) origin: Origin, error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData)
-> Stylesheet<Impl> { -> Stylesheet<Impl> {
// TODO: bytes.as_slice could be bytes.container_as_bytes() // TODO: bytes.as_slice could be bytes.container_as_bytes()
let (string, _) = decode_stylesheet_bytes( let (string, _) = decode_stylesheet_bytes(
bytes, protocol_encoding_label, environment_encoding); bytes, protocol_encoding_label, environment_encoding);
Stylesheet::from_str(&string, base_url, origin, error_reporter) Stylesheet::from_str(&string, base_url, origin, error_reporter, extra_data)
} }
pub fn from_str(css: &str, base_url: Url, origin: Origin, pub fn from_str(css: &str, base_url: Url, origin: Origin,
error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet<Impl> { error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData) -> Stylesheet<Impl> {
let rule_parser = TopLevelRuleParser { let rule_parser = TopLevelRuleParser {
context: ParserContext::new(origin, &base_url, error_reporter.clone()), context: ParserContext::new_with_extra_data(origin, &base_url, error_reporter.clone(),
extra_data),
state: Cell::new(State::Start), state: Cell::new(State::Start),
_impl: PhantomData, _impl: PhantomData,
}; };

View file

@ -24,6 +24,7 @@ use style::context::{ReflowGoal};
use style::dom::{TDocument, TElement, TNode}; use style::dom::{TDocument, TElement, TNode};
use style::error_reporting::StdoutErrorReporter; use style::error_reporting::StdoutErrorReporter;
use style::parallel; use style::parallel;
use style::parser::ParserContextExtraData;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::selector_impl::{SelectorImplExt, PseudoElementCascadeType}; use style::selector_impl::{SelectorImplExt, PseudoElementCascadeType};
use style::stylesheets::Origin; use style::stylesheets::Origin;
@ -132,7 +133,9 @@ pub extern "C" fn Servo_StylesheetFromUTF8Bytes(bytes: *const u8,
// FIXME(heycam): Pass in the real base URL. // FIXME(heycam): Pass in the real base URL.
let url = Url::parse("about:none").unwrap(); let url = Url::parse("about:none").unwrap();
let sheet = Arc::new(Stylesheet::from_str(input, url, origin, Box::new(StdoutErrorReporter))); let extra_data = ParserContextExtraData { };
let sheet = Arc::new(Stylesheet::from_str(input, url, origin, Box::new(StdoutErrorReporter),
extra_data));
unsafe { unsafe {
transmute(sheet) transmute(sheet)
} }

View file

@ -37,6 +37,7 @@ use style::dom::{TDocument, TElement, TNode, TRestyleDamage, UnsafeNode};
use style::element_state::ElementState; use style::element_state::ElementState;
#[allow(unused_imports)] // Used in commented-out code. #[allow(unused_imports)] // Used in commented-out code.
use style::error_reporting::StdoutErrorReporter; use style::error_reporting::StdoutErrorReporter;
use style::parser::ParserContextExtraData;
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock}; use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
#[allow(unused_imports)] // Used in commented-out code. #[allow(unused_imports)] // Used in commented-out code.
use style::properties::{parse_style_attribute}; use style::properties::{parse_style_attribute};
@ -330,7 +331,11 @@ impl<'le> TElement for GeckoElement<'le> {
let attr = self.get_attr(&ns!(), &atom!("style")); let attr = self.get_attr(&ns!(), &atom!("style"));
// FIXME(bholley): Real base URL and error reporter. // FIXME(bholley): Real base URL and error reporter.
let base_url = Url::parse("http://www.example.org").unwrap(); let base_url = Url::parse("http://www.example.org").unwrap();
attr.map(|v| parse_style_attribute(&v, &base_url, Box::new(StdoutErrorReporter))) // FIXME(heycam): Needs real ParserContextExtraData so that URLs parse
// properly.
let extra_data = ParserContextExtraData::default();
attr.map(|v| parse_style_attribute(&v, &base_url, Box::new(StdoutErrorReporter),
extra_data))
*/ */
} }