Changeset 198216 in webkit


Ignore:
Timestamp:
Mar 15, 2016 10:26:50 AM (8 years ago)
Author:
Antti Koivisto
Message:

Source/WebCore:
REGRESSION (196383): Class change invalidation does not handle :not correctly
https://bugs.webkit.org/show_bug.cgi?id=155493
<rdar://problem/24846762>

Reviewed by Andreas Kling.

We fail to invalidate bar style in

:not(.foo) bar { }

when class foo is added or removed.

There is a logic error in the invalidation code. It assumes that class addition can only make new selectors match
and removal make them not match. This is not true when :not is present.

  • style/AttributeChangeInvalidation.h:

(WebCore::Style::AttributeChangeInvalidation::AttributeChangeInvalidation):

  • style/ClassChangeInvalidation.cpp:

(WebCore::Style::ClassChangeInvalidation::invalidateStyle):

Invalidate style and collect full set of rules that may affect descendant style.

(WebCore::Style::ClassChangeInvalidation::invalidateDescendantStyle):

Invalidate with this set both before and after committing the changes.

(WebCore::Style::ClassChangeInvalidation::computeClassChange): Deleted.

  • style/ClassChangeInvalidation.h:

(WebCore::Style::ClassChangeInvalidation::ClassChangeInvalidation):
(WebCore::Style::ClassChangeInvalidation::~ClassChangeInvalidation):

LayoutTests:
Class change invalidation does not handle :not correctly
https://bugs.webkit.org/show_bug.cgi?id=155493
<rdar://problem/24846762>

Reviewed by Andreas Kling.

  • fast/css/style-invalidation-attribute-change-descendants-expected.txt:
  • fast/css/style-invalidation-attribute-change-descendants.html:

Also add :not case for attribute changes (which handles this correctly already).

  • fast/css/style-invalidation-class-change-descendants-expected.txt:
  • fast/css/style-invalidation-class-change-descendants.html:

