Skip to content

Commit

Permalink
Avoid the generic writer parameter for PropertyDeclaration serializat…
Browse files Browse the repository at this point in the history
…ion.

MozReview-Commit-ID: JR3IcL1NRHO
  • Loading branch information
bholley committed Jan 22, 2018
1 parent f5dd50d commit 5526947
Show file tree
Hide file tree
Showing 21 changed files with 227 additions and 108 deletions.
12 changes: 8 additions & 4 deletions components/script/dom/cssstyledeclaration.rs
Expand Up @@ -21,7 +21,7 @@ use style::properties::{DeclarationSource, Importance, PropertyDeclarationBlock,
use style::properties::{parse_one_declaration_into, parse_style_attribute, SourcePropertyDeclaration};
use style::selector_parser::PseudoElement;
use style::shared_lock::Locked;
use style_traits::{ParsingMode, ToCss};
use style_traits::ParsingMode;

// http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
#[dom_struct]
Expand Down Expand Up @@ -85,7 +85,8 @@ impl CSSStyleOwner {
// [1]: https://github.com/whatwg/html/issues/2306
if let Some(pdb) = attr {
let guard = shared_lock.read();
let serialization = pdb.read_with(&guard).to_css_string();
let mut serialization = String::new();
pdb.read_with(&guard).to_css(&mut serialization).unwrap();
el.set_attribute(&local_name!("style"),
AttrValue::Declaration(serialization,
pdb));
Expand Down Expand Up @@ -415,7 +416,8 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
self.owner.with_block(|pdb| {
pdb.declarations().get(index as usize).map(|declaration| {
let important = pdb.declarations_importance().get(index);
let mut css = declaration.to_css_string();
let mut css = String::new();
declaration.to_css(&mut css).unwrap();
if important {
css += " !important";
}
Expand All @@ -427,7 +429,9 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-csstext
fn CssText(&self) -> DOMString {
self.owner.with_block(|pdb| {
DOMString::from(pdb.to_css_string())
let mut serialization = String::new();
pdb.to_css(&mut serialization).unwrap();
DOMString::from(serialization)
})
}

Expand Down
6 changes: 3 additions & 3 deletions components/style/counter_style/mod.rs
Expand Up @@ -17,8 +17,9 @@ use selectors::parser::SelectorParseErrorKind;
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
#[allow(unused_imports)] use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::fmt;
use std::fmt::{self, Write};
use std::ops::Range;
use str::CssStringWriter;
use style_traits::{Comma, OneOrMoreSeparated, ParseError, StyleParseErrorKind, ToCss};
use values::CustomIdent;

Expand Down Expand Up @@ -228,8 +229,7 @@ macro_rules! counter_style_descriptors {
}

impl ToCssWithGuard for CounterStyleRuleData {
fn to_css<W>(&self, _guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
where W: fmt::Write {
fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
dest.write_str("@counter-style ")?;
self.name.to_css(dest)?;
dest.write_str(" {\n")?;
Expand Down
6 changes: 3 additions & 3 deletions components/style/font_face.rs
Expand Up @@ -20,7 +20,8 @@ use parser::{ParserContext, ParserErrorContext, Parse};
use properties::longhands::font_language_override;
use selectors::parser::SelectorParseErrorKind;
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
use std::fmt;
use std::fmt::{self, Write};
use str::CssStringWriter;
use style_traits::{Comma, OneOrMoreSeparated, ParseError, StyleParseErrorKind, ToCss};
use values::computed::font::FamilyName;
use values::specified::url::SpecifiedUrl;
Expand Down Expand Up @@ -272,8 +273,7 @@ macro_rules! font_face_descriptors_common {

impl ToCssWithGuard for FontFaceRuleData {
// Serialization of FontFaceRule is not specced.
fn to_css<W>(&self, _guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
where W: fmt::Write {
fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
dest.write_str("@font-face {\n")?;
$(
if let Some(ref value) = self.$ident {
Expand Down
10 changes: 5 additions & 5 deletions components/style/gecko/rules.rs
Expand Up @@ -17,7 +17,9 @@ use gecko_bindings::sugar::refptr::{RefPtr, UniqueRefPtr};
use nsstring::nsString;
use properties::longhands::font_language_override;
use shared_lock::{ToCssWithGuard, SharedRwLockReadGuard};
use std::{fmt, str};
use std::fmt::{self, Write};
use std::str;
use str::CssStringWriter;
use values::computed::font::FamilyName;
use values::generics::FontSettings;

Expand Down Expand Up @@ -200,8 +202,7 @@ impl From<FontFaceRuleData> for FontFaceRule {
}

impl ToCssWithGuard for FontFaceRule {
fn to_css<W>(&self, _guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
where W: fmt::Write {
fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
let mut css_text = nsString::new();
unsafe {
bindings::Gecko_CSSFontFaceRule_GetCssText(self.get(), &mut *css_text);
Expand Down Expand Up @@ -237,8 +238,7 @@ impl From<counter_style::CounterStyleRuleData> for CounterStyleRule {
}

impl ToCssWithGuard for CounterStyleRule {
fn to_css<W>(&self, _guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
where W: fmt::Write {
fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
let mut css_text = nsString::new();
unsafe {
bindings::Gecko_CSSCounterStyle_GetCssText(self.get(), &mut *css_text);
Expand Down
71 changes: 36 additions & 35 deletions components/style/properties/declaration_block.rs
Expand Up @@ -19,6 +19,7 @@ use smallvec::SmallVec;
use std::fmt;
use std::iter::{DoubleEndedIterator, Zip};
use std::slice::Iter;
use str::{CssString, CssStringBorrow, CssStringWriter};
use style_traits::{ToCss, ParseError, ParsingMode, StyleParseErrorKind};
use stylesheets::{CssRuleType, Origin, UrlExtraData};
use super::*;
Expand Down Expand Up @@ -306,9 +307,7 @@ impl PropertyDeclarationBlock {
/// Find the value of the given property in this block and serialize it
///
/// <https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue>
pub fn property_value_to_css<W>(&self, property: &PropertyId, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
pub fn property_value_to_css(&self, property: &PropertyId, dest: &mut CssStringWriter) -> fmt::Result {
// Step 1.1: done when parsing a string to PropertyId

// Step 1.2
Expand Down Expand Up @@ -608,15 +607,13 @@ impl PropertyDeclarationBlock {
}

/// Take a declaration block known to contain a single property and serialize it.
pub fn single_value_to_css<W>(
pub fn single_value_to_css(
&self,
property: &PropertyId,
dest: &mut W,
dest: &mut CssStringWriter,
computed_values: Option<&ComputedValues>,
custom_properties_block: Option<&PropertyDeclarationBlock>,
) -> fmt::Result
where
W: fmt::Write,
{
match property.as_shorthand() {
Err(_longhand_or_custom) => {
Expand Down Expand Up @@ -664,7 +661,7 @@ impl PropertyDeclarationBlock {
let iter = self.declarations.iter();
match shorthand.get_shorthand_appendable_value(iter) {
Some(AppendableValue::Css { css, .. }) => {
dest.write_str(css)
css.append_to(dest)
},
Some(AppendableValue::DeclarationsForShorthand(_, decls)) => {
shorthand.longhands_to_css(decls, dest)
Expand Down Expand Up @@ -738,11 +735,13 @@ impl PropertyDeclarationBlock {
}
}

impl ToCss for PropertyDeclarationBlock {
// https://drafts.csswg.org/cssom/#serialize-a-css-declaration-block
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
impl PropertyDeclarationBlock {
/// Like the method on ToCss, but without the type parameter to avoid
/// accidentally monomorphizing this large function multiple times for
/// different writers.
///
/// https://drafts.csswg.org/cssom/#serialize-a-css-declaration-block
pub fn to_css(&self, dest: &mut CssStringWriter) -> fmt::Result {
let mut is_first_serialization = true; // trailing serializations should have a prepended space

// Step 1 -> dest = result list
Expand Down Expand Up @@ -835,7 +834,7 @@ impl ToCss for PropertyDeclarationBlock {

// We avoid re-serializing if we're already an
// AppendableValue::Css.
let mut v = String::new();
let mut v = CssString::new();
let value = match (appendable_value, found_system) {
(AppendableValue::Css { css, with_variables }, _) => {
debug_assert!(!css.is_empty());
Expand All @@ -848,7 +847,7 @@ impl ToCss for PropertyDeclarationBlock {
(_, Some(sys)) => {
sys.to_css(&mut v)?;
AppendableValue::Css {
css: &v,
css: CssStringBorrow::from(&v),
with_variables: false,
}
}
Expand All @@ -861,7 +860,7 @@ impl ToCss for PropertyDeclarationBlock {
}

AppendableValue::Css {
css: &v,
css: CssStringBorrow::from(&v),
with_variables: false,
}
}
Expand All @@ -871,14 +870,14 @@ impl ToCss for PropertyDeclarationBlock {
// We need to check the shorthand whether it's an alias property or not.
// If it's an alias property, it should be serialized like its longhand.
if shorthand.flags().contains(PropertyFlags::SHORTHAND_ALIAS_PROPERTY) {
append_serialization::<_, Cloned<slice::Iter< _>>, _>(
append_serialization::<Cloned<slice::Iter< _>>, _>(
dest,
&property,
value,
importance,
&mut is_first_serialization)?;
} else {
append_serialization::<_, Cloned<slice::Iter< _>>, _>(
append_serialization::<Cloned<slice::Iter< _>>, _>(
dest,
&shorthand,
value,
Expand Down Expand Up @@ -913,7 +912,7 @@ impl ToCss for PropertyDeclarationBlock {
// "error: unable to infer enough type information about `_`;
// type annotations or generic parameter binding required [E0282]"
// Use the same type as earlier call to reuse generated code.
append_serialization::<_, Cloned<slice::Iter<_>>, _>(
append_serialization::<Cloned<slice::Iter<_>>, _>(
dest,
&property,
AppendableValue::Declaration(declaration),
Expand Down Expand Up @@ -945,7 +944,7 @@ pub enum AppendableValue<'a, I>
/// or when storing a serialized shorthand value before appending directly.
Css {
/// The raw CSS string.
css: &'a str,
css: CssStringBorrow<'a>,
/// Whether the original serialization contained variables or not.
with_variables: bool,
}
Expand All @@ -966,15 +965,16 @@ fn handle_first_serialization<W>(dest: &mut W,
}

/// Append a given kind of appendable value to a serialization.
pub fn append_declaration_value<'a, W, I>(dest: &mut W,
appendable_value: AppendableValue<'a, I>)
-> fmt::Result
where W: fmt::Write,
I: Iterator<Item=&'a PropertyDeclaration>,
pub fn append_declaration_value<'a, I>(
dest: &mut CssStringWriter,
appendable_value: AppendableValue<'a, I>,
) -> fmt::Result
where
I: Iterator<Item=&'a PropertyDeclaration>,
{
match appendable_value {
AppendableValue::Css { css, .. } => {
dest.write_str(css)
css.append_to(dest)
},
AppendableValue::Declaration(decl) => {
decl.to_css(dest)
Expand All @@ -986,15 +986,16 @@ pub fn append_declaration_value<'a, W, I>(dest: &mut W,
}

/// Append a given property and value pair to a serialization.
pub fn append_serialization<'a, W, I, N>(dest: &mut W,
property_name: &N,
appendable_value: AppendableValue<'a, I>,
importance: Importance,
is_first_serialization: &mut bool)
-> fmt::Result
where W: fmt::Write,
I: Iterator<Item=&'a PropertyDeclaration>,
N: ToCss,
pub fn append_serialization<'a, I, N>(
dest: &mut CssStringWriter,
property_name: &N,
appendable_value: AppendableValue<'a, I>,
importance: Importance,
is_first_serialization: &mut bool
) -> fmt::Result
where
I: Iterator<Item=&'a PropertyDeclaration>,
N: ToCss,
{
handle_first_serialization(dest, is_first_serialization)?;

Expand Down
26 changes: 18 additions & 8 deletions components/style/properties/properties.mako.rs
Expand Up @@ -16,8 +16,10 @@ use custom_properties::CustomPropertiesBuilder;
use servo_arc::{Arc, UniqueArc};
use smallbitvec::SmallBitVec;
use std::borrow::Cow;
use std::{fmt, mem, ops};
use std::cell::RefCell;
use std::fmt::{self, Write};
use std::mem;
use std::ops;

#[cfg(feature = "servo")] use cssparser::RGBA;
use cssparser::{CowRcStr, Parser, TokenSerializationType, serialize_identifier};
Expand Down Expand Up @@ -46,6 +48,7 @@ use values::computed;
use values::computed::NonNegativeLength;
use rule_tree::{CascadeLevel, StrongRuleNode};
use self::computed_value_flags::*;
use str::{CssString, CssStringBorrow, CssStringWriter};
use style_adjuster::StyleAdjuster;

pub use self::declaration_block::*;
Expand Down Expand Up @@ -898,7 +901,7 @@ impl ShorthandId {
if let Some(css) = first_declaration.with_variables_from_shorthand(self) {
if declarations2.all(|d| d.with_variables_from_shorthand(self) == Some(css)) {
return Some(AppendableValue::Css {
css: css,
css: CssStringBorrow::from(css),
with_variables: true,
});
}
Expand All @@ -909,7 +912,7 @@ impl ShorthandId {
if let Some(keyword) = first_declaration.get_css_wide_keyword() {
if declarations2.all(|d| d.get_css_wide_keyword() == Some(keyword)) {
return Some(AppendableValue::Css {
css: keyword.to_str(),
css: CssStringBorrow::from(keyword.to_str()),
with_variables: false,
});
}
Expand Down Expand Up @@ -1463,14 +1466,21 @@ impl fmt::Debug for PropertyDeclaration {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.id().to_css(f)?;
f.write_str(": ")?;
self.to_css(f)

// Because PropertyDeclaration::to_css requires CssStringWriter, we can't write
// it directly to f, and need to allocate an intermediate string. This is
// fine for debug-only code.
let mut s = CssString::new();
self.to_css(&mut s)?;
write!(f, "{}", s)
}
}

impl ToCss for PropertyDeclaration {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
impl PropertyDeclaration {
/// Like the method on ToCss, but without the type parameter to avoid
/// accidentally monomorphizing this large function multiple times for
/// different writers.
pub fn to_css(&self, dest: &mut CssStringWriter) -> fmt::Result {
match *self {
% for property in data.longhands:
PropertyDeclaration::${property.camel_case}(ref value) =>
Expand Down
11 changes: 6 additions & 5 deletions components/style/shared_lock.rs
Expand Up @@ -13,6 +13,7 @@ use std::cell::UnsafeCell;
use std::fmt;
#[cfg(feature = "gecko")]
use std::ptr;
use str::{CssString, CssStringWriter};
use stylesheets::Origin;

/// A shared read/write lock that can protect multiple objects.
Expand Down Expand Up @@ -219,18 +220,18 @@ mod compile_time_assert {
impl<'a> Marker2 for SharedRwLockWriteGuard<'a> {} // Assert SharedRwLockWriteGuard: !Copy
}

/// Like ToCss, but with a lock guard given by the caller.
/// Like ToCss, but with a lock guard given by the caller, and with the writer specified
/// concretely rather than with a parameter.
pub trait ToCssWithGuard {
/// Serialize `self` in CSS syntax, writing to `dest`, using the given lock guard.
fn to_css<W>(&self, guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
where W: fmt::Write;
fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result;

/// Serialize `self` in CSS syntax using the given lock guard and return a string.
///
/// (This is a convenience wrapper for `to_css` and probably should not be overridden.)
#[inline]
fn to_css_string(&self, guard: &SharedRwLockReadGuard) -> String {
let mut s = String::new();
fn to_css_string(&self, guard: &SharedRwLockReadGuard) -> CssString {
let mut s = CssString::new();
self.to_css(guard, &mut s).unwrap();
s
}
Expand Down

0 comments on commit 5526947

Please sign in to comment.