Bug 1105098 - Make AnimationTimeline always return the same parent object (even after document.open()) and replace the document's timeline if the document is reset. r=smaug,birtles
authorJonathan Watt <jwatt@jwatt.org>
Mon, 26 Jan 2015 17:08:51 +0000
changeset 226547 76c4ed3a6c8f4cd3f9a61232140962d3536cb485
parent 226546 4cd85bbe71b43f2abf65d0525dcca96058cc60ba
child 226548 640111b4c868b95ce167b9ab95e08797d1c0b6b2
push id28200
push userkwierso@gmail.com
push dateThu, 29 Jan 2015 23:01:46 +0000
treeherdermozilla-central@4380ed39de3a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, birtles
bugs1105098
milestone38.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 1105098 - Make AnimationTimeline always return the same parent object (even after document.open()) and replace the document's timeline if the document is reset. r=smaug,birtles
dom/animation/AnimationTimeline.cpp
dom/animation/AnimationTimeline.h
dom/base/nsDocument.cpp
--- a/dom/animation/AnimationTimeline.cpp
+++ b/dom/animation/AnimationTimeline.cpp
@@ -10,17 +10,17 @@
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsRefreshDriver.h"
 #include "nsDOMNavigationTiming.h"
 
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationTimeline, mDocument)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationTimeline, mDocument, mWindow)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnimationTimeline, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnimationTimeline, Release)
 
 JSObject*
 AnimationTimeline::WrapObject(JSContext* aCx)
 {
   return AnimationTimelineBinding::Wrap(aCx, this);
--- a/dom/animation/AnimationTimeline.h
+++ b/dom/animation/AnimationTimeline.h
@@ -5,43 +5,46 @@
 
 #ifndef mozilla_dom_AnimationTimeline_h
 #define mozilla_dom_AnimationTimeline_h
 
 #include "nsWrapperCache.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/TimeStamp.h"
+#include "nsIGlobalObject.h"
 #include "js/TypeDecls.h"
 #include "nsIDocument.h"
 #include "nsRefreshDriver.h"
 
 struct JSContext;
 
 namespace mozilla {
 namespace dom {
 
 class AnimationTimeline MOZ_FINAL : public nsWrapperCache
 {
 public:
   explicit AnimationTimeline(nsIDocument* aDocument)
     : mDocument(aDocument)
+    , mWindow(aDocument->GetParentObject())
   {
+    MOZ_ASSERT(mWindow);
   }
 
 protected:
   virtual ~AnimationTimeline() { }
 
 public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationTimeline)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AnimationTimeline)
 
   nsIGlobalObject* GetParentObject() const
   {
-    return mDocument->GetParentObject();
+    return mWindow;
   }
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   // AnimationTimeline methods
   Nullable<TimeDuration> GetCurrentTime() const;
 
   // Wrapper functions for AnimationTimeline DOM methods when called from
   // script.
@@ -65,17 +68,22 @@ public:
   {
     nsRefreshDriver* refreshDriver = GetRefreshDriver();
     return refreshDriver && refreshDriver->IsTestControllingRefreshesEnabled();
   }
 
 protected:
   TimeStamp GetCurrentTimeStamp() const;
 
+  // Sometimes documents can be given a new window, or windows can be given a
+  // new document (e.g. document.open()). Since GetParentObject is required to
+  // _always_ return the same object it can't get the window from our
+  // mDocument, which is why we have pointers to both our document and window.
   nsCOMPtr<nsIDocument> mDocument;
+  nsCOMPtr<nsIGlobalObject> mWindow;
 
   // The most recently used refresh driver time. This is used in cases where
   // we don't have a refresh driver (e.g. because we are in a display:none
   // iframe).
   mutable TimeStamp mLastRefreshDriverTime;
 };
 
 } // namespace dom
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -2285,16 +2285,21 @@ nsDocument::Reset(nsIChannel* aChannel, 
     if (securityManager) {
       securityManager->GetChannelResultPrincipal(aChannel,
                                                  getter_AddRefs(principal));
     }
   }
 
   ResetToURI(uri, aLoadGroup, principal);
 
+  // Note that, since mTiming does not change during a reset, the
+  // navigationStart time remains unchanged and therefore any future new
+  // timeline will have the same global clock time as the old one.
+  mAnimationTimeline = nullptr;
+
   nsCOMPtr<nsIPropertyBag2> bag = do_QueryInterface(aChannel);
   if (bag) {
     nsCOMPtr<nsIURI> baseURI;
     bag->GetPropertyAsInterface(NS_LITERAL_STRING("baseURI"),
                                 NS_GET_IID(nsIURI), getter_AddRefs(baseURI));
     if (baseURI) {
       mDocumentBaseURI = baseURI;
       mChromeXHRDocBaseURI = baseURI;