Bug 647518 part 1. Make requestAnimationFrame return handles for animation frame requests. r=roc
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 06 Dec 2011 23:43:18 -0500
changeset 82944 378505d09d172af1c95d105bce9af2315a680867
parent 82941 3080aa9f675d8fc53be2771a7bc825190b9c4903
child 82945 3e232dd3af61794ac5ba8333ff4e57a8521ae808
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs647518
milestone11.0a1
Bug 647518 part 1. Make requestAnimationFrame return handles for animation frame requests. r=roc
content/base/public/nsIDocument.h
content/base/src/nsDocument.cpp
content/base/test/Makefile.in
content/base/test/test_bug647518.html
dom/base/nsGlobalWindow.cpp
dom/interfaces/base/nsIDOMWindow.idl
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1524,17 +1524,18 @@ public:
    * Lookup an image element using its associated ID, which is usually provided
    * by |-moz-element()|. Similar to GetElementById, with the difference that
    * elements set using mozSetImageElement have higher priority.
    * @param aId the ID associated the element we want to lookup
    * @return the element associated with |aId|
    */
   virtual Element* LookupImageElement(const nsAString& aElementId) = 0;
 
-  void ScheduleFrameRequestCallback(nsIFrameRequestCallback* aCallback);
+  nsresult ScheduleFrameRequestCallback(nsIFrameRequestCallback* aCallback,
+                                        PRInt32 *aHandle);
 
   typedef nsTArray< nsCOMPtr<nsIFrameRequestCallback> > FrameRequestCallbackList;
   /**
    * Put this document's frame request callbacks into the provided
    * list, and forget about them.
    */
   void TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks);
 
@@ -1805,23 +1806,43 @@ protected:
   PRUint32 mEventsSuppressed;
 
   /**
    * The number number of external scripts (ones with the src attribute) that
    * have this document as their owner and that are being evaluated right now.
    */
   PRUint32 mExternalScriptsBeingEvaluated;
 
+  /**
+   * The current frame request callback handle
+   */
+  PRInt32 mFrameRequestCallbackCounter;
+
   // Weak reference to mScriptGlobalObject QI:d to nsPIDOMWindow,
   // updated on every set of mSecriptGlobalObject.
   nsPIDOMWindow *mWindow;
 
   nsCOMPtr<nsIDocumentEncoder> mCachedEncoder;
 
-  FrameRequestCallbackList mFrameRequestCallbacks;
+  struct FrameRequest {
+    FrameRequest(nsIFrameRequestCallback* aCallback,
+                 PRInt32 aHandle) :
+      mCallback(aCallback),
+      mHandle(aHandle)
+    {}
+
+    // Conversion operator so that we can append these to a
+    // FrameRequestCallbackList
+    operator nsIFrameRequestCallback* const () const { return mCallback; }
+    
+    nsCOMPtr<nsIFrameRequestCallback> mCallback;
+    PRInt32 mHandle;
+  };
+
+  nsTArray<FrameRequest> mFrameRequestCallbacks;
 
   // This object allows us to evict ourself from the back/forward cache.  The
   // pointer is non-null iff we're currently in the bfcache.
   nsIBFCacheEntry *mBFCacheEntry;
 
   // Our base target.
   nsString mBaseTarget;
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -8036,25 +8036,37 @@ nsIDocument::CreateStaticClone(nsISuppor
         }
       }
     }
   }
   mCreatingStaticClone = false;
   return clonedDoc.forget();
 }
 
