mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
bug 1483963, cache the index of a child node when ordering animations for event dispatch, r=hiro,ehsan
--HG-- extra : rebase_source : f98586625b199e7b2d0eb7db8dc9c1c5235289fe
This commit is contained in:
parent
017918778d
commit
57b81277a0
@ -61,6 +61,7 @@ public:
|
||||
: DOMEventTargetHelper(aGlobal)
|
||||
, mPlaybackRate(1.0)
|
||||
, mAnimationIndex(sNextAnimationIndex++)
|
||||
, mCachedChildIndex(-1)
|
||||
, mPendingState(PendingState::NotPending)
|
||||
, mFinishedAtLastComposeStyle(false)
|
||||
, mIsRelevant(false)
|
||||
@ -405,6 +406,8 @@ public:
|
||||
*/
|
||||
virtual void MaybeQueueCancelEvent(const StickyTimeDuration& aActiveTime) {};
|
||||
|
||||
int32_t& CachedChildIndexRef() { return mCachedChildIndex; }
|
||||
|
||||
protected:
|
||||
void SilentlySetCurrentTime(const TimeDuration& aNewCurrentTime);
|
||||
void CancelNoUpdate();
|
||||
@ -579,6 +582,10 @@ protected:
|
||||
// possible for two different objects to have the same index.
|
||||
uint64_t mAnimationIndex;
|
||||
|
||||
// While ordering Animation objects for event dispatch, the index of the
|
||||
// target node in its parent may be cached in mCachedChildIndex.
|
||||
int32_t mCachedChildIndex;
|
||||
|
||||
// Indicates if the animation is in the pending state (and what state it is
|
||||
// waiting to enter when it finished pending). We use this rather than
|
||||
// checking if this animation is tracked by a PendingAnimationTracker because
|
||||
|
@ -247,6 +247,10 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& pending : mPendingEvents) {
|
||||
pending.mAnimation->CachedChildIndexRef() = -1;
|
||||
}
|
||||
|
||||
// FIXME: Replace with mPendingEvents.StableSort when bug 1147091 is
|
||||
// fixed.
|
||||
std::stable_sort(mPendingEvents.begin(), mPendingEvents.end(),
|
||||
|
@ -2654,9 +2654,12 @@ nsContentUtils::GetCommonFlattenedTreeAncestorForStyle(Element* aElement1,
|
||||
|
||||
/* static */
|
||||
bool
|
||||
nsContentUtils::PositionIsBefore(nsINode* aNode1, nsINode* aNode2)
|
||||
nsContentUtils::PositionIsBefore(nsINode* aNode1, nsINode* aNode2,
|
||||
int32_t* aNode1Index,
|
||||
int32_t* aNode2Index)
|
||||
{
|
||||
return (aNode2->CompareDocumentPosition(*aNode1) &
|
||||
// Note, CompareDocumentPosition takes the latter params in different order.
|
||||
return (aNode2->CompareDocumentPosition(*aNode1, aNode2Index, aNode1Index) &
|
||||
(Node_Binding::DOCUMENT_POSITION_PRECEDING |
|
||||
Node_Binding::DOCUMENT_POSITION_DISCONNECTED)) ==
|
||||
Node_Binding::DOCUMENT_POSITION_PRECEDING;
|
||||
|
@ -434,8 +434,14 @@ public:
|
||||
/**
|
||||
* Returns true if aNode1 is before aNode2 in the same connected
|
||||
* tree.
|
||||
* aNode1Index and aNode2Index are in/out arguments. If non-null, and value is
|
||||
* not -1, that value is used instead of calling slow ComputeIndexOf on the
|
||||
* parent node. If value is -1, the value will be set to the return value of
|
||||
* ComputeIndexOf.
|
||||
*/
|
||||
static bool PositionIsBefore(nsINode* aNode1, nsINode* aNode2);
|
||||
static bool PositionIsBefore(nsINode* aNode1, nsINode* aNode2,
|
||||
int32_t* aNode1Index = nullptr,
|
||||
int32_t* aNode2Index = nullptr);
|
||||
|
||||
/**
|
||||
* Utility routine to compare two "points", where a point is a
|
||||
|
@ -752,7 +752,9 @@ nsINode::LookupPrefix(const nsAString& aNamespaceURI, nsAString& aPrefix)
|
||||
}
|
||||
|
||||
uint16_t
|
||||
nsINode::CompareDocumentPosition(nsINode& aOtherNode) const
|
||||
nsINode::CompareDocumentPosition(nsINode& aOtherNode,
|
||||
int32_t* aThisIndex,
|
||||
int32_t* aOtherIndex) const
|
||||
{
|
||||
if (this == &aOtherNode) {
|
||||
return 0;
|
||||
@ -852,9 +854,38 @@ nsINode::CompareDocumentPosition(nsINode& aOtherNode) const
|
||||
// child1 or child2 can be an attribute here. This will work fine since
|
||||
// ComputeIndexOf will return -1 for the attribute making the
|
||||
// attribute be considered before any child.
|
||||
return parent->ComputeIndexOf(child1) < parent->ComputeIndexOf(child2) ?
|
||||
int32_t child1Index;
|
||||
bool cachedChild1Index = false;
|
||||
if (&aOtherNode == child1 && aOtherIndex) {
|
||||
cachedChild1Index = true;
|
||||
child1Index = *aOtherIndex != -1 ?
|
||||
*aOtherIndex : parent->ComputeIndexOf(child1);
|
||||
} else {
|
||||
child1Index = parent->ComputeIndexOf(child1);
|
||||
}
|
||||
|
||||
int32_t child2Index;
|
||||
bool cachedChild2Index = false;
|
||||
if (this == child2 && aThisIndex) {
|
||||
cachedChild2Index = true;
|
||||
child2Index = *aThisIndex != -1 ?
|
||||
*aThisIndex : parent->ComputeIndexOf(child2);
|
||||
} else {
|
||||
child2Index = parent->ComputeIndexOf(child2);
|
||||
}
|
||||
|
||||
uint16_t retVal = child1Index < child2Index ?
|
||||
Node_Binding::DOCUMENT_POSITION_PRECEDING :
|
||||
Node_Binding::DOCUMENT_POSITION_FOLLOWING;
|
||||
|
||||
if (cachedChild1Index) {
|
||||
*aOtherIndex = child1Index;
|
||||
}
|
||||
if (cachedChild2Index) {
|
||||
*aThisIndex = child2Index;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
parent = child1;
|
||||
}
|
||||
|
@ -1769,7 +1769,11 @@ public:
|
||||
{
|
||||
return HasChildren();
|
||||
}
|
||||
uint16_t CompareDocumentPosition(nsINode& aOther) const;
|
||||
|
||||
// See nsContentUtils::PositionIsBefore for aThisIndex and aOtherIndex usage.
|
||||
uint16_t CompareDocumentPosition(nsINode& aOther,
|
||||
int32_t* aThisIndex = nullptr,
|
||||
int32_t* aOtherIndex = nullptr) const;
|
||||
void GetNodeValue(nsAString& aNodeValue)
|
||||
{
|
||||
GetNodeValueInternal(aNodeValue);
|
||||
|
@ -122,14 +122,17 @@ public:
|
||||
return mTarget == aOther.mTarget;
|
||||
}
|
||||
|
||||
bool LessThan(const OwningElementRef& aOther) const
|
||||
bool LessThan(int32_t& aChildIndex, const OwningElementRef& aOther,
|
||||
int32_t& aOtherChildIndex) const
|
||||
{
|
||||
MOZ_ASSERT(mTarget.mElement && aOther.mTarget.mElement,
|
||||
"Elements to compare should not be null");
|
||||
|
||||
if (mTarget.mElement != aOther.mTarget.mElement) {
|
||||
return nsContentUtils::PositionIsBefore(mTarget.mElement,
|
||||
aOther.mTarget.mElement);
|
||||
aOther.mTarget.mElement,
|
||||
&aChildIndex,
|
||||
&aOtherChildIndex);
|
||||
}
|
||||
|
||||
return mTarget.mPseudoType == CSSPseudoElementType::NotPseudo ||
|
||||
|
@ -155,7 +155,10 @@ CSSAnimation::HasLowerCompositeOrderThan(const CSSAnimation& aOther) const
|
||||
|
||||
// 1. Sort by document order
|
||||
if (!mOwningElement.Equals(aOther.mOwningElement)) {
|
||||
return mOwningElement.LessThan(aOther.mOwningElement);
|
||||
return mOwningElement.LessThan(
|
||||
const_cast<CSSAnimation*>(this)->CachedChildIndexRef(),
|
||||
aOther.mOwningElement,
|
||||
const_cast<CSSAnimation*>(&aOther)->CachedChildIndexRef());
|
||||
}
|
||||
|
||||
// 2. (Same element and pseudo): Sort by position in animation-name
|
||||
|
@ -362,7 +362,10 @@ CSSTransition::HasLowerCompositeOrderThan(const CSSTransition& aOther) const
|
||||
|
||||
// 1. Sort by document order
|
||||
if (!mOwningElement.Equals(aOther.mOwningElement)) {
|
||||
return mOwningElement.LessThan(aOther.mOwningElement);
|
||||
return mOwningElement.LessThan(
|
||||
const_cast<CSSTransition*>(this)->CachedChildIndexRef(),
|
||||
aOther.mOwningElement,
|
||||
const_cast<CSSTransition*>(&aOther)->CachedChildIndexRef());
|
||||
}
|
||||
|
||||
// 2. (Same element and pseudo): Sort by transition generation
|
||||
|
Loading…
Reference in New Issue
Block a user