Add :not case.

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r198211 r198216  
     12016-03-15  Antti Koivisto  <antti@apple.com>
     2
     3        Class change invalidation does not handle :not correctly
     4        https://bugs.webkit.org/show_bug.cgi?id=155493
     5        <rdar://problem/24846762>
     6
     7        Reviewed by Andreas Kling.
     8
     9        * fast/css/style-invalidation-attribute-change-descendants-expected.txt:
     10        * fast/css/style-invalidation-attribute-change-descendants.html:
     11
     12            Also add :not case for attribute changes (which handles this correctly already).
     13
     14        * fast/css/style-invalidation-class-change-descendants-expected.txt:
     15        * fast/css/style-invalidation-class-change-descendants.html:
     16
     17            Add :not case.
     18
    1192016-03-14  Jer Noble  <jer.noble@apple.com>
    220
  • trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants-expected.txt

    r196636 r198216  
    44
    55
     6Setting attribute 'mynotattr' value ''
    67PASS hasExpectedStyle is true
    78PASS testStyleChangeType("root", "NoStyleChange") || testStyleChangeType("root", "InlineStyleChange") is true
     
    144145PASS testStyleChangeType("inert", "NoStyleChange") is true
    145146PASS hasExpectedStyle is true
     147Removing attribute 'mynotattr'
     148PASS testStyleChangeType("root", "NoStyleChange") || testStyleChangeType("root", "InlineStyleChange") is true
     149PASS testStyleChangeType("target", "InlineStyleChange") is true
     150PASS testStyleChangeType("inert", "NoStyleChange") is true
     151PASS hasExpectedStyle is true
     152Setting attribute 'mynotattr' value 'value'
     153PASS testStyleChangeType("root", "NoStyleChange") || testStyleChangeType("root", "InlineStyleChange") is true
     154PASS testStyleChangeType("target", "InlineStyleChange") is true
     155PASS testStyleChangeType("inert", "NoStyleChange") is true
     156PASS hasExpectedStyle is true
    146157PASS successfullyParsed is true
    147158
  • trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants.html

    r196636 r198216  
    4141[myattr2] > target {
    4242    color: rgb(9, 0, 0);
     43}
     44
     45root:not([mynotattr]) target {
     46    color: rgb(10, 0, 0);
    4347}
    4448
     
    126130}
    127131
     132setAttribute('mynotattr', '');
     133
    128134checkStyle(0);
    129135testStyleInvalidation("NoStyleChange");
     
    236242setAttribute('myattr2', 'foo');
    237243testStyleInvalidation("NoStyleChange");
     244checkStyle(1);
     245
     246removeAttribute('mynotattr');
     247testStyleInvalidation("InlineStyleChange");
     248checkStyle(10);
     249
     250setAttribute('mynotattr', 'value');
     251testStyleInvalidation("InlineStyleChange");
    238252checkStyle(1);
    239253
  • trunk/LayoutTests/fast/css/style-invalidation-class-change-descendants-expected.txt

    r196575 r198216  
    44
    55
     6Adding class style5
    67PASS hasExpectedStyle is true
    78PASS testStyleChangeType("root", "NoStyleChange") || testStyleChangeType("root", "InlineStyleChange") is true
     
    5253PASS testStyleChangeType("inert", "NoStyleChange") is true
    5354PASS hasExpectedStyle is true
     55Removing class style5
     56PASS testStyleChangeType("root", "NoStyleChange") || testStyleChangeType("root", "InlineStyleChange") is true
     57PASS testStyleChangeType("target", "InlineStyleChange") is true
     58PASS testStyleChangeType("inert", "NoStyleChange") is true
     59PASS hasExpectedStyle is true
     60Adding class style5
     61PASS testStyleChangeType("root", "NoStyleChange") || testStyleChangeType("root", "InlineStyleChange") is true
     62PASS testStyleChangeType("target", "InlineStyleChange") is true
     63PASS testStyleChangeType("inert", "NoStyleChange") is true
     64PASS hasExpectedStyle is true
    5465PASS successfullyParsed is true
    5566
  • trunk/LayoutTests/fast/css/style-invalidation-class-change-descendants.html

    r196575 r198216  
    2121root.style4 > target inert {
    2222    color: rgb(4, 4, 4);
     23}
     24
     25root:not(.style5) target {
     26    color: rgb(5, 5, 5);
    2327}
    2428
     
    106110}
    107111
     112addClass('style5');
     113
    108114checkStyle(0);
    109115testStyleInvalidation("NoStyleChange");
     
    144150checkStyle(0);
    145151
     152removeClass('style5');
     153testStyleInvalidation("InlineStyleChange");
     154checkStyle(5);
     155
     156addClass('style5');
     157testStyleInvalidation("InlineStyleChange");
     158checkStyle(0);
     159
    146160</script>
    147161<script src="../../resources/js-test-post.js"></script>
  • trunk/Source/WebCore/ChangeLog

    r198211 r198216  
     12016-03-15  Antti Koivisto  <antti@apple.com>
     2
     3        REGRESSION (196383): Class change invalidation does not handle :not correctly
     4        https://bugs.webkit.org/show_bug.cgi?id=155493
     5        <rdar://problem/24846762>
     6
     7        Reviewed by Andreas Kling.
     8
     9        We fail to invalidate bar style in
     10
     11            :not(.foo) bar { }
     12
     13        when class foo is added or removed.
     14
     15        There is a logic error in the invalidation code. It assumes that class addition can only make new selectors match
     16        and removal make them not match. This is not true when :not is present.
     17
     18        * style/AttributeChangeInvalidation.h:
     19        (WebCore::Style::AttributeChangeInvalidation::AttributeChangeInvalidation):
     20        * style/ClassChangeInvalidation.cpp:
     21        (WebCore::Style::ClassChangeInvalidation::invalidateStyle):
     22
     23            Invalidate style and collect full set of rules that may affect descendant style.
     24
     25        (WebCore::Style::ClassChangeInvalidation::invalidateDescendantStyle):
     26
     27            Invalidate with this set both before and after committing the changes.
     28
     29        (WebCore::Style::ClassChangeInvalidation::computeClassChange): Deleted.
     30        * style/ClassChangeInvalidation.h:
     31        (WebCore::Style::ClassChangeInvalidation::ClassChangeInvalidation):
     32        (WebCore::Style::ClassChangeInvalidation::~ClassChangeInvalidation):
     33
    1342016-03-14  Jer Noble  <jer.noble@apple.com>
    235
  • trunk/Source/WebCore/style/AttributeChangeInvalidation.h

    r196629 r198216  
    4747    Element& m_element;
    4848
    49     RuleSet* m_descendantInvalidationRuleSet { nullptr };
     49    const RuleSet* m_descendantInvalidationRuleSet { nullptr };
    5050};
    5151
  • trunk/Source/WebCore/style/ClassChangeInvalidation.cpp

    r196560 r198216  
    3535namespace Style {
    3636
    37 auto ClassChangeInvalidation::collectClasses(const SpaceSplitString& classes) -> ClassChangeVector
     37using ClassChangeVector = Vector<AtomicStringImpl*, 4>;
     38
     39static ClassChangeVector collectClasses(const SpaceSplitString& classes)
    3840{
    3941    ClassChangeVector result;
     
    4446}
    4547
    46 void ClassChangeInvalidation::computeClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses)
     48static ClassChangeVector computeClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses)
    4749{
    4850    unsigned oldSize = oldClasses.size();
    4951    unsigned newSize = newClasses.size();
    5052
    51     if (!oldSize) {
    52         m_addedClasses = collectClasses(newClasses);
    53         return;
    54     }
    55     if (!newSize) {
    56         m_removedClasses = collectClasses(oldClasses);
    57         return;
    58     }
     53    if (!oldSize)
     54        return collectClasses(newClasses);
     55    if (!newSize)
     56        return collectClasses(oldClasses);
     57
     58    ClassChangeVector changedClasses;
    5959
    6060    BitVector remainingClassBits;
     
    7171        if (foundFromBoth)
    7272            continue;
    73         m_addedClasses.append(newClasses[i].impl());
     73        changedClasses.append(newClasses[i].impl());
    7474    }
    7575    for (unsigned i = 0; i < oldSize; ++i) {
     
    7777        if (remainingClassBits.quickGet(i))
    7878            continue;
    79         m_removedClasses.append(oldClasses[i].impl());
     79        changedClasses.append(oldClasses[i].impl());
    8080    }
     81
     82    return changedClasses;
    8183}
    8284
    83 void ClassChangeInvalidation::invalidateStyle(const ClassChangeVector& changedClasses)
     85void ClassChangeInvalidation::invalidateStyle(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses)
    8486{
     87    auto changedClasses = computeClassChange(oldClasses, newClasses);
     88
    8589    auto& ruleSets = m_element.styleResolver().ruleSets();
    8690
    87     Vector<AtomicStringImpl*, 4> changedClassesAffectingStyle;
     91    ClassChangeVector changedClassesAffectingStyle;
    8892    for (auto* changedClass : changedClasses) {
    8993        if (ruleSets.features().classesInRules.contains(changedClass))
     
    108112        if (!ancestorClassRules)
    109113            continue;
     114        m_descendantInvalidationRuleSets.append(ancestorClassRules);
     115    }
     116}
     117
     118void ClassChangeInvalidation::invalidateDescendantStyle()
     119{
     120    for (auto* ancestorClassRules : m_descendantInvalidationRuleSets) {
    110121        StyleInvalidationAnalysis invalidationAnalysis(*ancestorClassRules);
    111122        invalidationAnalysis.invalidateStyle(m_element);
  • trunk/Source/WebCore/style/ClassChangeInvalidation.h

    r196629 r198216  
    4545
    4646private:
    47     using ClassChangeVector = Vector<AtomicStringImpl*, 4>;
    48 
    49     void computeClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses);
    50     void invalidateStyle(const ClassChangeVector&);
    51 
    52     static ClassChangeVector collectClasses(const SpaceSplitString&);
     47    void invalidateStyle(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses);
     48    void invalidateDescendantStyle();
    5349
    5450    const bool m_isEnabled;
    5551    Element& m_element;
    5652
    57     ClassChangeVector m_addedClasses;
    58     ClassChangeVector m_removedClasses;
     53    Vector<const RuleSet*, 4> m_descendantInvalidationRuleSets;
    5954};
    6055
     
    6661    if (!m_isEnabled)
    6762        return;
    68     computeClassChange(oldClasses, newClasses);
    69     invalidateStyle(m_removedClasses);
     63    invalidateStyle(oldClasses, newClasses);
     64    invalidateDescendantStyle();
    7065}
    7166
     
    7469    if (!m_isEnabled)
    7570        return;
    76     invalidateStyle(m_addedClasses);
     71    invalidateDescendantStyle();
    7772}
    7873   
Note: See TracChangeset for help on using the changeset viewer.