Bug 647518 part 1. Make requestAnimationFrame return handles for animation frame requests. r=roc
--- 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;
/**