Bug 1307295 - Do not request restyle for animations on orphaned element. r=birtles

Also we skip to update the cascade and compose style for orphaned elements if
the animation reqeusted restyle but the target element has been removed from
document before a subsequent tick.

MozReview-Commit-ID: 3I6uyvuSPO5

--HG--
extra : rebase_source : 817b123a4e1b64c89cfbe796073d88410792bf84
This commit is contained in:
Hiroyuki Ikezoe 2016-10-12 15:58:53 +09:00
Родитель ec76d557f1
Коммит 2653be237d
2 изменённых файлов: 78 добавлений и 1 удалений

Просмотреть файл

@ -178,6 +178,11 @@ EffectCompositor::RequestRestyle(dom::Element* aElement,
return;
}
// Ignore animations on orphaned elements.
if (!aElement->IsInComposedDoc()) {
return;
}
auto& elementsToRestyle = mElementsToRestyle[aCascadeLevel];
PseudoElementHashEntry::KeyType key = { aElement, aPseudoType };
@ -417,7 +422,11 @@ EffectCompositor::AddStyleUpdatesTo(RestyleTracker& aTracker)
nsTArray<PseudoElementHashEntry::KeyType> elementsToRestyle(
elementSet.Count());
for (auto iter = elementSet.Iter(); !iter.Done(); iter.Next()) {
elementsToRestyle.AppendElement(iter.Key());
// Skip animations on elements that have been orphaned since they
// requested a restyle.
if (iter.Key().mElement->IsInComposedDoc()) {
elementsToRestyle.AppendElement(iter.Key());
}
}
for (auto& pseudoElem : elementsToRestyle) {

Просмотреть файл

@ -743,6 +743,74 @@ waitForAllPaints(function() {
}
);
add_task(function* restyling_for_animation_on_orphaned_element() {
var div = addDiv(null);
var animation = div.animate({ marginLeft: [ '0px', '100px' ] },
100 * MS_PER_SEC);
yield animation.ready;
div.remove();
var markers = yield observeStyling(5);
is(markers.length, 0,
'Animation on orphaned element should not cause restyles');
document.body.appendChild(div);
markers = yield observeStyling(1);
// We are observing restyles in rAF callback which is processed before
// restyling process in each frame, so in the first frame there should be
// no observed restyle since we don't process restyle while the element
// is not attached to the document.
is(markers.length, 0,
'We observe no restyle in the first frame right after re-atatching ' +
'to the document');
markers = yield observeStyling(5);
is(markers.length, 5,
'Animation on re-attached to the document begins to update style');
yield ensureElementRemoval(div);
});
add_task_if_omta_enabled(
// Tests that if we remove an element from the document whose animation
// cascade needs recalculating, that it is correctly updated when it is
// re-attached to the document.
function* restyling_for_opacity_animation_on_re_attached_element() {
var div = addDiv(null, { style: 'opacity: 1 ! important' });
var animation = div.animate({ opacity: [0, 1] }, 100 * MS_PER_SEC);
yield animation.ready;
ok(!animation.isRunningOnCompositor,
'The opacity animation overridden by an !important rule is NOT ' +
'running on the compositor');
// Drop the !important rule to update the cascade.
div.style.setProperty('opacity', '1', '');
div.remove();
var markers = yield observeStyling(5);
is(markers.length, 0,
'Opacity animation on orphaned element should not cause restyles');
document.body.appendChild(div);
// Need a frame to give the animation a chance to be sent to the
// compositor.
yield waitForFrame();
ok(animation.isRunningOnCompositor,
'The opacity animation which is no longer overridden by the ' +
'!important rule begins running on the compositor even if the ' +
'!important rule had been dropped before the target element was ' +
'removed');
yield ensureElementRemoval(div);
}
);
});
</script>