From ccff9b294f17ff4214e1c488817d48a10c95c2f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 27 May 2019 11:45:12 +0000 Subject: [PATCH] style: Use cbindgen for URIs. This doesn't clean up as much as a whole, but it's a step in the right direction. In particular, it allows us to start using simple bindings for: * Filters * Shapes and images, almost. Need to: * Get rid of the complex -moz- gradient parsing (let layout.css.simple-moz-gradient.enabled get to release). * Counters, almost. Need to: * Share the Attr representation with Gecko, by not using Option<>. * Just another variant should be enough (ContentItem::{Attr,Prefixedattr}, maybe). Which in turn allows us to remove a whole lot of bindings in followups to this. The setup changes a bit. This also removes the double pointer I complained about while reviewing the shared UA sheet patches. The old setup is: ``` SpecifiedUrl * CssUrl * Arc * String * UrlExtraData * UrlValueSource * Arc * load id * resolved uri * CORS mode. * ... ``` The new one removes the double reference to the url data via URLValue, and looks like: ``` SpecifiedUrl * CssUrl * Arc * String * UrlExtraData * CorsMode * LoadData * load id * resolved URI ``` The LoadData is the only mutable bit that C++ can change, and is not used from Rust. Ideally, in the future, we could just use rust-url to resolve the URL after parsing or something, and make it all immutable. Maybe. I've verified that this approach still works with the UA sheet patches (via the LoadDataSource::Lazy). The reordering of mWillChange is to avoid nsStyleDisplay from going over the size limit. We want to split it up anyway in bug 1552587, but mBinding gains a tag member, which means that we were having a bit of extra padding. One thing I want to explore is to see if we can abuse rustc's non-zero optimizations to predict the layout from C++, but that's something to explore at some other point in time and with a lot of care and help from Michael (who sits next to me and works on rustc ;)). Differential Revision: https://phabricator.services.mozilla.com/D31742 --- components/servo_arc/lib.rs | 3 + components/style/font_face.rs | 2 +- components/style/gecko/conversions.rs | 7 +- components/style/gecko/url.rs | 379 ++++++++---------- .../style/gecko_bindings/sugar/refptr.rs | 36 +- components/style/properties/gecko.mako.rs | 67 +--- .../style/properties/longhands/box.mako.rs | 1 - components/style/stylesheets/mod.rs | 17 +- components/style/stylesheets/rule_parser.rs | 4 +- components/style/values/generics/url.rs | 19 +- components/style/values/specified/url.rs | 2 +- 11 files changed, 239 insertions(+), 298 deletions(-) diff --git a/components/servo_arc/lib.rs b/components/servo_arc/lib.rs index 09f381c62df..e1496b7971a 100644 --- a/components/servo_arc/lib.rs +++ b/components/servo_arc/lib.rs @@ -90,6 +90,9 @@ const STATIC_REFCOUNT: usize = usize::MAX; /// usage of PhantomData. /// /// [`Arc`]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html +/// +/// cbindgen:derive-eq=false +/// cbindgen:derive-neq=false #[repr(C)] pub struct Arc { p: ptr::NonNull>, diff --git a/components/style/font_face.rs b/components/style/font_face.rs index 655c8846f76..c8e7e65785b 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -55,7 +55,7 @@ impl OneOrMoreSeparated for Source { #[repr(u8)] #[allow(missing_docs)] pub enum FontFaceSourceListComponent { - Url(*const crate::gecko_bindings::structs::mozilla::css::URLValue), + Url(*const crate::gecko::url::CssUrl), Local(*mut crate::gecko_bindings::structs::nsAtom), FormatHint { length: usize, diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 06e201bf2b5..0be8a81e66a 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -122,11 +122,11 @@ impl nsStyleImage { match image { GenericImage::Gradient(boxed_gradient) => self.set_gradient(*boxed_gradient), GenericImage::Url(ref url) => unsafe { - bindings::Gecko_SetLayerImageImageValue(self, url.url_value_ptr()) + bindings::Gecko_SetLayerImageImageValue(self, url); }, GenericImage::Rect(ref image_rect) => { unsafe { - bindings::Gecko_SetLayerImageImageValue(self, image_rect.url.url_value_ptr()); + bindings::Gecko_SetLayerImageImageValue(self, &image_rect.url); bindings::Gecko_InitializeImageCropRect(self); // Set CropRect @@ -584,9 +584,10 @@ pub mod basic_shape { impl<'a> From<&'a StyleShapeSource> for ClippingShape { fn from(other: &'a StyleShapeSource) -> Self { - use crate::values::generics::image::Image as GenericImage; match other.mType { StyleShapeSourceType::Image => unsafe { + use crate::values::generics::image::Image as GenericImage; + let shape_image = &*other.__bindgen_anon_1.mShapeImage.as_ref().mPtr; let image = shape_image.into_image().expect("Cannot convert to Image"); match image { diff --git a/components/style/gecko/url.rs b/components/style/gecko/url.rs index dbbb3399da7..8435895b895 100644 --- a/components/style/gecko/url.rs +++ b/components/style/gecko/url.rs @@ -5,13 +5,11 @@ //! Common handling for the specified value CSS url() values. use crate::gecko_bindings::bindings; -use crate::gecko_bindings::structs::root::mozilla::css::URLValue; -use crate::gecko_bindings::structs::root::mozilla::CORSMode; -use crate::gecko_bindings::structs::root::nsStyleImageRequest; -use crate::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI}; +use crate::gecko_bindings::structs; +use crate::gecko_bindings::structs::nsStyleImageRequest; use crate::gecko_bindings::sugar::refptr::RefPtr; use crate::parser::{Parse, ParserContext}; -use crate::stylesheets::UrlExtraData; +use crate::stylesheets::{UrlExtraData, CorsMode}; use crate::values::computed::{Context, ToComputedValue}; use cssparser::Parser; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; @@ -27,25 +25,63 @@ use to_shmem::{SharedMemoryBuilder, ToShmem}; /// A CSS url() value for gecko. #[css(function = "url")] #[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] +#[repr(C)] pub struct CssUrl(pub Arc); /// Data shared between CssUrls. -#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] +/// +/// cbindgen:derive-eq=false +/// cbindgen:derive-neq=false +#[derive(Debug, SpecifiedValueInfo, ToCss, ToShmem)] +#[repr(C)] pub struct CssUrlData { /// The URL in unresolved string form. - serialization: String, + serialization: crate::OwnedStr, /// The URL extra data. #[css(skip)] pub extra_data: UrlExtraData, + + /// The CORS mode that will be used for the load. + #[css(skip)] + cors_mode: CorsMode, + + /// Data to trigger a load from Gecko. This is mutable in C++. + /// + /// TODO(emilio): Maybe we can eagerly resolve URLs and make this immutable? + #[css(skip)] + load_data: LoadDataSource, +} + +impl PartialEq for CssUrlData { + fn eq(&self, other: &Self) -> bool { + self.serialization == other.serialization && + self.extra_data == other.extra_data && + self.cors_mode == other.cors_mode + } } impl CssUrl { + fn parse_with_cors_mode<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + cors_mode: CorsMode, + ) -> Result> { + let url = input.expect_url()?; + Ok(Self::parse_from_string(url.as_ref().to_owned(), context, cors_mode)) + } + /// Parse a URL from a string value that is a valid CSS token for a URL. - pub fn parse_from_string(url: String, context: &ParserContext) -> Self { + pub fn parse_from_string( + url: String, + context: &ParserContext, + cors_mode: CorsMode, + ) -> Self { CssUrl(Arc::new(CssUrlData { - serialization: url, + serialization: url.into(), extra_data: context.url_data.clone(), + cors_mode, + load_data: LoadDataSource::Owned(LoadData::default()), })) } @@ -85,27 +121,12 @@ impl CssUrlData { } } -#[cfg(debug_assertions)] -impl Drop for CssUrlData { - fn drop(&mut self) { - assert!( - !URL_VALUE_TABLE - .read() - .unwrap() - .contains_key(&CssUrlDataKey(self as *mut _ as *const _)), - "All CssUrlData objects used as keys in URL_VALUE_TABLE should be \ - from shared memory style sheets, and so should never be dropped", - ); - } -} - impl Parse for CssUrl { fn parse<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - let url = input.expect_url()?; - Ok(Self::parse_from_string(url.as_ref().to_owned(), context)) + Self::parse_with_cors_mode(context, input, CorsMode::None) } } @@ -122,143 +143,101 @@ impl MallocSizeOf for CssUrl { } } -/// A key type for URL_VALUE_TABLE. +/// A key type for LOAD_DATA_TABLE. #[derive(Eq, Hash, PartialEq)] -struct CssUrlDataKey(*const CssUrlData); +struct LoadDataKey(*const LoadDataSource); -unsafe impl Sync for CssUrlDataKey {} -unsafe impl Send for CssUrlDataKey {} +unsafe impl Sync for LoadDataKey {} +unsafe impl Send for LoadDataKey {} -/// The source of a Gecko URLValue object for a SpecifiedUrl. -#[derive(Clone, Debug)] -pub enum URLValueSource { - /// A strong reference to a Gecko URLValue object. - URLValue(RefPtr), - /// A CORSMode value used to lazily construct a Gecko URLValue object. - /// - /// The lazily created object will be stored in URL_VALUE_TABLE. - CORSMode(CORSMode), +/// The load data for a given URL. This is mutable from C++, for now at least. +#[repr(C)] +#[derive(Debug)] +pub struct LoadData { + resolved: RefPtr, + load_id: u64, + tried_to_resolve: bool, } -impl ToShmem for URLValueSource { +impl Drop for LoadData { + fn drop(&mut self) { + if self.load_id != 0 { + unsafe { + bindings::Gecko_LoadData_DeregisterLoad(self); + } + } + } +} + +impl Default for LoadData { + fn default() -> Self { + Self { + resolved: RefPtr::null(), + load_id: 0, + tried_to_resolve: false, + } + } +} + +/// The data for a load, or a lazy-loaded, static member that will be stored in +/// LOAD_DATA_TABLE, keyed by the memory location of this object, which is +/// always in the heap because it's inside the CssUrlData object. +/// +/// This type is meant not to be used from C++ so we don't derive helper +/// methods. +/// +/// cbindgen:derive-helper-methods=false +#[derive(Debug)] +#[repr(u8, C)] +pub enum LoadDataSource { + /// An owned copy of the load data. + Owned(LoadData), + /// A lazily-resolved copy of it. + Lazy, +} + +impl LoadDataSource { + /// Gets the load data associated with the source. + /// + /// This relies on the source on being in a stable location if lazy. + #[inline] + pub unsafe fn get(&self) -> *const LoadData { + match *self { + LoadDataSource::Owned(ref d) => return d, + LoadDataSource::Lazy => {}, + } + + let key = LoadDataKey(self); + + { + let guard = LOAD_DATA_TABLE.read().unwrap(); + if let Some(r) = guard.get(&key) { + return &**r; + } + } + let mut guard = LOAD_DATA_TABLE.write().unwrap(); + let r = guard.entry(key).or_insert_with(Default::default); + &**r + } +} + +impl ToShmem for LoadDataSource { fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> ManuallyDrop { ManuallyDrop::new(match self { - URLValueSource::URLValue(r) => URLValueSource::CORSMode(r.mCORSMode), - URLValueSource::CORSMode(c) => URLValueSource::CORSMode(*c), + LoadDataSource::Owned(..) => LoadDataSource::Lazy, + LoadDataSource::Lazy => LoadDataSource::Lazy, }) } } /// A specified non-image `url()` value. -#[derive(Clone, Debug, SpecifiedValueInfo, ToCss, ToShmem)] -pub struct SpecifiedUrl { - /// The specified url value. - pub url: CssUrl, - /// Gecko's URLValue so that we can reuse it while rematching a - /// property with this specified value. - /// - /// Box this to avoid SpecifiedUrl getting bigger than two words, - /// and increasing the size of PropertyDeclaration. - #[css(skip)] - url_value: Box, -} +pub type SpecifiedUrl = CssUrl; -fn make_url_value(url: &CssUrl, cors_mode: CORSMode) -> RefPtr { - unsafe { - let ptr = bindings::Gecko_URLValue_Create(url.0.clone().into_strong(), cors_mode); - // We do not expect Gecko_URLValue_Create returns null. - debug_assert!(!ptr.is_null()); - RefPtr::from_addrefed(ptr) - } -} - -impl SpecifiedUrl { - /// Parse a URL from a string value. - pub fn parse_from_string(url: String, context: &ParserContext) -> Self { - Self::from_css_url(CssUrl::parse_from_string(url, context)) - } - - fn from_css_url_with_cors(url: CssUrl, cors: CORSMode) -> Self { - let url_value = Box::new(URLValueSource::URLValue(make_url_value(&url, cors))); - Self { url, url_value } - } - - fn from_css_url(url: CssUrl) -> Self { - use crate::gecko_bindings::structs::root::mozilla::CORSMode_CORS_NONE; - Self::from_css_url_with_cors(url, CORSMode_CORS_NONE) - } - - fn from_css_url_with_cors_anonymous(url: CssUrl) -> Self { - use crate::gecko_bindings::structs::root::mozilla::CORSMode_CORS_ANONYMOUS; - Self::from_css_url_with_cors(url, CORSMode_CORS_ANONYMOUS) - } - - fn with_url_value(&self, f: F) -> T - where - F: FnOnce(&RefPtr) -> T, - { - match *self.url_value { - URLValueSource::URLValue(ref r) => f(r), - URLValueSource::CORSMode(cors_mode) => { - { - let guard = URL_VALUE_TABLE.read().unwrap(); - if let Some(r) = guard.get(&(CssUrlDataKey(&*self.url.0 as *const _))) { - return f(r); - } - } - let mut guard = URL_VALUE_TABLE.write().unwrap(); - let r = guard - .entry(CssUrlDataKey(&*self.url.0 as *const _)) - .or_insert_with(|| make_url_value(&self.url, cors_mode)); - f(r) - }, - } - } - - /// Clone a new, strong reference to the Gecko URLValue. - pub fn clone_url_value(&self) -> RefPtr { - self.with_url_value(RefPtr::clone) - } - - /// Get a raw pointer to the URLValue held by this SpecifiedUrl, for FFI. - pub fn url_value_ptr(&self) -> *mut URLValue { - self.with_url_value(RefPtr::get) - } -} - -/// Clears URL_VALUE_TABLE. Entries in this table, which are for specified URL +/// Clears LOAD_DATA_TABLE. Entries in this table, which are for specified URL /// values that come from shared memory style sheets, would otherwise persist /// until the end of the process and be reported as leaks. pub fn shutdown() { - URL_VALUE_TABLE.write().unwrap().clear(); -} - -impl Parse for SpecifiedUrl { - fn parse<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - CssUrl::parse(context, input).map(Self::from_css_url) - } -} - -impl PartialEq for SpecifiedUrl { - fn eq(&self, other: &Self) -> bool { - self.url.eq(&other.url) - } -} - -impl Eq for SpecifiedUrl {} - -impl MallocSizeOf for SpecifiedUrl { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - let mut n = self.url.size_of(ops); - // Although this is a RefPtr, this is the primary reference because - // SpecifiedUrl is responsible for creating the url_value. So we - // measure unconditionally here. - n += unsafe { bindings::Gecko_URLValue_SizeOfIncludingThis(self.url_value_ptr()) }; - n - } + LOAD_DATA_TABLE.write().unwrap().clear(); } impl ToComputedValue for SpecifiedUrl { @@ -277,12 +256,13 @@ impl ToComputedValue for SpecifiedUrl { /// A specified image `url()` value. #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] +#[repr(C)] pub struct SpecifiedImageUrl(pub SpecifiedUrl); impl SpecifiedImageUrl { /// Parse a URL from a string value that is a valid CSS token for a URL. pub fn parse_from_string(url: String, context: &ParserContext) -> Self { - SpecifiedImageUrl(SpecifiedUrl::parse_from_string(url, context)) + SpecifiedImageUrl(SpecifiedUrl::parse_from_string(url, context, CorsMode::None)) } /// Provides an alternate method for parsing that associates the URL @@ -291,9 +271,11 @@ impl SpecifiedImageUrl { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - CssUrl::parse(context, input) - .map(SpecifiedUrl::from_css_url_with_cors_anonymous) - .map(SpecifiedImageUrl) + Ok(SpecifiedImageUrl(SpecifiedUrl::parse_with_cors_mode( + context, + input, + CorsMode::Anonymous, + )?)) } } @@ -320,59 +302,39 @@ impl ToComputedValue for SpecifiedImageUrl { } } -fn serialize_computed_url( - url_value: &URLValue, - dest: &mut CssWriter, - get_url: unsafe extern "C" fn(*const URLValue, *mut nsCString), -) -> fmt::Result -where - W: Write, -{ - dest.write_str("url(")?; - unsafe { - let mut string = nsCString::new(); - get_url(url_value, &mut string); - string.as_str_unchecked().to_css(dest)?; - } - dest.write_char(')') -} - /// The computed value of a CSS non-image `url()`. /// /// The only difference between specified and computed URLs is the /// serialization. #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)] +#[repr(C)] pub struct ComputedUrl(pub SpecifiedUrl); +impl ComputedUrl { + fn serialize_with( + &self, + function: unsafe extern "C" fn(*const Self, *mut nsCString), + dest: &mut CssWriter, + ) -> fmt::Result + where + W: Write, + { + dest.write_str("url(")?; + unsafe { + let mut string = nsCString::new(); + function(self, &mut string); + string.as_str_unchecked().to_css(dest)?; + } + dest.write_char(')') + } +} + impl ToCss for ComputedUrl { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: Write, { - self.0 - .with_url_value(|r| serialize_computed_url(r, dest, bindings::Gecko_GetComputedURLSpec)) - } -} - -impl ComputedUrl { - /// Convert from RefPtr to ComputedUrl. - pub unsafe fn from_url_value(url_value: RefPtr) -> Self { - let css_url = &*url_value.mCssUrl.mRawPtr; - let url = CssUrl(CssUrlData::as_arc(&css_url).clone_arc()); - ComputedUrl(SpecifiedUrl { - url, - url_value: Box::new(URLValueSource::URLValue(url_value)), - }) - } - - /// Clone a new, strong reference to the Gecko URLValue. - pub fn clone_url_value(&self) -> RefPtr { - self.0.clone_url_value() - } - - /// Get a raw pointer to the URLValue held by this ComputedUrl, for FFI. - pub fn url_value_ptr(&self) -> *mut URLValue { - self.0.url_value_ptr() + self.serialize_with(bindings::Gecko_GetComputedURLSpec, dest) } } @@ -380,39 +342,26 @@ impl ComputedUrl { #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)] pub struct ComputedImageUrl(pub ComputedUrl); +impl ComputedImageUrl { + /// Convert from nsStyleImageRequest to ComputedImageUrl. + pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Self { + image_request.mImageURL.clone() + } +} + impl ToCss for ComputedImageUrl { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: Write, { - (self.0).0.with_url_value(|r| { - serialize_computed_url(r, dest, bindings::Gecko_GetComputedImageURLSpec) - }) - } -} - -impl ComputedImageUrl { - /// Convert from nsStyleImageReques to ComputedImageUrl. - pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Self { - let url_value = image_request.mImageValue.to_safe(); - ComputedImageUrl(ComputedUrl::from_url_value(url_value)) - } - - /// Clone a new, strong reference to the Gecko URLValue. - pub fn clone_url_value(&self) -> RefPtr { - self.0.clone_url_value() - } - - /// Get a raw pointer to the URLValue held by this ComputedImageUrl, for FFI. - pub fn url_value_ptr(&self) -> *mut URLValue { - self.0.url_value_ptr() + self.0.serialize_with(bindings::Gecko_GetComputedImageURLSpec, dest) } } lazy_static! { - /// A table mapping CssUrlData objects to their lazily created Gecko - /// URLValue objects. - static ref URL_VALUE_TABLE: RwLock>> = { + /// A table mapping CssUrlData objects to their lazily created LoadData + /// objects. + static ref LOAD_DATA_TABLE: RwLock>> = { Default::default() }; } diff --git a/components/style/gecko_bindings/sugar/refptr.rs b/components/style/gecko_bindings/sugar/refptr.rs index 90cc5284bc4..c5246733976 100644 --- a/components/style/gecko_bindings/sugar/refptr.rs +++ b/components/style/gecko_bindings/sugar/refptr.rs @@ -63,15 +63,25 @@ impl RefPtr { } } + /// Returns whether the current pointer is null. + pub fn is_null(&self) -> bool { + self.ptr.is_null() + } + + /// Returns a null pointer. + pub fn null() -> Self { + Self { + ptr: ptr::null_mut(), + _marker: PhantomData, + } + } + /// Create a new RefPtr from a pointer obtained from FFI. /// - /// The pointer must be valid and non null. - /// /// This method calls addref() internally pub unsafe fn new(ptr: *mut T) -> Self { - debug_assert!(!ptr.is_null()); let ret = RefPtr { - ptr: ptr, + ptr, _marker: PhantomData, }; ret.addref(); @@ -97,8 +107,10 @@ impl RefPtr { /// Addref the inner data, obviously leaky on its own. pub fn addref(&self) { - unsafe { - (*self.ptr).addref(); + if !self.ptr.is_null() { + unsafe { + (*self.ptr).addref(); + } } } @@ -106,7 +118,9 @@ impl RefPtr { /// /// Call only when the data actually needs releasing. pub unsafe fn release(&self) { - (*self.ptr).release(); + if !self.ptr.is_null() { + (*self.ptr).release(); + } } } @@ -130,6 +144,7 @@ impl UniqueRefPtr { impl Deref for RefPtr { type Target = T; fn deref(&self) -> &T { + debug_assert!(!self.ptr.is_null()); unsafe { &*self.ptr } } } @@ -152,7 +167,6 @@ impl structs::RefPtr { /// /// Must be called on a valid, non-null structs::RefPtr. pub unsafe fn to_safe(&self) -> RefPtr { - debug_assert!(!self.mRawPtr.is_null()); let r = RefPtr { ptr: self.mRawPtr, _marker: PhantomData, @@ -290,9 +304,9 @@ impl_threadsafe_refcount!( bindings::Gecko_ReleaseURLExtraDataArbitraryThread ); impl_threadsafe_refcount!( - structs::mozilla::css::URLValue, - bindings::Gecko_AddRefCSSURLValueArbitraryThread, - bindings::Gecko_ReleaseCSSURLValueArbitraryThread + structs::nsIURI, + bindings::Gecko_AddRefnsIURIArbitraryThread, + bindings::Gecko_ReleasensIURIArbitraryThread ); impl_threadsafe_refcount!( structs::mozilla::css::GridTemplateAreasValue, diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index dd5bcf2febf..45e3124c858 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -278,7 +278,7 @@ impl ComputedValuesInner { #[allow(non_snake_case)] pub fn has_moz_binding(&self) -> bool { - !self.get_box().gecko.mBinding.mRawPtr.is_null() + !self.get_box().gecko.mBinding.is_none() } } @@ -550,7 +550,7 @@ def set_gecko_property(ffi_name, expr): unsafe { bindings::Gecko_nsStyleSVGPaint_SetURLValue( paint, - url.url_value_ptr(), + &url ) } } @@ -591,7 +591,6 @@ def set_gecko_property(ffi_name, expr): #[allow(non_snake_case)] pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { - use crate::values::computed::url::ComputedUrl; use crate::values::generics::svg::{SVGPaint, SVGPaintKind}; use self::structs::nsStyleSVGPaintType; use self::structs::nsStyleSVGFallbackType; @@ -613,8 +612,7 @@ def set_gecko_property(ffi_name, expr): nsStyleSVGPaintType::eStyleSVGPaintType_ContextStroke => SVGPaintKind::ContextStroke, nsStyleSVGPaintType::eStyleSVGPaintType_Server => { SVGPaintKind::PaintServer(unsafe { - let url = RefPtr::new(*paint.mPaint.mPaintServer.as_ref()); - ComputedUrl::from_url_value(url) + paint.mPaint.mPaintServer.as_ref().clone() }) } nsStyleSVGPaintType::eStyleSVGPaintType_Color => { @@ -735,45 +733,6 @@ def set_gecko_property(ffi_name, expr): } -<%def name="impl_css_url(ident, gecko_ffi_name)"> - #[allow(non_snake_case)] - pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { - match v { - UrlOrNone::Url(ref url) => { - self.gecko.${gecko_ffi_name}.set_move(url.clone_url_value()) - } - UrlOrNone::None => { - unsafe { - self.gecko.${gecko_ffi_name}.clear(); - } - } - } - } - #[allow(non_snake_case)] - pub fn copy_${ident}_from(&mut self, other: &Self) { - unsafe { - self.gecko.${gecko_ffi_name}.set(&other.gecko.${gecko_ffi_name}); - } - } - #[allow(non_snake_case)] - pub fn reset_${ident}(&mut self, other: &Self) { - self.copy_${ident}_from(other) - } - - #[allow(non_snake_case)] - pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { - use crate::values::computed::url::ComputedUrl; - - if self.gecko.${gecko_ffi_name}.mRawPtr.is_null() { - return UrlOrNone::none() - } - - UrlOrNone::Url(unsafe { - ComputedUrl::from_url_value(self.gecko.${gecko_ffi_name}.to_safe()) - }) - } - - <%def name="impl_logical(name, **kwargs)"> ${helpers.logical_setter(name)} @@ -879,7 +838,6 @@ impl Clone for ${style_struct.gecko_struct_name} { "SVGOpacity": impl_svg_opacity, "SVGPaint": impl_svg_paint, "SVGWidth": impl_svg_length, - "url::UrlOrNone": impl_css_url, } def longhand_method(longhand): @@ -2164,8 +2122,7 @@ fn static_assert() { animation-iteration-count animation-timing-function clear transition-duration transition-delay transition-timing-function transition-property - transform-style -moz-binding shape-outside - -webkit-line-clamp""" %> + transform-style shape-outside -webkit-line-clamp""" %> <%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}"> #[inline] pub fn set_display(&mut self, v: longhands::display::computed_value::T) { @@ -2205,7 +2162,6 @@ fn static_assert() { gecko_inexhaustive=True, ) %> ${impl_keyword('clear', 'mBreakType', clear_keyword)} - ${impl_css_url('_moz_binding', 'mBinding')} ${impl_transition_time_value('delay', 'Delay')} ${impl_transition_time_value('duration', 'Duration')} ${impl_transition_timing_function()} @@ -2834,10 +2790,7 @@ fn static_assert() { } UrlOrNone::Url(ref url) => { unsafe { - Gecko_SetListStyleImageImageValue( - &mut *self.gecko, - url.url_value_ptr(), - ); + Gecko_SetListStyleImageImageValue(&mut *self.gecko, url); } } } @@ -3145,7 +3098,7 @@ fn static_assert() { }, Url(ref url) => { unsafe { - bindings::Gecko_nsStyleFilter_SetURLValue(gecko_filter, url.url_value_ptr()); + bindings::Gecko_nsStyleFilter_SetURLValue(gecko_filter, url); } }, } @@ -3164,7 +3117,6 @@ fn static_assert() { pub fn clone_filter(&self) -> longhands::filter::computed_value::T { use crate::values::generics::effects::Filter; - use crate::values::computed::url::ComputedUrl; use crate::gecko_bindings::structs::NS_STYLE_FILTER_BLUR; use crate::gecko_bindings::structs::NS_STYLE_FILTER_BRIGHTNESS; use crate::gecko_bindings::structs::NS_STYLE_FILTER_CONTRAST; @@ -3205,8 +3157,7 @@ fn static_assert() { }, NS_STYLE_FILTER_URL => { Filter::Url(unsafe { - let url = RefPtr::new(*filter.__bindgen_anon_1.mURL.as_ref()); - ComputedUrl::from_url_value(url) + filter.__bindgen_anon_1.mURL.as_ref().clone() }) } _ => unreachable!("Unknown filter function?"), @@ -3550,7 +3501,7 @@ clip-path unsafe { Gecko_SetCursorImageValue( &mut self.gecko.mCursorImages[i], - v.images[i].url.url_value_ptr(), + &v.images[i].url ); } @@ -3769,7 +3720,7 @@ clip-path unsafe { bindings::Gecko_SetContentDataImageValue( &mut self.gecko.mContents[i], - url.url_value_ptr(), + url, ) } } diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index 7bfd1fa67d5..f37d5968b24 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -644,7 +644,6 @@ ${helpers.predefined_type( "basic_shape::FloatAreaShape", "generics::basic_shape::ShapeSource::None", products="gecko", - boxed=True, animation_value_type="basic_shape::FloatAreaShape", flags="APPLIES_TO_FIRST_LETTER", spec="https://drafts.csswg.org/css-shapes/#shape-outside-property", diff --git a/components/style/stylesheets/mod.rs b/components/style/stylesheets/mod.rs index 16842021e8d..205da1f0645 100644 --- a/components/style/stylesheets/mod.rs +++ b/components/style/stylesheets/mod.rs @@ -63,9 +63,15 @@ pub use self::stylesheet::{StylesheetContents, StylesheetInDocument, UserAgentSt pub use self::supports_rule::SupportsRule; pub use self::viewport_rule::ViewportRule; -/// Extra data that the backend may need to resolve url values. -#[cfg(not(feature = "gecko"))] -pub type UrlExtraData = ::servo_url::ServoUrl; +/// The CORS mode used for a CSS load. +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, ToShmem)] +pub enum CorsMode { + /// No CORS mode, so cross-origin loads can be done. + None, + /// Anonymous CORS request. + Anonymous, +} /// Extra data that the backend may need to resolve url values. /// @@ -82,8 +88,13 @@ pub type UrlExtraData = ::servo_url::ServoUrl; /// `from_ptr_ref` can work. #[cfg(feature = "gecko")] #[derive(PartialEq)] +#[repr(C)] pub struct UrlExtraData(usize); +/// Extra data that the backend may need to resolve url values. +#[cfg(not(feature = "gecko"))] +pub type UrlExtraData = ::servo_url::ServoUrl; + #[cfg(feature = "gecko")] impl Clone for UrlExtraData { fn clone(&self) -> UrlExtraData { diff --git a/components/style/stylesheets/rule_parser.rs b/components/style/stylesheets/rule_parser.rs index a3ec24174ed..6b070317610 100644 --- a/components/style/stylesheets/rule_parser.rs +++ b/components/style/stylesheets/rule_parser.rs @@ -20,7 +20,7 @@ use crate::stylesheets::stylesheet::Namespaces; use crate::stylesheets::supports_rule::SupportsCondition; use crate::stylesheets::viewport_rule; use crate::stylesheets::{CssRule, CssRuleType, CssRules, RulesMutateError, StylesheetLoader}; -use crate::stylesheets::{DocumentRule, FontFeatureValuesRule, KeyframesRule, MediaRule}; +use crate::stylesheets::{CorsMode, DocumentRule, FontFeatureValuesRule, KeyframesRule, MediaRule}; use crate::stylesheets::{NamespaceRule, PageRule, StyleRule, SupportsRule, ViewportRule}; use crate::values::computed::font::FamilyName; use crate::values::{CssUrl, CustomIdent, KeyframesName}; @@ -197,7 +197,7 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { } let url_string = input.expect_url_or_string()?.as_ref().to_owned(); - let url = CssUrl::parse_from_string(url_string, &self.context); + let url = CssUrl::parse_from_string(url_string, &self.context, CorsMode::None); let media = MediaList::parse(&self.context, input); let media = Arc::new(self.shared_lock.wrap(media)); diff --git a/components/style/values/generics/url.rs b/components/style/values/generics/url.rs index 9dbed038630..1f271033036 100644 --- a/components/style/values/generics/url.rs +++ b/components/style/values/generics/url.rs @@ -5,6 +5,8 @@ //! Generic types for url properties. /// An image url or none, used for example in list-style-image +/// +/// cbindgen:derive-tagged-enum-copy-constructor=true #[derive( Animate, Clone, @@ -21,16 +23,27 @@ ToResolvedValue, ToShmem, )] -pub enum UrlOrNone { +#[repr(C, u8)] +pub enum GenericUrlOrNone { /// `none` None, - /// `A URL` - Url(Url), + /// A URL. + Url(U), } +pub use self::GenericUrlOrNone as UrlOrNone; + impl UrlOrNone { /// Initial "none" value for properties such as `list-style-image` pub fn none() -> Self { UrlOrNone::None } + + /// Returns whether the value is `none`. + pub fn is_none(&self) -> bool { + match *self { + UrlOrNone::None => true, + UrlOrNone::Url(..) => false, + } + } } diff --git a/components/style/values/specified/url.rs b/components/style/values/specified/url.rs index ecf0eaae00c..b0a69b362d8 100644 --- a/components/style/values/specified/url.rs +++ b/components/style/values/specified/url.rs @@ -4,7 +4,7 @@ //! Common handling for the specified value CSS url() values. -use crate::values::generics::url::UrlOrNone as GenericUrlOrNone; +use crate::values::generics::url::GenericUrlOrNone; #[cfg(feature = "gecko")] pub use crate::gecko::url::{SpecifiedImageUrl, SpecifiedUrl};