blob: ddb9df18a94c335f210a5207509c966106c7192e [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/animation/ElementAnimation.h"
#include "core/css/CSSStyleSheet.h"
#include "core/css/PropertyDescriptor.h"
#include "core/css/PropertyRegistration.h"
#include "core/frame/WebLocalFrameImpl.h"
#include "core/page/Page.h"
#include "core/testing/sim/SimCompositor.h"
#include "core/testing/sim/SimDisplayItemList.h"
#include "core/testing/sim/SimRequest.h"
#include "core/testing/sim/SimTest.h"
#include "platform/testing/RuntimeEnabledFeaturesTestHelpers.h"
#include "platform/wtf/Time.h"
#include "public/web/WebScriptSource.h"
namespace blink {
class AnimationSimTest : public SimTest {};
TEST_F(AnimationSimTest, CustomPropertyBaseComputedStyle) {
// This is a regression test for bug where custom property animations failed
// to disable the baseComputedStyle optimisation. When custom property
// animations are in effect we lose the guarantee that the baseComputedStyle
// optimisation relies on where the non-animated style rules always produce
// the same ComputedStyle. This is not the case if they use var() references
// to custom properties that are being animated.
// The bug was that we never cleared the existing baseComputedStyle during a
// custom property animation so the stale ComputedStyle object would hang
// around and not be valid in the exit frame of the next custom property
// animation.
ScopedCSSVariables2ForTest css_variables2(true);
ScopedCSSAdditiveAnimationsForTest css_additive_animation(true);
ScopedStackedCSSPropertyAnimationsForTest stacked_css_property_animation(
true);
WebView().GetPage()->Animator().Clock().DisableSyntheticTimeForTesting();
SimRequest main_resource("https://example.com/", "text/html");
LoadURL("https://example.com/");
main_resource.Complete("<div id=\"target\"></div>");
Element* target = GetDocument().getElementById("target");
// CSS.registerProperty({
// name: '--x',
// syntax: '<percentage>',
// initialValue: '0%',
// })
DummyExceptionStateForTesting exception_state;
PropertyDescriptor property_descriptor;
property_descriptor.setName("--x");
property_descriptor.setSyntax("<percentage>");
property_descriptor.setInitialValue("0%");
PropertyRegistration::registerProperty(&GetDocument(), property_descriptor,
exception_state);
EXPECT_FALSE(exception_state.HadException());
// target.style.setProperty('--x', '100%');
target->style()->setProperty(&GetDocument(), "--x", "100%", g_empty_string,
exception_state);
EXPECT_FALSE(exception_state.HadException());
// target.animate({'--x': '100%'}, 1000);
scoped_refptr<StringKeyframe> keyframe = StringKeyframe::Create();
keyframe->SetCSSPropertyValue("--x", GetDocument().GetPropertyRegistry(),
"100%", GetDocument().GetSecureContextMode(),
GetDocument().ElementSheet().Contents());
StringKeyframeVector keyframes;
keyframes.push_back(std::move(keyframe));
Timing timing;
timing.iteration_duration = 1; // Seconds.
ElementAnimation::animateInternal(
*target, StringKeyframeEffectModel::Create(keyframes), timing);
// This sets the baseComputedStyle on the animation exit frame.
Compositor().BeginFrame(1);
Compositor().BeginFrame(1);
// target.style.setProperty('--x', '0%');
target->style()->setProperty(&GetDocument(), "--x", "0%", g_empty_string,
exception_state);
EXPECT_FALSE(exception_state.HadException());
// target.animate({'--x': '100%'}, 1000);
keyframe = StringKeyframe::Create();
keyframe->SetCSSPropertyValue("--x", GetDocument().GetPropertyRegistry(),
"100%", GetDocument().GetSecureContextMode(),
GetDocument().ElementSheet().Contents());
keyframes.clear();
keyframes.push_back(std::move(keyframe));
timing = Timing::Defaults();
timing.iteration_duration = 1; // Seconds.
ElementAnimation::animateInternal(
*target, StringKeyframeEffectModel::Create(keyframes), timing);
// This (previously) would not clear the existing baseComputedStyle and would
// crash on the equality assertion in the exit frame when it tried to update
// it.
Compositor().BeginFrame(1);
Compositor().BeginFrame(1);
}
} // namespace blink