mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Animation shorthand should be serialized only when the value lists have the same length.
Fixes #15398 The previous commit did most of the work here of updating the algorithm to skip shorthands if a shorthand value was an empty string. This commit just updates animations LonghandToSerialize's implementation of to_css_declared to write an empty string value if the list lengths differ (and updates the test to match).
This commit is contained in:
parent
a0998d30d4
commit
bcafe21dc9
4 changed files with 40 additions and 46 deletions
|
@ -344,23 +344,21 @@ impl ToCss for PropertyDeclarationBlock {
|
||||||
|
|
||||||
// Substep 5 - Let value be the result of invoking serialize a CSS
|
// Substep 5 - Let value be the result of invoking serialize a CSS
|
||||||
// value of current longhands.
|
// value of current longhands.
|
||||||
let mut value = String::from("");
|
let mut value = String::new();
|
||||||
match shorthand.get_shorthand_appendable_value(current_longhands.iter().cloned()) {
|
match shorthand.get_shorthand_appendable_value(current_longhands.iter().cloned()) {
|
||||||
None => continue,
|
None => continue,
|
||||||
Some(appendable_value) => {
|
Some(appendable_value) => {
|
||||||
// Also demo test of overflow with important - I think it'll not
|
|
||||||
// be correct.
|
|
||||||
try!(append_declaration_value(&mut value, appendable_value));
|
try!(append_declaration_value(&mut value, appendable_value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Substep 6
|
// Substep 6
|
||||||
if value == "" {
|
if value.is_empty() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Substeps 7 and 8
|
// Substeps 7 and 8
|
||||||
try!(append_serialization::<W, Cloned<slice::Iter< &PropertyDeclaration>>, _>(
|
try!(append_serialization::<W, Cloned<slice::Iter< _>>, _>(
|
||||||
dest, &shorthand, AppendableValue::Css(&value), importance,
|
dest, &shorthand, AppendableValue::Css(&value), importance,
|
||||||
&mut is_first_serialization));
|
&mut is_first_serialization));
|
||||||
|
|
||||||
|
@ -417,7 +415,8 @@ pub enum AppendableValue<'a, I>
|
||||||
/// FIXME: This needs more docs, where are the shorthands expanded? We print
|
/// FIXME: This needs more docs, where are the shorthands expanded? We print
|
||||||
/// the property name before-hand, don't we?
|
/// the property name before-hand, don't we?
|
||||||
DeclarationsForShorthand(ShorthandId, I),
|
DeclarationsForShorthand(ShorthandId, I),
|
||||||
/// A raw CSS string, coming for example from a property with CSS variables.
|
/// A raw CSS string, coming for example from a property with CSS variables,
|
||||||
|
/// or when storing a serialized shorthand value before appending directly.
|
||||||
Css(&'a str)
|
Css(&'a str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,7 +443,6 @@ pub fn append_declaration_value<'a, W, I>(dest: &mut W,
|
||||||
I: Iterator<Item=&'a PropertyDeclaration>,
|
I: Iterator<Item=&'a PropertyDeclaration>,
|
||||||
{
|
{
|
||||||
match appendable_value {
|
match appendable_value {
|
||||||
// Should be able to use this enum to pass the already serialized css?
|
|
||||||
AppendableValue::Css(css) => {
|
AppendableValue::Css(css) => {
|
||||||
try!(write!(dest, "{}", css))
|
try!(write!(dest, "{}", css))
|
||||||
},
|
},
|
||||||
|
@ -485,8 +483,10 @@ pub fn append_serialization<'a, W, I, N>(dest: &mut W,
|
||||||
// for normal parsed values, add a space between key: and value
|
// for normal parsed values, add a space between key: and value
|
||||||
try!(write!(dest, " "));
|
try!(write!(dest, " "));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&AppendableValue::DeclarationsForShorthand(..) => try!(write!(dest, " "))
|
// Currently append_serialization is only called with a Css or
|
||||||
|
// a Declaration AppendableValue.
|
||||||
|
&AppendableValue::DeclarationsForShorthand(..) => unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
try!(append_declaration_value(dest, appendable_value));
|
try!(append_declaration_value(dest, appendable_value));
|
||||||
|
|
|
@ -549,7 +549,7 @@ impl ShorthandId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find an return an appendable value for the given declarations.
|
/// Finds and returns an appendable value for the given declarations.
|
||||||
///
|
///
|
||||||
/// Returns the optional appendable value.
|
/// Returns the optional appendable value.
|
||||||
pub fn get_shorthand_appendable_value<'a, I>(self,
|
pub fn get_shorthand_appendable_value<'a, I>(self,
|
||||||
|
|
|
@ -279,27 +279,27 @@ macro_rules! try_parse_one {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: When the lengths are different, shorthand shouldn't be serialized
|
let len = extract_value(self.animation_name).map(|i| i.0.len()).unwrap_or(0);
|
||||||
// at all.
|
|
||||||
use std::cmp;
|
|
||||||
let mut len = 0;
|
|
||||||
% for name in "duration timing_function delay direction fill_mode iteration_count play_state name".split():
|
|
||||||
len = cmp::max(len, extract_value(self.animation_${name}).map(|i| i.0.len())
|
|
||||||
.unwrap_or(0));
|
|
||||||
% endfor
|
|
||||||
|
|
||||||
// There should be at least one declared value
|
// There should be at least one declared value
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
return dest.write_str("")
|
return dest.write_str("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If any value list length is differs then we don't do a shorthand serialization
|
||||||
|
// either.
|
||||||
|
% for name in "duration timing_function delay direction fill_mode iteration_count play_state".split():
|
||||||
|
if len != extract_value(self.animation_${name}).map(|i| i.0.len()).unwrap_or(0) {
|
||||||
|
return dest.write_str("")
|
||||||
|
}
|
||||||
|
% endfor
|
||||||
|
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
% for name in "duration timing_function delay direction fill_mode iteration_count play_state name".split():
|
% for name in "duration timing_function delay direction fill_mode iteration_count play_state name".split():
|
||||||
let ${name} = if let DeclaredValue::Value(ref arr) = *self.animation_${name} {
|
let ${name} = if let DeclaredValue::Value(ref arr) = *self.animation_${name} {
|
||||||
arr.0.get(i % arr.0.len())
|
&arr.0[i]
|
||||||
} else {
|
} else {
|
||||||
None
|
unreachable!()
|
||||||
};
|
};
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
|
@ -310,15 +310,11 @@ macro_rules! try_parse_one {
|
||||||
}
|
}
|
||||||
|
|
||||||
% for name in "duration timing_function delay direction fill_mode iteration_count play_state".split():
|
% for name in "duration timing_function delay direction fill_mode iteration_count play_state".split():
|
||||||
if let Some(${name}) = ${name} {
|
try!(${name}.to_css(dest));
|
||||||
try!(${name}.to_css(dest));
|
try!(write!(dest, " "));
|
||||||
try!(write!(dest, " "));
|
|
||||||
}
|
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
if let Some(name) = name {
|
try!(name.to_css(dest));
|
||||||
try!(name.to_css(dest));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1192,27 +1192,25 @@ mod shorthand_serialization {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_multiple_animations_unequal_property_lists() {
|
fn serialize_multiple_animations_unequal_property_lists() {
|
||||||
// Currently the implementation cycles values if the lists are
|
// When the lengths of property values are different, the shorthand serialization
|
||||||
// uneven. This is incorrect, in that we should serialize only
|
// should not be used. Previously the implementation cycled values if the lists were
|
||||||
// when the lists have the same length (both here and for background
|
// uneven. This is incorrect, in that we should serialize to a shorthand only when the
|
||||||
// and transition. See https://github.com/servo/servo/issues/15398 )
|
// lists have the same length (both here and for background and transition. See
|
||||||
let block = property_declaration_block("\
|
// https://github.com/servo/servo/issues/15398 )
|
||||||
animation-name: bounce, roll, flip, jump;\
|
let block_text = "\
|
||||||
animation-duration: 1s, 0.2s;\
|
animation-name: bounce, roll, flip, jump; \
|
||||||
animation-timing-function: ease-in, linear;\
|
animation-duration: 1s, 0.2s; \
|
||||||
animation-delay: 0s, 1s, 0.5s;\
|
animation-timing-function: ease-in, linear; \
|
||||||
animation-direction: normal;\
|
animation-delay: 0s, 1s, 0.5s; \
|
||||||
animation-fill-mode: forwards, backwards;\
|
animation-direction: normal; \
|
||||||
animation-iteration-count: infinite, 2;\
|
animation-fill-mode: forwards, backwards; \
|
||||||
animation-play-state: paused, running;");
|
animation-iteration-count: infinite, 2; \
|
||||||
|
animation-play-state: paused, running;";
|
||||||
|
let block = property_declaration_block(block_text);
|
||||||
|
|
||||||
let serialization = block.to_css_string();
|
let serialization = block.to_css_string();
|
||||||
|
|
||||||
assert_eq!(serialization, "animation: \
|
assert_eq!(serialization, block_text);
|
||||||
1s ease-in 0s normal forwards infinite paused bounce, \
|
|
||||||
0.2s linear 1s normal backwards 2 running roll, \
|
|
||||||
1s ease-in 0.5s normal forwards infinite paused flip, \
|
|
||||||
0.2s linear 0s normal backwards 2 running jump;")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue