Skip to content

Commit

Permalink
Bug 1123523 - Part 6: Listen for nsIAnimationObserver notifications a…
Browse files Browse the repository at this point in the history
…nd translate them to MutationObserver notifications. r=smaug
  • Loading branch information
rmottola committed Aug 4, 2019
1 parent 585e302 commit 9980c91
Show file tree
Hide file tree
Showing 3 changed files with 397 additions and 21 deletions.
161 changes: 153 additions & 8 deletions dom/base/nsDOMMutationObserver.cpp
Expand Up @@ -269,7 +269,7 @@ nsMutationReceiver::ContentRemoved(nsIDocument* aDocument,
// Try to avoid creating transient observer if the node
// already has an observer observing the same set of nodes.
nsMutationReceiver* orig = GetParent() ? GetParent() : this;
if (Observer()->GetReceiverFor(aChild, false) != orig) {
if (Observer()->GetReceiverFor(aChild, false, false) != orig) {
bool transientExists = false;
nsCOMArray<nsMutationReceiver>* transientReceivers = nullptr;
Observer()->mTransientReceivers.Get(aChild, &transientReceivers);
Expand All @@ -287,7 +287,13 @@ nsMutationReceiver::ContentRemoved(nsIDocument* aDocument,
if (!transientExists) {
// Make sure the elements which are removed from the
// subtree are kept in the same observation set.
transientReceivers->AppendObject(new nsMutationReceiver(aChild, orig));
nsMutationReceiver* tr;
if (orig->Animations()) {
tr = nsAnimationReceiver::Create(aChild, orig);
} else {
tr = nsMutationReceiver::Create(aChild, orig);
}
transientReceivers->AppendObject(tr);
}
}
}
Expand Down Expand Up @@ -316,6 +322,87 @@ void nsMutationReceiver::NodeWillBeDestroyed(const nsINode *aNode)
Disconnect(true);
}

void
nsAnimationReceiver::RecordAnimationMutation(AnimationPlayer* aPlayer,
AnimationMutation aMutationType)
{
Animation* source = aPlayer->GetSource();
if (!source) {
return;
}

Element* animationTarget = source->GetTarget();
if (!animationTarget) {
return;
}

if (!Animations() || !(Subtree() || animationTarget == Target()) ||
animationTarget->ChromeOnlyAccess()) {
return;
}

if (nsAutoAnimationMutationBatch::IsBatching()) {
if (nsAutoAnimationMutationBatch::GetBatchTarget() != animationTarget) {
return;
}

switch (aMutationType) {
case eAnimationMutation_Added:
nsAutoAnimationMutationBatch::AnimationAdded(aPlayer);
break;
case eAnimationMutation_Changed:
nsAutoAnimationMutationBatch::AnimationChanged(aPlayer);
break;
case eAnimationMutation_Removed:
nsAutoAnimationMutationBatch::AnimationRemoved(aPlayer);
break;
}

nsAutoAnimationMutationBatch::AddObserver(Observer());
return;
}

nsDOMMutationRecord* m =
Observer()->CurrentRecord(nsGkAtoms::animations);

NS_ASSERTION(!m->mTarget, "Wrong target!");

m->mTarget = animationTarget;

switch (aMutationType) {
case eAnimationMutation_Added:
m->mAddedAnimations.AppendElement(aPlayer);
break;
case eAnimationMutation_Changed:
m->mChangedAnimations.AppendElement(aPlayer);
break;
case eAnimationMutation_Removed:
m->mRemovedAnimations.AppendElement(aPlayer);
break;
}
}

void
nsAnimationReceiver::AnimationAdded(AnimationPlayer* aPlayer)
{
RecordAnimationMutation(aPlayer, eAnimationMutation_Added);
}

void
nsAnimationReceiver::AnimationChanged(AnimationPlayer* aPlayer)
{
RecordAnimationMutation(aPlayer, eAnimationMutation_Changed);
}

void
nsAnimationReceiver::AnimationRemoved(AnimationPlayer* aPlayer)
{
RecordAnimationMutation(aPlayer, eAnimationMutation_Removed);
}

NS_IMPL_ISUPPORTS_INHERITED(nsAnimationReceiver, nsMutationReceiver,
nsIAnimationObserver)

// Observer

NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMMutationObserver)
Expand Down Expand Up @@ -355,8 +442,13 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMMutationObserver)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

