From bb85f5faf09fac34f92a3e5c049c971e90ebf862 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Thu, 19 May 2016 11:58:31 +1000 Subject: [PATCH 1/7] Add an extra data field to ParserContext. This will be used for passing Gecko-specific information through the CSS parser in stylo. --- components/script/dom/cssstyledeclaration.rs | 5 ++- components/script/dom/element.rs | 4 ++- components/script/dom/htmllinkelement.rs | 4 ++- components/script/dom/htmlstyleelement.rs | 4 ++- components/style/parser.rs | 33 +++++++++++++++++-- .../style/properties/properties.mako.rs | 27 ++++++++++----- components/style/selector_matching.rs | 10 ++++-- components/style/stylesheets.rs | 19 +++++++---- ports/geckolib/glue.rs | 5 ++- ports/geckolib/wrapper.rs | 7 +++- 10 files changed, 91 insertions(+), 27 deletions(-) diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs index 97a3602a8e1..4c9d5744642 100644 --- a/components/script/dom/cssstyledeclaration.rs +++ b/components/script/dom/cssstyledeclaration.rs @@ -15,6 +15,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; @@ -239,7 +240,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 { diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 6c8066308b5..06a51baffb8 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -85,6 +85,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); diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 0a7ebb5de1b..0b328279485 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -37,6 +37,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; @@ -306,7 +307,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); diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index e91b1a1e064..4cc961eec95 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -17,6 +17,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; use util::str::DOMString; @@ -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)); diff --git a/components/style/parser.rs b/components/style/parser.rs index b044367e8dd..5a38c2f22b5 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -9,16 +9,38 @@ 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 { +} + +impl ParserContextExtraData { + #[cfg(not(feature = "gecko"))] + pub fn default() -> ParserContextExtraData { + ParserContextExtraData + } + + #[cfg(feature = "gecko")] + pub fn default() -> ParserContextExtraData { + ParserContextExtraData { } + } +} + pub struct ParserContext<'a> { pub stylesheet_origin: Origin, pub base_url: &'a Url, pub selector_context: SelectorParserContext, pub error_reporter: Box, + pub extra_data: ParserContextExtraData, } impl<'a> ParserContext<'a> { - pub fn new(stylesheet_origin: Origin, base_url: &'a Url, error_reporter: Box) - -> ParserContext<'a> { + pub fn new_with_extra_data(stylesheet_origin: Origin, base_url: &'a Url, + error_reporter: Box, + extra_data: ParserContextExtraData) + -> ParserContext<'a> { let mut selector_context = SelectorParserContext::new(); selector_context.in_user_agent_stylesheet = stylesheet_origin == Origin::UserAgent; ParserContext { @@ -26,8 +48,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) + -> ParserContext<'a> { + let extra_data = ParserContextExtraData::default(); + ParserContext::new_with_extra_data(stylesheet_origin, base_url, error_reporter, extra_data) + } } diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index dc15f7339d0..ec6fe6562e0 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -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, custom_properties: &Option>, f: F, - error_reporter: &mut StdBox) + error_reporter: &mut StdBox, + extra_data: ParserContextExtraData) where F: FnOnce(&DeclaredValue) { 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>, } -pub fn parse_style_attribute(input: &str, base_url: &Url, error_reporter: StdBox) +pub fn parse_style_attribute(input: &str, base_url: &Url, error_reporter: StdBox, + 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) +pub fn parse_one_declaration(name: &str, input: &str, base_url: &Url, error_reporter: StdBox, + extra_data: ParserContextExtraData) -> Result, ()> { - 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), diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs index c1989348f50..017a7443624 100644 --- a/components/style/selector_matching.rs +++ b/components/style/selector_matching.rs @@ -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'!"); diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 7a978263b2b..4de57e81d40 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -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 Stylesheet { pub fn from_bytes_iter>>( input: I, base_url: Url, protocol_encoding_label: Option<&str>, environment_encoding: Option, origin: Origin, - error_reporter: Box) -> Stylesheet { + error_reporter: Box, + 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) + environment_encoding, origin, error_reporter, + extra_data) } pub fn from_bytes(bytes: &[u8], base_url: Url, protocol_encoding_label: Option<&str>, environment_encoding: Option, - origin: Origin, error_reporter: Box) + origin: Origin, error_reporter: Box, + 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) + 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) -> Stylesheet { + error_reporter: Box, + extra_data: ParserContextExtraData) -> Stylesheet { 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, }; diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 0755b893b16..d4c268f58fb 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -24,6 +24,7 @@ use style::context::{ReflowGoal}; use style::dom::{TDocument, TElement, TNode}; use style::error_reporting::StdoutErrorReporter; use style::parallel; +use style::parser::ParserContextExtraData; use style::properties::ComputedValues; use style::selector_impl::{SelectorImplExt, PseudoElementCascadeType}; 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. 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 { transmute(sheet) } diff --git a/ports/geckolib/wrapper.rs b/ports/geckolib/wrapper.rs index e0040cf5745..a30060d416a 100644 --- a/ports/geckolib/wrapper.rs +++ b/ports/geckolib/wrapper.rs @@ -37,6 +37,7 @@ use style::dom::{TDocument, TElement, TNode, TRestyleDamage, UnsafeNode}; use style::element_state::ElementState; #[allow(unused_imports)] // Used in commented-out code. use style::error_reporting::StdoutErrorReporter; +use style::parser::ParserContextExtraData; use style::properties::{PropertyDeclaration, PropertyDeclarationBlock}; #[allow(unused_imports)] // Used in commented-out code. use style::properties::{parse_style_attribute}; @@ -330,7 +331,11 @@ impl<'le> TElement for GeckoElement<'le> { let attr = self.get_attr(&ns!(), &atom!("style")); // FIXME(bholley): Real base URL and error reporter. 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)) */ } From 9b63deb8ecc05f38185029cac06cdf455422783f Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Thu, 19 May 2016 14:31:20 +1000 Subject: [PATCH 2/7] Regenerate bindings with Holder types. --- ports/geckolib/gecko_bindings/bindings.rs | 29 ++- ports/geckolib/gecko_bindings/structs.rs | 188 ++++++++++++------ .../gecko_bindings/tools/regen_bindings.sh | 6 +- .../tools/regen_style_structs.sh | 3 + 4 files changed, 157 insertions(+), 69 deletions(-) diff --git a/ports/geckolib/gecko_bindings/bindings.rs b/ports/geckolib/gecko_bindings/bindings.rs index 6d943733a27..425fa65ea12 100644 --- a/ports/geckolib/gecko_bindings/bindings.rs +++ b/ports/geckolib/gecko_bindings/bindings.rs @@ -25,6 +25,8 @@ use structs::nsStyleSVGReset; use structs::nsStyleColumn; use structs::nsStyleEffects; use structs::SheetParsingMode; +use structs::nsMainThreadPtrHandle; +use structs::nsMainThreadPtrHolder; use heapsize::HeapSizeOf; unsafe impl Send for nsStyleFont {} unsafe impl Sync for nsStyleFont {} @@ -102,6 +104,8 @@ impl HeapSizeOf for nsStyleEffects { fn heap_size_of_children(&self) -> usize { pub enum nsIAtom { } pub enum nsINode { } pub type RawGeckoNode = nsINode; +pub enum nsIPrincipal { } +pub enum nsIURI { } pub enum Element { } pub type RawGeckoElement = Element; pub enum nsIDocument { } @@ -110,6 +114,8 @@ pub enum ServoNodeData { } pub enum ServoComputedValues { } pub enum RawServoStyleSheet { } pub enum RawServoStyleSet { } +pub type ThreadSafePrincipalHolder = nsMainThreadPtrHolder; +pub type ThreadSafeURIHolder = nsMainThreadPtrHolder; extern "C" { pub fn Gecko_ChildrenCount(node: *mut RawGeckoNode) -> u32; pub fn Gecko_NodeIsElement(node: *mut RawGeckoNode) -> bool; @@ -138,6 +144,8 @@ extern "C" { pub fn Gecko_IsVisitedLink(element: *mut RawGeckoElement) -> bool; pub fn Gecko_IsUnvisitedLink(element: *mut RawGeckoElement) -> bool; pub fn Gecko_IsRootElement(element: *mut RawGeckoElement) -> bool; + pub fn Gecko_LocalName(element: *mut RawGeckoElement) -> *mut nsIAtom; + pub fn Gecko_Namespace(element: *mut RawGeckoElement) -> *mut nsIAtom; pub fn Gecko_GetNodeData(node: *mut RawGeckoNode) -> *mut ServoNodeData; pub fn Gecko_SetNodeData(node: *mut RawGeckoNode, data: *mut ServoNodeData); @@ -159,8 +167,25 @@ extern "C" { pub fn Gecko_SetListStyleType(style_struct: *mut nsStyleList, type_: u32); pub fn Gecko_CopyListStyleTypeFrom(dst: *mut nsStyleList, src: *const nsStyleList); + pub fn Gecko_AddRefPrincipalArbitraryThread(aPtr: + *mut ThreadSafePrincipalHolder); + pub fn Gecko_ReleasePrincipalArbitraryThread(aPtr: + *mut ThreadSafePrincipalHolder); + pub fn Gecko_AddRefURIArbitraryThread(aPtr: *mut ThreadSafeURIHolder); + pub fn Gecko_ReleaseURIArbitraryThread(aPtr: *mut ThreadSafeURIHolder); + pub fn Gecko_SetMozBinding(style_struct: *mut nsStyleDisplay, + string_bytes: *const u8, string_length: u32, + base_uri: *mut ThreadSafeURIHolder, + referrer: *mut ThreadSafeURIHolder, + principal: *mut ThreadSafePrincipalHolder); + pub fn Gecko_CopyMozBindingFrom(des: *mut nsStyleDisplay, + src: *const nsStyleDisplay); pub fn Servo_StylesheetFromUTF8Bytes(bytes: *const u8, length: u32, - parsing_mode: SheetParsingMode) + parsing_mode: SheetParsingMode, + base: *mut ThreadSafeURIHolder, + referrer: *mut ThreadSafeURIHolder, + principal: + *mut ThreadSafePrincipalHolder) -> *mut RawServoStyleSheet; pub fn Servo_AddRefStyleSheet(sheet: *mut RawServoStyleSheet); pub fn Servo_ReleaseStyleSheet(sheet: *mut RawServoStyleSheet); @@ -202,8 +227,6 @@ extern "C" { ns: *mut nsIAtom, name: *mut nsIAtom, length: *mut u32) -> *const ::std::os::raw::c_char; - pub fn Gecko_LocalName(element: *mut RawGeckoElement) -> *mut nsIAtom; - pub fn Gecko_Namespace(element: *mut RawGeckoElement) -> *mut nsIAtom; pub fn Gecko_Construct_nsStyleFont(ptr: *mut nsStyleFont); pub fn Gecko_CopyConstruct_nsStyleFont(ptr: *mut nsStyleFont, other: *const nsStyleFont); diff --git a/ports/geckolib/gecko_bindings/structs.rs b/ports/geckolib/gecko_bindings/structs.rs index c2d4d178089..f736bc2896b 100644 --- a/ports/geckolib/gecko_bindings/structs.rs +++ b/ports/geckolib/gecko_bindings/structs.rs @@ -2747,7 +2747,6 @@ pub struct piecewise_construct_t; impl ::std::clone::Clone for piecewise_construct_t { fn clone(&self) -> Self { *self } } -pub enum tuple { } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pair<_T1, _T2> { @@ -3778,6 +3777,56 @@ pub type nscolor = u32; #[repr(i8)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum nsHexColorType { NoAlpha = 0, AllowAlpha = 1, } +/** + * Class to safely handle main-thread-only pointers off the main thread. + * + * Classes like XPCWrappedJS are main-thread-only, which means that it is + * forbidden to call methods on instances of these classes off the main thread. + * For various reasons (see bug 771074), this restriction recently began to + * apply to AddRef/Release as well. + * + * This presents a problem for consumers that wish to hold a callback alive + * on non-main-thread code. A common example of this is the proxy callback + * pattern, where non-main-thread code holds a strong-reference to the callback + * object, and dispatches new Runnables (also with a strong reference) to the + * main thread in order to execute the callback. This involves several AddRef + * and Release calls on the other thread, which is (now) verboten. + * + * The basic idea of this class is to introduce a layer of indirection. + * nsMainThreadPtrHolder is a threadsafe reference-counted class that internally + * maintains one strong reference to the main-thread-only object. It must be + * instantiated on the main thread (so that the AddRef of the underlying object + * happens on the main thread), but consumers may subsequently pass references + * to the holder anywhere they please. These references are meant to be opaque + * when accessed off-main-thread (assertions enforce this). + * + * The semantics of RefPtr > would be cumbersome, so + * we also introduce nsMainThreadPtrHandle, which is conceptually identical + * to the above (though it includes various convenience methods). The basic + * pattern is as follows. + * + * // On the main thread: + * nsCOMPtr callback = ...; + * nsMainThreadPtrHandle callbackHandle = + * new nsMainThreadPtrHolder(callback); + * // Pass callbackHandle to structs/classes that might be accessed on other + * // threads. + * + * All structs and classes that might be accessed on other threads should store + * an nsMainThreadPtrHandle rather than an nsCOMPtr. + */ +#[repr(C)] +#[derive(Debug)] +pub struct nsMainThreadPtrHolder { + pub mRefCnt: ThreadSafeAutoRefCnt, + pub mRawPtr: *mut T, + pub mStrict: bool, +} +#[repr(C)] +#[derive(Debug)] +pub struct nsMainThreadPtrHandle { + pub mPtr: RefPtr, +} /** * This structure precedes the string buffers "we" allocate. It may be the * case that nsTAString::mData does not point to one of these special @@ -3800,12 +3849,21 @@ fn bindgen_test_layout_nsStringBuffer() { } pub enum CSSStyleSheet { } #[repr(C)] +pub struct URLValueData { + pub _bindgen_opaque_blob: [u64; 5usize], +} +#[test] +fn bindgen_test_layout_URLValueData() { + assert_eq!(::std::mem::size_of::() , 40usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +#[repr(C)] pub struct URLValue { - pub _bindgen_opaque_blob: [u64; 7usize], + pub _bindgen_opaque_blob: [u64; 6usize], } #[test] fn bindgen_test_layout_URLValue() { - assert_eq!(::std::mem::size_of::() , 56usize); + assert_eq!(::std::mem::size_of::() , 48usize); assert_eq!(::std::mem::align_of::() , 8usize); } #[repr(C)] @@ -4553,22 +4611,22 @@ pub enum nsStyleUnit { } #[repr(C)] #[derive(Debug, Copy)] -pub struct nsStyleCoord_h_unnamed_10 { +pub struct nsStyleCoord_h_unnamed_14 { pub mInt: __BindgenUnionField, pub mFloat: __BindgenUnionField, pub mPointer: __BindgenUnionField<*mut ::std::os::raw::c_void>, pub _bindgen_data_: u64, } -impl nsStyleCoord_h_unnamed_10 { } -impl ::std::clone::Clone for nsStyleCoord_h_unnamed_10 { +impl nsStyleCoord_h_unnamed_14 { } +impl ::std::clone::Clone for nsStyleCoord_h_unnamed_14 { fn clone(&self) -> Self { *self } } #[test] -fn bindgen_test_layout_nsStyleCoord_h_unnamed_10() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); +fn bindgen_test_layout_nsStyleCoord_h_unnamed_14() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); } -pub type nsStyleUnion = nsStyleCoord_h_unnamed_10; +pub type nsStyleUnion = nsStyleCoord_h_unnamed_14; /** * Class that hold a single size specification used by the style * system. The size specification consists of two parts -- a number @@ -4763,27 +4821,27 @@ pub enum nsStyleImageType { pub struct nsStyleImage { pub mSubImages: u64, pub mType: nsStyleImageType, - pub nsStyleImage_nsStyleStruct_h_unnamed_13: nsStyleImage_nsStyleStruct_h_unnamed_13, + pub nsStyleImage_nsStyleStruct_h_unnamed_17: nsStyleImage_nsStyleStruct_h_unnamed_17, pub mCropRect: nsAutoPtr, pub mImageTracked: bool, } #[repr(C)] #[derive(Debug, Copy)] -pub struct nsStyleImage_nsStyleStruct_h_unnamed_13 { +pub struct nsStyleImage_nsStyleStruct_h_unnamed_17 { pub mImage: __BindgenUnionField<*mut imgRequestProxy>, pub mGradient: __BindgenUnionField<*mut nsStyleGradient>, pub mElementId: __BindgenUnionField<*mut ::std::os::raw::c_ushort>, pub _bindgen_data_: u64, } -impl nsStyleImage_nsStyleStruct_h_unnamed_13 { } -impl ::std::clone::Clone for nsStyleImage_nsStyleStruct_h_unnamed_13 { +impl nsStyleImage_nsStyleStruct_h_unnamed_17 { } +impl ::std::clone::Clone for nsStyleImage_nsStyleStruct_h_unnamed_17 { fn clone(&self) -> Self { *self } } #[test] -fn bindgen_test_layout_nsStyleImage_nsStyleStruct_h_unnamed_13() { - assert_eq!(::std::mem::size_of::() +fn bindgen_test_layout_nsStyleImage_nsStyleStruct_h_unnamed_17() { + assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() + assert_eq!(::std::mem::align_of::() , 8usize); } #[test] @@ -4833,7 +4891,7 @@ pub struct nsStyleImageLayers { } #[repr(u32)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum nsStyleImageLayers_nsStyleStruct_h_unnamed_14 { +pub enum nsStyleImageLayers_nsStyleStruct_h_unnamed_18 { shorthand = 0, color = 1, image = 2, @@ -5298,7 +5356,7 @@ fn bindgen_test_layout_nsStyleVisibility() { #[derive(Debug, Copy)] pub struct nsTimingFunction { pub mType: nsTimingFunction_Type, - pub nsTimingFunction_nsStyleStruct_h_unnamed_15: nsTimingFunction_nsStyleStruct_h_unnamed_15, + pub nsTimingFunction_nsStyleStruct_h_unnamed_19: nsTimingFunction_nsStyleStruct_h_unnamed_19, } #[repr(i32)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] @@ -5325,56 +5383,56 @@ pub enum nsTimingFunction_StepSyntax { pub enum nsTimingFunction_Keyword { Implicit = 0, Explicit = 1, } #[repr(C)] #[derive(Debug, Copy)] -pub struct nsTimingFunction_nsStyleStruct_h_unnamed_15 { - pub mFunc: __BindgenUnionField, - pub nsTimingFunction_nsStyleStruct_h_unnamed_15_nsStyleStruct_h_unnamed_17: __BindgenUnionField, +pub struct nsTimingFunction_nsStyleStruct_h_unnamed_19 { + pub mFunc: __BindgenUnionField, + pub nsTimingFunction_nsStyleStruct_h_unnamed_19_nsStyleStruct_h_unnamed_21: __BindgenUnionField, pub _bindgen_data_: [u32; 4usize], } -impl nsTimingFunction_nsStyleStruct_h_unnamed_15 { } -impl ::std::clone::Clone for nsTimingFunction_nsStyleStruct_h_unnamed_15 { +impl nsTimingFunction_nsStyleStruct_h_unnamed_19 { } +impl ::std::clone::Clone for nsTimingFunction_nsStyleStruct_h_unnamed_19 { fn clone(&self) -> Self { *self } } #[test] -fn bindgen_test_layout_nsTimingFunction_nsStyleStruct_h_unnamed_15() { - assert_eq!(::std::mem::size_of::() +fn bindgen_test_layout_nsTimingFunction_nsStyleStruct_h_unnamed_19() { + assert_eq!(::std::mem::size_of::() , 16usize); - assert_eq!(::std::mem::align_of::() + assert_eq!(::std::mem::align_of::() , 4usize); } #[repr(C)] #[derive(Debug, Copy)] -pub struct nsTimingFunction_nsStyleStruct_h_unnamed_15_nsStyleStruct_h_unnamed_16 { +pub struct nsTimingFunction_nsStyleStruct_h_unnamed_19_nsStyleStruct_h_unnamed_20 { pub mX1: f32, pub mY1: f32, pub mX2: f32, pub mY2: f32, } impl ::std::clone::Clone for - nsTimingFunction_nsStyleStruct_h_unnamed_15_nsStyleStruct_h_unnamed_16 { + nsTimingFunction_nsStyleStruct_h_unnamed_19_nsStyleStruct_h_unnamed_20 { fn clone(&self) -> Self { *self } } #[test] -fn bindgen_test_layout_nsTimingFunction_nsStyleStruct_h_unnamed_15_nsStyleStruct_h_unnamed_16() { - assert_eq!(::std::mem::size_of::() +fn bindgen_test_layout_nsTimingFunction_nsStyleStruct_h_unnamed_19_nsStyleStruct_h_unnamed_20() { + assert_eq!(::std::mem::size_of::() , 16usize); - assert_eq!(::std::mem::align_of::() + assert_eq!(::std::mem::align_of::() , 4usize); } #[repr(C)] #[derive(Debug, Copy)] -pub struct nsTimingFunction_nsStyleStruct_h_unnamed_15_nsStyleStruct_h_unnamed_17 { +pub struct nsTimingFunction_nsStyleStruct_h_unnamed_19_nsStyleStruct_h_unnamed_21 { pub mStepSyntax: nsTimingFunction_StepSyntax, pub mSteps: u32, } impl ::std::clone::Clone for - nsTimingFunction_nsStyleStruct_h_unnamed_15_nsStyleStruct_h_unnamed_17 { + nsTimingFunction_nsStyleStruct_h_unnamed_19_nsStyleStruct_h_unnamed_21 { fn clone(&self) -> Self { *self } } #[test] -fn bindgen_test_layout_nsTimingFunction_nsStyleStruct_h_unnamed_15_nsStyleStruct_h_unnamed_17() { - assert_eq!(::std::mem::size_of::() +fn bindgen_test_layout_nsTimingFunction_nsStyleStruct_h_unnamed_19_nsStyleStruct_h_unnamed_21() { + assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() + assert_eq!(::std::mem::align_of::() , 4usize); } impl ::std::clone::Clone for nsTimingFunction { @@ -5519,26 +5577,26 @@ pub enum nsStyleContentType { #[derive(Debug)] pub struct nsStyleContentData { pub mType: nsStyleContentType, - pub mContent: nsStyleContentData_nsStyleStruct_h_unnamed_18, + pub mContent: nsStyleContentData_nsStyleStruct_h_unnamed_22, pub mImageTracked: bool, } #[repr(C)] #[derive(Debug, Copy)] -pub struct nsStyleContentData_nsStyleStruct_h_unnamed_18 { +pub struct nsStyleContentData_nsStyleStruct_h_unnamed_22 { pub mString: __BindgenUnionField<*mut ::std::os::raw::c_ushort>, pub mImage: __BindgenUnionField<*mut imgRequestProxy>, pub mCounters: __BindgenUnionField<*mut Array>, pub _bindgen_data_: u64, } -impl nsStyleContentData_nsStyleStruct_h_unnamed_18 { } -impl ::std::clone::Clone for nsStyleContentData_nsStyleStruct_h_unnamed_18 { +impl nsStyleContentData_nsStyleStruct_h_unnamed_22 { } +impl ::std::clone::Clone for nsStyleContentData_nsStyleStruct_h_unnamed_22 { fn clone(&self) -> Self { *self } } #[test] -fn bindgen_test_layout_nsStyleContentData_nsStyleStruct_h_unnamed_18() { - assert_eq!(::std::mem::size_of::() +fn bindgen_test_layout_nsStyleContentData_nsStyleStruct_h_unnamed_22() { + assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() + assert_eq!(::std::mem::align_of::() , 8usize); } #[test] @@ -5672,26 +5730,26 @@ pub enum nsStyleSVGOpacitySource { #[repr(C)] #[derive(Debug)] pub struct nsStyleSVGPaint { - pub mPaint: nsStyleSVGPaint_nsStyleStruct_h_unnamed_19, + pub mPaint: nsStyleSVGPaint_nsStyleStruct_h_unnamed_23, pub mType: nsStyleSVGPaintType, pub mFallbackColor: nscolor, } #[repr(C)] #[derive(Debug, Copy)] -pub struct nsStyleSVGPaint_nsStyleStruct_h_unnamed_19 { +pub struct nsStyleSVGPaint_nsStyleStruct_h_unnamed_23 { pub mColor: __BindgenUnionField, pub mPaintServer: __BindgenUnionField<*mut nsIURI>, pub _bindgen_data_: u64, } -impl nsStyleSVGPaint_nsStyleStruct_h_unnamed_19 { } -impl ::std::clone::Clone for nsStyleSVGPaint_nsStyleStruct_h_unnamed_19 { +impl nsStyleSVGPaint_nsStyleStruct_h_unnamed_23 { } +impl ::std::clone::Clone for nsStyleSVGPaint_nsStyleStruct_h_unnamed_23 { fn clone(&self) -> Self { *self } } #[test] -fn bindgen_test_layout_nsStyleSVGPaint_nsStyleStruct_h_unnamed_19() { - assert_eq!(::std::mem::size_of::() +fn bindgen_test_layout_nsStyleSVGPaint_nsStyleStruct_h_unnamed_23() { + assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() + assert_eq!(::std::mem::align_of::() , 8usize); } #[test] @@ -5758,25 +5816,25 @@ fn bindgen_test_layout_nsStyleBasicShape() { #[derive(Debug)] pub struct nsStyleClipPath { pub mType: i32, - pub nsStyleClipPath_nsStyleStruct_h_unnamed_20: nsStyleClipPath_nsStyleStruct_h_unnamed_20, + pub nsStyleClipPath_nsStyleStruct_h_unnamed_24: nsStyleClipPath_nsStyleStruct_h_unnamed_24, pub mSizingBox: u8, } #[repr(C)] #[derive(Debug, Copy)] -pub struct nsStyleClipPath_nsStyleStruct_h_unnamed_20 { +pub struct nsStyleClipPath_nsStyleStruct_h_unnamed_24 { pub mBasicShape: __BindgenUnionField<*mut nsStyleBasicShape>, pub mURL: __BindgenUnionField<*mut nsIURI>, pub _bindgen_data_: u64, } -impl nsStyleClipPath_nsStyleStruct_h_unnamed_20 { } -impl ::std::clone::Clone for nsStyleClipPath_nsStyleStruct_h_unnamed_20 { +impl nsStyleClipPath_nsStyleStruct_h_unnamed_24 { } +impl ::std::clone::Clone for nsStyleClipPath_nsStyleStruct_h_unnamed_24 { fn clone(&self) -> Self { *self } } #[test] -fn bindgen_test_layout_nsStyleClipPath_nsStyleStruct_h_unnamed_20() { - assert_eq!(::std::mem::size_of::() +fn bindgen_test_layout_nsStyleClipPath_nsStyleStruct_h_unnamed_24() { + assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() + assert_eq!(::std::mem::align_of::() , 8usize); } #[test] @@ -5789,24 +5847,24 @@ fn bindgen_test_layout_nsStyleClipPath() { pub struct nsStyleFilter { pub mType: i32, pub mFilterParameter: nsStyleCoord, - pub nsStyleFilter_nsStyleStruct_h_unnamed_21: nsStyleFilter_nsStyleStruct_h_unnamed_21, + pub nsStyleFilter_nsStyleStruct_h_unnamed_25: nsStyleFilter_nsStyleStruct_h_unnamed_25, } #[repr(C)] #[derive(Debug, Copy)] -pub struct nsStyleFilter_nsStyleStruct_h_unnamed_21 { +pub struct nsStyleFilter_nsStyleStruct_h_unnamed_25 { pub mURL: __BindgenUnionField<*mut nsIURI>, pub mDropShadow: __BindgenUnionField<*mut nsCSSShadowArray>, pub _bindgen_data_: u64, } -impl nsStyleFilter_nsStyleStruct_h_unnamed_21 { } -impl ::std::clone::Clone for nsStyleFilter_nsStyleStruct_h_unnamed_21 { +impl nsStyleFilter_nsStyleStruct_h_unnamed_25 { } +impl ::std::clone::Clone for nsStyleFilter_nsStyleStruct_h_unnamed_25 { fn clone(&self) -> Self { *self } } #[test] -fn bindgen_test_layout_nsStyleFilter_nsStyleStruct_h_unnamed_21() { - assert_eq!(::std::mem::size_of::() +fn bindgen_test_layout_nsStyleFilter_nsStyleStruct_h_unnamed_25() { + assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() + assert_eq!(::std::mem::align_of::() , 8usize); } #[test] diff --git a/ports/geckolib/gecko_bindings/tools/regen_bindings.sh b/ports/geckolib/gecko_bindings/tools/regen_bindings.sh index cce6f21ddfb..da147247541 100755 --- a/ports/geckolib/gecko_bindings/tools/regen_bindings.sh +++ b/ports/geckolib/gecko_bindings/tools/regen_bindings.sh @@ -50,7 +50,7 @@ do done # Other mapped types. -for TYPE in SheetParsingMode +for TYPE in SheetParsingMode nsMainThreadPtrHandle nsMainThreadPtrHolder do MAP_GECKO_TYPES=$MAP_GECKO_TYPES"-blacklist-type $TYPE " MAP_GECKO_TYPES=$MAP_GECKO_TYPES"-raw-line 'use structs::$TYPE;' " @@ -59,6 +59,8 @@ done # Check for the include directory. +export OBJDIR="$1" +export SRCDIR="$1/.." # Not necessarily true, but let's assume. export DIST_INCLUDE="$1/dist/include" if [ ! -d "$DIST_INCLUDE" ]; then echo "$DIST_INCLUDE: directory not found" @@ -72,6 +74,8 @@ export RUST_BACKTRACE=1 eval ./rust-bindgen/target/debug/bindgen \ -x c++ -std=gnu++0x \ "-I$DIST_INCLUDE" \ + "-I$DIST_INCLUDE/nspr/" \ + "-I$SRCDIR/nsprpub/pr/include/" \ $PLATFORM_DEPENDENT_DEFINES \ -o ../bindings.rs \ -no-type-renaming \ diff --git a/ports/geckolib/gecko_bindings/tools/regen_style_structs.sh b/ports/geckolib/gecko_bindings/tools/regen_style_structs.sh index 5f9c77c146a..64b56284026 100755 --- a/ports/geckolib/gecko_bindings/tools/regen_style_structs.sh +++ b/ports/geckolib/gecko_bindings/tools/regen_style_structs.sh @@ -102,8 +102,10 @@ export RUST_BACKTRACE=1 -match "pair" \ -match "SheetParsingMode.h" \ -match "StaticPtr.h" \ + -match "nsProxyRelease.h" \ -blacklist-type "IsDestructibleFallbackImpl" \ -blacklist-type "IsDestructibleFallback" \ + -blacklist-type "nsProxyReleaseEvent" \ -opaque-type "nsIntMargin" \ -opaque-type "nsIntPoint" \ -opaque-type "nsIntRect" \ @@ -116,6 +118,7 @@ export RUST_BACKTRACE=1 -opaque-type "CounterStyleManager" \ -opaque-type "ImageValue" \ -opaque-type "URLValue" \ + -opaque-type "URLValueData" \ -opaque-type "nsIPrincipal" \ -opaque-type "nsDataHashtable" \ -opaque-type "imgIRequest" \ From 6dfb51f272d70f92563dd9a3444ebf04ad8a9bdc Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Thu, 19 May 2016 14:24:46 +1000 Subject: [PATCH 3/7] Add smart pointer types for Gecko refcounted objects. --- ports/geckolib/gecko_bindings/lib.rs | 4 ++ ports/geckolib/gecko_bindings/ptr.rs | 59 ++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 ports/geckolib/gecko_bindings/ptr.rs diff --git a/ports/geckolib/gecko_bindings/lib.rs b/ports/geckolib/gecko_bindings/lib.rs index b6d684b5891..d1bfb30985d 100644 --- a/ports/geckolib/gecko_bindings/lib.rs +++ b/ports/geckolib/gecko_bindings/lib.rs @@ -2,9 +2,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#![feature(concat_idents)] +#![feature(type_macros)] + extern crate heapsize; #[allow(dead_code, non_camel_case_types)] pub mod bindings; +pub mod ptr; #[allow(dead_code, non_camel_case_types, non_snake_case, non_upper_case_globals)] pub mod structs; diff --git a/ports/geckolib/gecko_bindings/ptr.rs b/ports/geckolib/gecko_bindings/ptr.rs new file mode 100644 index 00000000000..089df6f70b1 --- /dev/null +++ b/ports/geckolib/gecko_bindings/ptr.rs @@ -0,0 +1,59 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use bindings::*; +use heapsize::HeapSizeOf; +use std::fmt::{self, Debug}; + +// Defines an Arc-like type that manages a refcounted Gecko object stored +// in a ThreadSafeFooHolder smart pointer. Used in tandem with the +// NS_DECL_HOLDER_FFI_REFCOUNTING-defined types and functions in Gecko. +macro_rules! define_holder_arc { + ($arc_type:ident, $name:ident, $holder_type:ident) => ( + #[derive(PartialEq)] + pub struct $arc_type { + ptr: *mut $holder_type, + } + + impl $arc_type { + pub fn new(data: *mut $holder_type) -> $arc_type { + debug_assert!(!data.is_null()); + unsafe { concat_idents!(Gecko_AddRef, $name, ArbitraryThread)(data); } + $arc_type { + ptr: data + } + } + + pub fn as_raw(&self) -> *mut $holder_type { self.ptr } + } + + unsafe impl Send for $arc_type {} + unsafe impl Sync for $arc_type {} + + impl Clone for $arc_type { + fn clone(&self) -> $arc_type { + $arc_type::new(self.ptr) + } + } + + impl Drop for $arc_type { + fn drop(&mut self) { + unsafe { concat_idents!(Gecko_Release, $name, ArbitraryThread)(self.ptr); } + } + } + + impl HeapSizeOf for $arc_type { + fn heap_size_of_children(&self) -> usize { 0 } + } + + impl Debug for $arc_type { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, stringify!($name)) + } + } + ) +} + +define_holder_arc!(GeckoArcPrincipal, Principal, ThreadSafePrincipalHolder); +define_holder_arc!(GeckoArcURI, URI, ThreadSafeURIHolder); From 6d67aa8a01c3f1e1d45d40273625b86817d8d216 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Thu, 19 May 2016 15:40:10 +1000 Subject: [PATCH 4/7] Pass Gecko sheet base/referrer/principal from Servo_StylesheetFromUTF8Bytes through ParserContext. --- components/style/Cargo.toml | 3 ++- components/style/lib.rs | 2 ++ components/style/parser.rs | 7 ++++++- ports/geckolib/Cargo.lock | 1 + ports/geckolib/glue.rs | 15 ++++++++++++--- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 5198dc05b14..566506e987e 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -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" diff --git a/components/style/lib.rs b/components/style/lib.rs index 00d5d079066..4ec45e45e04 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -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] diff --git a/components/style/parser.rs b/components/style/parser.rs index 5a38c2f22b5..eadb778db55 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -5,6 +5,8 @@ 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; @@ -14,6 +16,9 @@ pub struct ParserContextExtraData; #[cfg(feature = "gecko")] pub struct ParserContextExtraData { + pub base: Option, + pub referrer: Option, + pub principal: Option, } impl ParserContextExtraData { @@ -24,7 +29,7 @@ impl ParserContextExtraData { #[cfg(feature = "gecko")] pub fn default() -> ParserContextExtraData { - ParserContextExtraData { } + ParserContextExtraData { base: None, referrer: None, principal: None } } } diff --git a/ports/geckolib/Cargo.lock b/ports/geckolib/Cargo.lock index 3e88bea0062..54b62cd7830 100644 --- a/ports/geckolib/Cargo.lock +++ b/ports/geckolib/Cargo.lock @@ -453,6 +453,7 @@ dependencies = [ "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gecko_bindings 0.0.1", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index d4c268f58fb..578fb5a1a77 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -10,7 +10,8 @@ use env_logger; use euclid::Size2D; use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode}; use gecko_bindings::bindings::{RawServoStyleSet, RawServoStyleSheet, ServoComputedValues, ServoNodeData}; -use gecko_bindings::bindings::{nsIAtom}; +use gecko_bindings::bindings::{ThreadSafePrincipalHolder, ThreadSafeURIHolder, nsIAtom}; +use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI}; use gecko_bindings::structs::SheetParsingMode; use properties::GeckoComputedValues; use selector_impl::{GeckoSelectorImpl, PseudoElement, SharedStyleContext, Stylesheet}; @@ -121,7 +122,11 @@ pub extern "C" fn Servo_DropNodeData(data: *mut ServoNodeData) -> () { #[no_mangle] pub extern "C" fn Servo_StylesheetFromUTF8Bytes(bytes: *const u8, length: u32, - mode: SheetParsingMode) -> *mut RawServoStyleSheet { + mode: SheetParsingMode, + base: *mut ThreadSafeURIHolder, + referrer: *mut ThreadSafeURIHolder, + principal: *mut ThreadSafePrincipalHolder) + -> *mut RawServoStyleSheet { let input = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) }; @@ -133,7 +138,11 @@ pub extern "C" fn Servo_StylesheetFromUTF8Bytes(bytes: *const u8, // FIXME(heycam): Pass in the real base URL. let url = Url::parse("about:none").unwrap(); - let extra_data = ParserContextExtraData { }; + let extra_data = ParserContextExtraData { + base: Some(GeckoArcURI::new(base)), + 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)); unsafe { From 44bdbed98952a88f3e6b886d27ed293316689451 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Thu, 19 May 2016 15:56:22 +1000 Subject: [PATCH 5/7] Support -moz-binding in geckolib. --- components/style/properties/helpers.mako.rs | 2 +- .../style/properties/longhand/box.mako.rs | 75 +++++++++++++++++++ ports/geckolib/properties.mako.rs | 24 +++++- 3 files changed, 98 insertions(+), 3 deletions(-) diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index af052179d2c..86961c89192 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -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; diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 6fd36b71a4d..f80a42c88d2 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -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(&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 { + 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(()) + }, + } + } + diff --git a/ports/geckolib/properties.mako.rs b/ports/geckolib/properties.mako.rs index 55a9a528bbd..387f5e02edb 100644 --- a/ports/geckolib/properties.mako.rs +++ b/ports/geckolib/properties.mako.rs @@ -16,7 +16,8 @@ use gecko_bindings::bindings::Gecko_Construct_${style_struct.gecko_ffi_name}; use gecko_bindings::bindings::Gecko_CopyConstruct_${style_struct.gecko_ffi_name}; use gecko_bindings::bindings::Gecko_Destroy_${style_struct.gecko_ffi_name}; % endfor -use gecko_bindings::bindings::{Gecko_CopyListStyleTypeFrom, Gecko_SetListStyleType}; +use gecko_bindings::bindings::{Gecko_CopyMozBindingFrom, Gecko_CopyListStyleTypeFrom}; +use gecko_bindings::bindings::{Gecko_SetMozBinding, Gecko_SetListStyleType}; use gecko_bindings::structs; use glue::ArcHelpers; use heapsize::HeapSizeOf; @@ -625,7 +626,7 @@ fn static_assert() { -<%self:impl_trait style_struct_name="Box" skip_longhands="display overflow-y vertical-align"> +<%self:impl_trait style_struct_name="Box" skip_longhands="display overflow-y vertical-align -moz-binding"> // We manually-implement the |display| property until we get general // infrastructure for preffing certain values. @@ -677,6 +678,25 @@ fn static_assert() { self.gecko.mVerticalAlign.mValue = other.gecko.mVerticalAlign.mValue; } + fn set__moz_binding(&mut self, v: longhands::_moz_binding::computed_value::T) { + use style::properties::longhands::_moz_binding::SpecifiedValue as BindingValue; + match v { + BindingValue::None => debug_assert!(self.gecko.mBinding.mRawPtr.is_null()), + BindingValue::Url(ref url, ref extra_data) => { + unsafe { + Gecko_SetMozBinding(&mut self.gecko, + url.as_str().as_ptr(), + url.as_str().len() as u32, + extra_data.base.as_raw(), + extra_data.referrer.as_raw(), + extra_data.principal.as_raw()); + } + } + } + } + fn copy__moz_binding_from(&mut self, other: &Self) { + unsafe { Gecko_CopyMozBindingFrom(&mut self.gecko, &other.gecko); } + } <%self:impl_trait style_struct_name="Background" skip_longhands="background-color" skip_additionals="*"> From e75b1c3b32e5c2d064316c1fe133b2bdb86fba2b Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Tue, 24 May 2016 12:06:28 +1000 Subject: [PATCH 6/7] Re-use Url serialization in values::specified::Image. --- components/style/values.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/components/style/values.rs b/components/style/values.rs index 2f295bd8775..9492a028cfc 100644 --- a/components/style/values.rs +++ b/components/style/values.rs @@ -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(&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) } From f2b1ef4e45164b03a621ae5a9b7b96f5025006c1 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Tue, 24 May 2016 14:03:55 +1000 Subject: [PATCH 7/7] fixup! Add an extra data field to ParserContext. --- tests/unit/style/media_queries.rs | 7 +++++-- tests/unit/style/stylesheets.rs | 7 +++++-- tests/unit/style/viewport.rs | 5 +++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/unit/style/media_queries.rs b/tests/unit/style/media_queries.rs index daa6f1c2569..c806f4ee8ad 100644 --- a/tests/unit/style/media_queries.rs +++ b/tests/unit/style/media_queries.rs @@ -8,6 +8,7 @@ use euclid::size::Size2D; use std::borrow::ToOwned; use style::error_reporting::ParseErrorReporter; use style::media_queries::*; +use style::parser::ParserContextExtraData; use style::servo::Stylesheet; use style::stylesheets::{Origin, CSSRuleIteratorExt}; use style::values::specified; @@ -25,7 +26,8 @@ impl ParseErrorReporter for CSSErrorReporterTest { fn test_media_rule(css: &str, callback: F) where F: Fn(&MediaQueryList, &str) { let url = Url::parse("http://localhost").unwrap(); - let stylesheet = Stylesheet::from_str(css, url, Origin::Author, Box::new(CSSErrorReporterTest)); + let stylesheet = Stylesheet::from_str(css, url, Origin::Author, Box::new(CSSErrorReporterTest), + ParserContextExtraData::default()); let mut rule_count = 0; for rule in stylesheet.rules().media() { rule_count += 1; @@ -36,7 +38,8 @@ fn test_media_rule(css: &str, callback: F) where F: Fn(&MediaQueryList, &str) fn media_query_test(device: &Device, css: &str, expected_rule_count: usize) { let url = Url::parse("http://localhost").unwrap(); - let ss = Stylesheet::from_str(css, url, Origin::Author, Box::new(CSSErrorReporterTest)); + let ss = Stylesheet::from_str(css, url, Origin::Author, Box::new(CSSErrorReporterTest), + ParserContextExtraData::default()); let rule_count = ss.effective_rules(device).style().count(); assert!(rule_count == expected_rule_count, css.to_owned()); } diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 91822093ea2..a771cae0800 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -9,6 +9,7 @@ use std::borrow::ToOwned; use std::sync::Arc; use std::sync::Mutex; use string_cache::{Atom, Namespace}; +use style::parser::ParserContextExtraData; use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, DeclaredValue, longhands}; use style::stylesheets::{CSSRule, StyleRule, Origin}; use style::error_reporting::ParseErrorReporter; @@ -26,7 +27,8 @@ fn test_parse_stylesheet() { "; let url = Url::parse("about::test").unwrap(); let stylesheet = Stylesheet::from_str(css, url, Origin::UserAgent, - Box::new(CSSErrorReporterTest)); + Box::new(CSSErrorReporterTest), + ParserContextExtraData::default()); assert_eq!(stylesheet, Stylesheet { origin: Origin::UserAgent, media: None, @@ -205,7 +207,8 @@ 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, error_reporter, + ParserContextExtraData::default()); let mut errors = errors.lock().unwrap(); diff --git a/tests/unit/style/viewport.rs b/tests/unit/style/viewport.rs index 316e7c25340..61168d65ad5 100644 --- a/tests/unit/style/viewport.rs +++ b/tests/unit/style/viewport.rs @@ -8,7 +8,7 @@ use euclid::size::Size2D; use media_queries::CSSErrorReporterTest; use style::error_reporting::ParseErrorReporter; use style::media_queries::{Device, MediaType}; -use style::parser::ParserContext; +use style::parser::{ParserContext, ParserContextExtraData}; use style::servo::Stylesheet; use style::stylesheets::{Origin, CSSRuleIteratorExt}; use style::values::specified::Length::{self, ViewportPercentage}; @@ -20,7 +20,8 @@ use url::Url; macro_rules! stylesheet { ($css:expr, $origin:ident, $error_reporter:expr) => { - Stylesheet::from_str($css, Url::parse("http://localhost").unwrap(), Origin::$origin, $error_reporter); + Stylesheet::from_str($css, Url::parse("http://localhost").unwrap(), Origin::$origin, $error_reporter, + ParserContextExtraData::default()); } }