Checking in for nallen@acm.org, bug 13350. Making the DOM branch callback code limit the ammount of time we allow Mozilla to spend in JS by time, in stead of limiting only by the number of executed branches. r=jst@mozilla.jstenback.com, sr=brendan@mozilla.org, a=chofmann@mozilla.org

This commit is contained in:
jst%mozilla.jstenback.com 2004-02-11 22:22:05 +00:00
parent feda3ad1b7
commit 2ea10607f7
3 changed files with 60 additions and 8 deletions

View File

@ -77,6 +77,8 @@
#include "nsITimer.h"
#include "nsDOMClassInfo.h"
#include "nsIAtom.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
// For locale aware string methods
#include "nsUnicharUtils.h"
@ -131,6 +133,8 @@ static PRBool sDidShutdown;
static PRInt32 sContextCount;
static PRTime sMaxScriptRunTime;
static nsIScriptSecurityManager *sSecurityManager;
static nsICollation *gCollation;
@ -394,17 +398,20 @@ NotifyXPCIfExceptionPending(JSContext *cx)
}
}
// The number of branch callbacks between calls to JS_MaybeGC
#define MAYBE_GC_BRANCH_COUNT_MASK 0x00000fff // 4095
#define MAYBE_STOP_BRANCH_COUNT_MASK 0x003fffff
// The number of branch callbacks between elapsed time checks. This is
// slightly more than the number of callbacks a slow machine makes in a second
// when running a script that makes callbacks infrequently.
#define MAYBE_STOP_BRANCH_COUNT_MASK 0x00007fff // 32767
// This function is called after each JS branch callback
JSBool JS_DLL_CALLBACK
nsJSContext::DOMBranchCallback(JSContext *cx, JSScript *script)
{
// Get the native context
nsJSContext *ctx = NS_STATIC_CAST(nsJSContext *, ::JS_GetContextPrivate(cx));
if (!ctx)
return JS_TRUE;
// Filter out most of the calls to this callback
if (++ctx->mBranchCallbackCount & MAYBE_GC_BRANCH_COUNT_MASK)
@ -413,10 +420,26 @@ nsJSContext::DOMBranchCallback(JSContext *cx, JSScript *script)
// Run the GC if we get this far.
JS_MaybeGC(cx);
// Filter out most of the calls to this callback that make it this far
// Filter out even more of the calls to this callback
if (ctx->mBranchCallbackCount & MAYBE_STOP_BRANCH_COUNT_MASK)
return JS_TRUE;
PRTime now = PR_Now();
// If this is the first time we've made it this far, we start timing how
// long the script has run
if (LL_IS_ZERO(ctx->mBranchCallbackTime)) {
ctx->mBranchCallbackTime = now;
return JS_TRUE;
}
PRTime duration;
LL_SUB(duration, now, ctx->mBranchCallbackTime);
// Check the amount of time this script has been running
if (LL_CMP(duration, <, sMaxScriptRunTime))
return JS_TRUE;
// If we get here we're most likely executing an infinite loop in JS,
// we'll tell the user about this and we'll give the user the option
// of stopping the execution of the script.
@ -444,10 +467,15 @@ nsJSContext::DOMBranchCallback(JSContext *cx, JSScript *script)
JSBool ret = JS_TRUE;
// Open the dialog.
if (NS_FAILED(prompt->Confirm(title.get(), msg.get(), &ret)))
return JS_TRUE;
nsresult rv = prompt->Confirm(title.get(), msg.get(), &ret);
if (NS_FAILED(rv) || !ret) {
return !ret;
// Allow the script to run this long again
ctx->mBranchCallbackTime = PR_Now();
return JS_TRUE;
}
return JS_FALSE;
}
#define JS_OPTIONS_DOT_STR "javascript.options."
@ -547,6 +575,7 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime) : mGCOnDestruction(PR_TRUE)
mTerminationFunc = nsnull;
mScriptsEnabled = PR_TRUE;
mBranchCallbackCount = 0;
mBranchCallbackTime = LL_ZERO;
mProcessingScriptTag=PR_FALSE;
InvalidateContextAndWrapperCache();
@ -1687,6 +1716,7 @@ nsJSContext::ScriptEvaluated(PRBool aTerminated)
}
mBranchCallbackCount = 0;
mBranchCallbackTime = LL_ZERO;
}
void
@ -1872,6 +1902,24 @@ nsJSEnvironment::Init()
}
#endif /* OJI */
// Initialize limit on script run time to 5 seconds
PRInt32 maxtime = 5;
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
PRInt32 time;
if (NS_SUCCEEDED(prefs->GetIntPref("dom.max_script_run_time", &time))) {
// Force the default for unreasonable values
if (time > 0)
maxtime = time;
}
}
PRTime usec_per_sec;
LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
LL_I2L(sMaxScriptRunTime, maxtime);
LL_MUL(sMaxScriptRunTime, sMaxScriptRunTime, usec_per_sec);
rv = CallGetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &sSecurityManager);
isInitialized = NS_SUCCEEDED(rv);

View File

@ -46,6 +46,7 @@
#include "nsIScriptSecurityManager.h"
#include "nsIXPCScriptNotify.h"
#include "nsITimer.h"
#include "prtime.h"
class nsJSContext : public nsIScriptContext,
@ -155,6 +156,7 @@ private:
PRPackedBool mProcessingScriptTag;
PRUint32 mBranchCallbackCount;
PRTime mBranchCallbackTime;
PRUint32 mDefaultJSOptions;
// mGlobalWrapperRef is used only to hold a strong reference to the

View File

@ -797,6 +797,8 @@ pref("config.use_system_prefs.accessibility", false);
pref("editor.resizing.preserve_ratio", true);
pref("editor.positioning.offset", 0);
pref("dom.max_script_run_time", 5);
#ifdef XP_WIN
pref("font.name.serif.ar", "Times New Roman");
pref("font.name.sans-serif.ar", "Arial");