diff --git a/dom/public/nsIScriptContext.h b/dom/public/nsIScriptContext.h index 5d010b3f947b..e2206e06f0da 100644 --- a/dom/public/nsIScriptContext.h +++ b/dom/public/nsIScriptContext.h @@ -140,6 +140,15 @@ public: * @return NS_OK if the method is successful */ NS_IMETHOD GetSecurityManager(nsIScriptSecurityManager** aInstancePtr) = 0; + + /** + * Inform the context that a script was evaluated. + * A GC may be done if "necessary." + * This call is necessary if script evaluation is done + * without using the EvaluateScript method. + * @return NS_OK if the method is successful + */ + NS_IMETHOD ScriptEvaluated(void) = 0; }; /** diff --git a/dom/src/base/nsGlobalWindow.cpp b/dom/src/base/nsGlobalWindow.cpp index 37f4debd323d..9e6c736cb8c8 100644 --- a/dom/src/base/nsGlobalWindow.cpp +++ b/dom/src/base/nsGlobalWindow.cpp @@ -1100,6 +1100,15 @@ GlobalWindowImpl::RunTimeout(nsTimeoutImpl *aTimeout) if (timeout->expr) { /* Evaluate the timeout expression. */ +#if 0 + // V says it would be nice if we could have a chokepoint + // for calling scripts instead of making a bunch of + // ScriptEvaluated() calls to clean things up. MMP + PRBool isundefined; + mContext->EvaluateString(nsAutoString(timeout->expr), + timeout->filename, + timeout->lineno, nsAutoString(""), &isundefined); +#endif JS_EvaluateScript(cx, (JSObject *)mScriptObject, timeout->expr, PL_strlen(timeout->expr), @@ -1121,6 +1130,8 @@ GlobalWindowImpl::RunTimeout(nsTimeoutImpl *aTimeout) timeout->argc + 1, timeout->argv, &result); } + mContext->ScriptEvaluated(); + mRunningTimeout = nsnull; /* If we have a regular interval timer, we re-fire the diff --git a/dom/src/base/nsJSEnvironment.cpp b/dom/src/base/nsJSEnvironment.cpp index 33259685a794..04955d404712 100644 --- a/dom/src/base/nsJSEnvironment.cpp +++ b/dom/src/base/nsJSEnvironment.cpp @@ -67,6 +67,7 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime) JS_SetContextPrivate(mContext, (void *)this); mNameSpaceManager = nsnull; mIsInitialized = PR_FALSE; + mNumEvaluations = 0; } nsJSContext::~nsJSContext() @@ -104,6 +105,8 @@ nsJSContext::EvaluateString(const nsString& aScript, aRetValue.Truncate(); } + ScriptEvaluated(); + return ret; } @@ -268,6 +271,19 @@ nsJSContext::GC() return NS_OK; } +NS_IMETHODIMP +nsJSContext::ScriptEvaluated(void) +{ + mNumEvaluations++; + + if (mNumEvaluations > 20) { + mNumEvaluations = 0; + GC(); + } + + return NS_OK; +} + NS_IMETHODIMP nsJSContext::GetNameSpaceManager(nsIScriptNameSpaceManager** aInstancePtr) { diff --git a/dom/src/base/nsJSEnvironment.h b/dom/src/base/nsJSEnvironment.h index 84a872e8a7d0..8155e7586302 100644 --- a/dom/src/base/nsJSEnvironment.h +++ b/dom/src/base/nsJSEnvironment.h @@ -29,6 +29,7 @@ private: JSContext *mContext; nsIScriptNameSpaceManager* mNameSpaceManager; PRBool mIsInitialized; + PRUint32 mNumEvaluations; public: nsJSContext(JSRuntime *aRuntime); @@ -53,6 +54,8 @@ public: NS_IMETHOD GetNameSpaceManager(nsIScriptNameSpaceManager** aInstancePtr); NS_IMETHOD GetSecurityManager(nsIScriptSecurityManager** aInstancePtr); + NS_IMETHOD ScriptEvaluated(void); + nsresult InitializeExternalClasses(); nsresult InitializeLiveConnectClasses(); }; diff --git a/dom/src/events/nsJSEventListener.cpp b/dom/src/events/nsJSEventListener.cpp index f968ae634579..f6002ab9e7a2 100644 --- a/dom/src/events/nsJSEventListener.cpp +++ b/dom/src/events/nsJSEventListener.cpp @@ -95,11 +95,13 @@ nsresult nsJSEventListener::ProcessEvent(nsIDOMEvent* aEvent) argv[0] = OBJECT_TO_JSVAL(mEventObj); if (PR_TRUE == JS_CallFunctionValue(mContext, mJSObj, funval, 1, argv, &result)) { + mScriptCX->ScriptEvaluated(); if (JSVAL_IS_BOOLEAN(result) && JSVAL_TO_BOOLEAN(result) == JS_FALSE) { return NS_ERROR_FAILURE; } return NS_OK; } + mScriptCX->ScriptEvaluated(); return NS_ERROR_FAILURE; }