Auto merge of #6979 - mbrubeck:counter, r=pcwalton

Fix crash caused by negative numbers in list counters.

Fixes #6818.  The test still fails because of #6978.

r? @pcwalton

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6979)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-08-04 18:37:10 -06:00
commit b9f00190e1
2 changed files with 30 additions and 10 deletions

View file

@ -531,37 +531,57 @@ pub fn static_representation(list_style_type: list_style_type::T) -> char {
/// Pushes the string that represents the value rendered using the given *alphabetic system* onto /// Pushes the string that represents the value rendered using the given *alphabetic system* onto
/// the accumulator per CSS-COUNTER-STYLES § 3.1.4. /// the accumulator per CSS-COUNTER-STYLES § 3.1.4.
fn push_alphabetic_representation(mut value: i32, system: &[char], accumulator: &mut String) { fn push_alphabetic_representation(mut value: i32, system: &[char], accumulator: &mut String) {
let mut abs_value = handle_negative_value(value, accumulator);
let mut string: SmallVec<[char; 8]> = SmallVec::new(); let mut string: SmallVec<[char; 8]> = SmallVec::new();
while value != 0 { while abs_value != 0 {
// Step 1. // Step 1.
value = value - 1; abs_value = abs_value - 1;
// Step 2. // Step 2.
string.push(system[(value as usize) % system.len()]); string.push(system[abs_value % system.len()]);
// Step 3. // Step 3.
value = ((value as usize) / system.len()) as i32; abs_value = abs_value / system.len();
} }
accumulator.extend(string.iter().cloned().rev()) accumulator.extend(string.iter().cloned().rev())
} }
/// Pushes the string that represents the value rendered using the given *numeric system* onto the /// Pushes the string that represents the value rendered using the given *numeric system* onto the
/// accumulator per CSS-COUNTER-STYLES § 3.1.4. /// accumulator per CSS-COUNTER-STYLES § 3.1.5.
fn push_numeric_representation(mut value: i32, system: &[char], accumulator: &mut String) { fn push_numeric_representation(mut value: i32, system: &[char], accumulator: &mut String) {
let mut abs_value = handle_negative_value(value, accumulator);
// Step 1. // Step 1.
if value == 0 { if abs_value == 0 {
accumulator.push(system[0]); accumulator.push(system[0]);
return return
} }
// Step 2. // Step 2.
let mut string: SmallVec<[char; 8]> = SmallVec::new(); let mut string: SmallVec<[char; 8]> = SmallVec::new();
while value != 0 { while abs_value != 0 {
// Step 2.1. // Step 2.1.
string.push(system[(value as usize) % system.len()]); string.push(system[abs_value % system.len()]);
// Step 2.2. // Step 2.2.
value = ((value as usize) / system.len()) as i32; abs_value = abs_value / system.len();
} }
// Step 3. // Step 3.
accumulator.extend(string.iter().cloned().rev()) accumulator.extend(string.iter().cloned().rev())
} }
/// If the system uses a negative sign, handle negative values per CSS-COUNTER-STYLES § 2.
///
/// Returns the absolute value of the counter.
fn handle_negative_value(value: i32, accumulator: &mut String) -> usize {
// 3. If the counter value is negative and the counter style uses a negative sign, instead
// generate an initial representation using the absolute value of the counter value.
if value < 0 {
// TODO: Support different negative signs using the 'negative' descriptor.
// https://drafts.csswg.org/date/2015-07-16/css-counter-styles/#counter-style-negative
accumulator.push('-');
value.abs() as usize
} else {
value as usize
}
}

View file

@ -1,3 +1,3 @@
[counter-reset-increment-002.htm] [counter-reset-increment-002.htm]
type: reftest type: reftest
expected: TIMEOUT expected: FAIL