Changeset 140299 in webkit


Ignore:
Timestamp:
Jan 20, 2013 10:59:35 PM (11 years ago)
Author:
shinyak@chromium.org
Message:

Distribution state becomes inconsistent with content/shadow reprojection
https://bugs.webkit.org/show_bug.cgi?id=106634

Reviewed by Hajime Morita.

Source/WebCore:

Distribution should be resolved from shallower ShadowDOM to deeper Shadow DOM. However, in the current implementation,
there is a case that distribution for deeper ShadowDOM happens to be resolved before distribution
for shallower ShadowDOM is resolved.

Here, we have 2 problems about distribution.
1) Invalidation state is not propagated to nested (= deeper) ShadowDOM.

  • This causes deeper ShadowDOM looks having a valid distribution though it should be invalid.

2) We are not resolving shallower ShadowDOM when deeper ShadowDOM's distribution is needed.

  • Because of (1), we have to check all the ancestor ShadowDOM.

For (1), we change invalidate() to invalidate nested ShadowDOM's distribution as well.
For (2), when resolving distribution, we will check the ancestor ShadowDOM's distribution state. If the ancestor's
distribution is not valid, we resolve it first.

For optimization of (1), actually we can skip invalidating distribution of some ShadowDOMs.
If ShadowRoot of deeper ShadowDOM does not have an InsertionPoint as children, we can skip invalidating
its distribution, because only children can be distributed to InsertionPoint.

Tests: fast/dom/shadow/distribution-crash.html

fast/dom/shadow/nested-reprojection-inconsistent.html

  • dom/ElementShadow.cpp:

(WebCore::ElementShadow::attach): Should resolve distribution from ancestor.

  • dom/ElementShadow.h:
  • html/shadow/ContentDistributor.cpp:

(WebCore::ContentDistributor::distribute): Added ASSERT that the parent ShadowRoot's distribution is resolved.
(WebCore::ContentDistributor::invalidate): For each InsertionPoint, we have to invalidate
its parent element's distribution (if it has ElementShadow).
(WebCore::ContentDistributor::ensureDistribution):

  • html/shadow/ContentDistributor.h:

(WebCore::ContentDistributor::isValid):

  • html/shadow/HTMLShadowElement.cpp:

(WebCore::HTMLShadowElement::olderShadowRoot): Should resolve distribution from ancestor.

  • html/shadow/InsertionPoint.cpp:

(WebCore::InsertionPoint::attach): ditto.
(WebCore::InsertionPoint::detach): ditto.
(WebCore::InsertionPoint::getDistributedNodes): ditto.
(WebCore::resolveReprojection): ditto.

LayoutTests:

  • fast/dom/shadow/distribution-crash-expected.txt: Added.
  • fast/dom/shadow/distribution-crash.html: Added.
  • fast/dom/shadow/nested-reprojection-inconsistent-expected.txt: Added.
  • fast/dom/shadow/nested-reprojection-inconsistent.html: Added.
Location:
trunk
Files:
4 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r140296 r140299  
     12013-01-20  Shinya Kawanaka  <shinyak@chromium.org>
     2
     3        Distribution state becomes inconsistent with content/shadow reprojection
     4        https://bugs.webkit.org/show_bug.cgi?id=106634
     5
     6        Reviewed by Hajime Morita.
     7
     8        * fast/dom/shadow/distribution-crash-expected.txt: Added.
     9        * fast/dom/shadow/distribution-crash.html: Added.
     10        * fast/dom/shadow/nested-reprojection-inconsistent-expected.txt: Added.
     11        * fast/dom/shadow/nested-reprojection-inconsistent.html: Added.
     12
    1132013-01-20  Kent Tamura  <tkent@chromium.org>
    214
  • trunk/Source/WebCore/ChangeLog

    r140297 r140299  
     12013-01-20  Shinya Kawanaka  <shinyak@chromium.org>
     2
     3        Distribution state becomes inconsistent with content/shadow reprojection
     4        https://bugs.webkit.org/show_bug.cgi?id=106634
     5
     6        Reviewed by Hajime Morita.
     7
     8        Distribution should be resolved from shallower ShadowDOM to deeper Shadow DOM. However, in the current implementation,
     9        there is a case that distribution for deeper ShadowDOM happens to be resolved before distribution
     10        for shallower ShadowDOM is resolved.
     11
     12        Here, we have 2 problems about distribution.
     13        1) Invalidation state is not propagated to nested (= deeper) ShadowDOM.
     14            - This causes deeper ShadowDOM looks having a valid distribution though it should be invalid.
     15        2) We are not resolving shallower ShadowDOM when deeper ShadowDOM's distribution is needed.
     16            - Because of (1), we have to check all the ancestor ShadowDOM.
     17
     18        For (1), we change invalidate() to invalidate nested ShadowDOM's distribution as well.
     19        For (2), when resolving distribution, we will check the ancestor ShadowDOM's distribution state. If the ancestor's
     20        distribution is not valid, we resolve it first.
     21
     22        For optimization of (1), actually we can skip invalidating distribution of some ShadowDOMs.
     23        If ShadowRoot of deeper ShadowDOM does not have an InsertionPoint as children, we can skip invalidating
     24        its distribution, because only children can be distributed to InsertionPoint.
     25
     26        Tests: fast/dom/shadow/distribution-crash.html
     27               fast/dom/shadow/nested-reprojection-inconsistent.html
     28
     29        * dom/ElementShadow.cpp:
     30        (WebCore::ElementShadow::attach): Should resolve distribution from ancestor.
     31        * dom/ElementShadow.h:
     32        * html/shadow/ContentDistributor.cpp:
     33        (WebCore::ContentDistributor::distribute): Added ASSERT that the parent ShadowRoot's distribution is resolved.
     34        (WebCore::ContentDistributor::invalidate): For each InsertionPoint, we have to invalidate
     35        its parent element's distribution (if it has ElementShadow).
     36        (WebCore::ContentDistributor::ensureDistribution):
     37        * html/shadow/ContentDistributor.h:
     38        (WebCore::ContentDistributor::isValid):
     39        * html/shadow/HTMLShadowElement.cpp:
     40        (WebCore::HTMLShadowElement::olderShadowRoot): Should resolve distribution from ancestor.
     41        * html/shadow/InsertionPoint.cpp:
     42        (WebCore::InsertionPoint::attach): ditto.
     43        (WebCore::InsertionPoint::detach): ditto.
     44        (WebCore::InsertionPoint::getDistributedNodes): ditto.
     45        (WebCore::resolveReprojection): ditto.
     46
    1472013-01-20  Dominic Mazzoni  <dmazzoni@google.com>
    248
  • trunk/Source/WebCore/dom/ElementShadow.cpp

    r139269 r140299  
    123123void ElementShadow::attach()
    124124{
    125     ensureDistribution();
     125    ContentDistributor::ensureDistribution(youngestShadowRoot());
     126
    126127    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
    127128        if (!root->attached())
  • trunk/Source/WebCore/dom/ElementShadow.h

    r139325 r140299  
    6565
    6666    void invalidateDistribution() { m_distributor.invalidateDistribution(host()); }
    67     void ensureDistribution() { m_distributor.ensureDistribution(host()); }
    6867    void didAffectSelector(AffectedSelectorMask mask) { m_distributor.didAffectSelector(host(), mask); }
    6968    void willAffectSelector() { m_distributor.willAffectSelector(host()); }
  • trunk/Source/WebCore/html/shadow/ContentDistributor.cpp

    r139410 r140299  
    214214    ASSERT(needsDistribution());
    215215    ASSERT(m_nodeToInsertionPoint.isEmpty());
     216    ASSERT(!host->containingShadowRoot() || host->containingShadowRoot()->owner()->distributor().isValid());
    216217
    217218    m_validity = Valid;
     
    281282                needsReattach = needsReattach || true;
    282283                insertionPoints[i]->clearDistribution();
     284
     285                // After insertionPoint's distribution is invalidated, its reprojection should also be invalidated.
     286                if (!insertionPoints[i]->isActive())
     287                    continue;
     288
     289                if (Element* parent = insertionPoints[i]->parentElement()) {
     290                    if (ElementShadow* shadow = parent->shadow())
     291                        shadow->invalidateDistribution();
     292                }
    283293            }
    284294        }
     
    339349}
    340350
    341 void ContentDistributor::ensureDistribution(Element* host)
    342 {
    343     if (!needsDistribution())
    344         return;
    345     distribute(host);
    346 }
    347 
    348 void ContentDistributor::ensureDistributionFromDocument(Element* source)
    349 {
    350     ContainerNode* mayShadow = source->treeScope()->rootNode();
    351     if (!mayShadow->isShadowRoot())
    352         return;
    353 
    354     Vector<Element*, 8> hosts;
    355     for (Element* current = toShadowRoot(mayShadow)->host(); current; current = current->shadowHost())
    356         hosts.append(current);
    357 
    358     for (size_t i = hosts.size(); i > 0; --i)
    359         hosts[i - 1]->shadow()->ensureDistribution();
     351void ContentDistributor::ensureDistribution(ShadowRoot* shadowRoot)
     352{
     353    ASSERT(shadowRoot);
     354
     355    Vector<ElementShadow*, 8> elementShadows;
     356    for (Element* current = shadowRoot->host(); current; current = current->shadowHost()) {
     357        ElementShadow* elementShadow = current->shadow();
     358        if (!elementShadow->distributor().needsDistribution())
     359            break;
     360
     361        elementShadows.append(elementShadow);
     362    }
     363
     364    for (size_t i = elementShadows.size(); i > 0; --i)
     365        elementShadows[i - 1]->distributor().distribute(elementShadows[i - 1]->host());
    360366}
    361367
  • trunk/Source/WebCore/html/shadow/ContentDistributor.h

    r139269 r140299  
    129129    void distributeNodeChildrenTo(InsertionPoint*, ContainerNode*);
    130130
    131     void ensureDistribution(Element* host);
    132131    void invalidateDistribution(Element* host);
    133132    void didShadowBoundaryChange(Element* host);
     
    135134    void willAffectSelector(Element* host);
    136135
    137     static void ensureDistributionFromDocument(Element* source);
     136    static void ensureDistribution(ShadowRoot*);
    138137
    139138private:
     
    147146
    148147    void setValidity(Validity validity) { m_validity = validity; }
     148    bool isValid() const { return m_validity == Valid; }
    149149    bool needsDistribution() const;
    150150    bool needsInvalidation() const { return m_validity != Invalidated; }
  • trunk/Source/WebCore/html/shadow/HTMLShadowElement.cpp

    r139410 r140299  
    5959ShadowRoot* HTMLShadowElement::olderShadowRoot()
    6060{
    61     if (!treeScope()->rootNode()->isShadowRoot())
     61    ShadowRoot* containingRoot = containingShadowRoot();
     62    if (!containingRoot)
    6263        return 0;
    6364
    64     ContentDistributor::ensureDistributionFromDocument(this);
     65    ContentDistributor::ensureDistribution(containingRoot);
    6566
    66     ShadowRoot* older = toShadowRoot(treeScope()->rootNode())->olderShadowRoot();
     67    ShadowRoot* older = containingRoot->olderShadowRoot();
    6768    if (!older || older->type() != ShadowRoot::AuthorShadowRoot || ScopeContentDistribution::assignedTo(older) != this)
    6869        return 0;
  • trunk/Source/WebCore/html/shadow/InsertionPoint.cpp

    r139400 r140299  
    5454void InsertionPoint::attach()
    5555{
    56     if (ShadowRoot* root = containingShadowRoot())
    57         root->owner()->ensureDistribution();
     56    if (ShadowRoot* shadowRoot = containingShadowRoot())
     57        ContentDistributor::ensureDistribution(shadowRoot);
    5858    for (size_t i = 0; i < m_distribution.size(); ++i) {
    5959        if (!m_distribution.at(i)->attached())
     
    6666void InsertionPoint::detach()
    6767{
    68     if (ShadowRoot* root = containingShadowRoot())
    69         root->owner()->ensureDistribution();
     68    if (ShadowRoot* shadowRoot = containingShadowRoot())
     69        ContentDistributor::ensureDistribution(shadowRoot);
     70
    7071    for (size_t i = 0; i < m_distribution.size(); ++i)
    7172        m_distribution.at(i)->detach();
     
    100101PassRefPtr<NodeList> InsertionPoint::getDistributedNodes() const
    101102{
    102     ContentDistributor::ensureDistributionFromDocument(const_cast<InsertionPoint*>(this));
     103    if (ShadowRoot* shadowRoot = containingShadowRoot())
     104        ContentDistributor::ensureDistribution(shadowRoot);
    103105
    104106    Vector<RefPtr<Node> > nodes;
     
    205207    while (current) {
    206208        if (ElementShadow* shadow = shadowOfParentForDistribution(current)) {
    207             shadow->ensureDistribution();
     209            if (ShadowRoot* root = current->containingShadowRoot())
     210                ContentDistributor::ensureDistribution(root);
    208211            if (InsertionPoint* insertedTo = shadow->distributor().findInsertionPointFor(projectedNode)) {
    209212                current = insertedTo;
Note: See TracChangeset for help on using the changeset viewer.