Bug 1249219 - Part 6: Support pseudo elements in Animation Mutation Observer. r=heycam
authorBoris Chiou <boris.chiou@gmail.com>
Mon, 21 Mar 2016 16:49:50 +0800
changeset 289695 2047b0726ff5493933365162d8b2c7d7d40fa8fe
parent 289694 d3e647f539b92d4d145fc3e4717581bbf4d8c374
child 289696 cc5d40fcf830cadbfd3cc02730a663c71217111c
push id30108
push usercbook@mozilla.com
push dateTue, 22 Mar 2016 11:14:31 +0000
treeherdermozilla-central@ea6298e1b4f7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1249219
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1249219 - Part 6: Support pseudo elements in Animation Mutation Observer. r=heycam We use the parent element of a pseudo element as the subject to be notified. Usage: We record animations targeting to pseudo elements by setting subtree attribute to true. MutationObserver(Node, { subtree: ture }); So all the animations targeting to the pseudo elements whose parentElement is the first argument will be recorded.
dom/animation/KeyframeEffect.cpp
dom/base/nsDOMMutationObserver.cpp
dom/base/nsDOMMutationObserver.h
dom/base/nsNodeUtils.cpp
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -2313,25 +2313,18 @@ KeyframeEffect::Constructor(
     ErrorResult& aRv)
 {
   return ConstructKeyframeEffect<KeyframeEffect>(aGlobal, aTarget, aFrames,
                                                  aOptions, aRv);
 }
 
 void KeyframeEffect::NotifySpecifiedTimingUpdated()
 {
-  nsIDocument* doc = nullptr;
-  // Bug 1249219:
-  // We don't support animation mutation observers on pseudo-elements yet.
-  if (mTarget &&
-      mPseudoType == CSSPseudoElementType::NotPseudo) {
-    doc = mTarget->OwnerDoc();
-  }
-
-  nsAutoAnimationMutationBatch mb(doc);
+  // Use the same document for a pseudo element and its parent element.
+  nsAutoAnimationMutationBatch mb(mTarget->OwnerDoc());
 
   if (mAnimation) {
     mAnimation->NotifyEffectTimingUpdated();
 
     if (mAnimation->IsRelevant()) {
       nsNodeUtils::AnimationChanged(mAnimation);
     }
 
--- a/dom/base/nsDOMMutationObserver.cpp
+++ b/dom/base/nsDOMMutationObserver.cpp
@@ -394,16 +394,22 @@ nsAnimationReceiver::RecordAnimationMuta
   }
 
   dom::Element* elem = animationTarget->mElement;
   if (!Animations() || !(Subtree() || elem == Target()) ||
       elem->ChromeOnlyAccess()) {
     return;
   }
 
+  // Record animations targeting to a pseudo element only when subtree is true.
+  if (animationTarget->mPseudoType != CSSPseudoElementType::NotPseudo &&
+      !Subtree()) {
+    return;
+  }
+
   if (nsAutoAnimationMutationBatch::IsBatching()) {
     switch (aMutationType) {
       case eAnimationMutation_Added:
         nsAutoAnimationMutationBatch::AnimationAdded(aAnimation, elem);
         break;
       case eAnimationMutation_Changed:
         nsAutoAnimationMutationBatch::AnimationChanged(aAnimation, elem);
         break;
--- a/dom/base/nsDOMMutationObserver.h
+++ b/dom/base/nsDOMMutationObserver.h
@@ -906,16 +906,18 @@ private:
     bool mChanged;
   };
 
   static nsAutoAnimationMutationBatch* sCurrentBatch;
   AutoTArray<nsDOMMutationObserver*, 2> mObservers;
   typedef nsTArray<Entry> EntryArray;
   nsClassHashtable<nsPtrHashKey<nsINode>, EntryArray> mEntryTable;
   // List of nodes referred to by mEntryTable so we can sort them
+  // For a specific pseudo element, we use its parent element as the
+  // batch target, so they will be put in the same EntryArray.
   nsTArray<nsINode*> mBatchTargets;
 };
 
 inline
 nsDOMMutationObserver*
 nsMutationReceiverBase::Observer()
 {
   return mParent ?
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -226,41 +226,32 @@ nsNodeUtils::ContentRemoved(nsINode* aCo
                              (document, container, aChild, aIndexInContainer,
                               aPreviousSibling));
 }
 
 Maybe<NonOwningAnimationTarget>
 nsNodeUtils::GetTargetForAnimation(const Animation* aAnimation)
 {
   KeyframeEffectReadOnly* effect = aAnimation->GetEffect();
-  if (!effect) {
-    return Nothing();
-  }
-
-  Maybe<NonOwningAnimationTarget> target = effect->GetTarget();
-
-  // TODO: remove this part later
-  if (target->mPseudoType != CSSPseudoElementType::NotPseudo) {
-    return Nothing();
-  }
-
-  return target;
+  return effect ? effect->GetTarget() : Nothing();
 }
 
 void
 nsNodeUtils::AnimationMutated(Animation* aAnimation,
                               AnimationMutationType aMutatedType)
 {
   Maybe<NonOwningAnimationTarget> target = GetTargetForAnimation(aAnimation);
   if (!target) {
     return;
   }
+
+  // A pseudo element and its parent element use the same owner doc.
   nsIDocument* doc = target->mElement->OwnerDoc();
-
   if (doc->MayHaveAnimationObservers()) {
+    // we use the its parent element as the subject in DOM Mutation Observer.
     Element* elem = target->mElement;
     switch (aMutatedType) {
       case AnimationMutationType::Added:
         IMPL_ANIMATION_NOTIFICATION(AnimationAdded, elem, (aAnimation));
         break;
       case AnimationMutationType::Changed:
         IMPL_ANIMATION_NOTIFICATION(AnimationChanged, elem, (aAnimation));
         break;