Split CssUrl from SpecifiedUrl for non-value URLs.

This commit is contained in:
Xidorn Quan 2018-03-08 21:31:09 +11:00
parent 0090fbb3c8
commit fa5d76c395
10 changed files with 86 additions and 47 deletions

View file

@ -34,7 +34,7 @@ use style::shared_lock::{Locked, SharedRwLock};
use style::stylesheets::{CssRules, ImportRule, Namespaces, Stylesheet, StylesheetContents, Origin}; use style::stylesheets::{CssRules, ImportRule, Namespaces, Stylesheet, StylesheetContents, Origin};
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader; use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::stylesheets::import_rule::ImportSheet; use style::stylesheets::import_rule::ImportSheet;
use style::values::specified::url::SpecifiedUrl; use style::values::CssUrl;
pub trait StylesheetOwner { pub trait StylesheetOwner {
/// Returns whether this element was inserted by the parser (i.e., it should /// Returns whether this element was inserted by the parser (i.e., it should
@ -276,7 +276,7 @@ impl<'a> StyleStylesheetLoader for StylesheetLoader<'a> {
/// the constructed `@import` rule. /// the constructed `@import` rule.
fn request_stylesheet( fn request_stylesheet(
&self, &self,
url: SpecifiedUrl, url: CssUrl,
source_location: SourceLocation, source_location: SourceLocation,
context: &ParserContext, context: &ParserContext,
lock: &SharedRwLock, lock: &SharedRwLock,

View file

@ -17,10 +17,10 @@ use servo_arc::{Arc, RawOffsetArc};
use std::mem; use std::mem;
use style_traits::ParseError; use style_traits::ParseError;
/// A specified url() value for gecko. Gecko does not eagerly resolve SpecifiedUrls. /// A CSS url() value for gecko.
#[css(function = "url")] #[css(function = "url")]
#[derive(Clone, Debug, PartialEq, ToCss)] #[derive(Clone, Debug, PartialEq, ToCss)]
pub struct SpecifiedUrl { pub struct CssUrl {
/// The URL in unresolved string form. /// The URL in unresolved string form.
/// ///
/// Refcounted since cloning this should be cheap and data: uris can be /// Refcounted since cloning this should be cheap and data: uris can be
@ -31,9 +31,8 @@ pub struct SpecifiedUrl {
#[css(skip)] #[css(skip)]
pub extra_data: RefPtr<URLExtraData>, pub extra_data: RefPtr<URLExtraData>,
} }
trivial_to_computed_value!(SpecifiedUrl);
impl SpecifiedUrl { impl CssUrl {
/// Try to parse a URL from a string value that is a valid CSS token for a /// Try to parse a URL from a string value that is a valid CSS token for a
/// URL. /// URL.
/// ///
@ -41,7 +40,7 @@ impl SpecifiedUrl {
pub fn parse_from_string<'a>(url: String, pub fn parse_from_string<'a>(url: String,
context: &ParserContext) context: &ParserContext)
-> Result<Self, ParseError<'a>> { -> Result<Self, ParseError<'a>> {
Ok(SpecifiedUrl { Ok(CssUrl {
serialization: Arc::new(url), serialization: Arc::new(url),
extra_data: context.url_data.clone(), extra_data: context.url_data.clone(),
}) })
@ -55,9 +54,8 @@ impl SpecifiedUrl {
} }
/// Convert from URLValueData to SpecifiedUrl. /// Convert from URLValueData to SpecifiedUrl.
pub unsafe fn from_url_value_data(url: &URLValueData) unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
-> Result<SpecifiedUrl, ()> { Ok(CssUrl {
Ok(SpecifiedUrl {
serialization: if url.mUsingRustString { serialization: if url.mUsingRustString {
let arc_type = url.mStrings.mRustString.as_ref() let arc_type = url.mStrings.mRustString.as_ref()
as *const _ as as *const _ as
@ -102,16 +100,16 @@ impl SpecifiedUrl {
} }
} }
impl Parse for SpecifiedUrl { impl Parse for CssUrl {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let url = input.expect_url()?; let url = input.expect_url()?;
Self::parse_from_string(url.as_ref().to_owned(), context) Self::parse_from_string(url.as_ref().to_owned(), context)
} }
} }
impl Eq for SpecifiedUrl {} impl Eq for CssUrl {}
impl MallocSizeOf for SpecifiedUrl { impl MallocSizeOf for CssUrl {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
// XXX: measure `serialization` once bug 1397971 lands // XXX: measure `serialization` once bug 1397971 lands
@ -122,13 +120,47 @@ impl MallocSizeOf for SpecifiedUrl {
} }
} }
/// A specified url() value for general usage.
#[derive(Clone, Debug, PartialEq, Eq, MallocSizeOf, ToCss)]
pub struct SpecifiedUrl {
/// The specified url value.
pub url: CssUrl,
}
trivial_to_computed_value!(SpecifiedUrl);
impl SpecifiedUrl {
fn from_css_url(url: CssUrl) -> Self {
SpecifiedUrl { url }
}
/// Convert from URLValueData to SpecifiedUrl.
pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
CssUrl::from_url_value_data(url).map(Self::from_css_url)
}
/// Create a bundled URI suitable for sending to Gecko
/// to be constructed into a css::URLValue.
///
/// XXX This is added temporially. It would be removed once we store
/// URLValue in SpecifiedUrl directly.
pub fn for_ffi(&self) -> ServoBundledURI {
self.url.for_ffi()
}
}
impl Parse for SpecifiedUrl {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
CssUrl::parse(context, input).map(Self::from_css_url)
}
}
/// A specified url() value for image. /// A specified url() value for image.
/// ///
/// This exists so that we can construct `ImageValue` and reuse it. /// This exists so that we can construct `ImageValue` and reuse it.
#[derive(Clone, Debug, ToCss)] #[derive(Clone, Debug, ToCss)]
pub struct SpecifiedImageUrl { pub struct SpecifiedImageUrl {
/// The specified url value. /// The specified url value.
pub url: SpecifiedUrl, pub url: CssUrl,
/// Gecko's ImageValue so that we can reuse it while rematching a /// Gecko's ImageValue so that we can reuse it while rematching a
/// property with this specified value. /// property with this specified value.
#[css(skip)] #[css(skip)]
@ -137,7 +169,7 @@ pub struct SpecifiedImageUrl {
trivial_to_computed_value!(SpecifiedImageUrl); trivial_to_computed_value!(SpecifiedImageUrl);
impl SpecifiedImageUrl { impl SpecifiedImageUrl {
fn from_specified_url(url: SpecifiedUrl) -> Self { fn from_css_url(url: CssUrl) -> Self {
let image_value = unsafe { let image_value = unsafe {
let ptr = bindings::Gecko_ImageValue_Create(url.for_ffi()); let ptr = bindings::Gecko_ImageValue_Create(url.for_ffi());
// We do not expect Gecko_ImageValue_Create returns null. // We do not expect Gecko_ImageValue_Create returns null.
@ -152,12 +184,12 @@ impl SpecifiedImageUrl {
url: String, url: String,
context: &ParserContext context: &ParserContext
) -> Result<Self, ParseError<'a>> { ) -> Result<Self, ParseError<'a>> {
SpecifiedUrl::parse_from_string(url, context).map(Self::from_specified_url) CssUrl::parse_from_string(url, context).map(Self::from_css_url)
} }
/// Convert from URLValueData to SpecifiedUrl. /// Convert from URLValueData to SpecifiedUrl.
pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> { pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
SpecifiedUrl::from_url_value_data(url).map(Self::from_specified_url) CssUrl::from_url_value_data(url).map(Self::from_css_url)
} }
/// Convert from nsStyleImageRequest to SpecifiedUrl. /// Convert from nsStyleImageRequest to SpecifiedUrl.
@ -174,7 +206,7 @@ impl SpecifiedImageUrl {
impl Parse for SpecifiedImageUrl { impl Parse for SpecifiedImageUrl {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
SpecifiedUrl::parse(context, input).map(Self::from_specified_url) CssUrl::parse(context, input).map(Self::from_css_url)
} }
} }

View file

@ -15,7 +15,7 @@ use std::sync::Arc;
use style_traits::{CssWriter, ParseError, ToCss}; use style_traits::{CssWriter, ParseError, ToCss};
use values::computed::{Context, ToComputedValue}; use values::computed::{Context, ToComputedValue};
/// A specified url() value for servo. /// A CSS url() value for servo.
/// ///
/// Servo eagerly resolves SpecifiedUrls, which it can then take advantage of /// Servo eagerly resolves SpecifiedUrls, which it can then take advantage of
/// when computing values. In contrast, Gecko uses a different URL backend, so /// when computing values. In contrast, Gecko uses a different URL backend, so
@ -24,7 +24,7 @@ use values::computed::{Context, ToComputedValue};
/// However, this approach is still not necessarily optimal: See /// However, this approach is still not necessarily optimal: See
/// <https://bugzilla.mozilla.org/show_bug.cgi?id=1347435#c6> /// <https://bugzilla.mozilla.org/show_bug.cgi?id=1347435#c6>
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)] #[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
pub struct SpecifiedUrl { pub struct CssUrl {
/// The original URI. This might be optional since we may insert computed /// The original URI. This might be optional since we may insert computed
/// values of images into the cascade directly, and we don't bother to /// values of images into the cascade directly, and we don't bother to
/// convert their serialization. /// convert their serialization.
@ -38,7 +38,7 @@ pub struct SpecifiedUrl {
resolved: Option<ServoUrl>, resolved: Option<ServoUrl>,
} }
impl SpecifiedUrl { impl CssUrl {
/// Try to parse a URL from a string value that is a valid CSS token for a /// Try to parse a URL from a string value that is a valid CSS token for a
/// URL. Never fails - the API is only fallible to be compatible with the /// URL. Never fails - the API is only fallible to be compatible with the
/// gecko version. /// gecko version.
@ -47,7 +47,7 @@ impl SpecifiedUrl {
-> Result<Self, ParseError<'a>> { -> Result<Self, ParseError<'a>> {
let serialization = Arc::new(url); let serialization = Arc::new(url);
let resolved = context.url_data.join(&serialization).ok(); let resolved = context.url_data.join(&serialization).ok();
Ok(SpecifiedUrl { Ok(CssUrl {
original: Some(serialization), original: Some(serialization),
resolved: resolved, resolved: resolved,
}) })
@ -88,7 +88,7 @@ impl SpecifiedUrl {
/// Creates an already specified url value from an already resolved URL /// Creates an already specified url value from an already resolved URL
/// for insertion in the cascade. /// for insertion in the cascade.
pub fn for_cascade(url: ServoUrl) -> Self { pub fn for_cascade(url: ServoUrl) -> Self {
SpecifiedUrl { CssUrl {
original: None, original: None,
resolved: Some(url), resolved: Some(url),
} }
@ -96,21 +96,21 @@ impl SpecifiedUrl {
/// Gets a new url from a string for unit tests. /// Gets a new url from a string for unit tests.
pub fn new_for_testing(url: &str) -> Self { pub fn new_for_testing(url: &str) -> Self {
SpecifiedUrl { CssUrl {
original: Some(Arc::new(url.into())), original: Some(Arc::new(url.into())),
resolved: ServoUrl::parse(url).ok(), resolved: ServoUrl::parse(url).ok(),
} }
} }
} }
impl Parse for SpecifiedUrl { impl Parse for CssUrl {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
let url = input.expect_url()?; let url = input.expect_url()?;
Self::parse_from_string(url.as_ref().to_owned(), context) Self::parse_from_string(url.as_ref().to_owned(), context)
} }
} }
impl PartialEq for SpecifiedUrl { impl PartialEq for CssUrl {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
// TODO(emilio): maybe we care about equality of the specified values if // TODO(emilio): maybe we care about equality of the specified values if
// present? Seems not. // present? Seems not.
@ -118,9 +118,9 @@ impl PartialEq for SpecifiedUrl {
} }
} }
impl Eq for SpecifiedUrl {} impl Eq for CssUrl {}
impl ToCss for SpecifiedUrl { impl ToCss for CssUrl {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where where
W: Write, W: Write,
@ -142,6 +142,9 @@ impl ToCss for SpecifiedUrl {
} }
} }
/// A specified url() value for servo.
pub type SpecifiedUrl = CssUrl;
impl ToComputedValue for SpecifiedUrl { impl ToComputedValue for SpecifiedUrl {
type ComputedValue = ComputedUrl; type ComputedValue = ComputedUrl;
@ -174,7 +177,7 @@ impl ToComputedValue for SpecifiedUrl {
} }
/// A specified image url() value for servo. /// A specified image url() value for servo.
pub type SpecifiedImageUrl = SpecifiedUrl; pub type SpecifiedImageUrl = CssUrl;
/// The computed value of a CSS `url()`, resolved relative to the stylesheet URL. /// The computed value of a CSS `url()`, resolved relative to the stylesheet URL.
#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] #[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]

View file

@ -17,7 +17,7 @@ use std::fmt::{self, Write};
use str::CssStringWriter; use str::CssStringWriter;
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use stylesheets::CssRules; use stylesheets::CssRules;
use values::specified::url::SpecifiedUrl; use values::CssUrl;
#[derive(Debug)] #[derive(Debug)]
/// A @-moz-document rule /// A @-moz-document rule
@ -75,7 +75,7 @@ impl DeepCloneWithLock for DocumentRule {
pub enum UrlMatchingFunction { pub enum UrlMatchingFunction {
/// Exact URL matching function. It evaluates to true whenever the /// Exact URL matching function. It evaluates to true whenever the
/// URL of the document being styled is exactly the URL given. /// URL of the document being styled is exactly the URL given.
Url(SpecifiedUrl), Url(CssUrl),
/// URL prefix matching function. It evaluates to true whenever the /// URL prefix matching function. It evaluates to true whenever the
/// URL of the document being styled has the argument to the /// URL of the document being styled has the argument to the
/// function as an initial substring (which is true when the two /// function as an initial substring (which is true when the two
@ -130,7 +130,7 @@ impl UrlMatchingFunction {
input.parse_nested_block(|input| { input.parse_nested_block(|input| {
Ok(UrlMatchingFunction::Regexp(input.expect_string()?.as_ref().to_owned())) Ok(UrlMatchingFunction::Regexp(input.expect_string()?.as_ref().to_owned()))
}) })
} else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) { } else if let Ok(url) = input.try(|input| CssUrl::parse(context, input)) {
Ok(UrlMatchingFunction::Url(url)) Ok(UrlMatchingFunction::Url(url))
} else { } else {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))

View file

@ -13,7 +13,7 @@ use std::fmt::{self, Write};
use str::CssStringWriter; use str::CssStringWriter;
use style_traits::{CssWriter, ToCss}; use style_traits::{CssWriter, ToCss};
use stylesheets::{StylesheetContents, StylesheetInDocument}; use stylesheets::{StylesheetContents, StylesheetInDocument};
use values::specified::url::SpecifiedUrl; use values::CssUrl;
/// A sheet that is held from an import rule. /// A sheet that is held from an import rule.
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
@ -80,7 +80,7 @@ impl DeepCloneWithLock for ImportSheet {
#[derive(Debug)] #[derive(Debug)]
pub struct ImportRule { pub struct ImportRule {
/// The `<url>` this `@import` rule is loading. /// The `<url>` this `@import` rule is loading.
pub url: SpecifiedUrl, pub url: CssUrl,
/// The stylesheet is always present. /// The stylesheet is always present.
/// ///

View file

@ -11,7 +11,7 @@ use parser::ParserContext;
use servo_arc::Arc; use servo_arc::Arc;
use shared_lock::{Locked, SharedRwLock}; use shared_lock::{Locked, SharedRwLock};
use stylesheets::import_rule::ImportRule; use stylesheets::import_rule::ImportRule;
use values::specified::url::SpecifiedUrl; use values::CssUrl;
/// The stylesheet loader is the abstraction used to trigger network requests /// The stylesheet loader is the abstraction used to trigger network requests
/// for `@import` rules. /// for `@import` rules.
@ -20,7 +20,7 @@ pub trait StylesheetLoader {
/// the constructed `@import` rule. /// the constructed `@import` rule.
fn request_stylesheet( fn request_stylesheet(
&self, &self,
url: SpecifiedUrl, url: CssUrl,
location: SourceLocation, location: SourceLocation,
context: &ParserContext, context: &ParserContext,
lock: &SharedRwLock, lock: &SharedRwLock,

View file

@ -28,10 +28,8 @@ use stylesheets::keyframes_rule::parse_keyframe_list;
use stylesheets::stylesheet::Namespaces; use stylesheets::stylesheet::Namespaces;
use stylesheets::supports_rule::SupportsCondition; use stylesheets::supports_rule::SupportsCondition;
use stylesheets::viewport_rule; use stylesheets::viewport_rule;
use values::CustomIdent; use values::{CssUrl, CustomIdent, KeyframesName};
use values::KeyframesName;
use values::computed::font::FamilyName; use values::computed::font::FamilyName;
use values::specified::url::SpecifiedUrl;
/// The parser for the top-level rules in a stylesheet. /// The parser for the top-level rules in a stylesheet.
pub struct TopLevelRuleParser<'a, R: 'a> { pub struct TopLevelRuleParser<'a, R: 'a> {
@ -134,7 +132,7 @@ pub enum AtRuleBlockPrelude {
/// A rule prelude for at-rule without block. /// A rule prelude for at-rule without block.
pub enum AtRuleNonBlockPrelude { pub enum AtRuleNonBlockPrelude {
/// A @import rule prelude. /// A @import rule prelude.
Import(SpecifiedUrl, Arc<Locked<MediaList>>, SourceLocation), Import(CssUrl, Arc<Locked<MediaList>>, SourceLocation),
/// A @namespace rule prelude. /// A @namespace rule prelude.
Namespace(Option<Prefix>, Namespace, SourceLocation), Namespace(Option<Prefix>, Namespace, SourceLocation),
} }
@ -174,13 +172,13 @@ impl<'a, 'i, R: ParseErrorReporter> AtRuleParser<'i> for TopLevelRuleParser<'a,
} }
let url_string = input.expect_url_or_string()?.as_ref().to_owned(); let url_string = input.expect_url_or_string()?.as_ref().to_owned();
let specified_url = SpecifiedUrl::parse_from_string(url_string, &self.context)?; let url = CssUrl::parse_from_string(url_string, &self.context)?;
let media = parse_media_query_list(&self.context, input, let media = parse_media_query_list(&self.context, input,
self.error_context.error_reporter); self.error_context.error_reporter);
let media = Arc::new(self.shared_lock.wrap(media)); let media = Arc::new(self.shared_lock.wrap(media));
let prelude = AtRuleNonBlockPrelude::Import(specified_url, media, location); let prelude = AtRuleNonBlockPrelude::Import(url, media, location);
return Ok(AtRuleType::WithoutBlock(prelude)); return Ok(AtRuleType::WithoutBlock(prelude));
}, },
"namespace" => { "namespace" => {
@ -228,12 +226,12 @@ impl<'a, 'i, R: ParseErrorReporter> AtRuleParser<'i> for TopLevelRuleParser<'a,
#[inline] #[inline]
fn rule_without_block(&mut self, prelude: AtRuleNonBlockPrelude) -> CssRule { fn rule_without_block(&mut self, prelude: AtRuleNonBlockPrelude) -> CssRule {
match prelude { match prelude {
AtRuleNonBlockPrelude::Import(specified_url, media, location) => { AtRuleNonBlockPrelude::Import(url, media, location) => {
let loader = let loader =
self.loader.expect("Expected a stylesheet loader for @import"); self.loader.expect("Expected a stylesheet loader for @import");
let import_rule = loader.request_stylesheet( let import_rule = loader.request_stylesheet(
specified_url, url,
location, location,
&self.context, &self.context,
&self.shared_lock, &self.shared_lock,

View file

@ -17,6 +17,11 @@ use std::hash;
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::distance::{ComputeSquaredDistance, SquaredDistance};
#[cfg(feature = "servo")]
pub use servo::url::CssUrl;
#[cfg(feature = "gecko")]
pub use gecko::url::CssUrl;
pub mod animated; pub mod animated;
pub mod computed; pub mod computed;
pub mod distance; pub mod distance;

View file

@ -152,7 +152,8 @@ impl Image {
/// for insertion in the cascade. /// for insertion in the cascade.
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
pub fn for_cascade(url: ServoUrl) -> Self { pub fn for_cascade(url: ServoUrl) -> Self {
GenericImage::Url(SpecifiedUrl::for_cascade(url)) use values::CssUrl;
GenericImage::Url(CssUrl::for_cascade(url))
} }
/// Parses a `-moz-element(# <element-id>)`. /// Parses a `-moz-element(# <element-id>)`.

View file

@ -13,7 +13,7 @@ use style::parser::ParserContext;
use style::shared_lock::{Locked, SharedRwLock}; use style::shared_lock::{Locked, SharedRwLock};
use style::stylesheets::{ImportRule, StylesheetLoader as StyleStylesheetLoader}; use style::stylesheets::{ImportRule, StylesheetLoader as StyleStylesheetLoader};
use style::stylesheets::import_rule::ImportSheet; use style::stylesheets::import_rule::ImportSheet;
use style::values::specified::url::SpecifiedUrl; use style::values::CssUrl;
pub struct StylesheetLoader(*mut Loader, *mut ServoStyleSheet, *mut SheetLoadData, *mut LoaderReusableStyleSheets); pub struct StylesheetLoader(*mut Loader, *mut ServoStyleSheet, *mut SheetLoadData, *mut LoaderReusableStyleSheets);
@ -29,7 +29,7 @@ impl StylesheetLoader {
impl StyleStylesheetLoader for StylesheetLoader { impl StyleStylesheetLoader for StylesheetLoader {
fn request_stylesheet( fn request_stylesheet(
&self, &self,
url: SpecifiedUrl, url: CssUrl,
source_location: SourceLocation, source_location: SourceLocation,
_context: &ParserContext, _context: &ParserContext,
lock: &SharedRwLock, lock: &SharedRwLock,