diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp index 4f7a34687882..4b8d9adf7ef1 100644 --- a/dom/animation/KeyframeEffect.cpp +++ b/dom/animation/KeyframeEffect.cpp @@ -112,7 +112,7 @@ void KeyframeEffect::SetComposite(const CompositeOperation& aComposite) { } if (mTarget) { - RefPtr computedStyle = GetTargetComputedStyle(); + RefPtr computedStyle = GetTargetComputedStyle(Flush::None); if (computedStyle) { UpdateProperties(computedStyle); } @@ -206,7 +206,7 @@ void KeyframeEffect::SetKeyframes(JSContext* aContext, return; } - RefPtr style = GetTargetComputedStyle(); + RefPtr style = GetTargetComputedStyle(Flush::None); SetKeyframes(std::move(keyframes), style); } @@ -768,7 +768,8 @@ void KeyframeEffect::RequestRestyle( } } -already_AddRefed KeyframeEffect::GetTargetComputedStyle() const { +already_AddRefed KeyframeEffect::GetTargetComputedStyle( + Flush aFlushType) const { if (!GetRenderedDocument()) { return nullptr; } @@ -784,7 +785,10 @@ already_AddRefed KeyframeEffect::GetTargetComputedStyle() const { OwningAnimationTarget kungfuDeathGrip(mTarget->mElement, mTarget->mPseudoType); - return nsComputedDOMStyle::GetComputedStyle(mTarget->mElement, pseudo); + return aFlushType == Flush::Style + ? nsComputedDOMStyle::GetComputedStyle(mTarget->mElement, pseudo) + : nsComputedDOMStyle::GetComputedStyleNoFlush(mTarget->mElement, + pseudo); } #ifdef DEBUG @@ -900,7 +904,7 @@ void KeyframeEffect::SetTarget( if (mTarget) { UpdateTargetRegistration(); - RefPtr computedStyle = GetTargetComputedStyle(); + RefPtr computedStyle = GetTargetComputedStyle(Flush::None); if (computedStyle) { UpdateProperties(computedStyle); } @@ -1032,7 +1036,7 @@ void KeyframeEffect::GetKeyframes(JSContext*& aCx, nsTArray& aResult, // we might end up returning variables as-is or empty string. That should be // acceptable however, since such a case is rare and this is only // short-term (and unshipped) behavior until bug 1391537 is fixed. - computedStyle = GetTargetComputedStyle(); + computedStyle = GetTargetComputedStyle(Flush::Style); } for (const Keyframe& keyframe : mKeyframes) { diff --git a/dom/animation/KeyframeEffect.h b/dom/animation/KeyframeEffect.h index 5d38a94fcbbb..9cdf3cd4578c 100644 --- a/dom/animation/KeyframeEffect.h +++ b/dom/animation/KeyframeEffect.h @@ -361,7 +361,12 @@ class KeyframeEffect : public AnimationEffect { // context. That's because calling GetComputedStyle when we are in the process // of building a ComputedStyle may trigger various forms of infinite // recursion. - already_AddRefed GetTargetComputedStyle() const; + enum class Flush { + Style, + None, + }; + already_AddRefed GetTargetComputedStyle( + Flush aFlushType) const; // A wrapper for marking cascade update according to the current // target and its effectSet. diff --git a/dom/animation/test/mozilla/file_restyles.html b/dom/animation/test/mozilla/file_restyles.html index 28114ef23b51..54146feeabac 100644 --- a/dom/animation/test/mozilla/file_restyles.html +++ b/dom/animation/test/mozilla/file_restyles.html @@ -1869,6 +1869,37 @@ waitForAllPaints(() => { await ensureElementRemoval(div); }); + add_task(async function restyling_on_create_animation() { + const div = addDiv(); + const docShell = getDocShellForObservingRestylesForWindow(window); + + const animationA = div.animate( + { transform: ['none', 'rotate(360deg)'] }, + 100 * MS_PER_SEC + ); + const animationB = div.animate({ opacity: [0, 1] }, 100 * MS_PER_SEC); + const animationC = div.animate( + { color: ['blue', 'green'] }, + 100 * MS_PER_SEC + ); + const animationD = div.animate( + { width: ['100px', '200px'] }, + 100 * MS_PER_SEC + ); + const animationE = div.animate( + { height: ['100px', '200px'] }, + 100 * MS_PER_SEC + ); + + const markers = docShell + .popProfileTimelineMarkers() + .filter(marker => marker.name === 'Styles' && !marker.isAnimationOnly); + docShell.recordProfileTimelineMarkers = false; + + is(markers.length, 0, 'Creating animations should not flush styles'); + + await ensureElementRemoval(div); + }); });