style: Avoid quadratic time serialization of a declaration block.

At least when the longhands aren't custom properties.

We should also look into not serializing the style attribute eagerly when it's
not needed... But a lot of code currently rely on attribute values being
dereferenciables to &str, so that's harder to fix.

We should really look into all those vectors around too, but that's probably
less urgent.
This commit is contained in:
Emilio Cobos Álvarez 2017-06-14 11:40:49 +02:00
parent c6da6ba060
commit 8b20d7a982
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C

View file

@ -590,7 +590,7 @@ impl ToCss for PropertyDeclarationBlock {
// Step 1 -> dest = result list // Step 1 -> dest = result list
// Step 2 // Step 2
let mut already_serialized = Vec::new(); let mut already_serialized = PropertyDeclarationIdSet::new();
// Step 3 // Step 3
for &(ref declaration, importance) in &*self.declarations { for &(ref declaration, importance) in &*self.declarations {
@ -598,7 +598,7 @@ impl ToCss for PropertyDeclarationBlock {
let property = declaration.id(); let property = declaration.id();
// Step 3.2 // Step 3.2
if already_serialized.contains(&property) { if already_serialized.contains(property) {
continue; continue;
} }
@ -606,8 +606,10 @@ impl ToCss for PropertyDeclarationBlock {
let shorthands = declaration.shorthands(); let shorthands = declaration.shorthands();
if !shorthands.is_empty() { if !shorthands.is_empty() {
// Step 3.3.1 // Step 3.3.1
//
// FIXME(emilio): All this looks terribly inefficient...
let mut longhands = self.declarations.iter() let mut longhands = self.declarations.iter()
.filter(|d| !already_serialized.contains(&d.0.id())) .filter(|d| !already_serialized.contains(d.0.id()))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// Step 3.3.2 // Step 3.3.2
@ -642,10 +644,10 @@ impl ToCss for PropertyDeclarationBlock {
} }
// Substep 1: // Substep 1:
// //
// Assuming that the PropertyDeclarationBlock contains no // Assuming that the PropertyDeclarationBlock contains no
// duplicate entries, if the current_longhands length is // duplicate entries, if the current_longhands length is
// equal to the properties length, it means that the // equal to the properties length, it means that the
// properties that map to shorthand are present in longhands // properties that map to shorthand are present in longhands
if current_longhands.len() != properties.len() { if current_longhands.len() != properties.len() {
continue; continue;
} }
@ -725,7 +727,7 @@ impl ToCss for PropertyDeclarationBlock {
for current_longhand in &current_longhands { for current_longhand in &current_longhands {
// Substep 9 // Substep 9
already_serialized.push(current_longhand.id()); already_serialized.insert(current_longhand.id());
let index_to_remove = longhands.iter().position(|l| l.0 == **current_longhand); let index_to_remove = longhands.iter().position(|l| l.0 == **current_longhand);
if let Some(index) = index_to_remove { if let Some(index) = index_to_remove {
// Substep 10 // Substep 10
@ -736,7 +738,7 @@ impl ToCss for PropertyDeclarationBlock {
} }
// Step 3.3.4 // Step 3.3.4
if already_serialized.contains(&property) { if already_serialized.contains(property) {
continue; continue;
} }
@ -756,7 +758,7 @@ impl ToCss for PropertyDeclarationBlock {
&mut is_first_serialization)?; &mut is_first_serialization)?;
// Step 3.3.8 // Step 3.3.8
already_serialized.push(property); already_serialized.insert(property);
} }
// Step 4 // Step 4