зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1049975 - Part 11: Fix mutation observer when setting effects. r=birtles
MozReview-Commit-ID: 3td2343LFxX --HG-- extra : rebase_source : 5bef088200975a09663803d2616adb7bd3fe2e2b
This commit is contained in:
Родитель
92bf15ed7b
Коммит
9ca8c808df
|
@ -140,6 +140,9 @@ Animation::SetEffectNoUpdate(AnimationEffectReadOnly* aEffect)
|
|||
return;
|
||||
}
|
||||
|
||||
AutoMutationBatchForAnimation mb(*this);
|
||||
bool wasRelevant = mIsRelevant;
|
||||
|
||||
if (mEffect) {
|
||||
if (!aEffect) {
|
||||
// If the new effect is null, call ResetPendingTasks before clearing
|
||||
|
@ -148,10 +151,19 @@ Animation::SetEffectNoUpdate(AnimationEffectReadOnly* aEffect)
|
|||
ResetPendingTasks();
|
||||
}
|
||||
|
||||
// We need to notify observers now because once we set mEffect to null
|
||||
// we won't be able to find the target element to notify.
|
||||
if (mIsRelevant) {
|
||||
nsNodeUtils::AnimationRemoved(this);
|
||||
}
|
||||
|
||||
// Break links with the old effect and then drop it.
|
||||
RefPtr<AnimationEffectReadOnly> oldEffect = mEffect;
|
||||
mEffect = nullptr;
|
||||
oldEffect->SetAnimation(nullptr);
|
||||
|
||||
// The following will not do any notification because mEffect is null.
|
||||
UpdateRelevance();
|
||||
}
|
||||
|
||||
if (aEffect) {
|
||||
|
@ -166,6 +178,14 @@ Animation::SetEffectNoUpdate(AnimationEffectReadOnly* aEffect)
|
|||
mEffect = newEffect;
|
||||
mEffect->SetAnimation(this);
|
||||
|
||||
// Update relevance and then notify possible add or change.
|
||||
// If the target is different, the change notification will be ignored by
|
||||
// AutoMutationBatchForAnimation.
|
||||
UpdateRelevance();
|
||||
if (wasRelevant && mIsRelevant) {
|
||||
nsNodeUtils::AnimationChanged(this);
|
||||
}
|
||||
|
||||
// Reschedule pending pause or pending play tasks.
|
||||
// If we have a pending animation, it will either be registered
|
||||
// in the pending animation tracker and have a null pending ready time,
|
||||
|
|
|
@ -1794,6 +1794,108 @@ addAsyncAnimTest("set_redundant_animation_target",
|
|||
yield await_frame();
|
||||
});
|
||||
|
||||
addAsyncAnimTest("set_null_animation_effect",
|
||||
{ observe: div, subtree: true }, function*() {
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ duration: 100 * MS_PER_SEC });
|
||||
yield await_frame();
|
||||
assert_records([{ added: [anim], changed: [], removed: [] }],
|
||||
"records after animation is added");
|
||||
|
||||
anim.effect = null;
|
||||
yield await_frame();
|
||||
assert_records([{ added: [], changed: [], removed: [anim] }],
|
||||
"records after animation is removed");
|
||||
|
||||
anim.cancel();
|
||||
yield await_frame();
|
||||
});
|
||||
|
||||
addAsyncAnimTest("set_effect_on_null_effect_animation",
|
||||
{ observe: div, subtree: true }, function*() {
|
||||
var anim = new Animation();
|
||||
anim.play();
|
||||
anim.effect = new KeyframeEffect(div, { opacity: [ 0, 1 ] },
|
||||
100 * MS_PER_SEC);
|
||||
yield await_frame();
|
||||
assert_records([{ added: [anim], changed: [], removed: [] }],
|
||||
"records after animation is added");
|
||||
|
||||
anim.cancel();
|
||||
yield await_frame();
|
||||
});
|
||||
|
||||
addAsyncAnimTest("replace_effect_targeting_on_the_same_element",
|
||||
{ observe: div, subtree: true }, function*() {
|
||||
var anim = div.animate({ marginLeft: [ "0px", "100px" ] },
|
||||
100 * MS_PER_SEC);
|
||||
yield await_frame();
|
||||
assert_records([{ added: [anim], changed: [], removed: [] }],
|
||||
"records after animation is added");
|
||||
|
||||
anim.effect = new KeyframeEffect(div, { opacity: [ 0, 1 ] },
|
||||
100 * MS_PER_SEC);
|
||||
yield await_frame();
|
||||
assert_records([{ added: [], changed: [anim], removed: [] }],
|
||||
"records after replace effects");
|
||||
|
||||
anim.cancel();
|
||||
yield await_frame();
|
||||
});
|
||||
|
||||
addAsyncAnimTest("replace_effect_targeting_on_the_same_element_not_in_effect",
|
||||
{ observe: div, subtree: true }, function*() {
|
||||
var anim = div.animate({ marginLeft: [ "0px", "100px" ] },
|
||||
100 * MS_PER_SEC);
|
||||
yield await_frame();
|
||||
assert_records([{ added: [anim], changed: [], removed: [] }],
|
||||
"records after animation is added");
|
||||
|
||||
anim.currentTime = 60 * MS_PER_SEC;
|
||||
yield await_frame();
|
||||
assert_records([{ added: [], changed: [anim], removed: [] }],
|
||||
"records after animation is changed");
|
||||
|
||||
anim.effect = new KeyframeEffect(div, { opacity: [ 0, 1 ] },
|
||||
50 * MS_PER_SEC);
|
||||
yield await_frame();
|
||||
assert_records([{ added: [], changed: [], removed: [anim] }],
|
||||
"records after replacing effects");
|
||||
|
||||
anim.cancel();
|
||||
yield await_frame();
|
||||
});
|
||||
|
||||
addAsyncAnimTest("set_effect_with_previous_animation",
|
||||
{ observe: div, subtree: true }, function*() {
|
||||
var child = document.createElement("div");
|
||||
div.appendChild(child);
|
||||
|
||||
var anim1 = div.animate({ marginLeft: [ "0px", "50px" ] },
|
||||
100 * MS_PER_SEC);
|
||||
var anim2 = child.animate({ marginLeft: [ "0px", "100px" ] },
|
||||
50 * MS_PER_SEC);
|
||||
yield await_frame();
|
||||
assert_records([{ added: [anim1], changed: [], removed: [] },
|
||||
{ added: [anim2], changed: [], removed: [] }],
|
||||
"records after animation is added");
|
||||
|
||||
// After setting a new effect, we remove the current animation, anim1, because
|
||||
// it is no longer attached to |div|, and then remove the previous animation,
|
||||
// anim2. Finally, add back the anim1 which is in effect on |child| now.
|
||||
// In addition, we sort them by tree order and they are batched.
|
||||
anim1.effect = anim2.effect;
|
||||
yield await_frame();
|
||||
assert_records([{ added: [], changed: [], removed: [anim1] }, // div
|
||||
{ added: [anim1], changed: [], removed: [anim2] }], // child
|
||||
"records after animation effects are changed");
|
||||
|
||||
anim1.cancel();
|
||||
anim2.cancel();
|
||||
child.remove();
|
||||
yield await_frame();
|
||||
});
|
||||
|
||||
// Run the tests.
|
||||
SimpleTest.requestLongerTimeout(2);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
|
Загрузка…
Ссылка в новой задаче