зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 6 changesets (bug 1237454
) for bc failures on /browser_toolbariconcolor_restyles.js. CLOSED TREE
Backed out changeset f8d771835fd2 (bug1237454
) Backed out changeset 2dbbfc331bdf (bug1237454
) Backed out changeset c481f409feaa (bug1237454
) Backed out changeset 0b9872865f0e (bug1237454
) Backed out changeset 43ca55e7c93b (bug1237454
) Backed out changeset 027b0c65d944 (bug1237454
)
This commit is contained in:
Родитель
ac18ab3f13
Коммит
b0e8772dcd
|
@ -1457,9 +1457,7 @@ KeyframeEffectReadOnly::CanThrottle() const
|
|||
if (presShell && !presShell->IsActive()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!frame->IsVisibleOrMayHaveVisibleDescendants() ||
|
||||
frame->IsScrolledOutOfView()) {
|
||||
if (frame->IsScrolledOutOfView()) {
|
||||
// If there are transform change hints, unthrottle the animation
|
||||
// periodically since it might affect the overflow region.
|
||||
if (mCumulativeChangeHint & (nsChangeHint_UpdatePostTransformOverflow |
|
||||
|
|
|
@ -658,7 +658,7 @@ waitForAllPaints(() => {
|
|||
await ensureElementRemoval(grandParent);
|
||||
});
|
||||
|
||||
add_task_if_omta_enabled(async function no_restyling_compositor_animations_in_visibility_hidden_element() {
|
||||
add_task_if_omta_enabled(async function no_restyling_compositor_animations_in_visiblily_hidden_element() {
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: opacity 100s; visibility: hidden' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
@ -668,9 +668,9 @@ waitForAllPaints(() => {
|
|||
|
||||
var markers = await observeStyling(5);
|
||||
|
||||
is(markers.length, 0,
|
||||
'Animations running on the compositor in visibility hidden element ' +
|
||||
'should never cause restyles');
|
||||
todo_is(markers.length, 0,
|
||||
'Bug 1237454: Animations running on the compositor in ' +
|
||||
'visibility hidden element should never cause restyles');
|
||||
await ensureElementRemoval(div);
|
||||
});
|
||||
|
||||
|
@ -727,296 +727,20 @@ waitForAllPaints(() => {
|
|||
await ensureElementRemoval(parentElement);
|
||||
});
|
||||
|
||||
add_task(
|
||||
async function restyling_animations_on_visibility_changed_element_having_child() {
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: background-color 100s;' });
|
||||
var childElement = addDiv(null);
|
||||
div.appendChild(childElement);
|
||||
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
await animation.ready;
|
||||
|
||||
// We don't check the animation causes restyles here since we already
|
||||
// check it in the first test case.
|
||||
|
||||
div.style.visibility = 'hidden';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
todo_is(markers.length, 0,
|
||||
'Animations running on visibility hidden element which ' +
|
||||
'has a child whose visiblity is inherited from the element and ' +
|
||||
'the element was initially visible');
|
||||
|
||||
await ensureElementRemoval(div);
|
||||
}
|
||||
);
|
||||
|
||||
add_task(
|
||||
async function restyling_animations_on_visibility_hidden_element_which_gets_visible() {
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: background-color 100s; visibility: hidden' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
|
||||
await animation.ready;
|
||||
var markers = await observeStyling(5);
|
||||
|
||||
is(markers.length, 0,
|
||||
'Animations running on visibility hidden element should never ' +
|
||||
'cause restyles');
|
||||
|
||||
div.style.visibility = 'visible';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 5,
|
||||
'Animations running that was on visibility hidden element which ' +
|
||||
'gets visible should not throttle restyling any more');
|
||||
|
||||
await ensureElementRemoval(div);
|
||||
}
|
||||
);
|
||||
|
||||
add_task(async function restyling_animations_in_visibility_changed_parent() {
|
||||
var parentDiv = addDiv(null, { style: 'visibility: hidden' });
|
||||
var div = addDiv(null, { style: 'animation: background-color 100s;' });
|
||||
parentDiv.appendChild(div);
|
||||
|
||||
add_task(async function no_restyling_main_thread_animations_in_visiblily_hidden_element() {
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: background-color 100s; visibility: hidden' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
await animation.ready;
|
||||
var markers = await observeStyling(5);
|
||||
|
||||
is(markers.length, 0,
|
||||
'Animations running in visibility hidden parent should never cause ' +
|
||||
'restyles');
|
||||
|
||||
parentDiv.style.visibility = 'visible';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 5,
|
||||
'Animations that was in visibility hidden parent should not ' +
|
||||
'throttle restyling any more');
|
||||
|
||||
parentDiv.style.visibility = 'hidden';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 0,
|
||||
'Animations that the parent element became visible should throttle ' +
|
||||
'restyling again');
|
||||
|
||||
await ensureElementRemoval(parentDiv);
|
||||
todo_is(markers.length, 0,
|
||||
'Bug 1237454: Animations running on the main-thread in ' +
|
||||
'visibility hidden element should never cause restyles');
|
||||
await ensureElementRemoval(div);
|
||||
});
|
||||
|
||||
add_task(
|
||||
async function restyling_animations_on_visibility_hidden_element_with_visibility_changed_children() {
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: background-color 100s; visibility: hidden' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
await animation.ready;
|
||||
var markers = await observeStyling(5);
|
||||
|
||||
is(markers.length, 0,
|
||||
'Animations on visibility hidden element having no visible children ' +
|
||||
'should never cause restyles');
|
||||
|
||||
var childElement = addDiv(null, { style: 'visibility: visible' });
|
||||
div.appendChild(childElement);
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 5,
|
||||
'Animations running on visibility hidden element but the element has ' +
|
||||
'a visible child should not throttle restyling');
|
||||
|
||||
childElement.style.visibility = 'hidden';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
todo_is(markers.length, 0,
|
||||
'Animations running on visibility hidden element that a child ' +
|
||||
'has become invisible should throttle restyling');
|
||||
|
||||
childElement.style.visibility = 'visible';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 5,
|
||||
'Animations running on visibility hidden element should not throttle ' +
|
||||
'restyling after the invisible element changed to visible');
|
||||
|
||||
childElement.remove();
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
todo_is(markers.length, 0,
|
||||
'Animations running on visibility hidden element should throttle ' +
|
||||
'restyling again after all visible descendants were removed');
|
||||
|
||||
await ensureElementRemoval(div);
|
||||
}
|
||||
);
|
||||
|
||||
add_task(
|
||||
async function restyling_animations_on_visiblity_hidden_element_having_oof_child() {
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: background-color 100s; position: absolute' });
|
||||
var childElement = addDiv(null,
|
||||
{ style: 'float: left; visibility: hidden' });
|
||||
div.appendChild(childElement);
|
||||
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
await animation.ready;
|
||||
|
||||
// We don't check the animation causes restyles here since we already
|
||||
// check it in the first test case.
|
||||
|
||||
div.style.visibility = 'hidden';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 0,
|
||||
'Animations running on visibility hidden element which has an ' +
|
||||
'out-of-flow child should throttle restyling');
|
||||
|
||||
await ensureElementRemoval(div);
|
||||
}
|
||||
);
|
||||
|
||||
add_task(
|
||||
async function restyling_animations_on_visibility_hidden_element_having_grandchild() {
|
||||
// element tree:
|
||||
//
|
||||
// root(visibility:hidden)
|
||||
// / \
|
||||
// childA childB
|
||||
// / \ / \
|
||||
// AA AB BA BB
|
||||
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: background-color 100s; visibility: hidden' });
|
||||
|
||||
var childA = addDiv(null);
|
||||
div.appendChild(childA);
|
||||
var childB = addDiv(null);
|
||||
div.appendChild(childB);
|
||||
|
||||
var grandchildAA = addDiv(null);
|
||||
childA.appendChild(grandchildAA);
|
||||
var grandchildAB = addDiv(null);
|
||||
childA.appendChild(grandchildAB);
|
||||
|
||||
var grandchildBA = addDiv(null);
|
||||
childB.appendChild(grandchildBA);
|
||||
var grandchildBB = addDiv(null);
|
||||
childB.appendChild(grandchildBB);
|
||||
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
await animation.ready;
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 0,
|
||||
'Animations on visibility hidden element having no visible ' +
|
||||
'descendants should never cause restyles');
|
||||
|
||||
childA.style.visibility = 'visible';
|
||||
grandchildAA.style.visibility = 'visible';
|
||||
grandchildAB.style.visibility = 'visible';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 5,
|
||||
'Animations running on visibility hidden element but the element has ' +
|
||||
'visible children should not throttle restyling');
|
||||
|
||||
// Make childA hidden again but both of grandchildAA and grandchildAB are
|
||||
// still visible.
|
||||
childA.style.visibility = 'hidden';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 5,
|
||||
'Animations running on visibility hidden element that a child has ' +
|
||||
'become invisible again but there are still visible children should ' +
|
||||
'not throttle restyling');
|
||||
|
||||
// Make grandchildAA hidden but grandchildAB is still visible.
|
||||
grandchildAA.style.visibility = 'hidden';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 5,
|
||||
'Animations running on visibility hidden element that a grandchild ' +
|
||||
'become invisible again but another grandchild is still visible ' +
|
||||
'should not throttle restyling');
|
||||
|
||||
|
||||
// Make childB and grandchildBA visible.
|
||||
childB.style.visibility = 'visible';
|
||||
grandchildBA.style.visibility = 'visible';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 5,
|
||||
'Animations running on visibility hidden element but the element has ' +
|
||||
'visible descendants should not throttle restyling');
|
||||
|
||||
// Make childB hidden but grandchildAB and grandchildBA are still visible.
|
||||
childB.style.visibility = 'hidden';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 5,
|
||||
'Animations running on visibility hidden element but the element has ' +
|
||||
'visible grandchildren should not throttle restyling');
|
||||
|
||||
// Make grandchildAB hidden but grandchildBA is still visible.
|
||||
grandchildAB.style.visibility = 'hidden';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 5,
|
||||
'Animations running on visibility hidden element but the element has ' +
|
||||
'a visible grandchild should not throttle restyling');
|
||||
|
||||
// Make grandchildBA hidden. Now all descedants are invisible.
|
||||
grandchildBA.style.visibility = 'hidden';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
todo_is(markers.length, 0,
|
||||
'Animations on visibility hidden element that all descendants have ' +
|
||||
'become invisible again should never cause restyles');
|
||||
|
||||
// Make childB visible.
|
||||
childB.style.visibility = 'visible';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 5,
|
||||
'Animations on visibility hidden element that has a visible child ' +
|
||||
'should never cause restyles');
|
||||
|
||||
// Make childB invisible again
|
||||
childB.style.visibility = 'hidden';
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
todo_is(markers.length, 0,
|
||||
'Animations on visibility hidden element that the visible child ' +
|
||||
'has become invisible again should never cause restyles');
|
||||
|
||||
await ensureElementRemoval(div);
|
||||
}
|
||||
);
|
||||
|
||||
add_task_if_omta_enabled(async function no_restyling_compositor_animations_after_pause_is_called() {
|
||||
var div = addDiv(null, { style: 'animation: opacity 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
|
|
@ -438,14 +438,12 @@ RestyleManager::ChangeHintToString(nsChangeHint aHint)
|
|||
"ReflowChangesSizeOrPosition", "UpdateComputedBSize",
|
||||
"UpdateUsesOpacity", "UpdateBackgroundPosition",
|
||||
"AddOrRemoveTransform", "CSSOverflowChange",
|
||||
"UpdateWidgetProperties", "UpdateTableCellSpans",
|
||||
"VisibilityChange"
|
||||
"UpdateWidgetProperties", "UpdateTableCellSpans"
|
||||
};
|
||||
static_assert(nsChangeHint_AllHints ==
|
||||
static_cast<uint32_t>((1ull << ArrayLength(names)) - 1),
|
||||
static_assert(nsChangeHint_AllHints == (1u << ArrayLength(names)) - 1,
|
||||
"Name list doesn't match change hints.");
|
||||
uint32_t hint = aHint & static_cast<uint32_t>((1ull << ArrayLength(names)) - 1);
|
||||
uint32_t rest = aHint & ~static_cast<uint32_t>((1ull << ArrayLength(names)) - 1);
|
||||
uint32_t hint = aHint & ((1u << ArrayLength(names)) - 1);
|
||||
uint32_t rest = aHint & ~((1u << ArrayLength(names)) - 1);
|
||||
if ((hint & NS_STYLE_HINT_REFLOW) == NS_STYLE_HINT_REFLOW) {
|
||||
result.AppendLiteral("NS_STYLE_HINT_REFLOW");
|
||||
hint = hint & ~NS_STYLE_HINT_REFLOW;
|
||||
|
@ -460,7 +458,7 @@ RestyleManager::ChangeHintToString(nsChangeHint aHint)
|
|||
any = true;
|
||||
}
|
||||
for (uint32_t i = 0; i < ArrayLength(names); i++) {
|
||||
if (hint & (1u << i)) {
|
||||
if (hint & (1 << i)) {
|
||||
if (any) {
|
||||
result.AppendLiteral(" | ");
|
||||
}
|
||||
|
@ -1729,9 +1727,6 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
|
|||
if (hint & nsChangeHint_UpdateTableCellSpans) {
|
||||
frameConstructor->UpdateTableCellSpans(content);
|
||||
}
|
||||
if (hint & nsChangeHint_VisibilityChange) {
|
||||
frame->UpdateVisibleDescendantsState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -245,14 +245,6 @@ enum nsChangeHint : uint32_t {
|
|||
*/
|
||||
nsChangeHint_UpdateTableCellSpans = 1 << 30,
|
||||
|
||||
/**
|
||||
* Indicates that the visiblity property changed.
|
||||
* This change hint is used for skip restyling for animations on
|
||||
* visibility:hidden elements in the case where the elements have no visible
|
||||
* descendants.
|
||||
*/
|
||||
nsChangeHint_VisibilityChange = 1u << 31,
|
||||
|
||||
// IMPORTANT NOTE: When adding a new hint, you will need to add it to
|
||||
// one of:
|
||||
//
|
||||
|
@ -268,7 +260,7 @@ enum nsChangeHint : uint32_t {
|
|||
/**
|
||||
* Dummy hint value for all hints. It exists for compile time check.
|
||||
*/
|
||||
nsChangeHint_AllHints = uint32_t((1ull << 32) - 1),
|
||||
nsChangeHint_AllHints = (1u << 31) - 1,
|
||||
};
|
||||
|
||||
// Redefine these operators to return nothing. This will catch any use
|
||||
|
@ -350,8 +342,7 @@ inline nsChangeHint operator^=(nsChangeHint& aLeft, nsChangeHint aRight)
|
|||
nsChangeHint_SyncFrameView | \
|
||||
nsChangeHint_UpdateCursor | \
|
||||
nsChangeHint_UpdateSubtreeOverflow | \
|
||||
nsChangeHint_UpdateTextPath | \
|
||||
nsChangeHint_VisibilityChange \
|
||||
nsChangeHint_UpdateTextPath \
|
||||
)
|
||||
|
||||
// The change hints that are never handled for descendants.
|
||||
|
@ -465,8 +456,7 @@ static_assert(!(nsChangeHint_Hints_AlwaysHandledForDescendants &
|
|||
nsChangeHint_AddOrRemoveTransform | \
|
||||
nsChangeHint_UpdatePostTransformOverflow | \
|
||||
nsChangeHint_UpdateTransformLayer | \
|
||||
nsChangeHint_UpdateUsesOpacity | \
|
||||
nsChangeHint_VisibilityChange)
|
||||
nsChangeHint_UpdateUsesOpacity)
|
||||
|
||||
// NB: Once we drop support for the old style system, this logic should be
|
||||
// inlined in the Servo style system to eliminate the FFI call.
|
||||
|
|
|
@ -734,12 +734,6 @@ nsFrame::Init(nsIContent* aContent,
|
|||
|
||||
if (::IsXULBoxWrapped(this))
|
||||
::InitBoxMetrics(this, false);
|
||||
|
||||
// For a newly created frame, we need to update this frame's visibility state.
|
||||
// Usually we update the state when the frame is restyled and has a
|
||||
// VisibilityChange change hint but we don't generate any change hints for
|
||||
// newly created frames.
|
||||
UpdateVisibleDescendantsState();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -11347,39 +11341,6 @@ nsIFrame::GetCompositorHitTestInfo(nsDisplayListBuilder* aBuilder)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Returns true if we can guarantee there is no visible descendants.
|
||||
static bool
|
||||
HasNoVisibleDescendants(const nsIFrame* aFrame)
|
||||
{
|
||||
for (nsIFrame::ChildListIterator lists(aFrame);
|
||||
!lists.IsDone();
|
||||
lists.Next()) {
|
||||
for (nsIFrame* f : lists.CurrentList()) {
|
||||
if (nsPlaceholderFrame::GetRealFrameFor(f)->
|
||||
IsVisibleOrMayHaveVisibleDescendants()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::UpdateVisibleDescendantsState()
|
||||
{
|
||||
if (StyleVisibility()->IsVisible()) {
|
||||
// Notify invisible ancestors that a visible descendant exists now.
|
||||
nsIFrame* ancestor;
|
||||
for (ancestor = GetInFlowParent();
|
||||
ancestor && !ancestor->StyleVisibility()->IsVisible();
|
||||
ancestor = ancestor->GetInFlowParent()) {
|
||||
ancestor->mAllDescendantsAreInvisible = false;
|
||||
}
|
||||
} else {
|
||||
mAllDescendantsAreInvisible = HasNoVisibleDescendants(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Box layout debugging
|
||||
#ifdef DEBUG_REFLOW
|
||||
int32_t gIndent2 = 0;
|
||||
|
|
|
@ -628,7 +628,6 @@ public:
|
|||
, mIsPrimaryFrame(false)
|
||||
, mMayHaveTransformAnimation(false)
|
||||
, mMayHaveOpacityAnimation(false)
|
||||
, mAllDescendantsAreInvisible(false)
|
||||
{
|
||||
mozilla::PodZero(&mOverflow);
|
||||
}
|
||||
|
@ -4090,13 +4089,6 @@ public:
|
|||
mMayHaveOpacityAnimation = true;
|
||||
}
|
||||
|
||||
// Returns true if this frame is visible or may have visible descendants.
|
||||
bool IsVisibleOrMayHaveVisibleDescendants() const {
|
||||
return !mAllDescendantsAreInvisible || StyleVisibility()->IsVisible();
|
||||
}
|
||||
// Update mAllDescendantsAreInvisible flag for this frame and ancestors.
|
||||
void UpdateVisibleDescendantsState();
|
||||
|
||||
/**
|
||||
* If this returns true, the frame it's called on should get the
|
||||
* NS_FRAME_HAS_DIRTY_CHILDREN bit set on it by the caller; either directly
|
||||
|
@ -4356,19 +4348,9 @@ private:
|
|||
bool mMayHaveTransformAnimation : 1;
|
||||
bool mMayHaveOpacityAnimation : 1;
|
||||
|
||||
/**
|
||||
* True if we are certain that all descendants are not visible.
|
||||
*
|
||||
* This flag is conservative in that it might sometimes be false even if, in
|
||||
* fact, all descendants are invisible.
|
||||
* For example; an element is visibility:visible and has a visibility:hidden
|
||||
* child. This flag is stil false in such case.
|
||||
*/
|
||||
bool mAllDescendantsAreInvisible : 1;
|
||||
|
||||
protected:
|
||||
|
||||
// There is no gap left here.
|
||||
// There is a 1-bit gap left here.
|
||||
|
||||
// Helpers
|
||||
/**
|
||||
|
|
|
@ -4103,10 +4103,6 @@ nsStyleVisibility::CalcDifference(const nsStyleVisibility& aNewData) const
|
|||
nsChangeHint_RepaintFrame;
|
||||
}
|
||||
if (mVisible != aNewData.mVisible) {
|
||||
if (mVisible == NS_STYLE_VISIBILITY_VISIBLE ||
|
||||
aNewData.mVisible == NS_STYLE_VISIBILITY_VISIBLE) {
|
||||
hint |= nsChangeHint_VisibilityChange;
|
||||
}
|
||||
if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
|
||||
(NS_STYLE_VISIBILITY_COLLAPSE == aNewData.mVisible)) {
|
||||
hint |= NS_STYLE_HINT_REFLOW;
|
||||
|
|
Загрузка…
Ссылка в новой задаче