Commit af8c16d9 authored by George Steel's avatar George Steel Committed by Commit Bot

Implement new pseudoElement interface on KeyframeEffect

Make target() return the originating element if target_ is a
PseudoElement (EventTarget still returns the layout object).

Add pseudoElement() property which returns the target pseudo-selector
if the target is a pseudo-element (null otherwise).
Invalid and unsupported pseudo-elements will still return a selector
and the originating element (from target()) but will not animated
(EventTarget returns null).

Add pseudoElement option to KeyframeEffect constructor.

Change-Id: Id7d16ea6966c533e56d1170462ff60a79b277fd5
Bug: 981894
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1921343
Commit-Queue: George Steel <gtsteel@chromium.org>
Reviewed-by: default avatarMajid Valipour <majidvp@chromium.org>
Reviewed-by: default avatarKevin Ellis <kevers@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726506}
parent f053c86a
......@@ -39,6 +39,7 @@
#include "third_party/blink/renderer/core/animation/timing_input.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/pseudo_element.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
......@@ -49,6 +50,34 @@
namespace blink {
namespace {
// Verifies that a pseudo-element selector lexes and canonicalizes legacy forms
bool ValidateAndCanonicalizePseudo(String& selector) {
if (selector.IsEmpty()) {
if (!selector.IsNull())
selector = String(); // null
return true;
} else if (selector.StartsWith("::")) {
return true;
} else if (selector == ":before") {
selector = "::before";
return true;
} else if (selector == ":after") {
selector = "::after";
return true;
} else if (selector == ":first-letter") {
selector = "::first-letter";
return true;
} else if (selector == ":first-line") {
selector = "::first-line";
return true;
}
return false;
}
} // namespace
KeyframeEffect* KeyframeEffect::Create(
ScriptState* script_state,
Element* element,
......@@ -61,17 +90,40 @@ KeyframeEffect* KeyframeEffect::Create(
return nullptr;
EffectModel::CompositeOperation composite = EffectModel::kCompositeReplace;
String pseudo = String();
if (options.IsKeyframeEffectOptions()) {
composite = EffectModel::StringToCompositeOperation(
options.GetAsKeyframeEffectOptions()->composite())
auto* effect_options = options.GetAsKeyframeEffectOptions();
composite =
EffectModel::StringToCompositeOperation(effect_options->composite())
.value();
if (RuntimeEnabledFeatures::WebAnimationsAPIEnabled() &&
!effect_options->pseudoElement().IsEmpty()) {
pseudo = effect_options->pseudoElement();
if (!ValidateAndCanonicalizePseudo(pseudo)) {
// TODO(gtsteel): update when
// https://github.com/w3c/csswg-drafts/issues/4586 resolves
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
"A valid pseudo-selector must start with ::.");
}
}
}
KeyframeEffectModelBase* model = EffectInput::Convert(
element, keyframes, composite, script_state, exception_state);
if (exception_state.HadException())
return nullptr;
return MakeGarbageCollected<KeyframeEffect>(element, model, timing);
KeyframeEffect* effect =
MakeGarbageCollected<KeyframeEffect>(element, model, timing);
if (!pseudo.IsEmpty()) {
effect->target_pseudo_ = pseudo;
if (element) {
effect->effect_target_ =
element->GetPseudoElement(CSSSelector::ParsePseudoId(pseudo));
}
}
return effect;
}
KeyframeEffect* KeyframeEffect::Create(ScriptState* script_state,
......@@ -103,23 +155,63 @@ KeyframeEffect::KeyframeEffect(Element* target,
EventDelegate* event_delegate)
: AnimationEffect(timing, event_delegate),
effect_target_(target),
target_element_(target),
target_pseudo_(),
model_(model),
sampled_effect_(nullptr),
priority_(priority) {
DCHECK(model_);
// fix target for css animations and transitions
if (target && target->IsPseudoElement()) {
target_element_ = target->parentElement();
DCHECK(!target_element_->IsPseudoElement());
target_pseudo_ = target->tagName();
}
}
KeyframeEffect::~KeyframeEffect() = default;
void KeyframeEffect::setTarget(Element* target) {
if (effect_target_ == target)
return;
void KeyframeEffect::setTarget(Element* new_target) {
DCHECK(!new_target || !new_target->IsPseudoElement());
target_element_ = new_target;
RefreshTarget();
}
const String& KeyframeEffect::pseudoElement() {
return target_pseudo_;
}
void KeyframeEffect::setPseudoElement(String pseudo,
ExceptionState& exception_state) {
if (ValidateAndCanonicalizePseudo(pseudo)) {
target_pseudo_ = pseudo;
} else {
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
"A valid pseudo-selector must start with ::.");
}
RefreshTarget();
}
void KeyframeEffect::RefreshTarget() {
Element* new_target;
if (!target_element_) {
new_target = nullptr;
} else if (target_pseudo_.IsEmpty()) {
new_target = target_element_;
} else {
PseudoId pseudoId = CSSSelector::ParsePseudoId(target_pseudo_);
new_target = target_element_->GetPseudoElement(pseudoId);
}
if (new_target != effect_target_) {
DetachTarget(GetAnimation());
effect_target_ = target;
effect_target_ = new_target;
AttachTarget(GetAnimation());
InvalidateAndNotifyOwner();
}
}
String KeyframeEffect::composite() const {
......@@ -320,6 +412,7 @@ bool KeyframeEffect::HasPlayingAnimation() const {
void KeyframeEffect::Trace(blink::Visitor* visitor) {
visitor->Trace(effect_target_);
visitor->Trace(target_element_);
visitor->Trace(model_);
visitor->Trace(sampled_effect_);
AnimationEffect::Trace(visitor);
......
......@@ -77,8 +77,13 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
bool IsKeyframeEffect() const override { return true; }
// IDL implementation.
Element* target() const { return effect_target_; }
// Returns the target element. If the animation targets a pseudo-element,
// this returns the originating element.
Element* target() const { return target_element_; }
void setTarget(Element*);
const String& pseudoElement();
void setPseudoElement(String, ExceptionState&);
String composite() const;
void setComposite(String);
HeapVector<ScriptValue> getKeyframes(ScriptState*);
......@@ -138,6 +143,7 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
void Detach() override;
void AttachTarget(Animation*);
void DetachTarget(Animation*);
void RefreshTarget();
AnimationTimeDelta CalculateTimeToEffectChange(
bool forwards,
base::Optional<double> inherited_time,
......@@ -148,6 +154,8 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
bool AnimationsPreserveAxisAlignment(const PropertyHandle&) const;
Member<Element> effect_target_;
Member<Element> target_element_;
String target_pseudo_;
Member<KeyframeEffectModelBase> model_;
Member<SampledEffect> sampled_effect_;
......
......@@ -39,6 +39,7 @@ enum CompositeOperation { "replace", "add", "accumulate" };
[CallWith=ScriptState, RaisesException] constructor(Element? target, object? keyframes, optional (unrestricted double or KeyframeEffectOptions) options);
[CallWith=ScriptState, RaisesException] constructor(KeyframeEffect source);
attribute Element? target;
[RuntimeEnabled=WebAnimationsAPI, RaisesException=Setter] attribute CSSOMString? pseudoElement;
[RuntimeEnabled=WebAnimationsAPI] attribute CompositeOperation composite;
[CallWith=ScriptState, RuntimeEnabled=WebAnimationsAPI] sequence<object> getKeyframes();
[CallWith=ScriptState, RaisesException, RuntimeEnabled=WebAnimationsAPI] void setKeyframes(object? keyframes);
......
......@@ -7,4 +7,5 @@
dictionary KeyframeEffectOptions : EffectTiming {
// TODO(alancutter): Implement iterationComposite
CompositeOperation composite = "replace";
CSSOMString? pseudoElement = null;
};
......@@ -12,6 +12,6 @@ PASS Finished but not filling CSS Animations are not returned
PASS Yet-to-start CSS Animations are returned
PASS CSS Animations canceled via the API are not returned
PASS CSS Animations canceled and restarted via the API are returned
FAIL CSS Animations targetting (pseudo-)elements should have correct order after sorting assert_equals: Animation #1 has null pseudo type expected (object) null but got (undefined) undefined
FAIL CSS Animations targetting (pseudo-)elements should have correct order after sorting assert_equals: Animation #3 has expected target expected Element node <div id="parent" style="animation: animBottom 100s"><div ... but got Element node <div style="animation: animBottom 100s"></div>
Harness: the test ran to completion.
......@@ -17,9 +17,9 @@ PASS getAnimations returns objects with the same identity
PASS getAnimations for CSS Animations that are canceled
FAIL getAnimations for CSS Animations follows animation-name order assert_equals: animation order after prepending to list expected "anim1" but got "anim2"
PASS { subtree: false } on a leaf element returns the element's animations and ignore pseudo-elements
FAIL { subtree: true } on a leaf element returns the element's animations and its pseudo-elements' animations assert_equals: The animation targeting the parent element should be returned first expected (object) null but got (undefined) undefined
PASS { subtree: true } on a leaf element returns the element's animations and its pseudo-elements' animations
PASS { subtree: false } on an element with a child returns only the element's animations
FAIL { subtree: true } on an element with a child returns animations from the element, its pseudo-elements, its child and its child pseudo-elements assert_equals: The animation targeting the parent element should be returned first expected (object) null but got (undefined) undefined
FAIL { subtree: true } on an element with a child returns animations from the element, its pseudo-elements, its child and its child pseudo-elements assert_equals: The animation targeting the ::after pesudo-element should be returned third expected (string) "::after" but got (object) null
PASS { subtree: true } on an element with many descendants returns animations from all the descendants
Harness: the test ran to completion.
This is a testharness.js-based test.
PASS getAnimations for non-animated content
PASS getAnimations for CSS Transitions
FAIL CSS Transitions targetting (pseudo-)elements should have correct order after sorting assert_equals: Transition #1 has null pseudo type expected (object) null but got (undefined) undefined
FAIL CSS Transitions targetting (pseudo-)elements should have correct order after sorting assert_equals: Transition #3 has expected target expected Element node <div style="display: list-item; left: 100px; transition: ... but got Element node <div style="left: 100px; transition: left 100s ease 0s;">...
PASS Transitions are not returned after they have finished
Harness: the test ran to completion.
This is a testharness.js-based test.
Found 143 tests; 131 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
Found 143 tests; 133 PASS, 10 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS idl_test setup
PASS idl_test validation
PASS Partial interface Document: original interface defined
......@@ -107,14 +107,14 @@ PASS KeyframeEffect interface: existence and properties of interface prototype o
PASS KeyframeEffect interface: existence and properties of interface prototype object's "constructor" property
PASS KeyframeEffect interface: existence and properties of interface prototype object's @@unscopables property
PASS KeyframeEffect interface: attribute target
FAIL KeyframeEffect interface: attribute pseudoElement assert_true: The prototype object must have a property "pseudoElement" expected true got false
PASS KeyframeEffect interface: attribute pseudoElement
PASS KeyframeEffect interface: attribute composite
PASS KeyframeEffect interface: operation getKeyframes()
PASS KeyframeEffect interface: operation setKeyframes(object)
PASS KeyframeEffect must be primary interface of new KeyframeEffect(null, null)
PASS Stringification of new KeyframeEffect(null, null)
PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "target" with the proper type
FAIL KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "pseudoElement" with the proper type assert_inherits: property "pseudoElement" not found in prototype chain
PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "pseudoElement" with the proper type
PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "composite" with the proper type
PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "getKeyframes()" with the proper type
PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "setKeyframes(object)" with the proper type
......
This is a testharness.js-based test.
Found 142 tests; 138 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS Element.animate() creates an Animation object
PASS Element.animate() creates an Animation object in the relevant realm of the target element
PASS Element.animate() creates an Animation object with a KeyframeEffect
PASS Element.animate() creates an Animation object with a KeyframeEffect that is created in the relevant realm of the target element
PASS Element.animate() accepts empty keyframe lists (input: [])
PASS Element.animate() accepts empty keyframe lists (input: null)
PASS Element.animate() accepts empty keyframe lists (input: undefined)
PASS Element.animate() accepts a one property two value property-indexed keyframes specification
PASS Element.animate() accepts a one shorthand property two value property-indexed keyframes specification
PASS Element.animate() accepts a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification
PASS Element.animate() accepts a two property (one shorthand and one of its shorthand components) two value property-indexed keyframes specification
PASS Element.animate() accepts a two property two value property-indexed keyframes specification
PASS Element.animate() accepts a two property property-indexed keyframes specification with different numbers of values
PASS Element.animate() accepts a property-indexed keyframes specification with an invalid value
PASS Element.animate() accepts a one property two value property-indexed keyframes specification that needs to stringify its values
PASS Element.animate() accepts a property-indexed keyframes specification with a CSS variable reference
PASS Element.animate() accepts a property-indexed keyframes specification with a CSS variable reference in a shorthand property
PASS Element.animate() accepts a one property one value property-indexed keyframes specification
PASS Element.animate() accepts a one property one non-array value property-indexed keyframes specification
PASS Element.animate() accepts a one property two value property-indexed keyframes specification where the first value is invalid
PASS Element.animate() accepts a one property two value property-indexed keyframes specification where the second value is invalid
PASS Element.animate() accepts a property-indexed keyframes specification with a CSS variable as the property
PASS Element.animate() accepts a property-indexed keyframe with a single offset
PASS Element.animate() accepts a property-indexed keyframe with an array of offsets
PASS Element.animate() accepts a property-indexed keyframe with an array of offsets that is too short
PASS Element.animate() accepts a property-indexed keyframe with an array of offsets that is too long
PASS Element.animate() accepts a property-indexed keyframe with an empty array of offsets
PASS Element.animate() accepts a property-indexed keyframe with an array of offsets with an embedded null value
PASS Element.animate() accepts a property-indexed keyframe with an array of offsets with a trailing null value
PASS Element.animate() accepts a property-indexed keyframe with an array of offsets with leading and trailing null values
PASS Element.animate() accepts a property-indexed keyframe with an array of offsets with adjacent null values
PASS Element.animate() accepts a property-indexed keyframe with an array of offsets with all null values (and too many at that)
PASS Element.animate() accepts a property-indexed keyframe with a single null offset
PASS Element.animate() accepts a property-indexed keyframe with an array of offsets that is not strictly ascending in the unused part of the array
PASS Element.animate() accepts a property-indexed keyframe without any specified easing
PASS Element.animate() accepts a property-indexed keyframe with a single easing
PASS Element.animate() accepts a property-indexed keyframe with an array of easings
PASS Element.animate() accepts a property-indexed keyframe with an array of easings that is too short
PASS Element.animate() accepts a property-indexed keyframe with a single-element array of easings
PASS Element.animate() accepts a property-indexed keyframe with an empty array of easings
PASS Element.animate() accepts a property-indexed keyframe with an array of easings that is too long
PASS Element.animate() accepts a property-indexed keyframe with a single composite operation
PASS Element.animate() accepts a property-indexed keyframe with a composite array
PASS Element.animate() accepts a property-indexed keyframe with a composite array that is too short
PASS Element.animate() accepts a property-indexed keyframe with a composite array that is too long
PASS Element.animate() accepts a property-indexed keyframe with a single-element composite array
PASS Element.animate() accepts a one property one keyframe sequence
PASS Element.animate() accepts a one property two keyframe sequence
PASS Element.animate() accepts a two property two keyframe sequence
PASS Element.animate() accepts a one shorthand property two keyframe sequence
PASS Element.animate() accepts a two property (a shorthand and one of its component longhands) two keyframe sequence
PASS Element.animate() accepts a two property keyframe sequence where one property is missing from the first keyframe
PASS Element.animate() accepts a two property keyframe sequence where one property is missing from the last keyframe
PASS Element.animate() accepts a one property two keyframe sequence that needs to stringify its values
PASS Element.animate() accepts a keyframe sequence with a CSS variable reference
PASS Element.animate() accepts a keyframe sequence with a CSS variable reference in a shorthand property
PASS Element.animate() accepts a keyframe sequence with a CSS variable as its property
PASS Element.animate() accepts a keyframe sequence with duplicate values for a given interior offset
PASS Element.animate() accepts a keyframe sequence with duplicate values for offsets 0 and 1
PASS Element.animate() accepts a two property four keyframe sequence
PASS Element.animate() accepts a single keyframe sequence with omitted offset
PASS Element.animate() accepts a single keyframe sequence with null offset
PASS Element.animate() accepts a single keyframe sequence with string offset
PASS Element.animate() accepts a one property keyframe sequence with some omitted offsets
PASS Element.animate() accepts a one property keyframe sequence with some null offsets
PASS Element.animate() accepts a two property keyframe sequence with some omitted offsets
PASS Element.animate() accepts a one property keyframe sequence with all omitted offsets
PASS Element.animate() accepts a keyframe sequence with different easing values, but the same easing value for a given offset
PASS Element.animate() accepts a keyframe sequence with different composite values, but the same composite value for a given offset
PASS Element.animate() does not accept keyframes with an out-of-bounded positive offset
PASS Element.animate() does not accept keyframes with an out-of-bounded negative offset
PASS Element.animate() does not accept property-indexed keyframes not loosely sorted by offset
PASS Element.animate() does not accept property-indexed keyframes not loosely sorted by offset even though not all offsets are specified
PASS Element.animate() does not accept property-indexed keyframes with offsets out of range
PASS Element.animate() does not accept keyframes not loosely sorted by offset
PASS Element.animate() does not accept property-indexed keyframes with an invalid easing value
PASS Element.animate() does not accept property-indexed keyframes with an invalid easing value as one of the array values
PASS Element.animate() does not accept property-indexed keyframe with an invalid easing in the unused part of the array of easings
PASS Element.animate() does not accept empty property-indexed keyframe with an invalid easing
PASS Element.animate() does not accept empty property-indexed keyframe with an invalid easings array
PASS Element.animate() does not accept a keyframe sequence with an invalid easing value
PASS Element.animate() does not accept property-indexed keyframes with an invalid composite value
PASS Element.animate() does not accept property-indexed keyframes with an invalid composite value as one of the array values
PASS Element.animate() does not accept keyframes with an invalid composite value
PASS Element.animate() accepts a double as an options argument
PASS Element.animate() accepts a KeyframeAnimationOptions argument
PASS Element.animate() accepts an absent options argument
PASS Element.animate() does not accept invalid delay value: NaN
PASS Element.animate() does not accept invalid delay value: Infinity
PASS Element.animate() does not accept invalid delay value: -Infinity
PASS Element.animate() accepts a duration of 'auto' using a dictionary object
PASS Element.animate() does not accept invalid duration value: -1
PASS Element.animate() does not accept invalid duration value: NaN
PASS Element.animate() does not accept invalid duration value: -Infinity
PASS Element.animate() does not accept invalid duration value: "abc"
PASS Element.animate() does not accept invalid duration value: -1 using a dictionary object
PASS Element.animate() does not accept invalid duration value: NaN using a dictionary object
PASS Element.animate() does not accept invalid duration value: -Infinity using a dictionary object
PASS Element.animate() does not accept invalid duration value: "abc" using a dictionary object
PASS Element.animate() does not accept invalid duration value: "100" using a dictionary object
PASS Element.animate() does not accept invalid easing: ''
PASS Element.animate() does not accept invalid easing: '7'
PASS Element.animate() does not accept invalid easing: 'test'
PASS Element.animate() does not accept invalid easing: 'initial'
PASS Element.animate() does not accept invalid easing: 'inherit'
PASS Element.animate() does not accept invalid easing: 'unset'
PASS Element.animate() does not accept invalid easing: 'unrecognized'
PASS Element.animate() does not accept invalid easing: 'var(--x)'
PASS Element.animate() does not accept invalid easing: 'ease-in-out, ease-out'
PASS Element.animate() does not accept invalid easing: 'cubic-bezier(1.1, 0, 1, 1)'
PASS Element.animate() does not accept invalid easing: 'cubic-bezier(0, 0, 1.1, 1)'
PASS Element.animate() does not accept invalid easing: 'cubic-bezier(-0.1, 0, 1, 1)'
PASS Element.animate() does not accept invalid easing: 'cubic-bezier(0, 0, -0.1, 1)'
PASS Element.animate() does not accept invalid easing: 'cubic-bezier(0.1, 0, 4, 0.4)'
PASS Element.animate() does not accept invalid easing: 'steps(-1, start)'
PASS Element.animate() does not accept invalid easing: 'steps(0.1, start)'
PASS Element.animate() does not accept invalid easing: 'steps(3, nowhere)'
PASS Element.animate() does not accept invalid easing: 'steps(-3, end)'
PASS Element.animate() does not accept invalid easing: 'function (a){return a}'
PASS Element.animate() does not accept invalid easing: 'function (x){return x}'
PASS Element.animate() does not accept invalid easing: 'function(x, y){return 0.3}'
PASS Element.animate() does not accept invalid iterationStart value: -1
PASS Element.animate() does not accept invalid iterationStart value: NaN
PASS Element.animate() does not accept invalid iterationStart value: Infinity
PASS Element.animate() does not accept invalid iterationStart value: -Infinity
PASS Element.animate() does not accept invalid iterations value: -1
PASS Element.animate() does not accept invalid iterations value: -Infinity
PASS Element.animate() does not accept invalid iterations value: NaN
PASS Element.animate() correctly sets the id attribute when no id is specified
PASS Element.animate() correctly sets the id attribute
PASS Element.animate() correctly sets the Animation's timeline
PASS Element.animate() correctly sets the Animation's timeline when triggered on an element in a different document
PASS Element.animate() calls play on the Animation
PASS Element.animate() does NOT trigger a style change event
PASS animate() with pseudoElement parameter creates an Animation object
PASS animate() with pseudoElement parameter without content creates an Animation object
PASS animate() with pseudoElement parameter creates an Animation object for ::marker
PASS animate() with pseudoElement parameter creates an Animation object for ::first-line
FAIL animate() with pseudoElement an Animation object targeting the correct pseudo-element assert_equals: The returned Animation targets the correct selector expected (string) "::before" but got (undefined) undefined
FAIL animate() with pseudoElement without content creates an Animation object targeting the correct pseudo-element assert_equals: The returned Animation targets the correct selector expected (string) "::before" but got (undefined) undefined
FAIL animate() with pseudoElement an Animation object targeting the correct pseudo-element for ::marker assert_equals: The returned Animation targets the correct selector expected (string) "::marker" but got (undefined) undefined
FAIL animate() with pseudoElement an Animation object targeting the correct pseudo-element for ::first-line assert_equals: The returned Animation targets the correct selector expected (string) "::first-line" but got (undefined) undefined
Harness: the test ran to completion.
This is a testharness.js-based test.
FAIL All property keys are recognized assert_in_array: Test property 'iterationComposite' should be one of the properties on KeyframeEffect value "iterationComposite" not in array ["getTiming", "getComputedTiming", "updateTiming", "target", "composite", "getKeyframes", "setKeyframes", "KeyframeEffect constructor", "KeyframeEffect copy constructor"]
FAIL All property keys are recognized assert_in_array: Test property 'iterationComposite' should be one of the properties on KeyframeEffect value "iterationComposite" not in array ["getTiming", "getComputedTiming", "updateTiming", "target", "composite", "pseudoElement", "getKeyframes", "setKeyframes", "KeyframeEffect constructor", "KeyframeEffect copy constructor"]
PASS KeyframeEffect.getTiming does NOT trigger a style change event
PASS KeyframeEffect.getComputedTiming does NOT trigger a style change event
PASS KeyframeEffect.updateTiming does NOT trigger a style change event
PASS KeyframeEffect.target does NOT trigger a style change event
PASS KeyframeEffect.composite does NOT trigger a style change event
PASS KeyframeEffect.pseudoElement does NOT trigger a style change event
PASS KeyframeEffect.getKeyframes does NOT trigger a style change event
PASS KeyframeEffect.setKeyframes does NOT trigger a style change event
PASS KeyframeEffect.KeyframeEffect constructor does NOT trigger a style change event
......
......@@ -121,6 +121,15 @@ const tests = {
},
});
},
pseudoElement: MakeInEffectTest({
setup: elem => elem.animate(
{opacity: [0.5, 1]},
{duration: 100 * MS_PER_SEC, pseudoElement: '::before'}
),
test: effect => {
effect.pseudoElement = null;
},
}),
iterationComposite: UsePropertyTest(effect => {
// Get iterationComposite
effect.iterationComposite;
......
......@@ -4,19 +4,19 @@ PASS Test setting target from null to a valid target
PASS Test setting target from a valid target to null
PASS Test setting target from a valid target to another target
PASS Target element can be set to a foreign element
FAIL Change target from null to an existing pseudoElement setting target first. assert_equals: Value at 50% progress after setting new target expected "50px" but got "10px"
FAIL Change target from null to an existing pseudoElement setting pseudoElement first. assert_equals: Value at 50% progress after setting new target expected "50px" but got "10px"
PASS Change target from null to an existing pseudoElement setting target first.
PASS Change target from null to an existing pseudoElement setting pseudoElement first.
PASS Change target from an existing pseudo-element to the originating element.
FAIL Change target from an existing to a different existing pseudo-element by setting target. assert_equals: Animation targets specified pseudo-element (pseudo-selector) expected (string) "::before" but got (undefined) undefined
FAIL Change target from an existing to a different existing pseudo-element by setting pseudoElement. assert_equals: Value of 2nd element (currently targeted) after changing the effect target expected "50px" but got "20px"
FAIL Change target from a non-existing to a different existing pseudo-element by setting target. assert_equals: Animation targets specified pseudo-element (pseudo-selector) expected (string) "::before" but got (undefined) undefined
FAIL Change target from a non-existing to a different existing pseudo-element by setting pseudoElement. assert_equals: Value of 2nd element (currently targeted) after changing the effect target expected "50px" but got "20px"
PASS Change target from an existing to a different existing pseudo-element by setting target.
PASS Change target from an existing to a different existing pseudo-element by setting pseudoElement.
PASS Change target from a non-existing to a different existing pseudo-element by setting target.
PASS Change target from a non-existing to a different existing pseudo-element by setting pseudoElement.
FAIL Change target from null to a non-existing pseudoElement setting target first. assert_equals: Value at 50% progress after setting new target expected "50px" but got "10px"
FAIL Change target from null to a non-existing pseudoElement setting pseudoElement first. assert_equals: Value at 50% progress after setting new target expected "50px" but got "10px"
PASS Change target from a non-existing pseudo-element to the originating element.
FAIL Change target from an existing to a different non-existing pseudo-element by setting target. assert_equals: Animation targets specified pseudo-element (pseudo-selector) expected (string) "::before" but got (undefined) undefined
FAIL Change target from an existing to a different non-existing pseudo-element by setting target. assert_equals: Value of 2nd element (currently targeted) after changing the effect target expected "50px" but got "20px"
FAIL Change target from an existing to a different non-existing pseudo-element by setting pseudoElement. assert_equals: Value of 2nd element (currently targeted) after changing the effect target expected "50px" but got "20px"
FAIL Change target from a non-existing to a different non-existing pseudo-element by setting target. assert_equals: Animation targets specified pseudo-element (pseudo-selector) expected (string) "::before" but got (undefined) undefined
FAIL Change target from a non-existing to a different non-existing pseudo-element by setting target. assert_equals: Value of 2nd element (currently targeted) after changing the effect target expected "50px" but got "20px"
FAIL Change target from a non-existing to a different non-existing pseudo-element by setting pseudoElement. assert_equals: Value of 2nd element (currently targeted) after changing the effect target expected "50px" but got "20px"
Harness: the test ran to completion.
......@@ -4613,11 +4613,13 @@ interface KeyboardLayoutMap
interface KeyframeEffect : AnimationEffect
attribute @@toStringTag
getter composite
getter pseudoElement
getter target
method constructor
method getKeyframes
method setKeyframes
setter composite
setter pseudoElement
setter target
interface LargestContentfulPaint : PerformanceEntry
attribute @@toStringTag
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment