Bug 36734

Summary: Implement symbolic CSS3 list-style-types
Product: WebKit Reporter: Daniel Bates <dbates>
Component: CSSAssignee: Daniel Bates <dbates>
Status: RESOLVED FIXED    
Severity: Normal CC: abarth, adman.com, bdakin, darin, eric, hyatt, ian, jwieczorek, Ms2ger, webkit.review.bot
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
Bug Depends on: 42803    
Bug Blocks:    
Attachments:
Description Flags
Patch with test case
darin: review-
Patch with test case
none
Patch with test case
darin: review-
Patch with test case
none
Patch with test case
none
Patch with test case darin: review+

Description Daniel Bates 2010-03-28 16:19:00 PDT
We should implement all of the symbolic CSS3 list-style-types as per section 4.5 of the CSS3 Lists module <http://www.w3.org/TR/css3-lists/#symbolic>.
Comment 1 Daniel Bates 2010-03-29 14:17:11 PDT
Created attachment 51965 [details]
Patch with test case
Comment 2 WebKit Review Bot 2010-03-29 14:23:15 PDT
Attachment 51965 [details] did not pass style-queue:

Failed to run "WebKitTools/Scripts/check-webkit-style" exit_code: 1
File not a recognized type to check. Skipping: "WebCore/css/CSSValueKeywords.in"
File not a recognized type to check. Skipping: "WebCore/inspector/front-end/SourceCSSTokenizer.re2js"
WebCore/rendering/RenderListMarker.cpp:1048:  A case label should not be indented, but line up with its switch statement.  [whitespace/indent] [4]
WebCore/rendering/RenderListMarker.cpp:1436:  A case label should not be indented, but line up with its switch statement.  [whitespace/indent] [4]
Total errors found: 2 in 9 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 3 Darin Adler 2010-03-29 17:38:27 PDT
See bug 36724 for my ideas about how to make some text-only tests for list numbering.
Comment 4 Darin Adler 2010-03-29 17:39:03 PDT
Mac early warning system says there was a failure, but I don't see what the error was.
Comment 5 Darin Adler 2010-03-29 17:51:32 PDT
Comment on attachment 51965 [details]
Patch with test case

> -        isNegativeNumber = true;
> +        isNegativeNumber = type == SymbolicSequence ? false : true; // Symbolics cannot be negative.

For clarity I suggest writing either this:

    isNegativeNumber = type != SymbolicSequence; // Symbolics cannot be negative.

Or this:

    if (type != SymbolicSequence)
        isNegativeNumber = true; // Symbolics cannot be negative.

It seems to me that the ?: expression is too oblique. Especially "? false : true", which is just a sideways way to write "!".

Another way to do this is to let isNegativeNumber get set, and then change it below to:

    if (isNegativeNumber && type != SymbolicSequence)
        letters[lettersSize - ++length] = hyphenMinus;

Because symbolics can indeed be negative. They just don't show a minus sign when they are.

> +        unsigned numSymbols = ceil((double) (numberShadow + 1) / sequenceSize) - 1;

There is no need to involve floating point. The following expression gives the same result for all the positive numbers I tried:

    unsigned numSymbols = numberShadow / sequenceSize;

You should use that instead unless there's a reason not to.

> +            width = m_text.isEmpty() ? 0 : font.width(m_text); // no suffix for these types

I don't think you need a special case here for the empty string.

> +        case Asterisks:
> +        case Footnotes: {
> +            if (m_text.isEmpty())
> +                return IntRect();
> +            const Font& font = style()->font();
> +            return IntRect(x(), y() + font.ascent(), font.width(m_text), font.height());
> +        }

I'm not sure you need it here either.

