mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Less cloning and dynamic dispatch.
This commit is contained in:
parent
7d7aac212b
commit
dc829da07e
3 changed files with 63 additions and 40 deletions
|
@ -13,6 +13,8 @@ use dom::element::{Element, StylePriority};
|
||||||
use dom::node::{Node, window_from_node};
|
use dom::node::{Node, window_from_node};
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
use std::cell::Ref;
|
||||||
|
use std::slice;
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
use style::parser::ParserContextExtraData;
|
use style::parser::ParserContextExtraData;
|
||||||
use style::properties::{PropertyDeclaration, Shorthand};
|
use style::properties::{PropertyDeclaration, Shorthand};
|
||||||
|
@ -140,14 +142,22 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||||
|
|
||||||
// Step 2.2.2 & 2.2.3
|
// Step 2.2.2 & 2.2.3
|
||||||
match declaration {
|
match declaration {
|
||||||
Some(declaration) => list.push(declaration.clone()),
|
Some(declaration) => list.push(declaration),
|
||||||
None => return DOMString::new(),
|
None => return DOMString::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2.3
|
// Step 2.3
|
||||||
let mut list = list.iter().map(|x| &*x);
|
// Work around closures not being Clone
|
||||||
let serialized_value = shorthand.serialize_shorthand_to_string(&mut list);
|
#[derive(Clone)]
|
||||||
|
struct Map<'a, 'b: 'a>(slice::Iter<'a, Ref<'b, PropertyDeclaration>>);
|
||||||
|
impl<'a, 'b> Iterator for Map<'a, 'b> {
|
||||||
|
type Item = &'a PropertyDeclaration;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
self.0.next().map(|r| &**r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let serialized_value = shorthand.serialize_shorthand_to_string(Map(list.iter()));
|
||||||
return DOMString::from(serialized_value);
|
return DOMString::from(serialized_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -699,10 +699,11 @@ impl Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_property_with_attrs_style(&self) {
|
fn sync_property_with_attrs_style(&self) {
|
||||||
let mut style_str = String::new();
|
let style_str = if let &Some(ref declarations) = &*self.style_attribute().borrow() {
|
||||||
if let &Some(ref declarations) = &*self.style_attribute().borrow() {
|
declarations.to_css_string()
|
||||||
declarations.to_css(&mut style_str).unwrap();
|
} else {
|
||||||
}
|
String::new()
|
||||||
|
};
|
||||||
|
|
||||||
let new_style = AttrValue::String(style_str);
|
let new_style = AttrValue::String(style_str);
|
||||||
|
|
||||||
|
|
|
@ -318,11 +318,11 @@ impl ToCss for PropertyDeclarationBlock {
|
||||||
let mut current_longhands = Vec::new();
|
let mut current_longhands = Vec::new();
|
||||||
let mut important_count = 0;
|
let mut important_count = 0;
|
||||||
|
|
||||||
for longhand in longhands.iter() {
|
for &(longhand, longhand_important) in longhands.iter() {
|
||||||
let longhand_name = longhand.0.name();
|
let longhand_name = longhand.name();
|
||||||
if properties.iter().any(|p| &longhand_name == *p) {
|
if properties.iter().any(|p| &longhand_name == *p) {
|
||||||
current_longhands.push(longhand.0);
|
current_longhands.push(longhand);
|
||||||
if longhand.1 == true {
|
if longhand_important {
|
||||||
important_count += 1;
|
important_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,7 +348,7 @@ impl ToCss for PropertyDeclarationBlock {
|
||||||
try!(
|
try!(
|
||||||
shorthand.serialize_shorthand_to_buffer(
|
shorthand.serialize_shorthand_to_buffer(
|
||||||
dest,
|
dest,
|
||||||
&mut current_longhands.iter().cloned(),
|
current_longhands.iter().cloned(),
|
||||||
&mut is_first_serialization
|
&mut is_first_serialization
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -376,12 +376,20 @@ impl ToCss for PropertyDeclarationBlock {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use std::iter::Cloned;
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
// Steps 3.3.5, 3.3.6 & 3.3.7
|
// Steps 3.3.5, 3.3.6 & 3.3.7
|
||||||
try!(append_serialization(dest,
|
// Need to specify an iterator type here even though it’s unused to work around
|
||||||
&property.to_string(),
|
// "error: unable to infer enough type information about `_`;
|
||||||
AppendableValue::Declaration(declaration),
|
// type annotations or generic parameter binding required [E0282]"
|
||||||
important,
|
// Use the same type as earlier call to reuse generated code.
|
||||||
&mut is_first_serialization));
|
try!(append_serialization::<W, Cloned<slice::Iter< &PropertyDeclaration>>>(
|
||||||
|
dest,
|
||||||
|
&property.to_string(),
|
||||||
|
AppendableValue::Declaration(declaration),
|
||||||
|
important,
|
||||||
|
&mut is_first_serialization));
|
||||||
|
|
||||||
// Step 3.3.8
|
// Step 3.3.8
|
||||||
already_serialized.push(property);
|
already_serialized.push(property);
|
||||||
|
@ -392,17 +400,20 @@ impl ToCss for PropertyDeclarationBlock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AppendableValue<'a> {
|
enum AppendableValue<'a, I>
|
||||||
|
where I: Iterator<Item=&'a PropertyDeclaration> {
|
||||||
Declaration(&'a PropertyDeclaration),
|
Declaration(&'a PropertyDeclaration),
|
||||||
DeclarationsForShorthand(&'a mut Iterator<Item=&'a PropertyDeclaration>),
|
DeclarationsForShorthand(I),
|
||||||
Css(&'a str)
|
Css(&'a str)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append_serialization<W>(dest: &mut W,
|
fn append_serialization<'a, W, I>(dest: &mut W,
|
||||||
property_name: &str,
|
property_name: &str,
|
||||||
appendable_value: AppendableValue,
|
appendable_value: AppendableValue<'a, I>,
|
||||||
is_important: bool,
|
is_important: bool,
|
||||||
is_first_serialization: &mut bool) -> fmt::Result where W: fmt::Write {
|
is_first_serialization: &mut bool)
|
||||||
|
-> fmt::Result
|
||||||
|
where W: fmt::Write, I: Iterator<Item=&'a PropertyDeclaration> {
|
||||||
|
|
||||||
// after first serialization(key: value;) add whitespace between the pairs
|
// after first serialization(key: value;) add whitespace between the pairs
|
||||||
if !*is_first_serialization {
|
if !*is_first_serialization {
|
||||||
|
@ -611,7 +622,8 @@ impl Shorthand {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes possible shorthand value to String.
|
/// Serializes possible shorthand value to String.
|
||||||
pub fn serialize_shorthand_to_string(self, declarations: &mut Iterator<Item=&PropertyDeclaration>) -> String {
|
pub fn serialize_shorthand_to_string<'a, I>(self, declarations: I) -> String
|
||||||
|
where I: Iterator<Item=&'a PropertyDeclaration> + Clone {
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
self.serialize_shorthand_to_buffer(&mut result, declarations, &mut true).unwrap();
|
self.serialize_shorthand_to_buffer(&mut result, declarations, &mut true).unwrap();
|
||||||
result
|
result
|
||||||
|
@ -620,28 +632,28 @@ impl Shorthand {
|
||||||
|
|
||||||
/// Serializes possible shorthand value to input buffer given a list of longhand declarations.
|
/// Serializes possible shorthand value to input buffer given a list of longhand declarations.
|
||||||
/// On success, returns true if shorthand value is written and false if no shorthand value is present.
|
/// On success, returns true if shorthand value is written and false if no shorthand value is present.
|
||||||
pub fn serialize_shorthand_to_buffer<W>(self,
|
pub fn serialize_shorthand_to_buffer<'a, W, I>(self,
|
||||||
dest: &mut W,
|
dest: &mut W,
|
||||||
declarations: &mut Iterator<Item=&PropertyDeclaration>,
|
declarations: I,
|
||||||
is_first_serialization: &mut bool)
|
is_first_serialization: &mut bool)
|
||||||
-> Result<bool, fmt::Error> where W: Write {
|
-> Result<bool, fmt::Error>
|
||||||
|
where W: Write, I: Iterator<Item=&'a PropertyDeclaration> + Clone {
|
||||||
|
|
||||||
// FIXME: I know that creating this list here is wrong, but I couldn't get it to compile otherwise
|
// Only cloning iterators (a few pointers each) not declarations.
|
||||||
// using plain iterators, need advice!
|
let mut declarations2 = declarations.clone();
|
||||||
let declaration_list: Vec<_> = declarations.cloned().collect();
|
let mut declarations3 = declarations.clone();
|
||||||
let mut declarations = declaration_list.iter();
|
|
||||||
|
|
||||||
let first_declaration = match declarations.next() {
|
let first_declaration = match declarations2.next() {
|
||||||
Some(declaration) => declaration,
|
Some(declaration) => declaration,
|
||||||
None => return Ok(false)
|
None => return Ok(false)
|
||||||
};
|
};
|
||||||
|
|
||||||
let property_name = &self.name();
|
let property_name = self.name();
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-variables/#variables-in-shorthands
|
// https://drafts.csswg.org/css-variables/#variables-in-shorthands
|
||||||
if let Some(css) = first_declaration.with_variables_from_shorthand(self) {
|
if let Some(css) = first_declaration.with_variables_from_shorthand(self) {
|
||||||
if declarations.all(|d| d.with_variables_from_shorthand(self) == Some(css)) {
|
if declarations2.all(|d| d.with_variables_from_shorthand(self) == Some(css)) {
|
||||||
return append_serialization(
|
return append_serialization::<W, I>(
|
||||||
dest, property_name, AppendableValue::Css(css), false, is_first_serialization
|
dest, property_name, AppendableValue::Css(css), false, is_first_serialization
|
||||||
).and_then(|_| Ok(true));
|
).and_then(|_| Ok(true));
|
||||||
}
|
}
|
||||||
|
@ -650,12 +662,12 @@ impl Shorthand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !declaration_list.iter().any(|d| d.with_variables()) {
|
if !declarations3.any(|d| d.with_variables()) {
|
||||||
try!(
|
try!(
|
||||||
append_serialization(
|
append_serialization(
|
||||||
dest,
|
dest,
|
||||||
property_name,
|
property_name,
|
||||||
AppendableValue::DeclarationsForShorthand(&mut declaration_list.iter()),
|
AppendableValue::DeclarationsForShorthand(declarations),
|
||||||
false,
|
false,
|
||||||
is_first_serialization
|
is_first_serialization
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue