зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
Коммит
289f67a603
|
@ -23,7 +23,9 @@ CSSPseudoElement::CSSPseudoElement(dom::Element* aElement,
|
|||
: mOriginatingElement(aElement), mPseudoType(aType) {
|
||||
MOZ_ASSERT(aElement);
|
||||
MOZ_ASSERT(
|
||||
aType == PseudoStyleType::after || aType == PseudoStyleType::before,
|
||||
aType == PseudoStyleType::after ||
|
||||
aType == PseudoStyleType::before ||
|
||||
aType == PseudoStyleType::marker,
|
||||
"Unexpected Pseudo Type");
|
||||
}
|
||||
|
||||
|
@ -106,10 +108,13 @@ nsAtom* CSSPseudoElement::GetCSSPseudoElementPropertyAtom(
|
|||
case PseudoStyleType::after:
|
||||
return nsGkAtoms::cssPseudoElementAfterProperty;
|
||||
|
||||
case PseudoStyleType::marker:
|
||||
return nsGkAtoms::cssPseudoElementMarkerProperty;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Should not try to get CSSPseudoElement "
|
||||
"other than ::before or ::after");
|
||||
"other than ::before, ::after or ::marker");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ class CSSPseudoElement final : public nsWrapperCache {
|
|||
dom::Element* aElement, PseudoStyleType aType);
|
||||
|
||||
private:
|
||||
// Only ::before and ::after are supported.
|
||||
// Only ::before, ::after and ::marker are supported.
|
||||
CSSPseudoElement(dom::Element* aElement, PseudoStyleType aType);
|
||||
|
||||
static nsAtom* GetCSSPseudoElementPropertyAtom(PseudoStyleType aType);
|
||||
|
|
|
@ -335,18 +335,22 @@ void EffectCompositor::ClearRestyleRequestsFor(Element* aElement) {
|
|||
|
||||
PseudoStyleType pseudoType = aElement->GetPseudoElementType();
|
||||
if (pseudoType == PseudoStyleType::NotPseudo) {
|
||||
PseudoElementHashEntry::KeyType notPseudoKey = {aElement,
|
||||
PseudoStyleType::NotPseudo};
|
||||
PseudoElementHashEntry::KeyType beforePseudoKey = {aElement,
|
||||
PseudoStyleType::before};
|
||||
PseudoElementHashEntry::KeyType afterPseudoKey = {aElement,
|
||||
PseudoStyleType::after};
|
||||
PseudoElementHashEntry::KeyType notPseudoKey =
|
||||
{aElement, PseudoStyleType::NotPseudo};
|
||||
PseudoElementHashEntry::KeyType beforePseudoKey =
|
||||
{aElement, PseudoStyleType::before};
|
||||
PseudoElementHashEntry::KeyType afterPseudoKey =
|
||||
{aElement, PseudoStyleType::after};
|
||||
PseudoElementHashEntry::KeyType markerPseudoKey =
|
||||
{aElement, PseudoStyleType::marker};
|
||||
|
||||
elementsToRestyle.Remove(notPseudoKey);
|
||||
elementsToRestyle.Remove(beforePseudoKey);
|
||||
elementsToRestyle.Remove(afterPseudoKey);
|
||||
elementsToRestyle.Remove(markerPseudoKey);
|
||||
} else if (pseudoType == PseudoStyleType::before ||
|
||||
pseudoType == PseudoStyleType::after) {
|
||||
pseudoType == PseudoStyleType::after ||
|
||||
pseudoType == PseudoStyleType::marker) {
|
||||
Element* parentElement = aElement->GetParentElement();
|
||||
MOZ_ASSERT(parentElement);
|
||||
PseudoElementHashEntry::KeyType key = {parentElement, pseudoType};
|
||||
|
@ -444,9 +448,13 @@ bool EffectCompositor::GetServoAnimationRule(
|
|||
return nsLayoutUtils::GetAfterPseudo(aElement);
|
||||
}
|
||||
|
||||
if (aPseudoType == PseudoStyleType::marker) {
|
||||
return nsLayoutUtils::GetMarkerPseudo(aElement);
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Should not try to get the element to restyle for "
|
||||
"a pseudo other that :before or :after");
|
||||
"a pseudo other that :before, :after or ::marker");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -520,7 +528,8 @@ EffectCompositor::GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame) {
|
|||
|
||||
if (pseudoType != PseudoStyleType::NotPseudo &&
|
||||
pseudoType != PseudoStyleType::before &&
|
||||
pseudoType != PseudoStyleType::after) {
|
||||
pseudoType != PseudoStyleType::after &&
|
||||
pseudoType != PseudoStyleType::marker) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -530,7 +539,8 @@ EffectCompositor::GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame) {
|
|||
}
|
||||
|
||||
if (pseudoType == PseudoStyleType::before ||
|
||||
pseudoType == PseudoStyleType::after) {
|
||||
pseudoType == PseudoStyleType::after ||
|
||||
pseudoType == PseudoStyleType::marker) {
|
||||
content = content->GetParent();
|
||||
if (!content) {
|
||||
return result;
|
||||
|
@ -722,7 +732,8 @@ bool EffectCompositor::PreTraverseInSubtree(ServoTraversalFlags aFlags,
|
|||
// of the root element later in this function, but for pseudo elements the
|
||||
// element in mElementsToRestyle is the parent of the pseudo.
|
||||
if (aRoot && (aRoot->IsGeneratedContentContainerForBefore() ||
|
||||
aRoot->IsGeneratedContentContainerForAfter())) {
|
||||
aRoot->IsGeneratedContentContainerForAfter() ||
|
||||
aRoot->IsGeneratedContentContainerForMarker())) {
|
||||
aRoot = aRoot->GetParentElement();
|
||||
}
|
||||
|
||||
|
@ -865,7 +876,8 @@ bool EffectCompositor::PreTraverse(dom::Element* aElement,
|
|||
bool found = false;
|
||||
if (aPseudoType != PseudoStyleType::NotPseudo &&
|
||||
aPseudoType != PseudoStyleType::before &&
|
||||
aPseudoType != PseudoStyleType::after) {
|
||||
aPseudoType != PseudoStyleType::after &&
|
||||
aPseudoType != PseudoStyleType::marker) {
|
||||
return found;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ class EffectCompositor {
|
|||
void PostRestyleForThrottledAnimations();
|
||||
|
||||
// Clear all pending restyle requests for the given (pseudo-) element (and its
|
||||
// ::before and ::after elements if the given element is not pseudo).
|
||||
// ::before, ::after and ::marker elements if the given element is not pseudo).
|
||||
void ClearRestyleRequestsFor(dom::Element* aElement);
|
||||
|
||||
// Called when computed style on the specified (pseudo-) element might
|
||||
|
@ -203,7 +203,7 @@ class EffectCompositor {
|
|||
|
||||
// Returns the target element for restyling.
|
||||
//
|
||||
// If |aPseudoType| is ::after or ::before, returns the generated content
|
||||
// If |aPseudoType| is ::after, ::before or ::marker, returns the generated content
|
||||
// element of which |aElement| is the parent. If |aPseudoType| is any other
|
||||
// pseudo type (other than PseudoStyleType::NotPseudo) returns nullptr.
|
||||
// Otherwise, returns |aElement|.
|
||||
|
|
|
@ -150,7 +150,9 @@ nsAtom** EffectSet::GetEffectSetPropertyAtoms() {
|
|||
static nsAtom* effectSetPropertyAtoms[] = {
|
||||
nsGkAtoms::animationEffectsProperty,
|
||||
nsGkAtoms::animationEffectsForBeforeProperty,
|
||||
nsGkAtoms::animationEffectsForAfterProperty, nullptr};
|
||||
nsGkAtoms::animationEffectsForAfterProperty,
|
||||
nsGkAtoms::animationEffectsForMarkerProperty,
|
||||
nullptr};
|
||||
|
||||
return effectSetPropertyAtoms;
|
||||
}
|
||||
|
@ -167,10 +169,13 @@ nsAtom* EffectSet::GetEffectSetPropertyAtom(PseudoStyleType aPseudoType) {
|
|||
case PseudoStyleType::after:
|
||||
return nsGkAtoms::animationEffectsForAfterProperty;
|
||||
|
||||
case PseudoStyleType::marker:
|
||||
return nsGkAtoms::animationEffectsForMarkerProperty;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Should not try to get animation effects for "
|
||||
"a pseudo other that :before or :after");
|
||||
"a pseudo other that :before, :after or ::marker");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -942,6 +942,7 @@ void KeyframeEffect::GetTarget(
|
|||
switch (mTarget->mPseudoType) {
|
||||
case PseudoStyleType::before:
|
||||
case PseudoStyleType::after:
|
||||
case PseudoStyleType::marker:
|
||||
aRv.SetValue().SetAsCSSPseudoElement() =
|
||||
CSSPseudoElement::GetCSSPseudoElement(mTarget->mElement,
|
||||
mTarget->mPseudoType);
|
||||
|
@ -1389,6 +1390,8 @@ nsIFrame* KeyframeEffect::GetPrimaryFrame() const {
|
|||
frame = nsLayoutUtils::GetBeforeFrame(mTarget->mElement);
|
||||
} else if (mTarget->mPseudoType == PseudoStyleType::after) {
|
||||
frame = nsLayoutUtils::GetAfterFrame(mTarget->mElement);
|
||||
} else if (mTarget->mPseudoType == PseudoStyleType::marker) {
|
||||
frame = nsLayoutUtils::GetMarkerFrame(mTarget->mElement);
|
||||
} else {
|
||||
frame = mTarget->mElement->GetPrimaryFrame();
|
||||
MOZ_ASSERT(mTarget->mPseudoType == PseudoStyleType::NotPseudo,
|
||||
|
|
|
@ -1777,7 +1777,8 @@ nsresult Element::BindToTree(Document* aDocument, nsIContent* aParent,
|
|||
PseudoStyleType pseudoType = GetPseudoElementType();
|
||||
if ((pseudoType == PseudoStyleType::NotPseudo ||
|
||||
pseudoType == PseudoStyleType::before ||
|
||||
pseudoType == PseudoStyleType::after) &&
|
||||
pseudoType == PseudoStyleType::after ||
|
||||
pseudoType == PseudoStyleType::marker) &&
|
||||
EffectSet::GetEffectSet(this, pseudoType)) {
|
||||
if (nsPresContext* presContext = aDocument->GetPresContext()) {
|
||||
presContext->EffectCompositor()->RequestRestyle(
|
||||
|
@ -1913,9 +1914,11 @@ void Element::UnbindFromTree(bool aDeep, bool aNullParent) {
|
|||
if (MayHaveAnimations()) {
|
||||
DeleteProperty(nsGkAtoms::transitionsOfBeforeProperty);
|
||||
DeleteProperty(nsGkAtoms::transitionsOfAfterProperty);
|
||||
DeleteProperty(nsGkAtoms::transitionsOfMarkerProperty);
|
||||
DeleteProperty(nsGkAtoms::transitionsProperty);
|
||||
DeleteProperty(nsGkAtoms::animationsOfBeforeProperty);
|
||||
DeleteProperty(nsGkAtoms::animationsOfAfterProperty);
|
||||
DeleteProperty(nsGkAtoms::animationsOfMarkerProperty);
|
||||
DeleteProperty(nsGkAtoms::animationsProperty);
|
||||
if (document) {
|
||||
if (nsPresContext* presContext = document->GetPresContext()) {
|
||||
|
@ -3493,14 +3496,19 @@ void Element::GetAnimations(const AnimationFilter& filter,
|
|||
} else if (IsGeneratedContentContainerForAfter()) {
|
||||
elem = GetParentElement();
|
||||
pseudoType = PseudoStyleType::after;
|
||||
} else if (IsGeneratedContentContainerForMarker()) {
|
||||
elem = GetParentElement();
|
||||
pseudoType = PseudoStyleType::marker;
|
||||
}
|
||||
|
||||
if (!elem) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!filter.mSubtree || pseudoType == PseudoStyleType::before ||
|
||||
pseudoType == PseudoStyleType::after) {
|
||||
if (!filter.mSubtree ||
|
||||
pseudoType == PseudoStyleType::before ||
|
||||
pseudoType == PseudoStyleType::after ||
|
||||
pseudoType == PseudoStyleType::marker) {
|
||||
GetAnimationsUnsorted(elem, pseudoType, aAnimations);
|
||||
} else {
|
||||
for (nsIContent* node = this; node; node = node->GetNextNode(this)) {
|
||||
|
@ -3514,6 +3522,8 @@ void Element::GetAnimations(const AnimationFilter& filter,
|
|||
aAnimations);
|
||||
Element::GetAnimationsUnsorted(element, PseudoStyleType::after,
|
||||
aAnimations);
|
||||
Element::GetAnimationsUnsorted(element, PseudoStyleType::marker,
|
||||
aAnimations);
|
||||
}
|
||||
}
|
||||
aAnimations.Sort(AnimationPtrComparator<RefPtr<Animation>>());
|
||||
|
@ -3525,7 +3535,8 @@ void Element::GetAnimationsUnsorted(Element* aElement,
|
|||
nsTArray<RefPtr<Animation>>& aAnimations) {
|
||||
MOZ_ASSERT(aPseudoType == PseudoStyleType::NotPseudo ||
|
||||
aPseudoType == PseudoStyleType::after ||
|
||||
aPseudoType == PseudoStyleType::before,
|
||||
aPseudoType == PseudoStyleType::before ||
|
||||
aPseudoType == PseudoStyleType::marker,
|
||||
"Unsupported pseudo type");
|
||||
MOZ_ASSERT(aElement, "Null element");
|
||||
|
||||
|
|
|
@ -1230,6 +1230,8 @@ void nsGlobalWindowInner::FreeInnerObjects() {
|
|||
mExternal = nullptr;
|
||||
mInstallTrigger = nullptr;
|
||||
|
||||
mLocalStorage = nullptr;
|
||||
mSessionStorage = nullptr;
|
||||
mPerformance = nullptr;
|
||||
|
||||
mSharedWorkers.Clear();
|
||||
|
|
|
@ -1983,6 +1983,7 @@ void RestyleManager::AnimationsWithDestroyedFrame ::
|
|||
StopAnimationsWithoutFrame(mContents, PseudoStyleType::NotPseudo);
|
||||
StopAnimationsWithoutFrame(mBeforeContents, PseudoStyleType::before);
|
||||
StopAnimationsWithoutFrame(mAfterContents, PseudoStyleType::after);
|
||||
StopAnimationsWithoutFrame(mAfterContents, PseudoStyleType::marker);
|
||||
}
|
||||
|
||||
void RestyleManager::AnimationsWithDestroyedFrame ::StopAnimationsWithoutFrame(
|
||||
|
@ -2004,6 +2005,10 @@ void RestyleManager::AnimationsWithDestroyedFrame ::StopAnimationsWithoutFrame(
|
|||
if (nsLayoutUtils::GetAfterFrame(content)) {
|
||||
continue;
|
||||
}
|
||||
} else if (aPseudoType == PseudoStyleType::marker) {
|
||||
if (nsLayoutUtils::GetMarkerFrame(content)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
dom::Element* element = content->AsElement();
|
||||
|
||||
|
|
|
@ -263,6 +263,10 @@ class RestyleManager {
|
|||
MOZ_ASSERT(aContent->NodeInfo()->NameAtom() ==
|
||||
nsGkAtoms::mozgeneratedcontentafter);
|
||||
mAfterContents.AppendElement(aContent->GetParent());
|
||||
} else if (pseudoType == PseudoStyleType::marker) {
|
||||
MOZ_ASSERT(aContent->NodeInfo()->NameAtom() ==
|
||||
nsGkAtoms::mozgeneratedcontentmarker);
|
||||
mMarkerContents.AppendElement(aContent->GetParent());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,12 +282,13 @@ class RestyleManager {
|
|||
// Below three arrays might include elements that have already had their
|
||||
// animations or transitions stopped.
|
||||
//
|
||||
// mBeforeContents and mAfterContents hold the real element rather than
|
||||
// the content node for the generated content (which might change during
|
||||
// a reframe)
|
||||
// mBeforeContents, mAfterContents and mMarkerContents hold the real element
|
||||
// rather than the content node for the generated content (which might
|
||||
// change during a reframe)
|
||||
nsTArray<RefPtr<nsIContent>> mContents;
|
||||
nsTArray<RefPtr<nsIContent>> mBeforeContents;
|
||||
nsTArray<RefPtr<nsIContent>> mAfterContents;
|
||||
nsTArray<RefPtr<nsIContent>> mMarkerContents;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style>
|
||||
#target::marker {
|
||||
content: 'content';
|
||||
}
|
||||
#target {
|
||||
display: list-item;
|
||||
margin-left: 200px;
|
||||
}
|
||||
</style>
|
||||
<div id='target'></div>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { content: 'content'; }
|
||||
to { content: ''; }
|
||||
}
|
||||
#target::marker {
|
||||
content: 'initial';
|
||||
animation: anim 100s paused;
|
||||
}
|
||||
#target {
|
||||
display: list-item;
|
||||
margin-left: 200px;
|
||||
}
|
||||
</style>
|
||||
<div id='target'></div>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { content: ''; }
|
||||
to { content: 'content'; }
|
||||
}
|
||||
#target::marker {
|
||||
content: 'initial';
|
||||
animation: anim 100s linear -50s paused;
|
||||
}
|
||||
#target {
|
||||
display: list-item;
|
||||
margin-left: 200px;
|
||||
}
|
||||
</style>
|
||||
<div id='target'></div>
|
||||
</html>
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<title>In visibility hidden color animation on pseudo element</title>
|
||||
<style>
|
||||
|
||||
div::marker {
|
||||
visibility: visible;
|
||||
color: blue;
|
||||
content: "Color Animation";
|
||||
}
|
||||
|
||||
div {
|
||||
color: black;
|
||||
visibility: hidden;
|
||||
display: list-item;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div>color animation on visible psuedo element attached to invisible element</div>
|
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<title>In visibility hidden color animation on pseudo element</title>
|
||||
<style>
|
||||
|
||||
@keyframes color {
|
||||
0% { color: black }
|
||||
1% { color: blue }
|
||||
100% { color: blue }
|
||||
}
|
||||
|
||||
div::marker {
|
||||
visibility: visible;
|
||||
content: "Color Animation";
|
||||
animation: color 0.1s 1 forwards;
|
||||
}
|
||||
|
||||
div {
|
||||
color: black;
|
||||
visibility: hidden;
|
||||
display: list-item;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div id="target">color animation on visible pseudo element attached to invisible element</div>
|
||||
<script>
|
||||
|
||||
document.getElementById("target").addEventListener("animationend", AnimationEndListener);
|
||||
|
||||
function AnimationEndListener(event) {
|
||||
setTimeout(RemoveReftestWait, 0);
|
||||
}
|
||||
|
||||
function RemoveReftestWait() {
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
}
|
||||
|
||||
</script>
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style>
|
||||
#target::marker {
|
||||
content: '';
|
||||
background-color: rgb(255, 255, 255);
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
position: absolute;
|
||||
}
|
||||
#target {
|
||||
display: list-item;
|
||||
list-style-position: inside;
|
||||
}
|
||||
</style>
|
||||
<div id="target"></div>
|
||||
</html>
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { background-color: rgb(255, 255, 255); }
|
||||
to { background-color: rgb(255, 255, 255); }
|
||||
}
|
||||
#target::marker {
|
||||
content: 'initial';
|
||||
background-color: rgb(0, 0, 0);
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
position: absolute;
|
||||
}
|
||||
#target.hover::marker{
|
||||
content: '';
|
||||
animation: anim 100s steps(1, start);
|
||||
}
|
||||
#target {
|
||||
display: list-item;
|
||||
list-style-position: inside;
|
||||
}
|
||||
</style>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
window.addEventListener("load", () => {
|
||||
target.className = 'hover';
|
||||
target.addEventListener('animationstart', () => {
|
||||
document.documentElement.classList.remove('reftest-wait');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
|
@ -8,6 +8,7 @@ fails != print-no-animations.html print-no-animations-notref.html # reftest harn
|
|||
== animation-on-empty-height-frame.html about:blank
|
||||
== in-visibility-hidden-animation.html in-visibility-hidden-animation-ref.html
|
||||
== in-visibility-hidden-animation-pseudo-element.html in-visibility-hidden-animation-pseudo-element-ref.html
|
||||
== in-visibility-hidden-animation-marker-pseudo-element.html in-visibility-hidden-animation-marker-pseudo-element-ref.html
|
||||
== partially-out-of-view-animation.html partially-out-of-view-animation-ref.html
|
||||
== animate-display-table-opacity.html animate-display-table-opacity-ref.html
|
||||
# We need to run 100% opacity test case when OMTA is disabled to check that the animation creates a stacking context even if the animation is not running on the compositor
|
||||
|
@ -57,9 +58,13 @@ fails-if(layerChecksEnabled) == background-position-important.html background-po
|
|||
== stop-animation-on-discarded-pseudo-element.html about:blank
|
||||
|
||||
== updating-animation-on-pseudo-element.html updating-animation-on-pseudo-element-ref.html
|
||||
== updating-animation-on-marker-pseudo-element.html updating-animation-on-marker-pseudo-element-ref.html
|
||||
== content-on-pseudo-element-at-beginning.html content-on-pseudo-element-ref.html
|
||||
== content-on-pseudo-element-at-half.html content-on-pseudo-element-ref.html
|
||||
== content-on-marker-pseudo-element-at-beginning.html content-on-marker-pseudo-element-at-beginning-ref.html
|
||||
== content-on-marker-pseudo-element-at-half.html content-on-marker-pseudo-element-at-beginning-ref.html
|
||||
== reframe-and-animation-starts-at-the-same-time.html reframe-and-animation-starts-at-the-same-time-ref.html
|
||||
== marker-reframe-and-animation-starts-at-the-same-time.html marker-reframe-and-animation-starts-at-the-same-time-ref.html
|
||||
== change-animation-name-to-none-in-rule.html change-animation-name-in-rule-ref.html
|
||||
== change-animation-name-to-other-in-rule.html change-animation-name-in-rule-ref.html
|
||||
== change-animation-name-to-non-existent-in-rule.html change-animation-name-in-rule-ref.html
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<style>
|
||||
#target::marker {
|
||||
content: 'marker';
|
||||
margin-left: 10em;
|
||||
font-size: 20px;
|
||||
}
|
||||
#target {
|
||||
display: list-item;
|
||||
margin-left: 200px;
|
||||
}
|
||||
</style>
|
||||
<div id="target"></div>
|
||||
</html>
|
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { margin-left: 10em; }
|
||||
to { margin-left: 10em; }
|
||||
}
|
||||
#target::marker {
|
||||
content: 'marker';
|
||||
}
|
||||
#target.anim::marker {
|
||||
animation: anim 100s infinite;
|
||||
font-size: 10px;
|
||||
}
|
||||
#target.bigger-font::marker {
|
||||
font-size: 20px;
|
||||
}
|
||||
#target {
|
||||
display: list-item;
|
||||
margin-left: 200px;
|
||||
}
|
||||
</style>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
addEventListener('DOMContentLoaded', () => {
|
||||
var target = document.getElementById('target');
|
||||
|
||||
// Start an animation on pseudo element.
|
||||
target.classList.add('anim');
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
// The animation on pseudo element should be updated
|
||||
// when the target element classes are modified.
|
||||
target.classList.add('bigger-font');
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
document.documentElement.classList.remove('reftest-wait');
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
|
@ -117,6 +117,8 @@ AnimationCollection<AnimationType>::GetPropertyAtomForPseudoType(
|
|||
propName = TraitsType::BeforePropertyAtom();
|
||||
} else if (aPseudoType == PseudoStyleType::after) {
|
||||
propName = TraitsType::AfterPropertyAtom();
|
||||
} else if (aPseudoType == PseudoStyleType::marker) {
|
||||
propName = TraitsType::MarkerPropertyAtom();
|
||||
}
|
||||
|
||||
return propName;
|
||||
|
|
|
@ -47,7 +47,7 @@ class CommonAnimationManager {
|
|||
/**
|
||||
* Stop animations on the element. This method takes the real element
|
||||
* rather than the element for the generated content for animations on
|
||||
* ::before and ::after.
|
||||
* ::before, ::after and ::marker.
|
||||
*/
|
||||
void StopAnimationsForElement(dom::Element* aElement,
|
||||
PseudoStyleType aPseudoType) {
|
||||
|
@ -123,6 +123,10 @@ class OwningElementRef final {
|
|||
|
||||
return mTarget.mPseudoType == PseudoStyleType::NotPseudo ||
|
||||
(mTarget.mPseudoType == PseudoStyleType::before &&
|
||||
aOther.mTarget.mPseudoType == PseudoStyleType::after) ||
|
||||
(mTarget.mPseudoType == PseudoStyleType::marker &&
|
||||
aOther.mTarget.mPseudoType == PseudoStyleType::before) ||
|
||||
(mTarget.mPseudoType == PseudoStyleType::marker &&
|
||||
aOther.mTarget.mPseudoType == PseudoStyleType::after);
|
||||
}
|
||||
|
||||
|
|
|
@ -470,6 +470,11 @@ static PseudoStyleType GetPseudoTypeFromElementForAnimation(
|
|||
return PseudoStyleType::after;
|
||||
}
|
||||
|
||||
if (aElementOrPseudo->IsGeneratedContentContainerForMarker()) {
|
||||
aElementOrPseudo = aElementOrPseudo->GetParent()->AsElement();
|
||||
return PseudoStyleType::marker;
|
||||
}
|
||||
|
||||
return PseudoStyleType::NotPseudo;
|
||||
}
|
||||
|
||||
|
|
|
@ -1228,6 +1228,11 @@ already_AddRefed<ComputedStyle> ServoStyleSet::ResolveStyleLazilyInternal(
|
|||
elementForStyleResolution = pseudo;
|
||||
pseudoTypeForStyleResolution = PseudoStyleType::NotPseudo;
|
||||
}
|
||||
} else if (aPseudoType == PseudoStyleType::marker) {
|
||||
if (Element* pseudo = nsLayoutUtils::GetMarkerPseudo(aElement)) {
|
||||
elementForStyleResolution = pseudo;
|
||||
pseudoTypeForStyleResolution = PseudoStyleType::NotPseudo;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<ComputedStyle> computedValues =
|
||||
|
|
|
@ -255,6 +255,9 @@ struct AnimationTypeTraits<dom::CSSAnimation> {
|
|||
static nsAtom* AfterPropertyAtom() {
|
||||
return nsGkAtoms::animationsOfAfterProperty;
|
||||
}
|
||||
static nsAtom* MarkerPropertyAtom() {
|
||||
return nsGkAtoms::animationsOfMarkerProperty;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
|
|
@ -119,6 +119,8 @@ nsString nsCSSPseudoElements::PseudoTypeAsString(Type aPseudoType) {
|
|||
return NS_LITERAL_STRING("::before");
|
||||
case PseudoStyleType::after:
|
||||
return NS_LITERAL_STRING("::after");
|
||||
case PseudoStyleType::marker:
|
||||
return NS_LITERAL_STRING("::marker");
|
||||
default:
|
||||
MOZ_ASSERT(aPseudoType == PseudoStyleType::NotPseudo,
|
||||
"Unexpected pseudo type");
|
||||
|
|
|
@ -135,6 +135,10 @@ static bool DocumentNeedsRestyle(const Document* aDocument, Element* aElement,
|
|||
if (EffectSet::GetEffectSet(aElement, PseudoStyleType::after)) {
|
||||
return true;
|
||||
}
|
||||
} else if (aPseudo == nsCSSPseudoElements::marker()) {
|
||||
if (EffectSet::GetEffectSet(aElement, PseudoStyleType::marker)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -276,6 +276,9 @@ struct AnimationTypeTraits<dom::CSSTransition> {
|
|||
static nsAtom* AfterPropertyAtom() {
|
||||
return nsGkAtoms::transitionsOfAfterProperty;
|
||||
}
|
||||
static nsAtom* MarkerPropertyAtom() {
|
||||
return nsGkAtoms::transitionsOfMarkerProperty;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Animations Test: AnimationEvent pseudoElement</title>
|
||||
<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations/#interface-animationevent">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
#target::marker {
|
||||
content: "";
|
||||
animation: move 1s;
|
||||
}
|
||||
|
||||
@keyframes move {
|
||||
to { transform: translate(100px); }
|
||||
}
|
||||
|
||||
#target {
|
||||
display: list-item;
|
||||
list-style-position: inside;
|
||||
}
|
||||
</style>
|
||||
<div id='target'></div>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
var target = document.getElementById('target');
|
||||
target.addEventListener("animationstart", t.step_func(function(evt) {
|
||||
assert_true(evt instanceof window.AnimationEvent);
|
||||
assert_equals(evt.pseudoElement, "::marker");
|
||||
|
||||
t.done();
|
||||
}), true);
|
||||
}, "AnimationEvent should have the correct pseudoElement memeber");
|
||||
</script>
|
||||
|
|
@ -243,6 +243,12 @@ test(t => {
|
|||
assert_class_string(anim, 'Animation', 'The returned object is an Animation');
|
||||
}, 'CSSPseudoElement.animate() creates an Animation object');
|
||||
|
||||
test(t => {
|
||||
const pseudoTarget = getPseudoElement(t, 'marker');
|
||||
const anim = pseudoTarget.animate(null);
|
||||
assert_class_string(anim, 'Animation', 'The returned object is an Animation for ::marker');
|
||||
}, 'CSSPseudoElement.animate() creates an Animation object for ::marker');
|
||||
|
||||
test(t => {
|
||||
const pseudoTarget = getPseudoElement(t, 'before');
|
||||
const anim = pseudoTarget.animate(null);
|
||||
|
@ -250,5 +256,13 @@ test(t => {
|
|||
'The returned Animation targets to the correct object');
|
||||
}, 'CSSPseudoElement.animate() creates an Animation object targeting ' +
|
||||
'to the correct CSSPseudoElement object');
|
||||
|
||||
test(t => {
|
||||
const pseudoTarget = getPseudoElement(t, 'marker');
|
||||
const anim = pseudoTarget.animate(null);
|
||||
assert_equals(anim.effect.target, pseudoTarget,
|
||||
'The returned Animation targets to the correct object for ::marker');
|
||||
}, 'CSSPseudoElement.animate() creates an Animation object targeting ' +
|
||||
'to the correct CSSPseudoElement object for ::marker');
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -93,6 +93,9 @@ function getPseudoElement(test, type) {
|
|||
[`.pseudo::${type}`]: 'animation: anim 10s; ' +
|
||||
'content: \'\';' });
|
||||
const div = createDiv(test);
|
||||
if (type == 'marker') {
|
||||
div.style.display = 'list-item';
|
||||
}
|
||||
div.classList.add('pseudo');
|
||||
const anims = document.getAnimations();
|
||||
assert_true(anims.length >= 1);
|
||||
|
|
|
@ -2049,15 +2049,19 @@ STATIC_ATOMS = [
|
|||
Atom("animationsProperty", "AnimationsProperty"), # FrameAnimations*
|
||||
Atom("animationsOfBeforeProperty", "AnimationsOfBeforeProperty"), # FrameAnimations*
|
||||
Atom("animationsOfAfterProperty", "AnimationsOfAfterProperty"), # FrameAnimations*
|
||||
Atom("animationsOfMarkerProperty", "AnimationsOfMarkerProperty"), # FrameAnimations*
|
||||
Atom("animationEffectsProperty", "AnimationEffectsProperty"), # EffectSet*
|
||||
Atom("animationEffectsForBeforeProperty", "AnimationsEffectsForBeforeProperty"), # EffectSet*
|
||||
Atom("animationEffectsForAfterProperty", "AnimationsEffectsForAfterProperty"), # EffectSet*
|
||||
Atom("animationEffectsForMarkerProperty", "AnimationsEffectsForMarkerProperty"), # EffectSet*
|
||||
Atom("beforePseudoProperty", "beforePseudoProperty"), # nsXMLElement*
|
||||
Atom("cssPseudoElementBeforeProperty", "CSSPseudoElementBeforeProperty"), # CSSPseudoElement*
|
||||
Atom("cssPseudoElementAfterProperty", "CSSPseudoElementAfterProperty"), # CSSPseudoElement*
|
||||
Atom("cssPseudoElementMarkerProperty", "CSSPseudoElementMarkerProperty"), # CSSPseudoElement*
|
||||
Atom("transitionsProperty", "TransitionsProperty"), # FrameTransitions*
|
||||
Atom("transitionsOfBeforeProperty", "TransitionsOfBeforeProperty"), # FrameTransitions*
|
||||
Atom("transitionsOfAfterProperty", "TransitionsOfAfterProperty"), # FrameTransitions*
|
||||
Atom("transitionsOfMarkerProperty", "TransitionsOfMarkerProperty"), # FrameTransitions*
|
||||
Atom("genConInitializerProperty", "QuoteNodeProperty"),
|
||||
Atom("labelMouseDownPtProperty", "LabelMouseDownPtProperty"),
|
||||
Atom("lockedStyleStates", "lockedStyleStates"),
|
||||
|
|
Загрузка…
Ссылка в новой задаче