fix bug 52579. Avoid infinite recursion dialog when JS is run by xpconnect on DOM context. a,r=brendan@mozilla.org

This commit is contained in:
jband%netscape.com 2000-09-15 06:17:08 +00:00
Родитель 7eb4f33a20
Коммит feed45599c
4 изменённых файлов: 55 добавлений и 19 удалений

Просмотреть файл

@ -301,9 +301,14 @@ public:
* A GC may be done if "necessary."
* This call is necessary if script evaluation is done
* without using the EvaluateScript method.
* @param aTerminated If true then call termination function if it was
* previously set. Within DOM this will always be true, but outside
* callers (such as xpconnect) who may do script evaluations nested
* inside DOM script evaluations can pass false to avoid premature
* calls to the termination function.
* @return NS_OK if the method is successful
*/
NS_IMETHOD ScriptEvaluated(void) = 0;
NS_IMETHOD ScriptEvaluated(PRBool aTerminated) = 0;
/**
* Let the script context know who its owner is.

Просмотреть файл

@ -603,7 +603,7 @@ nsJSContext::EvaluateString(const nsAReadableString& aScript,
aRetValue.Truncate();
}
ScriptEvaluated();
ScriptEvaluated(PR_TRUE);
// Pop here, after JS_ValueToString and any other possible evaluation.
if (NS_FAILED(stack->Pop(nsnull)))
@ -740,7 +740,7 @@ nsJSContext::ExecuteScript(void* aScriptObject,
aRetValue->Truncate();
}
ScriptEvaluated();
ScriptEvaluated(PR_TRUE);
// Pop here, after JS_ValueToString and any other possible evaluation.
if (NS_FAILED(stack->Pop(nsnull)))
@ -908,7 +908,7 @@ nsJSContext::CallEventHandler(void *aTarget, void *aHandler, PRUint32 argc,
? !JSVAL_IS_BOOLEAN(val) || (aReverseReturnResult ? !JSVAL_TO_BOOLEAN(val) : JSVAL_TO_BOOLEAN(val))
: JS_TRUE;
ScriptEvaluated();
ScriptEvaluated(PR_TRUE);
}
if (NS_FAILED(stack->Pop(nsnull)))
@ -1288,9 +1288,9 @@ nsJSContext::GC()
}
NS_IMETHODIMP
nsJSContext::ScriptEvaluated(void)
nsJSContext::ScriptEvaluated(PRBool aTerminated)
{
if (mTerminationFunc) {
if (aTerminated && mTerminationFunc) {
(*mTerminationFunc)(mRef);
mRef = nsnull;
mTerminationFunc = nsnull;

Просмотреть файл

@ -126,7 +126,7 @@ public:
NS_IMETHOD GetNameSpaceManager(nsIScriptNameSpaceManager** aInstancePtr);
NS_IMETHOD GetSecurityManager(nsIScriptSecurityManager** aInstancePtr);
NS_IMETHOD ScriptEvaluated(void);
NS_IMETHOD ScriptEvaluated(PRBool aTerminated);
NS_IMETHOD SetOwner(nsIScriptContextOwner* owner);
NS_IMETHOD GetOwner(nsIScriptContextOwner** owner);
NS_IMETHOD SetTerminationFunction(nsScriptTerminationFunc aFunc,

Просмотреть файл

@ -43,6 +43,34 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsXPCWrappedJSClass, nsIXPCWrappedJSClass)
// the value of this variable is never used - we use its address as a sentinel
static uint32 zero_methods_descriptor;
static inline void DoPreScriptEvaluated(JSContext* cx)
{
// XXX should we do this?
// JS_BeginRequest(cx);
}
static inline void DoPostScriptEvaluated(JSContext* cx)
{
// XXX should we do this?
// JS_EndRequest(cx);
#ifndef XPCONNECT_STANDALONE
// If this is a DOM JSContext, then notify nsIScriptContext of script
// completion so that it can reset its infinite loop detection mechanism.
//
// XXX We rely on the rule that if any JSContext in our JSRuntime has a
// private set then that private *must* be a pointer to an nsISupports.
nsISupports *supports = (nsISupports*) JS_GetContextPrivate(cx);
if(supports)
{
nsCOMPtr<nsIScriptContext> scx = do_QueryInterface(supports);
if(scx)
scx->ScriptEvaluated(PR_FALSE);
}
#endif /* XPCONNECT_STANDALONE */
}
// static
nsXPCWrappedJSClass*
nsXPCWrappedJSClass::GetNewOrUsedClass(XPCJSRuntime* rt,
@ -169,8 +197,10 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSObject* jsobj, REFNSIID aIID
if(!OBJ_GET_PROPERTY(cx, jsobj, funid, &fun) || JSVAL_IS_PRIMITIVE(fun))
return nsnull;
DoPreScriptEvaluated(cx);
// XXX we should install an error reporter that will sent reports to
// some as yet non-existent JS error console via a service.
// the JS error console service.
jsval e;
JSBool hadExpection = JS_GetPendingException(cx, &e);
@ -181,6 +211,7 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSObject* jsobj, REFNSIID aIID
jsval args[1] = {OBJECT_TO_JSVAL(id)};
success = JS_CallFunctionValue(cx, jsobj, fun, 1, args, &retval);
}
if(success)
success = JS_ValueToObject(cx, retval, &retObj);
JS_SetErrorReporter(cx, older);
@ -189,6 +220,8 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSObject* jsobj, REFNSIID aIID
else
JS_ClearPendingException(cx);
DoPostScriptEvaluated(cx);
return success ? retObj : nsnull;
}
@ -507,6 +540,8 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
if(!xpc || !cx || !xpcc || !IsReflectable(methodIndex))
goto pre_call_clean_up;
DoPreScriptEvaluated(cx);
xpcc->SetPendingResult(pending_result);
xpcc->SetException(nsnull);
xpc->SetPendingException(nsnull);
@ -800,21 +835,14 @@ pre_call_clean_up:
{
if(NS_FAILED(e_result))
{
// XXX we should send the error string to some as yet
// non-existent JS error console via a service.
// Below is a quick hack to show the error/exception text
// via printf in debug builds only
#ifdef DEBUG
static const char line[] =
"************************************************************\n";
static const char disclaimer[] =
"** NOTE: This report will only be printed in DEBUG builds.**\n";
static const char preamble[] =
"* Call to xpconnect wrapped JSObject produced this error: *\n";
static const char cant_get_text[] =
"FAILED TO GET TEXT FROM EXCEPTION\n";
printf(line);
printf(disclaimer);
printf(preamble);
char* text;
if(NS_SUCCEEDED(xpc_exception->ToString(&text)) && text)
@ -825,8 +853,8 @@ pre_call_clean_up:
}
else
printf(cant_get_text);
printf(line);
#endif
printf(line);
// Log the exception to the JS Console, so that users can do
// something with it.
nsCOMPtr<nsIConsoleService> consoleService
@ -839,6 +867,7 @@ pre_call_clean_up:
rv = xpc_exception->GetData(getter_AddRefs(errorData));
if(NS_SUCCEEDED(rv))
scriptError = do_QueryInterface(errorData);
if(nsnull == scriptError)
{
// No luck getting one from the exception, so
@ -892,7 +921,6 @@ pre_call_clean_up:
}
}
}
if(nsnull != scriptError)
consoleService->LogMessage(scriptError);
}
@ -1144,7 +1172,10 @@ done:
nsMemory::Free((void*)conditional_iid);
if(cx)
{
JS_SetErrorReporter(cx, older);
DoPostScriptEvaluated(cx);
}
NS_IF_RELEASE(xpc);
#ifdef DEBUG_stats_jband