Bug 520386. Don't clear scope while executing code in that scope. r=bzbarsky@mit.edu, sr=jst@mozilla.org
This commit is contained in:
@@ -930,6 +930,55 @@ nsGlobalWindow::ClearControllers()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ClearScopeEvent : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClearScopeEvent(nsGlobalWindow *innerWindow)
|
||||||
|
: mInnerWindow(innerWindow) {
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
mInnerWindow->ReallyClearScope(this);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<nsGlobalWindow> mInnerWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
nsGlobalWindow::ReallyClearScope(nsRunnable *aRunnable)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(IsInnerWindow(), "Must be an inner window");
|
||||||
|
|
||||||
|
nsIScriptContext *jsscx = GetContextInternal();
|
||||||
|
if (jsscx && jsscx->GetExecutingScript()) {
|
||||||
|
if (!aRunnable) {
|
||||||
|
aRunnable = new ClearScopeEvent(this);
|
||||||
|
if (!aRunnable) {
|
||||||
|
// The only reason that we clear scope here is to try to prevent
|
||||||
|
// leaks. Failing to clear scope might mean that we'll leak more
|
||||||
|
// but if we don't have enough memory to allocate a ClearScopeEvent
|
||||||
|
// we probably don't have to worry about this anyway.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_DispatchToMainThread(aRunnable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRUint32 lang_id;
|
||||||
|
NS_STID_FOR_ID(lang_id) {
|
||||||
|
// Note that scx comes from the outer window. If this is an inner
|
||||||
|
// window, it may not be the current inner for its outer.
|
||||||
|
nsIScriptContext *scx = GetScriptContextInternal(lang_id);
|
||||||
|
if (scx)
|
||||||
|
scx->ClearScope(mScriptGlobals[NS_STID_INDEX(lang_id)], PR_TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsGlobalWindow::FreeInnerObjects(PRBool aClearScope)
|
nsGlobalWindow::FreeInnerObjects(PRBool aClearScope)
|
||||||
{
|
{
|
||||||
@@ -983,14 +1032,9 @@ nsGlobalWindow::FreeInnerObjects(PRBool aClearScope)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (aClearScope) {
|
if (aClearScope) {
|
||||||
PRUint32 lang_id;
|
// NB: This might not clear our scope, but fire an event to do so
|
||||||
NS_STID_FOR_ID(lang_id) {
|
// instead.
|
||||||
// Note that scx comes from the outer window. If this is an inner
|
ReallyClearScope(nsnull);
|
||||||
// window, it may not be the current inner for its outer.
|
|
||||||
nsIScriptContext *scx = GetScriptContextInternal(lang_id);
|
|
||||||
if (scx)
|
|
||||||
scx->ClearScope(mScriptGlobals[NS_STID_INDEX(lang_id)], PR_TRUE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDummyJavaPluginOwner) {
|
if (mDummyJavaPluginOwner) {
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ class nsGlobalWindowObserver;
|
|||||||
class nsGlobalWindow;
|
class nsGlobalWindow;
|
||||||
class nsDummyJavaPluginOwner;
|
class nsDummyJavaPluginOwner;
|
||||||
class PostMessageEvent;
|
class PostMessageEvent;
|
||||||
|
class nsRunnable;
|
||||||
|
|
||||||
class nsDOMOfflineResourceList;
|
class nsDOMOfflineResourceList;
|
||||||
class nsGeolocation;
|
class nsGeolocation;
|
||||||
@@ -238,6 +239,7 @@ public:
|
|||||||
nsPIDOMWindow* GetPrivateParent();
|
nsPIDOMWindow* GetPrivateParent();
|
||||||
// callback for close event
|
// callback for close event
|
||||||
void ReallyCloseWindow();
|
void ReallyCloseWindow();
|
||||||
|
void ReallyClearScope(nsRunnable *aRunnable);
|
||||||
|
|
||||||
// nsISupports
|
// nsISupports
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
|
|||||||
@@ -56,10 +56,10 @@ class nsScriptObjectHolder;
|
|||||||
|
|
||||||
typedef void (*nsScriptTerminationFunc)(nsISupports* aRef);
|
typedef void (*nsScriptTerminationFunc)(nsISupports* aRef);
|
||||||
|
|
||||||
// 87482b5e-e019-4df5-9bc2-b2a51b1f2d28
|
// A4FE2B52-62B5-40C3-BF9C-5E0A27B10F90
|
||||||
#define NS_ISCRIPTCONTEXT_IID \
|
#define NS_ISCRIPTCONTEXT_IID \
|
||||||
{ 0x87482b5e, 0xe019, 0x4df5, \
|
{ 0xA4FE2B52, 0x62B5, 0x40C3, \
|
||||||
{ 0x9b, 0xc2, 0xb2, 0xa5, 0x1b, 0x1f, 0x2d, 0x28 } }
|
{ 0xBF, 0x9C, 0x5E, 0x0A, 0x27, 0xB1, 0x0F, 0x90 } }
|
||||||
|
|
||||||
/* This MUST match JSVERSION_DEFAULT. This version stuff if we don't
|
/* This MUST match JSVERSION_DEFAULT. This version stuff if we don't
|
||||||
know what language we have is a little silly... */
|
know what language we have is a little silly... */
|
||||||
@@ -402,6 +402,11 @@ public:
|
|||||||
virtual PRBool GetProcessingScriptTag() = 0;
|
virtual PRBool GetProcessingScriptTag() = 0;
|
||||||
virtual void SetProcessingScriptTag(PRBool aResult) = 0;
|
virtual void SetProcessingScriptTag(PRBool aResult) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to find out if this script context might be executing script.
|
||||||
|
*/
|
||||||
|
virtual PRBool GetExecutingScript() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the context whether or not to GC when destroyed. An optimization
|
* Tell the context whether or not to GC when destroyed. An optimization
|
||||||
* used when the window is a [i]frame, so GC will happen anyway.
|
* used when the window is a [i]frame, so GC will happen anyway.
|
||||||
|
|||||||
@@ -1312,7 +1312,9 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsJSContext::nsJSContext(JSRuntime *aRuntime) : mGCOnDestruction(PR_TRUE)
|
nsJSContext::nsJSContext(JSRuntime *aRuntime)
|
||||||
|
: mGCOnDestruction(PR_TRUE),
|
||||||
|
mExecuteDepth(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
++sContextCount;
|
++sContextCount;
|
||||||
@@ -1522,6 +1524,8 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
|
|||||||
JSAutoRequest ar(mContext);
|
JSAutoRequest ar(mContext);
|
||||||
nsJSVersionSetter setVersion(mContext, aVersion);
|
nsJSVersionSetter setVersion(mContext, aVersion);
|
||||||
|
|
||||||
|
++mExecuteDepth;
|
||||||
|
|
||||||
ok = ::JS_EvaluateUCScriptForPrincipals(mContext,
|
ok = ::JS_EvaluateUCScriptForPrincipals(mContext,
|
||||||
(JSObject *)aScopeObject,
|
(JSObject *)aScopeObject,
|
||||||
jsprin,
|
jsprin,
|
||||||
@@ -1531,6 +1535,8 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
|
|||||||
aLineNo,
|
aLineNo,
|
||||||
&val);
|
&val);
|
||||||
|
|
||||||
|
--mExecuteDepth;
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
// Tell XPConnect about any pending exceptions. This is needed
|
// Tell XPConnect about any pending exceptions. This is needed
|
||||||
// to avoid dropping JS exceptions in case we got here through
|
// to avoid dropping JS exceptions in case we got here through
|
||||||
@@ -1688,6 +1694,8 @@ nsJSContext::EvaluateString(const nsAString& aScript,
|
|||||||
|
|
||||||
nsJSContext::TerminationFuncHolder holder(this);
|
nsJSContext::TerminationFuncHolder holder(this);
|
||||||
|
|
||||||
|
++mExecuteDepth;
|
||||||
|
|
||||||
// SecurityManager said "ok", but don't compile if aVersion is unknown.
|
// SecurityManager said "ok", but don't compile if aVersion is unknown.
|
||||||
// Since the caller is responsible for parsing the version strings, we just
|
// Since the caller is responsible for parsing the version strings, we just
|
||||||
// check it isn't JSVERSION_UNKNOWN.
|
// check it isn't JSVERSION_UNKNOWN.
|
||||||
@@ -1731,6 +1739,8 @@ nsJSContext::EvaluateString(const nsAString& aScript,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--mExecuteDepth;
|
||||||
|
|
||||||
// Pop here, after JS_ValueToString and any other possible evaluation.
|
// Pop here, after JS_ValueToString and any other possible evaluation.
|
||||||
if (NS_FAILED(stack->Pop(nsnull)))
|
if (NS_FAILED(stack->Pop(nsnull)))
|
||||||
rv = NS_ERROR_FAILURE;
|
rv = NS_ERROR_FAILURE;
|
||||||
@@ -1849,6 +1859,7 @@ nsJSContext::ExecuteScript(void *aScriptObject,
|
|||||||
|
|
||||||
nsJSContext::TerminationFuncHolder holder(this);
|
nsJSContext::TerminationFuncHolder holder(this);
|
||||||
JSAutoRequest ar(mContext);
|
JSAutoRequest ar(mContext);
|
||||||
|
++mExecuteDepth;
|
||||||
ok = ::JS_ExecuteScript(mContext,
|
ok = ::JS_ExecuteScript(mContext,
|
||||||
(JSObject *)aScopeObject,
|
(JSObject *)aScopeObject,
|
||||||
(JSScript*)::JS_GetPrivate(mContext,
|
(JSScript*)::JS_GetPrivate(mContext,
|
||||||
@@ -1868,6 +1879,8 @@ nsJSContext::ExecuteScript(void *aScriptObject,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--mExecuteDepth;
|
||||||
|
|
||||||
// Pop here, after JS_ValueToString and any other possible evaluation.
|
// Pop here, after JS_ValueToString and any other possible evaluation.
|
||||||
if (NS_FAILED(stack->Pop(nsnull)))
|
if (NS_FAILED(stack->Pop(nsnull)))
|
||||||
rv = NS_ERROR_FAILURE;
|
rv = NS_ERROR_FAILURE;
|
||||||
@@ -2111,8 +2124,10 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, void *aScope, void *aHandler
|
|||||||
|
|
||||||
jsval funval = OBJECT_TO_JSVAL(static_cast<JSObject *>(aHandler));
|
jsval funval = OBJECT_TO_JSVAL(static_cast<JSObject *>(aHandler));
|
||||||
JSAutoRequest ar(mContext);
|
JSAutoRequest ar(mContext);
|
||||||
|
++mExecuteDepth;
|
||||||
PRBool ok = ::JS_CallFunctionValue(mContext, target,
|
PRBool ok = ::JS_CallFunctionValue(mContext, target,
|
||||||
funval, argc, argv, &rval);
|
funval, argc, argv, &rval);
|
||||||
|
--mExecuteDepth;
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
// Tell XPConnect about any pending exceptions. This is needed
|
// Tell XPConnect about any pending exceptions. This is needed
|
||||||
@@ -3498,6 +3513,12 @@ nsJSContext::SetProcessingScriptTag(PRBool aFlag)
|
|||||||
mProcessingScriptTag = aFlag;
|
mProcessingScriptTag = aFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsJSContext::GetExecutingScript()
|
||||||
|
{
|
||||||
|
return JS_IsRunning(mContext) || mExecuteDepth > 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsJSContext::SetGCOnDestruction(PRBool aGCOnDestruction)
|
nsJSContext::SetGCOnDestruction(PRBool aGCOnDestruction)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -149,6 +149,8 @@ public:
|
|||||||
virtual PRBool GetProcessingScriptTag();
|
virtual PRBool GetProcessingScriptTag();
|
||||||
virtual void SetProcessingScriptTag(PRBool aResult);
|
virtual void SetProcessingScriptTag(PRBool aResult);
|
||||||
|
|
||||||
|
virtual PRBool GetExecutingScript();
|
||||||
|
|
||||||
virtual void SetGCOnDestruction(PRBool aGCOnDestruction);
|
virtual void SetGCOnDestruction(PRBool aGCOnDestruction);
|
||||||
|
|
||||||
virtual nsresult InitClasses(void *aGlobalObj);
|
virtual nsresult InitClasses(void *aGlobalObj);
|
||||||
@@ -292,6 +294,7 @@ private:
|
|||||||
PRPackedBool mGCOnDestruction;
|
PRPackedBool mGCOnDestruction;
|
||||||
PRPackedBool mProcessingScriptTag;
|
PRPackedBool mProcessingScriptTag;
|
||||||
|
|
||||||
|
PRUint32 mExecuteDepth;
|
||||||
PRUint32 mDefaultJSOptions;
|
PRUint32 mDefaultJSOptions;
|
||||||
PRTime mOperationCallbackTime;
|
PRTime mOperationCallbackTime;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user