style: Make css::URLValue hold on to a CssUrlData, not just its serialization.

Differential Revision: https://phabricator.services.mozilla.com/D8874
This commit is contained in:
Cameron McCormack 2018-10-17 12:36:49 +00:00 committed by Emilio Cobos Álvarez
parent ecb9de4acd
commit c4491ea39d
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 35 additions and 42 deletions

View file

@ -8,6 +8,7 @@
#![allow(non_snake_case, missing_docs)] #![allow(non_snake_case, missing_docs)]
use gecko::url::CssUrlData;
use gecko_bindings::bindings::RawServoCounterStyleRule; use gecko_bindings::bindings::RawServoCounterStyleRule;
use gecko_bindings::bindings::RawServoFontFeatureValuesRule; use gecko_bindings::bindings::RawServoFontFeatureValuesRule;
use gecko_bindings::bindings::RawServoImportRule; use gecko_bindings::bindings::RawServoImportRule;
@ -27,6 +28,7 @@ use gecko_bindings::structs::RawServoFontFaceRule;
use gecko_bindings::structs::RawServoMediaList; use gecko_bindings::structs::RawServoMediaList;
use gecko_bindings::structs::RawServoStyleRule; use gecko_bindings::structs::RawServoStyleRule;
use gecko_bindings::structs::RawServoStyleSheetContents; use gecko_bindings::structs::RawServoStyleSheetContents;
use gecko_bindings::structs::RawServoCssUrlData;
use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI, Strong}; use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI, Strong};
use media_queries::MediaList; use media_queries::MediaList;
use properties::{ComputedValues, PropertyDeclarationBlock}; use properties::{ComputedValues, PropertyDeclarationBlock};
@ -110,6 +112,9 @@ impl_arc_ffi!(Locked<FontFaceRule> => RawServoFontFaceRule
impl_arc_ffi!(Locked<CounterStyleRule> => RawServoCounterStyleRule impl_arc_ffi!(Locked<CounterStyleRule> => RawServoCounterStyleRule
[Servo_CounterStyleRule_AddRef, Servo_CounterStyleRule_Release]); [Servo_CounterStyleRule_AddRef, Servo_CounterStyleRule_Release]);
impl_arc_ffi!(CssUrlData => RawServoCssUrlData
[Servo_CssUrlData_AddRef, Servo_CssUrlData_Release]);
// RuleNode is a Arc-like type but it does not use Arc. // RuleNode is a Arc-like type but it does not use Arc.
impl StrongRuleNode { impl StrongRuleNode {

View file

@ -6,17 +6,16 @@
use cssparser::Parser; use cssparser::Parser;
use gecko_bindings::bindings; use gecko_bindings::bindings;
use gecko_bindings::structs::ServoBundledURI; use gecko_bindings::structs::root::nsStyleImageRequest;
use gecko_bindings::structs::root::{RustString, nsStyleImageRequest};
use gecko_bindings::structs::root::mozilla::CORSMode; use gecko_bindings::structs::root::mozilla::CORSMode;
use gecko_bindings::structs::root::mozilla::css::URLValue; use gecko_bindings::structs::root::mozilla::css::URLValue;
use gecko_bindings::sugar::ownership::{HasArcFFI, FFIArcHelpers};
use gecko_bindings::sugar::refptr::RefPtr; use gecko_bindings::sugar::refptr::RefPtr;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use nsstring::nsCString; use nsstring::nsCString;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use servo_arc::{Arc, RawOffsetArc}; use servo_arc::Arc;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::mem;
use style_traits::{CssWriter, ParseError, ToCss}; use style_traits::{CssWriter, ParseError, ToCss};
use stylesheets::UrlExtraData; use stylesheets::UrlExtraData;
use values::computed::{Context, ToComputedValue}; use values::computed::{Context, ToComputedValue};
@ -24,12 +23,13 @@ use values::computed::{Context, ToComputedValue};
/// A CSS url() value for gecko. /// A CSS url() value for gecko.
#[css(function = "url")] #[css(function = "url")]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)] #[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
pub struct CssUrl { pub struct CssUrl(pub Arc<CssUrlData>);
/// Data shared between CssUrls.
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
pub struct CssUrlData {
/// The URL in unresolved string form. /// The URL in unresolved string form.
/// serialization: String,
/// Refcounted since cloning this should be cheap and data: uris can be
/// really large.
serialization: Arc<String>,
/// The URL extra data. /// The URL extra data.
#[css(skip)] #[css(skip)]
@ -39,10 +39,10 @@ pub struct CssUrl {
impl CssUrl { impl CssUrl {
/// Parse a URL from a string value that is a valid CSS token for a URL. /// 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) -> Self {
CssUrl { CssUrl(Arc::new(CssUrlData {
serialization: Arc::new(url), serialization: url,
extra_data: context.url_data.clone(), extra_data: context.url_data.clone(),
} }))
} }
/// Returns true if the URL is definitely invalid. We don't eagerly resolve /// Returns true if the URL is definitely invalid. We don't eagerly resolve
@ -52,44 +52,26 @@ impl CssUrl {
false false
} }
/// Convert from URLValue to CssUrl.
unsafe fn from_url_value(url: &URLValue) -> Self {
let arc_type = &url.mString as *const _ as *const RawOffsetArc<String>;
CssUrl {
serialization: Arc::from_raw_offset((*arc_type).clone()),
extra_data: UrlExtraData(url.mExtraData.to_safe()),
}
}
/// Returns true if this URL looks like a fragment. /// Returns true if this URL looks like a fragment.
/// See https://drafts.csswg.org/css-values/#local-urls /// See https://drafts.csswg.org/css-values/#local-urls
pub fn is_fragment(&self) -> bool { pub fn is_fragment(&self) -> bool {
self.as_str().chars().next().map_or(false, |c| c == '#') self.as_str().chars().next().map_or(false, |c| c == '#')
} }
/// Return the unresolved url as string, or the empty string if it's
/// invalid.
#[inline]
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
impl CssUrlData {
/// Return the unresolved url as string, or the empty string if it's /// Return the unresolved url as string, or the empty string if it's
/// invalid. /// invalid.
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> &str {
&*self.serialization &*self.serialization
} }
/// Little helper for Gecko's ffi.
pub fn as_slice_components(&self) -> (*const u8, usize) {
(
self.serialization.as_str().as_ptr(),
self.serialization.as_str().len(),
)
}
/// Create a bundled URI suitable for sending to Gecko
/// to be constructed into a css::URLValue
pub fn for_ffi(&self) -> ServoBundledURI {
let arc_offset = Arc::into_raw_offset(self.serialization.clone());
ServoBundledURI {
mURLString: unsafe { mem::transmute::<_, RawOffsetArc<RustString>>(arc_offset) },
mExtraData: self.extra_data.0.get(),
}
}
} }
impl Parse for CssUrl { impl Parse for CssUrl {
@ -134,7 +116,11 @@ impl SpecifiedUrl {
fn from_css_url_with_cors(url: CssUrl, cors: CORSMode) -> Self { fn from_css_url_with_cors(url: CssUrl, cors: CORSMode) -> Self {
let url_value = unsafe { let url_value = unsafe {
let ptr = bindings::Gecko_URLValue_Create(url.for_ffi(), cors); let ptr = bindings::Gecko_URLValue_Create(
url.0.clone().into_strong(),
url.0.extra_data.0.get(),
cors,
);
// We do not expect Gecko_URLValue_Create returns null. // We do not expect Gecko_URLValue_Create returns null.
debug_assert!(!ptr.is_null()); debug_assert!(!ptr.is_null());
RefPtr::from_addrefed(ptr) RefPtr::from_addrefed(ptr)
@ -280,7 +266,8 @@ impl ToCss for ComputedUrl {
impl ComputedUrl { impl ComputedUrl {
/// Convert from RefPtr<URLValue> to ComputedUrl. /// Convert from RefPtr<URLValue> to ComputedUrl.
pub unsafe fn from_url_value(url_value: RefPtr<URLValue>) -> Self { pub unsafe fn from_url_value(url_value: RefPtr<URLValue>) -> Self {
let url = CssUrl::from_url_value(&*url_value); let css_url = &*url_value.mCssUrl.mRawPtr;
let url = CssUrl(CssUrlData::as_arc(&css_url).clone_arc());
ComputedUrl(SpecifiedUrl { url, url_value }) ComputedUrl(SpecifiedUrl { url, url_value })
} }
@ -311,7 +298,8 @@ impl ComputedImageUrl {
/// Convert from nsStyleImageReques to ComputedImageUrl. /// Convert from nsStyleImageReques to ComputedImageUrl.
pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Self { pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Self {
let url_value = image_request.mImageValue.to_safe(); let url_value = image_request.mImageValue.to_safe();
let url = CssUrl::from_url_value(&*url_value); let css_url = &*url_value.mCssUrl.mRawPtr;
let url = CssUrl(CssUrlData::as_arc(&css_url).clone_arc());
ComputedImageUrl(SpecifiedImageUrl(SpecifiedUrl { url, url_value })) ComputedImageUrl(SpecifiedImageUrl(SpecifiedUrl { url, url_value }))
} }