aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/construct.rs4
-rw-r--r--components/layout/display_list_builder.rs18
-rw-r--r--components/script/dom/element.rs2
-rw-r--r--components/servo/Cargo.lock1
-rw-r--r--components/style/gecko/conversions.rs8
-rw-r--r--components/style/parser.rs9
-rw-r--r--components/style/properties/gecko.mako.rs16
-rw-r--r--components/style/properties/longhand/svg.mako.rs36
-rw-r--r--components/style/values/computed/basic_shape.rs7
-rw-r--r--components/style/values/computed/image.rs20
-rw-r--r--components/style/values/computed/length.rs2
-rw-r--r--components/style/values/computed/mod.rs3
-rw-r--r--components/style/values/specified/basic_shape.rs24
-rw-r--r--components/style/values/specified/image.rs36
-rw-r--r--components/style/values/specified/mod.rs67
-rw-r--r--components/style/values/specified/url.rs165
-rw-r--r--components/style_traits/Cargo.toml1
-rw-r--r--components/style_traits/lib.rs1
-rw-r--r--components/style_traits/values.rs13
-rw-r--r--ports/cef/Cargo.lock1
-rw-r--r--ports/geckolib/Cargo.lock1
-rw-r--r--tests/unit/style/properties/serialization.rs19
22 files changed, 267 insertions, 187 deletions
diff --git a/components/layout/construct.rs b/components/layout/construct.rs
index 086b323e878..8841b1ab3e9 100644
--- a/components/layout/construct.rs
+++ b/components/layout/construct.rs
@@ -1205,9 +1205,9 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
-> ConstructionResult {
let flotation = FloatKind::from_property(flotation);
let marker_fragments = match node.style(self.style_context()).get_list().list_style_image {
- list_style_image::T::Url(ref url, ref _extra_data) => {
+ list_style_image::T::Url(ref url_value) => {
let image_info = box ImageFragmentInfo::new(node,
- Some((*url).clone()),
+ url_value.url().map(|u| (**u).clone()),
&self.layout_context.shared);
vec![Fragment::new(node, SpecificFragmentInfo::Image(image_info), self.layout_context)]
}
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs
index ec881ea9bcb..d5f3317cee5 100644
--- a/components/layout/display_list_builder.rs
+++ b/components/layout/display_list_builder.rs
@@ -612,14 +612,16 @@ impl FragmentDisplayListBuilding for Fragment {
style);
}
}
- Some(computed::Image::Url(ref image_url, ref _extra_data)) => {
- self.build_display_list_for_background_image(state,
- style,
- display_list_section,
- &bounds,
- &clip,
- image_url,
- i);
+ Some(computed::Image::Url(ref image_url)) => {
+ if let Some(url) = image_url.url() {
+ self.build_display_list_for_background_image(state,
+ style,
+ display_list_section,
+ &bounds,
+ &clip,
+ url,
+ i);
+ }
}
}
}
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 15a4ef816c8..ac65c01e24c 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -368,7 +368,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
PropertyDeclaration::BackgroundImage(DeclaredValue::Value(
background_image::SpecifiedValue(vec![
background_image::single_value::SpecifiedValue(Some(
- specified::Image::Url(url, specified::UrlExtraData { })
+ specified::Image::for_cascade(Some(Arc::new(url)), specified::url::UrlExtraData { })
))
])))));
}
diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock
index 49c10625db3..3bae647c7b2 100644
--- a/components/servo/Cargo.lock
+++ b/components/servo/Cargo.lock
@@ -2528,7 +2528,6 @@ dependencies = [
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs
index c002ebf86e7..6202b5f852f 100644
--- a/components/style/gecko/conversions.rs
+++ b/components/style/gecko/conversions.rs
@@ -120,11 +120,13 @@ impl nsStyleImage {
Image::Gradient(gradient) => {
self.set_gradient(gradient)
},
- Image::Url(ref url, ref extra_data) if with_url => {
+ Image::Url(ref url) if with_url => {
+ let (ptr, len) = url.as_slice_components();
+ let extra_data = url.extra_data();
unsafe {
Gecko_SetUrlImageValue(self,
- url.as_str().as_ptr(),
- url.as_str().len() as u32,
+ ptr,
+ len as u32,
extra_data.base.get(),
extra_data.referrer.get(),
extra_data.principal.get());
diff --git a/components/style/parser.rs b/components/style/parser.rs
index 1cf46a80d09..84d421b9ee6 100644
--- a/components/style/parser.rs
+++ b/components/style/parser.rs
@@ -66,15 +66,6 @@ impl<'a> ParserContext<'a> {
}
}
-
-impl<'a> ParserContext<'a> {
- pub fn parse_url(&self, input: &str) -> Url {
- self.base_url.join(input)
- .unwrap_or_else(|_| Url::parse("about:invalid").unwrap())
- }
-}
-
-
/// Defaults to a no-op.
/// Set a `RUST_LOG=style::errors` environment variable
/// to log CSS parse errors to stderr.
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index cead90fc571..f1ecd7ffd13 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -1036,11 +1036,13 @@ fn static_assert() {
use properties::longhands::_moz_binding::computed_value::T as BindingValue;
match v {
BindingValue::None => debug_assert!(self.gecko.mBinding.mRawPtr.is_null()),
- BindingValue::Url(ref url, ref extra_data) => {
+ BindingValue::Url(ref url) => {
+ let extra_data = url.extra_data();
+ let (ptr, len) = url.as_slice_components();
unsafe {
Gecko_SetMozBinding(&mut self.gecko,
- url.as_str().as_ptr(),
- url.as_str().len() as u32,
+ ptr,
+ len as u32,
extra_data.base.get(),
extra_data.referrer.get(),
extra_data.principal.get());
@@ -1441,11 +1443,13 @@ fn static_assert() {
Gecko_SetListStyleImageNone(&mut self.gecko);
}
}
- UrlOrNone::Url(ref url, ref extra_data) => {
+ UrlOrNone::Url(ref url) => {
+ let (ptr, len) = url.as_slice_components();
+ let extra_data = url.extra_data();
unsafe {
Gecko_SetListStyleImage(&mut self.gecko,
- url.as_str().as_ptr(),
- url.as_str().len() as u32,
+ ptr,
+ len as u32,
extra_data.base.get(),
extra_data.referrer.get(),
extra_data.principal.get());
diff --git a/components/style/properties/longhand/svg.mako.rs b/components/style/properties/longhand/svg.mako.rs
index 9d6667a8d97..a0d107f6326 100644
--- a/components/style/properties/longhand/svg.mako.rs
+++ b/components/style/properties/longhand/svg.mako.rs
@@ -149,20 +149,21 @@ ${helpers.single_keyword("mask-composite",
has_uncacheable_values="${product == 'gecko'}">
use std::fmt;
use style_traits::ToCss;
- use url::Url;
- use values::specified::{Image, UrlExtraData};
+ use std::sync::Arc;
+ use values::specified::Image;
+ use values::specified::url::SpecifiedUrl;
use values::NoViewportPercentage;
pub mod computed_value {
use std::fmt;
use style_traits::ToCss;
- use url::Url;
use values::computed;
+ use values::specified::url::SpecifiedUrl;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum T {
Image(computed::Image),
- Url(Url, computed::UrlExtraData),
+ Url(SpecifiedUrl),
None
}
@@ -171,7 +172,7 @@ ${helpers.single_keyword("mask-composite",
match *self {
T::None => dest.write_str("none"),
T::Image(ref image) => image.to_css(dest),
- T::Url(ref url, _) => url.to_css(dest),
+ T::Url(ref url) => url.to_css(dest),
}
}
}
@@ -183,7 +184,7 @@ ${helpers.single_keyword("mask-composite",
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedValue {
Image(Image),
- Url(Url, UrlExtraData),
+ Url(SpecifiedUrl),
None
}
@@ -191,7 +192,7 @@ ${helpers.single_keyword("mask-composite",
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
SpecifiedValue::Image(ref image) => image.to_css(dest),
- SpecifiedValue::Url(ref url, _) => url.to_css(dest),
+ SpecifiedValue::Url(ref url) => url.to_css(dest),
SpecifiedValue::None => dest.write_str("none"),
}
}
@@ -211,11 +212,16 @@ ${helpers.single_keyword("mask-composite",
} else {
let image = try!(Image::parse(context, input));
match image {
- Image::Url(url, data) => {
- if url.fragment().is_some() {
- Ok(SpecifiedValue::Url(url, data))
+ Image::Url(url_value) => {
+ let has_valid_url = match url_value.url() {
+ Some(url) => url.fragment().is_some(),
+ None => false,
+ };
+
+ if has_valid_url {
+ Ok(SpecifiedValue::Url(url_value))
} else {
- Ok(SpecifiedValue::Image(Image::Url(url, data)))
+ Ok(SpecifiedValue::Image(Image::Url(url_value)))
}
}
image => Ok(SpecifiedValue::Image(image))
@@ -231,8 +237,8 @@ ${helpers.single_keyword("mask-composite",
SpecifiedValue::None => computed_value::T::None,
SpecifiedValue::Image(ref image) =>
computed_value::T::Image(image.to_computed_value(context)),
- SpecifiedValue::Url(ref url, ref data) =>
- computed_value::T::Url(url.clone(), data.clone()),
+ SpecifiedValue::Url(ref url) =>
+ computed_value::T::Url(url.clone()),
}
}
@@ -242,8 +248,8 @@ ${helpers.single_keyword("mask-composite",
computed_value::T::None => SpecifiedValue::None,
computed_value::T::Image(ref image) =>
SpecifiedValue::Image(ToComputedValue::from_computed_value(image)),
- computed_value::T::Url(ref url, ref data) =>
- SpecifiedValue::Url(url.clone(), data.clone()),
+ computed_value::T::Url(ref url) =>
+ SpecifiedValue::Url(url.clone()),
}
}
}
diff --git a/components/style/values/computed/basic_shape.rs b/components/style/values/computed/basic_shape.rs
index d27fe94545b..6428022538f 100644
--- a/components/style/values/computed/basic_shape.rs
+++ b/components/style/values/computed/basic_shape.rs
@@ -10,17 +10,16 @@
use properties::shorthands::serialize_four_sides;
use std::fmt;
use style_traits::ToCss;
-use url::Url;
use values::computed::{BorderRadiusSize, LengthOrPercentage};
-use values::computed::UrlExtraData;
use values::computed::position::Position;
+use values::specified::url::SpecifiedUrl;
pub use values::specified::basic_shape::{FillRule, GeometryBox, ShapeBox};
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum ShapeSource<T> {
- Url(Url, UrlExtraData),
+ Url(SpecifiedUrl),
Shape(BasicShape, Option<T>),
Box(T),
None,
@@ -35,7 +34,7 @@ impl<T> Default for ShapeSource<T> {
impl<T: ToCss> ToCss for ShapeSource<T> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
- ShapeSource::Url(ref url, _) => url.to_css(dest),
+ ShapeSource::Url(ref url) => url.to_css(dest),
ShapeSource::Shape(ref shape, Some(ref reference)) => {
try!(shape.to_css(dest));
try!(dest.write_str(" "));
diff --git a/components/style/values/computed/image.rs b/components/style/values/computed/image.rs
index 4b825d1fbdd..f99ed74ac5e 100644
--- a/components/style/values/computed/image.rs
+++ b/components/style/values/computed/image.rs
@@ -10,10 +10,10 @@
use cssparser::Color as CSSColor;
use std::fmt;
use style_traits::ToCss;
-use url::Url;
use values::computed::{Context, Length, LengthOrPercentage, ToComputedValue};
use values::computed::position::Position;
-use values::specified::{self, AngleOrCorner, SizeKeyword, UrlExtraData};
+use values::specified::{self, AngleOrCorner, SizeKeyword};
+use values::specified::url::SpecifiedUrl;
impl ToComputedValue for specified::Image {
@@ -22,8 +22,8 @@ impl ToComputedValue for specified::Image {
#[inline]
fn to_computed_value(&self, context: &Context) -> Image {
match *self {
- specified::Image::Url(ref url, ref extra_data) => {
- Image::Url(url.clone(), extra_data.clone())
+ specified::Image::Url(ref url_value) => {
+ Image::Url(url_value.clone())
},
specified::Image::Gradient(ref gradient) => {
Image::Gradient(gradient.to_computed_value(context))
@@ -34,8 +34,8 @@ impl ToComputedValue for specified::Image {
#[inline]
fn from_computed_value(computed: &Image) -> Self {
match *computed {
- Image::Url(ref url, ref extra_data) => {
- specified::Image::Url(url.clone(), extra_data.clone())
+ Image::Url(ref url_value) => {
+ specified::Image::Url(url_value.clone())
},
Image::Gradient(ref linear_gradient) => {
specified::Image::Gradient(
@@ -51,14 +51,14 @@ impl ToComputedValue for specified::Image {
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Image {
- Url(Url, UrlExtraData),
+ Url(SpecifiedUrl),
Gradient(Gradient),
}
impl fmt::Debug for Image {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
- Image::Url(ref url, ref _extra_data) => write!(f, "url(\"{}\")", url),
+ Image::Url(ref url) => url.to_css(f),
Image::Gradient(ref grad) => {
if grad.repeating {
let _ = write!(f, "repeating-");
@@ -75,9 +75,7 @@ impl fmt::Debug for Image {
impl ToCss for Image {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
- Image::Url(ref url, _) => {
- url.to_css(dest)
- }
+ Image::Url(ref url) => url.to_css(dest),
Image::Gradient(ref gradient) => gradient.to_css(dest)
}
}
diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs
index b08c3806ceb..f3524523756 100644
--- a/components/style/values/computed/length.rs
+++ b/components/style/values/computed/length.rs
@@ -12,7 +12,7 @@ use values::{CSSFloat, Either, None_, specified};
pub use cssparser::Color as CSSColor;
pub use super::image::{EndingShape as GradientShape, Gradient, GradientKind, Image};
pub use super::image::{LengthOrKeyword, LengthOrPercentageOrKeyword};
-pub use values::specified::{Angle, BorderStyle, Time, UrlExtraData, UrlOrNone};
+pub use values::specified::{Angle, BorderStyle, Time, UrlOrNone};
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs
index 14e4f49d76c..1e57673d457 100644
--- a/components/style/values/computed/mod.rs
+++ b/components/style/values/computed/mod.rs
@@ -13,7 +13,8 @@ pub use cssparser::Color as CSSColor;
pub use self::image::{EndingShape as GradientShape, Gradient, GradientKind, Image};
pub use self::image::{LengthOrKeyword, LengthOrPercentageOrKeyword};
pub use super::{Either, None_};
-pub use super::specified::{Angle, BorderStyle, Time, UrlExtraData, UrlOrNone};
+pub use super::specified::{Angle, BorderStyle, Time, UrlOrNone};
+pub use super::specified::url::UrlExtraData;
pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto};
pub use self::length::{LengthOrPercentageOrAutoOrContent, LengthOrPercentageOrNone, LengthOrNone};
diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs
index 6f5bdb03953..88123ea1db1 100644
--- a/components/style/values/specified/basic_shape.rs
+++ b/components/style/values/specified/basic_shape.rs
@@ -12,12 +12,11 @@ use parser::{Parse, ParserContext};
use properties::shorthands::{parse_four_sides, serialize_four_sides};
use std::fmt;
use style_traits::ToCss;
-use url::Url;
use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue};
use values::computed::basic_shape as computed_basic_shape;
use values::specified::{BorderRadiusSize, LengthOrPercentage, Percentage};
-use values::specified::UrlExtraData;
use values::specified::position::{Keyword, Position};
+use values::specified::url::SpecifiedUrl;
/// A shape source, for some reference box
///
@@ -26,7 +25,7 @@ use values::specified::position::{Keyword, Position};
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum ShapeSource<T> {
- Url(Url, UrlExtraData),
+ Url(SpecifiedUrl),
Shape(BasicShape, Option<T>),
Box(T),
None,
@@ -41,7 +40,7 @@ impl<T> Default for ShapeSource<T> {
impl<T: ToCss> ToCss for ShapeSource<T> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
- ShapeSource::Url(ref url, _) => url.to_css(dest),
+ ShapeSource::Url(ref url) => url.to_css(dest),
ShapeSource::Shape(ref shape, Some(ref reference)) => {
try!(shape.to_css(dest));
try!(dest.write_str(" "));
@@ -59,13 +58,8 @@ impl<T: Parse + PartialEq + Copy> ShapeSource<T> {
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
if let Ok(_) = input.try(|input| input.expect_ident_matching("none")) {
Ok(ShapeSource::None)
- } else if let Ok(url) = input.try(|input| input.expect_url()) {
- match UrlExtraData::make_from(context) {
- Some(extra_data) => {
- Ok(ShapeSource::Url(context.parse_url(&url), extra_data))
- },
- None => Err(()),
- }
+ } else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
+ Ok(ShapeSource::Url(url))
} else {
fn parse_component<U: Parse>(input: &mut Parser, component: &mut Option<U>) -> bool {
if component.is_some() {
@@ -98,8 +92,8 @@ impl<T: ToComputedValue> ToComputedValue for ShapeSource<T> {
#[inline]
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
match *self {
- ShapeSource::Url(ref url, ref data) => {
- computed_basic_shape::ShapeSource::Url(url.clone(), data.clone())
+ ShapeSource::Url(ref url) => {
+ computed_basic_shape::ShapeSource::Url(url.to_computed_value(cx))
}
ShapeSource::Shape(ref shape, ref reference) => {
computed_basic_shape::ShapeSource::Shape(
@@ -116,8 +110,8 @@ impl<T: ToComputedValue> ToComputedValue for ShapeSource<T> {
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed {
- computed_basic_shape::ShapeSource::Url(ref url, ref data) => {
- ShapeSource::Url(url.clone(), data.clone())
+ computed_basic_shape::ShapeSource::Url(ref url) => {
+ ShapeSource::Url(SpecifiedUrl::from_computed_value(url))
}
computed_basic_shape::ShapeSource::Shape(ref shape, ref reference) => {
ShapeSource::Shape(
diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs
index f6a64ba3c3b..96af3fc91d3 100644
--- a/components/style/values/specified/image.rs
+++ b/components/style/values/specified/image.rs
@@ -11,49 +11,45 @@ use cssparser::Parser;
use parser::{Parse, ParserContext};
use std::f32::consts::PI;
use std::fmt;
+use std::sync::Arc;
use style_traits::ToCss;
use url::Url;
use values::computed::ComputedValueAsSpecified;
-use values::specified::{Angle, CSSColor, Length, LengthOrPercentage, UrlExtraData};
+use values::specified::{Angle, CSSColor, Length, LengthOrPercentage};
use values::specified::position::Position;
+use values::specified::url::{SpecifiedUrl, UrlExtraData};
/// Specified values for an image according to CSS-IMAGES.
/// https://drafts.csswg.org/css-images/#image-values
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Image {
- Url(Url, UrlExtraData),
+ Url(SpecifiedUrl),
Gradient(Gradient),
}
impl ToCss for Image {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
- Image::Url(ref url, ref _extra_data) => {
- url.to_css(dest)
- }
- Image::Gradient(ref gradient) => gradient.to_css(dest)
+ Image::Url(ref url_value) => url_value.to_css(dest),
+ Image::Gradient(ref gradient) => gradient.to_css(dest),
}
}
}
impl Image {
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> {
- if let Ok(url) = input.try(|input| input.expect_url()) {
- match UrlExtraData::make_from(context) {
- Some(extra_data) => {
- Ok(Image::Url(context.parse_url(&url), extra_data))
- },
- None => {
- // FIXME(heycam) should ensure we always have a principal, etc., when
- // parsing style attributes and re-parsing due to CSS Variables.
- println!("stylo: skipping declaration without ParserContextExtraData");
- Err(())
- },
- }
- } else {
- Ok(Image::Gradient(try!(Gradient::parse_function(input))))
+ if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
+ return Ok(Image::Url(url));
}
+
+ Ok(Image::Gradient(try!(Gradient::parse_function(input))))
+ }
+
+ /// Creates an already specified image value from an already resolved URL
+ /// for insertion in the cascade.
+ pub fn for_cascade(url: Option<Arc<Url>>, extra_data: UrlExtraData) -> Self {
+ Image::Url(SpecifiedUrl::for_cascade(url, extra_data))
}
}
diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs
index 339c565a240..eeed4139cd3 100644
--- a/components/style/values/specified/mod.rs
+++ b/components/style/values/specified/mod.rs
@@ -5,11 +5,8 @@
use app_units::Au;
use cssparser::{self, Parser, Token};
use euclid::size::Size2D;
-#[cfg(feature = "gecko")]
-use gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
use parser::ParserContext;
-#[cfg(feature = "gecko")]
-use parser::ParserContextExtraData;
+use self::url::SpecifiedUrl;
use std::ascii::AsciiExt;
use std::f32::consts::PI;
use std::fmt;
@@ -17,7 +14,6 @@ use std::ops::Mul;
use style_traits::ToCss;
use super::{CSSFloat, HasViewportPercentage, NoViewportPercentage};
use super::computed::{ComputedValueAsSpecified, Context, ToComputedValue};
-use url::Url;
pub use self::image::{AngleOrCorner, ColorStop, EndingShape as GradientEndingShape, Gradient};
pub use self::image::{GradientKind, HorizontalDirection, Image, LengthOrKeyword, LengthOrPercentageOrKeyword};
@@ -30,6 +26,7 @@ pub mod basic_shape;
pub mod image;
pub mod length;
pub mod position;
+pub mod url;
impl NoViewportPercentage for i32 {} // For PropertyDeclaration::Order
@@ -263,42 +260,6 @@ impl Angle {
}
}
-#[derive(PartialEq, Clone, Debug)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct UrlExtraData {
- #[cfg(feature = "gecko")]
- pub base: GeckoArcURI,
- #[cfg(feature = "gecko")]
- pub referrer: GeckoArcURI,
- #[cfg(feature = "gecko")]
- pub principal: GeckoArcPrincipal,
-}
-
-impl UrlExtraData {
- #[cfg(feature = "servo")]
- pub fn make_from(_: &ParserContext) -> Option<UrlExtraData> {
- Some(UrlExtraData { })
- }
-
- #[cfg(feature = "gecko")]
- pub fn make_from(context: &ParserContext) -> Option<UrlExtraData> {
- match context.extra_data {
- ParserContextExtraData {
- base: Some(ref base),
- referrer: Some(ref referrer),
- principal: Some(ref principal),
- } => {
- Some(UrlExtraData {
- base: base.clone(),
- referrer: referrer.clone(),
- principal: principal.clone(),
- })
- },
- _ => None,
- }
- }
-}
-
pub fn parse_border_radius(input: &mut Parser) -> Result<BorderRadiusSize, ()> {
input.try(BorderRadiusSize::parse).or_else(|()| {
match_ignore_ascii_case! { try!(input.expect_ident()),
@@ -546,7 +507,7 @@ impl ToCss for Opacity {
#[derive(PartialEq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum UrlOrNone {
- Url(Url, UrlExtraData),
+ Url(SpecifiedUrl),
None,
}
@@ -556,13 +517,8 @@ impl NoViewportPercentage for UrlOrNone {}
impl ToCss for UrlOrNone {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
- UrlOrNone::Url(ref url, _) => {
- url.to_css(dest)
- }
- UrlOrNone::None => {
- try!(dest.write_str("none"));
- Ok(())
- }
+ UrlOrNone::Url(ref url) => url.to_css(dest),
+ UrlOrNone::None => dest.write_str("none"),
}
}
}
@@ -573,17 +529,6 @@ impl UrlOrNone {
return Ok(UrlOrNone::None);
}
- let url = context.parse_url(&*try!(input.expect_url()));
- match UrlExtraData::make_from(context) {
- Some(extra_data) => {
- Ok(UrlOrNone::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 UrlOrNone declaration without ParserContextExtraData");
- Err(())
- },
- }
+ Ok(UrlOrNone::Url(try!(SpecifiedUrl::parse(context, input))))
}
}
diff --git a/components/style/values/specified/url.rs b/components/style/values/specified/url.rs
new file mode 100644
index 00000000000..b81c89f887d
--- /dev/null
+++ b/components/style/values/specified/url.rs
@@ -0,0 +1,165 @@
+/* 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/. */
+
+//! Common handling for the specified value CSS url() values.
+
+use cssparser::{CssStringWriter, Parser};
+#[cfg(feature = "gecko")]
+use gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
+use parser::ParserContext;
+#[cfg(feature = "gecko")]
+use parser::ParserContextExtraData;
+use std::fmt::{self, Write};
+use std::ptr;
+use std::sync::Arc;
+use style_traits::ToCss;
+use url::Url;
+use values::computed::ComputedValueAsSpecified;
+
+#[derive(PartialEq, Clone, Debug)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub struct UrlExtraData {
+ #[cfg(feature = "gecko")]
+ pub base: GeckoArcURI,
+ #[cfg(feature = "gecko")]
+ pub referrer: GeckoArcURI,
+ #[cfg(feature = "gecko")]
+ pub principal: GeckoArcPrincipal,
+}
+
+impl UrlExtraData {
+ #[cfg(feature = "servo")]
+ pub fn make_from(_: &ParserContext) -> Option<UrlExtraData> {
+ Some(UrlExtraData { })
+ }
+
+ #[cfg(feature = "gecko")]
+ pub fn make_from(context: &ParserContext) -> Option<UrlExtraData> {
+ match context.extra_data {
+ ParserContextExtraData {
+ base: Some(ref base),
+ referrer: Some(ref referrer),
+ principal: Some(ref principal),
+ } => {
+ Some(UrlExtraData {
+ base: base.clone(),
+ referrer: referrer.clone(),
+ principal: principal.clone(),
+ })
+ },
+ _ => None,
+ }
+ }
+}
+
+/// A specified url() value.
+#[derive(Clone, Debug)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub struct SpecifiedUrl {
+ /// 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
+ /// convert their serialization.
+ ///
+ /// Refcounted since cloning this should be cheap and data: uris can be
+ /// really large.
+ original: Option<Arc<String>>,
+
+ /// The resolved value for the url, if valid.
+ resolved: Option<Arc<Url>>,
+
+ /// Extra data used for Stylo.
+ extra_data: UrlExtraData,
+}
+
+impl SpecifiedUrl {
+ pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
+ let url = try!(input.expect_url());
+
+ let extra_data = match UrlExtraData::make_from(context) {
+ Some(extra_data) => extra_data,
+ None => {
+ // FIXME(heycam) should ensure we always have a principal, etc.,
+ // when parsing style attributes and re-parsing due to CSS
+ // Variables.
+ println!("stylo: skipping declaration without ParserContextExtraData");
+ return Err(())
+ },
+ };
+
+ let serialization = Arc::new(url.into_owned());
+ let resolved = context.base_url.join(&serialization).ok().map(Arc::new);
+ Ok(SpecifiedUrl {
+ original: Some(serialization),
+ resolved: resolved,
+ extra_data: extra_data,
+ })
+ }
+
+ pub fn extra_data(&self) -> &UrlExtraData {
+ &self.extra_data
+ }
+
+ pub fn url(&self) -> Option<&Arc<Url>> {
+ self.resolved.as_ref()
+ }
+
+ /// Little helper for Gecko's ffi.
+ pub fn as_slice_components(&self) -> (*const u8, usize) {
+ match self.resolved {
+ Some(ref url) => (url.as_str().as_ptr(), url.as_str().len()),
+ None => (ptr::null(), 0),
+ }
+ }
+
+ /// Creates an already specified url value from an already resolved URL
+ /// for insertion in the cascade.
+ pub fn for_cascade(url: Option<Arc<Url>>, extra_data: UrlExtraData) -> Self {
+ SpecifiedUrl {
+ original: None,
+ resolved: url,
+ extra_data: extra_data,
+ }
+ }
+
+ // Just for unit tests, don't use outside of them!
+ #[cfg(feature = "servo")]
+ pub fn new_for_testing(url: &str) -> Self {
+ SpecifiedUrl {
+ original: Some(Arc::new(url.into())),
+ resolved: Url::parse(url).ok().map(Arc::new),
+ extra_data: UrlExtraData {}
+ }
+ }
+}
+
+impl PartialEq for SpecifiedUrl {
+ fn eq(&self, other: &Self) -> bool {
+ // TODO(emilio): maybe we care about equality of the specified values if
+ // present? Seems not.
+ self.resolved == other.resolved &&
+ self.extra_data == other.extra_data
+ }
+}
+
+impl ToCss for SpecifiedUrl {
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+ try!(dest.write_str("url(\""));
+ let string = match self.original {
+ Some(ref original) => &**original,
+ None => match self.resolved {
+ Some(ref url) => url.as_str(),
+ // This can only happen if the url wasn't specified by the
+ // user *and* it's an invalid url that has been transformed
+ // back to specified value via the "uncompute" functionality.
+ None => "about:invalid",
+ }
+ };
+
+ try!(CssStringWriter::new(dest).write_str(string));
+ dest.write_str("\")")
+ }
+}
+
+// TODO(emilio): Maybe consider ComputedUrl to save a word in style structs?
+impl ComputedValueAsSpecified for SpecifiedUrl {}
diff --git a/components/style_traits/Cargo.toml b/components/style_traits/Cargo.toml
index 07bc967e664..af4c9314381 100644
--- a/components/style_traits/Cargo.toml
+++ b/components/style_traits/Cargo.toml
@@ -22,4 +22,3 @@ heapsize_derive = {version = "0.1", optional = true}
rustc-serialize = "0.3"
serde = {version = "0.8", optional = true}
serde_derive = {version = "0.8", optional = true}
-url = "1.2"
diff --git a/components/style_traits/lib.rs b/components/style_traits/lib.rs
index 4ddb4e6a846..7d8689a0084 100644
--- a/components/style_traits/lib.rs
+++ b/components/style_traits/lib.rs
@@ -23,7 +23,6 @@ extern crate euclid;
extern crate rustc_serialize;
#[cfg(feature = "servo")] extern crate serde;
#[cfg(feature = "servo")] #[macro_use] extern crate serde_derive;
-extern crate url;
/// Opaque type stored in type-unsafe work queues for parallel layout.
/// Must be transmutable to and from TNode.
diff --git a/components/style_traits/values.rs b/components/style_traits/values.rs
index 9e8d6b2a936..35c21545ca6 100644
--- a/components/style_traits/values.rs
+++ b/components/style_traits/values.rs
@@ -3,9 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use app_units::Au;
-use cssparser::CssStringWriter;
-use std::fmt::{self, Write};
-use url::Url;
+use std::fmt;
/// The real ToCss trait can't be implemented for types in crates that don't
/// depend on each other.
@@ -30,15 +28,6 @@ impl ToCss for Au {
}
}
-impl ToCss for Url {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- try!(dest.write_str("url(\""));
- try!(write!(CssStringWriter::new(dest), "{}", self));
- try!(dest.write_str("\")"));
- Ok(())
- }
-}
-
macro_rules! impl_to_css_for_predefined_type {
($name: ty) => {
impl<'a> ToCss for $name {
diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock
index 8e94b56ce50..00323809b2e 100644
--- a/ports/cef/Cargo.lock
+++ b/ports/cef/Cargo.lock
@@ -2357,7 +2357,6 @@ dependencies = [
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
diff --git a/ports/geckolib/Cargo.lock b/ports/geckolib/Cargo.lock
index 99e04ca7f95..04d618e46c2 100644
--- a/ports/geckolib/Cargo.lock
+++ b/ports/geckolib/Cargo.lock
@@ -373,7 +373,6 @@ dependencies = [
"cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
diff --git a/tests/unit/style/properties/serialization.rs b/tests/unit/style/properties/serialization.rs
index 3b920059b62..746a45b252e 100644
--- a/tests/unit/style/properties/serialization.rs
+++ b/tests/unit/style/properties/serialization.rs
@@ -9,9 +9,8 @@ pub use style::values::specified::{BorderStyle, BorderWidth, CSSColor, Length};
pub use style::values::specified::{LengthOrPercentage, LengthOrPercentageOrAuto, LengthOrPercentageOrAutoOrContent};
pub use style::properties::longhands::outline_color::computed_value::T as ComputedColor;
pub use style::values::RGBA;
-pub use style::values::specified::UrlExtraData;
+pub use style::values::specified::url::{UrlExtraData, SpecifiedUrl};
pub use style_traits::ToCss;
-pub use url::Url;
#[test]
fn property_declaration_block_should_serialize_correctly() {
@@ -430,9 +429,7 @@ mod shorthand_serialization {
let position = DeclaredValue::Value(ListStylePosition::inside);
let image = DeclaredValue::Value(ListStyleImage::Url(
- Url::parse("http://servo/test.png").unwrap(),
- UrlExtraData {},
- ));
+ SpecifiedUrl::new_for_testing("http://servo/test.png")));
let style_type = DeclaredValue::Value(ListStyleType::disc);
properties.push(PropertyDeclaration::ListStylePosition(position));
@@ -747,8 +744,7 @@ mod shorthand_serialization {
let attachment = single_vec_keyword_value!(attachment, scroll);
let image = single_vec_value!(image,
- Some(Image::Url(Url::parse("http://servo/test.png").unwrap(),
- UrlExtraData {})));
+ Some(Image::Url(SpecifiedUrl::new_for_testing("http://servo/test.png"))));
let size = single_vec_variant_value!(size,
size::single_value::SpecifiedValue::Explicit(
@@ -802,8 +798,7 @@ mod shorthand_serialization {
let attachment = single_vec_keyword_value!(attachment, scroll);
let image = single_vec_value!(image,
- Some(Image::Url(Url::parse("http://servo/test.png").unwrap(),
- UrlExtraData {})));
+ Some(Image::Url(SpecifiedUrl::new_for_testing("http://servo/test.png"))));
let size = single_vec_variant_value!(size,
size::single_value::SpecifiedValue::Explicit(
@@ -917,8 +912,7 @@ mod shorthand_serialization {
let image = single_vec_value_typedef!(image,
image::single_value::SpecifiedValue::Image(
- Image::Url(Url::parse("http://servo/test.png").unwrap(),
- UrlExtraData {})));
+ Image::Url(SpecifiedUrl::new_for_testing("http://servo/test.png"))));
let mode = single_vec_keyword_value!(mode, luminance);
@@ -968,8 +962,7 @@ mod shorthand_serialization {
let image = single_vec_value_typedef!(image,
image::single_value::SpecifiedValue::Image(
- Image::Url(Url::parse("http://servo/test.png").unwrap(),
- UrlExtraData {})));
+ Image::Url(SpecifiedUrl::new_for_testing("http://servo/test.png"))));
let mode = single_vec_keyword_value!(mode, luminance);