nsMutationReceiver*
nsDOMMutationObserver::GetReceiverFor(nsINode* aNode, bool aMayCreate)
nsDOMMutationObserver::GetReceiverFor(nsINode* aNode, bool aMayCreate,
bool aWantsAnimations)
{
MOZ_ASSERT(aMayCreate || !aWantsAnimations,
"the value of aWantsAnimations doesn't matter when aMayCreate is "
"false, so just pass in false for it");

if (!aMayCreate && !aNode->MayHaveDOMMutationObserver()) {
return nullptr;
}
Expand All @@ -370,7 +462,12 @@ nsDOMMutationObserver::GetReceiverFor(nsINode* aNode, bool aMayCreate)
return nullptr;
}

nsMutationReceiver* r = new nsMutationReceiver(aNode, this);
nsMutationReceiver* r;
if (aWantsAnimations) {
r = nsAnimationReceiver::Create(aNode, this);
} else {
r = nsMutationReceiver::Create(aNode, this);
}
mReceivers.AppendObject(r);
return r;
}
Expand All @@ -389,7 +486,7 @@ nsDOMMutationObserver::GetAllSubtreeObserversFor(nsINode* aNode,
nsINode* n = aNode;
while (n) {
if (n->MayHaveDOMMutationObserver()) {
nsMutationReceiver* r = GetReceiverFor(n, false);
nsMutationReceiver* r = GetReceiverFor(n, false, false);
if (r && r->Subtree() && !aReceivers.Contains(r)) {
aReceivers.AppendElement(r);
// If we've found all the receivers the observer has,
Expand Down Expand Up @@ -528,7 +625,7 @@ nsDOMMutationObserver::Observe(nsINode& aTarget,
}
}

nsMutationReceiver* r = GetReceiverFor(&aTarget, true);
nsMutationReceiver* r = GetReceiverFor(&aTarget, true, animations);
r->SetChildList(childList);
r->SetAttributes(attributes);
r->SetCharacterData(characterData);
Expand Down Expand Up @@ -860,10 +957,16 @@ nsAutoMutationBatch::Done()
for (uint32_t k = 0; k < allObservers.Length(); ++k) {
nsMutationReceiver* r = allObservers[k];
nsMutationReceiver* orig = r->GetParent() ? r->GetParent() : r;
if (ob->GetReceiverFor(removed, false) != orig) {
if (ob->GetReceiverFor(removed, false, false) != orig) {
// Make sure the elements which are removed from the
// subtree are kept in the same observation set.
transientReceivers->AppendObject(new nsMutationReceiver(removed, orig));
nsMutationReceiver* tr;
if (orig->Animations()) {
tr = nsAnimationReceiver::Create(removed, orig);
} else {
tr = nsMutationReceiver::Create(removed, orig);
}
transientReceivers->AppendObject(tr);
}
}
}
Expand All @@ -890,3 +993,45 @@ nsAutoMutationBatch::Done()
}
nsDOMMutationObserver::LeaveMutationHandling();
}

nsAutoAnimationMutationBatch*
nsAutoAnimationMutationBatch::sCurrentBatch = nullptr;

void
nsAutoAnimationMutationBatch::Done()
{
if (sCurrentBatch != this) {
return;
}

sCurrentBatch = mPreviousBatch;
if (mObservers.IsEmpty()) {
nsDOMMutationObserver::LeaveMutationHandling();
// Nothing to do.
return;
}

for (nsDOMMutationObserver* ob : mObservers) {
nsRefPtr<nsDOMMutationRecord> m =
new nsDOMMutationRecord(nsGkAtoms::animations, ob->GetParentObject());
m->mTarget = mBatchTarget;

for (const Entry& e : mEntries) {
if (e.mState == eState_Added) {
m->mAddedAnimations.AppendElement(e.mPlayer);
} else if (e.mState == eState_Removed) {
m->mRemovedAnimations.AppendElement(e.mPlayer);
} else if (e.mState == eState_RemainedPresent && e.mChanged) {
m->mChangedAnimations.AppendElement(e.mPlayer);
}
}

if (!m->mAddedAnimations.IsEmpty() ||
!m->mChangedAnimations.IsEmpty() ||
!m->mRemovedAnimations.IsEmpty()) {
ob->AppendMutationRecord(m.forget());
ob->ScheduleForRun();
}
}
nsDOMMutationObserver::LeaveMutationHandling();
}

0 comments on commit 9980c91

Please sign in to comment.