review- for the gratuitous floating point
Comment 6 Daniel Bates 2010-03-29 20:38:45 PDT
(In reply to comment #5)
> (From update of attachment 51965 [details])
> > -        isNegativeNumber = true;
> > +        isNegativeNumber = type == SymbolicSequence ? false : true; // Symbolics cannot be negative.
> 
> For clarity I suggest writing either this:
> 
>     isNegativeNumber = type != SymbolicSequence; // Symbolics cannot be
> negative.
> 
> Or this:
> 
>     if (type != SymbolicSequence)
>         isNegativeNumber = true; // Symbolics cannot be negative.
> 
> It seems to me that the ?: expression is too oblique. Especially "? false :
> true", which is just a sideways way to write "!".
> 
> Another way to do this is to let isNegativeNumber get set, and then change it
> below to:
> 
>     if (isNegativeNumber && type != SymbolicSequence)
>         letters[lettersSize - ++length] = hyphenMinus;

Will change, went with the last suggestion.

> Because symbolics can indeed be negative. They just don't show a minus sign
> when they are.
> 
> > +        unsigned numSymbols = ceil((double) (numberShadow + 1) / sequenceSize) - 1;

> 
> There is no need to involve floating point. The following expression gives the
> same result for all the positive numbers I tried:
> 
>     unsigned numSymbols = numberShadow / sequenceSize;

Will change.

> 
> You should use that instead unless there's a reason not to.
> 
> > +            width = m_text.isEmpty() ? 0 : font.width(m_text); // no suffix for these types
> 

Will change.

> I don't think you need a special case here for the empty string.
> 
> > +        case Asterisks:
> > +        case Footnotes: {
> > +            if (m_text.isEmpty())
> > +                return IntRect();
> > +            const Font& font = style()->font();
> > +            return IntRect(x(), y() + font.ascent(), font.width(m_text), font.height());
> > +        }
> 
> I'm not sure you need it here either.

Will change.
Comment 7 Daniel Bates 2010-03-29 20:44:42 PDT
Created attachment 51998 [details]
Patch with test case

Updated patch based on Darin's suggestions.

I am not marking this patch for review, yet, as I am looking into Darin's idea on how to make a text-only layout test for this.

Also, I am aware of the style issues. I suggest we do a stye clean-up patch either preceding or proceeding this bug.
Comment 8 Daniel Bates 2010-04-08 14:57:39 PDT
Comment on attachment 51998 [details]
Patch with test case

After looking over the discussion in bug #36724 which implied adding DRT support so that we can test using text-only tests, I suggest that we address this issue in a separate bug. I agree we should add this support since using render tree results seems unnecessary.

If Darin or anyone else feels that we should add DRT support/make it so that we can use text-only tests before proceeding with this patch then let me know.
Comment 9 WebKit Review Bot 2010-04-08 15:02:35 PDT
Attachment 51998 [details] did not pass style-queue:

Failed to run "WebKitTools/Scripts/check-webkit-style" exit_code: 1
WebCore/rendering/RenderListMarker.cpp:1048:  A case label should not be indented, but line up with its switch statement.  [whitespace/indent] [4]
WebCore/rendering/RenderListMarker.cpp:1436:  A case label should not be indented, but line up with its switch statement.  [whitespace/indent] [4]
Total errors found: 2 in 9 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 10 Jakub Wieczorek 2010-04-08 15:37:29 PDT
(In reply to comment #8)
> (From update of attachment 51998 [details])
> After looking over the discussion in bug #36724 which implied adding DRT
> support so that we can test using text-only tests, I suggest that we address
> this issue in a separate bug. I agree we should add this support since using
> render tree results seems unnecessary.
> 
> If Darin or anyone else feels that we should add DRT support/make it so that we
> can use text-only tests before proceeding with this patch then let me know.

FYI: Text-only test support for lists is being added as part of #37060.
Comment 11 Daniel Bates 2010-04-08 15:41:55 PDT
Comment on attachment 51998 [details]
Patch with test case

Will update test case with the landing of bug #37060, which includes DRT support.
Comment 12 Daniel Bates 2010-07-23 22:02:26 PDT
Created attachment 62485 [details]
Patch with test case

With the resolution of Bug #42054, converted test case to text.

This patch depends on the changes to the JavaScript script LayoutTests/fast/lists/resources/dump-list.js in the patch "[Patch] Part 1 of 2 (Updated tests and expected results)" of Bug #42803.
Comment 13 WebKit Review Bot 2010-07-23 22:04:38 PDT
Attachment 62485 [details] did not pass style-queue:

Failed to run "['WebKitTools/Scripts/check-webkit-style']" exit_code: 1
WebCore/rendering/RenderListMarker.cpp:1050:  A case label should not be indented, but line up with its switch statement.  [whitespace/indent] [4]
WebCore/rendering/RenderListMarker.cpp:1438:  A case label should not be indented, but line up with its switch statement.  [whitespace/indent] [4]
Total errors found: 2 in 9 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 14 Darin Adler 2010-07-24 12:52:25 PDT
Comment on attachment 62485 [details]
Patch with test case

>      const int lettersSize = sizeof(number) * 8 + 1; // Binary is the worst case; requires one character per bit plus a minus sign.

The new symbols sequence is now the worst case, much worse than binary. If you don't change something there will be buffer overflow.

> Index: LayoutTests/fast/lists/w3-css3-list-styles-symbolic-expected.txt
> ===================================================================
> --- LayoutTests/fast/lists/w3-css3-list-styles-symbolic-expected.txt	(revision 0)
> +++ LayoutTests/fast/lists/w3-css3-list-styles-symbolic-expected.txt	(revision 0)
> @@ -0,0 +1,13 @@
> +CSS3 Symbolic list-style-type
> +
> +asterisks
> +
> +PASS
> +PASS
> +PASS
> +footnotes
> +
> +PASS
> +PASS
> +PASS
> +

Tests that just write out "PASS PASS PASS" are suboptimal. Can you change this test so the output makes it clearer what is going on?

Do we need some kind of limit? I'm worried that you can generate millions of asterisks and cause problems that way. Some limit would prevent that possibility.

review- because I think this has a buffer overflow in it
Comment 15 Daniel Bates 2010-07-24 18:46:26 PDT
(In reply to comment #14)
> (From update of attachment 62485 [details])
> >      const int lettersSize = sizeof(number) * 8 + 1; // Binary is the worst case; requires one character per bit plus a minus sign.
> 
> The new symbols sequence is now the worst case, much worse than binary. If you don't change something there will be buffer overflow.

Thank you Darin for catching this issue. Will fix.

> 
> > Index: LayoutTests/fast/lists/w3-css3-list-styles-symbolic-expected.txt
> > ===================================================================
> > --- LayoutTests/fast/lists/w3-css3-list-styles-symbolic-expected.txt	(revision 0)
> > +++ LayoutTests/fast/lists/w3-css3-list-styles-symbolic-expected.txt	(revision 0)
> > @@ -0,0 +1,13 @@
> > +CSS3 Symbolic list-style-type
> > +
> > +asterisks
> > +
> > +PASS
> > +PASS
> [...]
> 
> Tests that just write out "PASS PASS PASS" are suboptimal. Can you change this test so the output makes it clearer what is going on?
>

Sure.

We should also make this message more descriptive in the expected results for tests: w3-css3-list-styles-alphabetic.html and w3-css3-list-styles-numeric.html (included in the patch for Bug #42803). Instead of posting an updated patch for Bug #42803, I thought it would be easier to review just the change to the PASS message. So, I filed Bug #42938. 

I'll update the expected results in this patch to use the updated PASS message.
Comment 16 Daniel Bates 2010-07-29 21:30:49 PDT
Created attachment 63028 [details]
Patch with test case

I picked the upper bound for the length of a symbolic marker to be lettersSize := sizeof(int) * 8 + 1 characters (i.e. the number of characters to represent a binary number plus a minus sign). Currently, we use a fixed sized array, but we want to reconsider this and/or special-case symbolics which use more characters per ordinal than other list style types.
Comment 17 WebKit Review Bot 2010-07-29 21:32:53 PDT
Attachment 63028 [details] did not pass style-queue:

Failed to run "['WebKitTools/Scripts/check-webkit-style']" exit_code: 1
WebCore/rendering/RenderListMarker.cpp:1053:  A case label should not be indented, but line up with its switch statement.  [whitespace/indent] [4]
WebCore/rendering/RenderListMarker.cpp:1441:  A case label should not be indented, but line up with its switch statement.  [whitespace/indent] [4]
Total errors found: 2 in 9 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 18 Darin Adler 2010-07-29 23:18:48 PDT
Comment on attachment 63028 [details]
Patch with test case

> +        unsigned numSymbols = (numberShadow / sequenceSize) % lettersSize;

This is unusual math, given that both numberShadow and lettersSize are int, not unsigned. You are testing it enough, I guess, but I worry since if it goes wrong we could have a buffer overrun.

Why is modulo the right thing to do? We want to go to zero symbols when we hit the maximum length? I would expect a computation involving min instead, and it would be more obvious that prevents the overrun.

I suppose having a maximum is good anyway to avoid crazy behavior, but if there was any argument in favor of supporting long symbolic sequences then I would suggest changing the code to heap allocate in the cases where necessary.
Comment 19 Daniel Bates 2010-07-29 23:22:21 PDT
Comment on attachment 63028 [details]
Patch with test case

Clearing review flag while I look into this further.
Comment 20 Daniel Bates 2010-08-14 19:53:25 PDT
Created attachment 64434 [details]
Patch with test case

Updated patch that substitutes a Vector<UChar> for the fixed sized stack-allocated array so that we can handle arbitrary length symbolics (up to architecture-specific size of int).

The spec. is unclear how we should handle a list with a symbolic list-style-type  and that has a starting ordinal of 0 or some x < 0, where x is an integer. Currently, this patch outputs one symbol and |x| symbols for starting ordinals 0 and x < 0, respectively. From the description of the alphabetic- and numeric- systems, the spec. seems to imply we should output decimal ordinals for these cases. I will try to contact Ian Hickson for his insight on these cases.
Comment 21 Daniel Bates 2010-08-26 21:26:54 PDT
(In reply to comment #20)
> Created an attachment (id=64434) [details]
> Patch with test case
> 
> Updated patch that substitutes a Vector<UChar> for the fixed sized stack-allocated array so that we can handle arbitrary length symbolics (up to architecture-specific size of int).
> 
> The spec. is unclear how we should handle a list with a symbolic list-style-type  and that has a starting ordinal of 0 or some x < 0, where x is an integer. Currently, this patch outputs one symbol and |x| symbols for starting ordinals 0 and x < 0, respectively. From the description of the alphabetic- and numeric- systems, the spec. seems to imply we should output decimal ordinals for these cases. I will try to contact Ian Hickson for his insight on these cases.

Spoke with Ian Hickson last weekend and he confirmed that we should fall back to the decimal list style for ordinals outside the representable range for a list style. In particular, for symbolic list style types we should fall back to the decimal list style for ordinals <= 0.

Bug #44486 implemented the necessary support infrastructure to support the fall back to the decimal list style.
Comment 22 Daniel Bates 2010-08-26 21:27:37 PDT
Created attachment 65675 [details]
Patch with test case
Comment 23 WebKit Review Bot 2010-08-26 21:32:14 PDT
Attachment 65675 [details] did not pass style-queue:

Failed to run "['WebKitTools/Scripts/check-webkit-style']" exit_code: 1
WebCore/rendering/RenderListMarker.cpp:1155:  A case label should not be indented, but line up with its switch statement.  [whitespace/indent] [4]
WebCore/rendering/RenderListMarker.cpp:1543:  A case label should not be indented, but line up with its switch statement.  [whitespace/indent] [4]
Total errors found: 2 in 9 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 24 Darin Adler 2010-08-27 10:48:01 PDT
Comment on attachment 65675 [details]
Patch with test case

> -static inline String toAlphabeticOrNumeric(int number, const UChar* sequence, int sequenceSize, SequenceType type)
> +static inline String toSequence(int number, const UChar* sequence, unsigned sequenceSize, SequenceType type)

The code for SymbolicSequence seems to share almost nothing with the alphabetic and numeric sequences. The assertion needed is different, the buffer size needed is different, the loop is different. About the only thing that's shared is the code to subtract one from the passed-in number.

I suggest implementing toSymbolic without calling toAlphabeticOrNumeric. There's no meaningful code sharing here.

Everything else looks fine.

r=me
Comment 25 Daniel Bates 2010-08-27 11:00:09 PDT
(In reply to comment #24)
> (From update of attachment 65675 [details])
> > -static inline String toAlphabeticOrNumeric(int number, const UChar* sequence, int sequenceSize, SequenceType type)
> > +static inline String toSequence(int number, const UChar* sequence, unsigned sequenceSize, SequenceType type)
> 
> The code for SymbolicSequence seems to share almost nothing with the alphabetic and numeric sequences. The assertion needed is different, the buffer size needed is different, the loop is different. About the only thing that's shared is the code to subtract one from the passed-in number.

You're right. I will separate symbolics out from this function as its implementation has become disjoint. I'll leave the name of the function as toAlphabeticOrNumeric.

> 
> I suggest implementing toSymbolic without calling toAlphabeticOrNumeric. There's no meaningful code sharing here.
>

Will do. 

> Everything else looks fine.
> 
> r=me

Thank you for the review.
Comment 26 Daniel Bates 2010-08-27 20:06:34 PDT
Committed r66296: <http://trac.webkit.org/changeset/66296>
Comment 27 WebKit Review Bot 2010-08-27 22:21:48 PDT
http://trac.webkit.org/changeset/66296 might have broken Qt Linux Release minimal
Comment 28 Adam Barth 2010-08-28 02:41:43 PDT
(In reply to comment #27)
> http://trac.webkit.org/changeset/66296 might have broken Qt Linux Release minimal

Looks like it broke compile there.
Comment 29 Daniel Bates 2010-08-28 08:26:50 PDT
(In reply to comment #28)
> (In reply to comment #27)
> > http://trac.webkit.org/changeset/66296 might have broken Qt Linux Release minimal
> 
> Looks like it broke compile there.

From looking at the stdio output <http://build.webkit.org/builders/Qt%20Linux%20Release%20minimal/builds/7850/steps/compile-webkit/logs/stdio> the compile failed because the slave was lost: "remoteFailed: [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionLost'>: Connection to the other side was lost in a non-clean fashion.
]".