Auto merge of #11287 - heycam:moz-binding, r=bholley

Support -moz-binding in geckolib

Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data:
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy --faster` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).

Either:
- [ ] There are tests for these changes OR
- [x] These changes do not require tests because changes target stylo

Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11287)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-05-24 14:41:04 -07:00
commit 2a2b88f42c
26 changed files with 447 additions and 114 deletions

View file

@ -16,6 +16,7 @@ use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::cell::Ref;
use string_cache::Atom;
use style::parser::ParserContextExtraData;
use style::properties::{PropertyDeclaration, Shorthand};
use style::properties::{is_supported_property, parse_one_declaration};
use style::selector_impl::PseudoElement;
@ -240,7 +241,9 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
// Step 6
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
let declarations = if let Ok(declarations) = declarations {

View file

@ -86,6 +86,7 @@ use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace, QualName};
use style::element_state::*;
use style::parser::ParserContextExtraData;
use style::properties::DeclaredValue;
use style::properties::longhands::{self, background_image, border_spacing, font_family, overflow_x, font_size};
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
@ -1977,7 +1978,8 @@ impl VirtualMethods for Element {
*self.style_attribute.borrow_mut() =
mutation.new_value(attr).map(|value| {
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() {
node.dirty(NodeDamage::NodeStyleDamaged);

View file

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

View file

@ -18,6 +18,7 @@ use layout_interface::{LayoutChan, Msg};
use std::sync::Arc;
use string_cache::Atom;
use style::media_queries::parse_media_query_list;
use style::parser::ParserContextExtraData;
use style::servo::Stylesheet;
use style::stylesheets::Origin;
@ -60,7 +61,8 @@ 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());
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 media = parse_media_query_list(&mut css_parser);
sheet.set_media(Some(media));

View file

@ -11,7 +11,7 @@ name = "style"
path = "lib.rs"
[features]
gecko = []
gecko = ["gecko_bindings"]
[dependencies]
app_units = {version = "0.2.3", features = ["plugins"]}
@ -20,6 +20,7 @@ cssparser = {version = "0.5.5", features = ["heap_size", "serde-serialization"]}
encoding = "0.2"
euclid = {version = "0.6.4", features = ["plugins"]}
fnv = "1.0"
gecko_bindings = {path = "../../ports/geckolib/gecko_bindings", optional = true}
heapsize = "0.3.0"
heapsize_plugin = "0.1.2"
lazy_static = "0.2"

View file

@ -28,6 +28,8 @@ extern crate cssparser;
extern crate encoding;
extern crate euclid;
extern crate fnv;
#[cfg(feature = "gecko")]
extern crate gecko_bindings;
extern crate heapsize;
#[allow(unused_extern_crates)]
#[macro_use]

View file

@ -5,20 +5,47 @@
use cssparser::{Parser, SourcePosition};
use error_reporting::ParseErrorReporter;
#[cfg(feature = "gecko")]
use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
use selectors::parser::ParserContext as SelectorParserContext;
use stylesheets::Origin;
use url::Url;
#[cfg(not(feature = "gecko"))]
pub struct ParserContextExtraData;
#[cfg(feature = "gecko")]
pub struct ParserContextExtraData {
pub base: Option<GeckoArcURI>,
pub referrer: Option<GeckoArcURI>,
pub principal: Option<GeckoArcPrincipal>,
}
impl ParserContextExtraData {
#[cfg(not(feature = "gecko"))]
pub fn default() -> ParserContextExtraData {
ParserContextExtraData
}
#[cfg(feature = "gecko")]
pub fn default() -> ParserContextExtraData {
ParserContextExtraData { base: None, referrer: None, principal: None }
}
}
pub struct ParserContext<'a> {
pub stylesheet_origin: Origin,
pub base_url: &'a Url,
pub selector_context: SelectorParserContext,
pub error_reporter: Box<ParseErrorReporter + Send>,
pub extra_data: ParserContextExtraData,
}
impl<'a> ParserContext<'a> {
pub fn new(stylesheet_origin: Origin, base_url: &'a Url, error_reporter: Box<ParseErrorReporter + Send>)
-> ParserContext<'a> {
pub fn new_with_extra_data(stylesheet_origin: Origin, base_url: &'a Url,
error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData)
-> ParserContext<'a> {
let mut selector_context = SelectorParserContext::new();
selector_context.in_user_agent_stylesheet = stylesheet_origin == Origin::UserAgent;
ParserContext {
@ -26,8 +53,15 @@ impl<'a> ParserContext<'a> {
base_url: base_url,
selector_context: selector_context,
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

@ -43,7 +43,7 @@
#![allow(unused_imports)]
% if not property.derived_from:
use cssparser::Parser;
use parser::ParserContext;
use parser::{ParserContext, ParserContextExtraData};
use properties::{CSSWideKeyword, DeclaredValue, Shorthand};
% endif
use error_reporting::ParseErrorReporter;

View file

@ -851,3 +851,78 @@ ${helpers.single_keyword("-moz-appearance",
gecko_ffi_name="mAppearance",
gecko_constant_prefix="NS_THEME",
products="gecko")}
// Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-binding
<%helpers:longhand name="-moz-binding" products="gecko">
use cssparser::{CssStringWriter, ToCss};
use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
use std::fmt::{self, Write};
use url::Url;
use values::computed::ComputedValueAsSpecified;
#[derive(PartialEq, Clone, Debug, HeapSizeOf)]
pub struct UrlExtraData {
pub base: GeckoArcURI,
pub referrer: GeckoArcURI,
pub principal: GeckoArcPrincipal,
}
#[derive(PartialEq, Clone, Debug, HeapSizeOf)]
pub enum SpecifiedValue {
Url(Url, UrlExtraData),
None,
}
impl ComputedValueAsSpecified for SpecifiedValue {}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
use values::LocalToCss;
match *self {
SpecifiedValue::Url(ref url, _) => {
url.to_css(dest)
}
SpecifiedValue::None => {
try!(dest.write_str("none"));
Ok(())
}
}
}
}
pub mod computed_value {
pub type T = super::SpecifiedValue;
}
#[inline] pub fn get_initial_value() -> SpecifiedValue {
SpecifiedValue::None
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue::None);
}
let url = context.parse_url(&*try!(input.expect_url()));
match context.extra_data {
ParserContextExtraData {
base: Some(ref base),
referrer: Some(ref referrer),
principal: Some(ref principal),
} => {
let extra_data = UrlExtraData {
base: base.clone(),
referrer: referrer.clone(),
principal: principal.clone(),
};
Ok(SpecifiedValue::Url(url, extra_data))
},
_ => {
// FIXME(heycam) should ensure we always have a principal, etc., when parsing
// style attributes and re-parsing due to CSS Variables.
println!("stylo: skipping -moz-binding declaration without ParserContextExtraData");
Err(())
},
}
}
</%helpers:longhand>

View file

@ -29,7 +29,7 @@ use euclid::size::Size2D;
use string_cache::Atom;
use computed_values;
use logical_geometry::{LogicalMargin, PhysicalSide, WritingMode};
use parser::{ParserContext, log_css_error};
use parser::{ParserContext, ParserContextExtraData, log_css_error};
use selectors::matching::DeclarationBlock;
use stylesheets::Origin;
use values::AuExtensionMethods;
@ -185,13 +185,18 @@ mod property_bit_field {
if let DeclaredValue::WithVariables {
ref css, first_token_type, ref base_url, from_shorthand
} = *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,
first_token_type,
base_url,
from_shorthand,
custom_properties,
f,
error_reporter);
error_reporter,
extra_data);
} else {
f(value);
}
@ -206,7 +211,8 @@ mod property_bit_field {
from_shorthand: Option<Shorthand>,
custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>,
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>) {
f(&
::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
// properties, so whatever...
let context = ParserContext::new(
::stylesheets::Origin::Author, base_url, (*error_reporter).clone());
let context = ParserContext::new_with_extra_data(
::stylesheets::Origin::Author, base_url, (*error_reporter).clone(),
extra_data);
Parser::new(&css).parse_entirely(|input| {
match from_shorthand {
None => {
@ -256,15 +263,17 @@ pub struct PropertyDeclarationBlock {
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 {
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))
}
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>, ()> {
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![];
match PropertyDeclaration::parse(name, &context, &mut Parser::new(input), &mut results) {
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => Ok(results),

View file

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

View file

@ -8,7 +8,7 @@ use encoding::EncodingRef;
use error_reporting::ParseErrorReporter;
use font_face::{FontFaceRule, parse_font_face_block};
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 selectors::parser::{Selector, SelectorImpl, parse_selector_list};
use smallvec::SmallVec;
@ -83,32 +83,37 @@ impl<Impl: SelectorImpl> Stylesheet<Impl> {
pub fn from_bytes_iter<I: Iterator<Item=Vec<u8>>>(
input: I, base_url: Url, protocol_encoding_label: Option<&str>,
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![];
// 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)
environment_encoding, origin, error_reporter,
extra_data)
}
pub fn from_bytes(bytes: &[u8],
base_url: Url,
protocol_encoding_label: Option<&str>,
environment_encoding: Option<EncodingRef>,
origin: Origin, error_reporter: Box<ParseErrorReporter + Send>)
origin: Origin, error_reporter: Box<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData)
-> Stylesheet<Impl> {
// 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)
Stylesheet::from_str(&string, base_url, origin, error_reporter, extra_data)
}
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 {
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),
_impl: PhantomData,
};

View file

@ -90,13 +90,13 @@ pub const FONT_MEDIUM_PX: i32 = 16;
pub mod specified {
use app_units::Au;
use cssparser::{self, CssStringWriter, Parser, ToCss, Token};
use cssparser::{self, Parser, ToCss, Token};
use euclid::size::Size2D;
use parser::ParserContext;
use std::ascii::AsciiExt;
use std::cmp;
use std::f32::consts::PI;
use std::fmt::{self, Write};
use std::fmt;
use std::ops::Mul;
use style_traits::values::specified::AllowedNumericType;
use super::AuExtensionMethods;
@ -1224,12 +1224,10 @@ pub mod specified {
impl ToCss for Image {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
use values::LocalToCss;
match *self {
Image::Url(ref url) => {
try!(dest.write_str("url(\""));
try!(write!(&mut CssStringWriter::new(dest), "{}", url));
try!(dest.write_str("\")"));
Ok(())
url.to_css(dest)
}
Image::LinearGradient(ref gradient) => gradient.to_css(dest)
}