-void
-nsIDocument::ScheduleFrameRequestCallback(nsIFrameRequestCallback* aCallback)
-{
+nsresult
+nsIDocument::ScheduleFrameRequestCallback(nsIFrameRequestCallback* aCallback,
+                                          PRInt32 *aHandle)
+{
+  if (mFrameRequestCallbackCounter == PR_INT32_MAX) {
+    // Can't increment without overflowing; bail out
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+  PRInt32 newHandle = ++mFrameRequestCallbackCounter;
+
   bool alreadyRegistered = !mFrameRequestCallbacks.IsEmpty();
-  if (mFrameRequestCallbacks.AppendElement(aCallback) &&
-      !alreadyRegistered && mPresShell && IsEventHandlingEnabled()) {
+  FrameRequest *request =
+    mFrameRequestCallbacks.AppendElement(FrameRequest(aCallback, newHandle));
+  NS_ASSERTION(request, "This is supposed to be infallible!");
+  if (!alreadyRegistered && mPresShell && IsEventHandlingEnabled()) {
     mPresShell->GetPresContext()->RefreshDriver()->
       ScheduleFrameRequestCallbacks(this);
   }
+
+  *aHandle = newHandle;
+  return NS_OK;
 }
 
 nsresult
 nsDocument::GetStateObject(nsIVariant** aState)
 {
   // Get the document's current state object. This is the object backing both
   // history.state and popStateEvent.state.
   //
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -506,16 +506,17 @@ include $(topsrcdir)/config/rules.mk
 		somedatas.resource \
 		somedatas.resource^headers^ \
 		delayedServerEvents.sjs \
 		test_html_in_xhr.html \
 		file_html_in_xhr.html \
 		file_html_in_xhr2.html \
 		file_html_in_xhr3.html \
 		file_html_in_xhr.sjs \
+		test_bug647518.html \
 		test_bug664916.html \
 		test_bug666604.html \
 		test_bug675121.html \
 		file_bug675121.sjs \
 		test_bug675166.html \
 		test_bug682554.html \
 		test_bug682592.html \
 		bug682592-subframe.html \
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug647518.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=647518
+-->
+<head>
+  <title>Test for Bug 647518</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=647518">Mozilla Bug 647518</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 647518 **/
+var handle1 = window.mozRequestAnimationFrame(function() {});
+ok(handle1 > 0, "Should get back a nonzero handle");
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -3869,31 +3869,31 @@ nsGlobalWindow::GetMozPaintCount(PRUint6
   if (!presShell)
     return NS_OK;
 
   *aResult = presShell->GetPaintCount();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsGlobalWindow::MozRequestAnimationFrame(nsIFrameRequestCallback* aCallback)
-{
-  FORWARD_TO_INNER(MozRequestAnimationFrame, (aCallback),
+nsGlobalWindow::MozRequestAnimationFrame(nsIFrameRequestCallback* aCallback,
+                                         PRInt32 *aHandle)
+{
+  FORWARD_TO_INNER(MozRequestAnimationFrame, (aCallback, aHandle),
                    NS_ERROR_NOT_INITIALIZED);
 
   if (!mDoc) {
     return NS_OK;
   }
 
   if (!aCallback) {
     return NS_ERROR_XPC_BAD_CONVERT_JS;
   }
 
-  mDoc->ScheduleFrameRequestCallback(aCallback);
-  return NS_OK;
+  return mDoc->ScheduleFrameRequestCallback(aCallback, aHandle);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetMozAnimationStartTime(PRInt64 *aTime)
 {
   FORWARD_TO_INNER(GetMozAnimationStartTime, (aTime), NS_ERROR_NOT_INITIALIZED);
 
   if (mDoc) {
--- a/dom/interfaces/base/nsIDOMWindow.idl
+++ b/dom/interfaces/base/nsIDOMWindow.idl
@@ -65,17 +65,17 @@ interface nsIDOMMozURLProperty : nsISupp
  * The nsIDOMWindow interface is the primary interface for a DOM
  * window object. It represents a single window object that may
  * contain child windows if the document in the window contains a
  * HTML frameset document or if the document contains iframe elements.
  *
  * @see <http://www.whatwg.org/html/#window>
  */
 
-[scriptable, uuid(8f577294-d572-4473-94b1-d2c5a74a2a74)]
+[scriptable, uuid(57b7ed24-c340-4994-a023-56ba578b78ab)]
 interface nsIDOMWindow : nsISupports
 {
   // the current browsing context
   readonly attribute nsIDOMWindow                       window;
 
   /* [replaceable] self */
   readonly attribute nsIDOMWindow                       self;
 
@@ -412,17 +412,17 @@ interface nsIDOMWindow : nsISupports
    */
   readonly attribute unsigned long long mozPaintCount;
 
   /**
    * Request a refresh of this browser window.
    *
    * @see <http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/RequestAnimationFrame/Overview.html>
    */
-  void
+  long
     mozRequestAnimationFrame(in nsIFrameRequestCallback aCallback);
 
   /**
    * The current animation start time in milliseconds since the epoch.
    */
   readonly attribute long long mozAnimationStartTime;
 
   /**