mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
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:
commit
2a2b88f42c
26 changed files with 447 additions and 114 deletions
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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'!");
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue