Bug 100507 - Progress bar shadow tree sometimes is not relayouted.
: Progress bar shadow tree sometimes is not relayouted.
Status: RESOLVED DUPLICATE of bug 83664
Product: WebKit
Classification: Unclassified
Component: Layout and Rendering
: 528+ (Nightly build)
: PC All
: P2 Normal
Assigned To: Nobody
Depends on:
  Show dependency treegraph
Reported: 2012-10-26 05:06 PDT by Andrey Khalyavin
Modified: 2012-10-29 02:18 PDT (History)
1 user (show)

See Also:

test page (758 bytes, text/html)
2012-10-26 05:06 PDT, Andrey Khalyavin
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrey Khalyavin 2012-10-26 05:06:54 PDT
Created attachment 170899 [details]
test page

Progress bar shadow tree sometimes is not relayouted.
Steps to reproduce:
1. Open page in attachment.
2. Click on a button.
3. See that first bar is updated while second bar is not.

What is going on behind the cover:
HTMLProgressElement has a shadow tree which consist in 3 nested divs. The most nested div (HTMLProgressElement::m_value) represents progress bar value and is updated by HTMLProgressElement::didElementStateChange method.

When javascripts on the page sets the second progress bar value, m_value node loses IsStyleAttributeValidFlag flag. Then <progress> element is inserted into tree and InDocumentFlag is set in m_value. Then Element::recalcStyle is called on HTMLProgressElement and it executes reattach method for it. Method reattach calls attach and as result m_value receives IsAttachedFlag. Then HTMLProgressElement::attach calls didElementStateChange method which calls m_value->setWidthPercentage which sets InlineStyleChange flag to m_value node and ChildNeedsStyleRecalc flag to all its parent nodes. But then reattach methods returns and Element::recalcStyle calls clearNeedsStyleRecalc and clearChildNeedsStyleRecalc methods on HTMLProgressElement node. 

So now we have m_value node that needs style recalculation but HTMLProgressElement node doesn't have ChildNeedsStyleRecalcFlag flag. As a result, any subsequent changes to progress element doesn't do anything since m_value is already marked as needed to recalculate style. But m_value never recalculates style since HTMLProgressElement doesn't have ChildNeedsRecalcFlag.
Comment 1 Takashi Sakamoto 2012-10-29 02:18:01 PDT
The reason why progress bar is not re-layouted is:
- HTMLProgressElement updates inline styles, i.e. setWidthPercentage, in HTMLProgressElement::attach().
- Element::recalcStyle updates HTMLProgressElement's style by using "reattach()".

            // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
            // attach recalculates the style for all children. No need to do it twice.

So after reattach(), clearNeedsStyleRecalc() and clearChildNeedsStyleRecalc() reset update flags set by setWidthPercentage. Now ProgressValueElement has had "InlineStyleChange" style change type, but its relayout flag is cleared. This disables "setNeedsStyleRecalc" to relayout:

void Node::setNeedsStyleRecalc(...)
    if (existingChangeType == NoStyleChange)

I will fix this issue by bug 83664.

Best regards,
Takashi Sakamoto

*** This bug has been marked as a duplicate of bug 83664 ***