Bug 142932 - CSS Selectors: fix attribute case-insensitive matching of Contain and List
Summary: CSS Selectors: fix attribute case-insensitive matching of Contain and List
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Benjamin Poulain
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-03-20 21:14 PDT by Benjamin Poulain
Modified: 2015-03-22 22:05 PDT (History)
2 users (show)

See Also:


Attachments
Patch (10.98 KB, patch)
2015-03-20 21:15 PDT, Benjamin Poulain
no flags Details | Formatted Diff | Diff
Patch (126.38 KB, patch)
2015-03-22 13:06 PDT, Benjamin Poulain
no flags Details | Formatted Diff | Diff
Patch (125.32 KB, patch)
2015-03-22 20:16 PDT, Benjamin Poulain
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Benjamin Poulain 2015-03-20 21:14:59 PDT
CSS Selectors: fix attribute case-insensitive matching of Contain and List
Comment 1 Benjamin Poulain 2015-03-20 21:15:20 PDT
Created attachment 249159 [details]
Patch
Comment 2 Benjamin Poulain 2015-03-22 13:06:18 PDT
Created attachment 249203 [details]
Patch
Comment 3 Darin Adler 2015-03-22 18:28:40 PDT
Comment on attachment 249203 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=249203&action=review

> Source/WTF/wtf/text/StringCommon.h:421
> +template <typename SearchCharacterType, typename MatchCharacterType>
> +size_t findIgnoringASCIICase(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned startOffset, unsigned searchLength, unsigned matchLength)

I think the searchCharacters pointer should be before adding startOffset and this function should add startOffset and we should remove all the "+ startOffset" from the callers.

> Source/WTF/wtf/text/StringCommon.h:424
> +    // delta is the number of additional times to test; delta == 0 means test only once.
> +    unsigned delta = searchLength - matchLength;

Seems we need to assert searchLength >= matchLength.

> Source/WTF/wtf/text/StringCommon.h:433
> +    unsigned i = 0;
> +    // Keep looping until we match.
> +    while (!equalIgnoringASCIICase(searchCharacters + i, matchCharacters, matchLength)) {
> +        if (i == delta)
> +            return notFound;
> +        ++i;
> +    }
> +    return startOffset + i;

I think this should be a for loop:

    unsigned i;
    for (i = 0; !equalIgnoringASCIICase(searchCharacters + i, matchCharacters, matchLength); ++i) {
        if (i == delta)
           return notFound;
    }
    return startOffset + i;

But I think we should write it in a more traditional fashion:

    for (unsigned i = 0; i <= delta; ++i) {
        if (equalIgnoringASCIICase(searchCharacters + i, matchCharacters, matchLength))
            return startOffset + i;
    }
    return notFound;

> Source/WTF/wtf/text/StringView.h:108
> +    WTF_EXPORT_STRING_API size_t findIgnoringASCIICase(const StringView&, unsigned startOffset) const;

If you have a StringView and want to apply a startOffset it’s just view.substring(startOffset) so it’s not really helpful to have this overload.

> Source/WTF/wtf/text/StringView.h:112
> +    WTF_EXPORT_STRING_API bool containsIgnoringASCIICase(const StringView&, unsigned startOffset) const;

If you have a StringView and want to apply a startOffset it’s just view.substring(startOffset) so it’s not really helpful to have this overload.

> Source/WebCore/css/SelectorChecker.cpp:460
> +        bool valueContainsSelectorValue;
> +        if (caseSensitive)
> +            valueContainsSelectorValue = value.contains(selectorValue);
> +        else
> +            valueContainsSelectorValue = value.containsIgnoringASCIICase(selectorValue);
> +
> +        if (!valueContainsSelectorValue || selectorValue.isEmpty())
>              return false;

This is strange code. Why call contains when selectorValue is empty? Why not just return first? Then we avoid the whole local variable thing:

    if (selectorValue.isEmpty())
        return false;
    if (caseSensitive) {
        if (value.contains(selectorValue))
            return false;
    } else {
        if (value.containsIgnoringASCIICase(selectorValue))
            return false;
    }

And in fact, that’s exactly the coding style used below for Begin and End.
Comment 4 Benjamin Poulain 2015-03-22 19:21:37 PDT
(In reply to comment #3)
> > Source/WebCore/css/SelectorChecker.cpp:460
> > +        bool valueContainsSelectorValue;
> > +        if (caseSensitive)
> > +            valueContainsSelectorValue = value.contains(selectorValue);
> > +        else
> > +            valueContainsSelectorValue = value.containsIgnoringASCIICase(selectorValue);
> > +
> > +        if (!valueContainsSelectorValue || selectorValue.isEmpty())
> >              return false;
> 
> This is strange code. Why call contains when selectorValue is empty? Why not
> just return first? Then we avoid the whole local variable thing:

The reason was that selectorValue.isEmpty() never happens in practice.

But you are right, better make this code clean. The CSS JIT does a much better job at making this fast.
Comment 5 Benjamin Poulain 2015-03-22 20:16:07 PDT
Created attachment 249218 [details]
Patch
Comment 6 WebKit Commit Bot 2015-03-22 22:05:27 PDT
Comment on attachment 249218 [details]
Patch

Clearing flags on attachment: 249218

Committed r181845: <http://trac.webkit.org/changeset/181845>
Comment 7 WebKit Commit Bot 2015-03-22 22:05:31 PDT
All reviewed patches have been landed.  Closing bug.