зеркало из https://github.com/mozilla/pjs.git
add improved support for dumping the JS stack from the native debugger or using the 'debugger' statement in JavaScript. Doc coming to the mozilla site soon. r=mccabe
This commit is contained in:
Родитель
669ded1e87
Коммит
321d0f8624
|
@ -717,7 +717,7 @@ void XXXDomNeverCalled()
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* This is here to be callable from a debugger */
|
||||
/* These are here to be callable from a debugger */
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIXPConnect.h"
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
@ -726,7 +726,17 @@ void DumpJSStack()
|
|||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIXPConnect, xpc, nsIXPConnect::GetCID(), &rv);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
xpc->DebugDumpJSStack();
|
||||
xpc->DebugDumpJSStack(PR_TRUE, PR_TRUE, PR_FALSE);
|
||||
else
|
||||
printf("failed to get XPConnect service!\n");
|
||||
}
|
||||
|
||||
void DumpJSEval(PRUint32 frame, const char* text)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIXPConnect, xpc, nsIXPConnect::GetCID(), &rv);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
xpc->DebugDumpEvalInJSStackFrame(frame, text);
|
||||
else
|
||||
printf("failed to get XPConnect service!\n");
|
||||
}
|
||||
|
|
|
@ -338,6 +338,10 @@ interface nsIXPConnect : nsISupports
|
|||
|
||||
void debugDump(in short depth);
|
||||
void debugDumpObject(in nsISupports aCOMObj, in short depth);
|
||||
void debugDumpJSStack();
|
||||
void debugDumpJSStack(in PRBool showArgs,
|
||||
in PRBool showLocals,
|
||||
in PRBool showThisProps);
|
||||
void debugDumpEvalInJSStackFrame(in PRUint32 aFrameNumber,
|
||||
in string aSourceText);
|
||||
};
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ CPPSRCS = \
|
|||
xpccomponents.cpp \
|
||||
xpccontext.cpp \
|
||||
xpcconvert.cpp \
|
||||
xpcdebug.cpp \
|
||||
xpcexception.cpp \
|
||||
xpcjsid.cpp \
|
||||
xpcjsruntime.cpp \
|
||||
|
|
|
@ -52,6 +52,7 @@ OBJS= \
|
|||
.\$(OBJDIR)\xpccomponents.obj \
|
||||
.\$(OBJDIR)\xpccontext.obj \
|
||||
.\$(OBJDIR)\xpcconvert.obj \
|
||||
.\$(OBJDIR)\xpcdebug.obj \
|
||||
.\$(OBJDIR)\xpcexception.obj \
|
||||
.\$(OBJDIR)\xpcjsid.obj \
|
||||
.\$(OBJDIR)\xpcjsruntime.obj \
|
||||
|
|
|
@ -725,6 +725,28 @@ nsXPConnect::SyncJSContexts(void)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void debugDump (in short depth); */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::DebugDump(PRInt16 depth)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
depth-- ;
|
||||
XPC_LOG_ALWAYS(("nsXPConnect @ %x with mRefCnt = %d", this, mRefCnt));
|
||||
XPC_LOG_INDENT();
|
||||
XPC_LOG_ALWAYS(("mArbitraryScriptable @ %x", mArbitraryScriptable));
|
||||
XPC_LOG_ALWAYS(("mInterfaceInfoManager @ %x", mInterfaceInfoManager));
|
||||
XPC_LOG_ALWAYS(("mContextStack @ %x", mContextStack));
|
||||
XPC_LOG_ALWAYS(("mThrower @ %x", mThrower));
|
||||
if(mRuntime)
|
||||
mRuntime->DebugDump(depth);
|
||||
else
|
||||
XPC_LOG_ALWAYS(("mRuntime is null"));
|
||||
nsXPCWrappedNativeScope::DebugDumpAllScopes(depth);
|
||||
XPC_LOG_OUTDENT();
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void debugDumpObject (in nsISupports aCOMObj, in short depth); */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::DebugDumpObject(nsISupports *p, PRInt16 depth)
|
||||
|
@ -785,76 +807,66 @@ nsXPConnect::DebugDumpObject(nsISupports *p, PRInt16 depth)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void debugDumpJSStack (); */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::DebugDumpJSStack(void)
|
||||
/* void debugDumpJSStack (in PRBool showArgs, in PRBool showLocals, in PRBool showThisProps); */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::DebugDumpJSStack(PRBool showArgs, PRBool showLocals, PRBool showThisProps)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
JSContext* cx;
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIJSContextStack, stack, "nsThreadJSContextStack", &rv);
|
||||
if(NS_FAILED(rv))
|
||||
printf("failed to get nsIJSContextStack service!\n");
|
||||
else if(NS_FAILED(stack->Peek(&cx)))
|
||||
printf("failed to peek into nsIJSContextStack service!\n");
|
||||
else if(!cx)
|
||||
printf("there is no JSContext on the nsIJSContextStack!\n");
|
||||
else
|
||||
xpc_DumpJSStack(cx, showArgs, showLocals, showThisProps);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIJSStackFrameLocation* stack;
|
||||
if(NS_FAILED(GetCurrentJSStack(&stack)) || !stack)
|
||||
{
|
||||
printf("call to GetCurrentJSStack failed\n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIJSStackFrameLocation* current = stack;
|
||||
NS_ADDREF(current);
|
||||
|
||||
while(1)
|
||||
{
|
||||
char* text;
|
||||
if(NS_FAILED(current->ToString(&text)))
|
||||
{
|
||||
printf("nsIJSStackFrameLocation::ToString failed!\n");
|
||||
NS_RELEASE(current);
|
||||
break;
|
||||
}
|
||||
printf("%s\n", text);
|
||||
nsAllocator::Free(text);
|
||||
nsIJSStackFrameLocation* prev = current;
|
||||
nsresult rv = prev->GetCaller(¤t);
|
||||
NS_RELEASE(prev);
|
||||
if(NS_FAILED(rv) || !current)
|
||||
break;
|
||||
}
|
||||
NS_RELEASE(stack);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* void debugDump (in short depth); */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::DebugDump(PRInt16 depth)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
depth-- ;
|
||||
XPC_LOG_ALWAYS(("nsXPConnect @ %x with mRefCnt = %d", this, mRefCnt));
|
||||
XPC_LOG_INDENT();
|
||||
XPC_LOG_ALWAYS(("mArbitraryScriptable @ %x", mArbitraryScriptable));
|
||||
XPC_LOG_ALWAYS(("mInterfaceInfoManager @ %x", mInterfaceInfoManager));
|
||||
XPC_LOG_ALWAYS(("mContextStack @ %x", mContextStack));
|
||||
XPC_LOG_ALWAYS(("mThrower @ %x", mThrower));
|
||||
if(mRuntime)
|
||||
mRuntime->DebugDump(depth);
|
||||
else
|
||||
XPC_LOG_ALWAYS(("mRuntime is null"));
|
||||
nsXPCWrappedNativeScope::DebugDumpAllScopes(depth);
|
||||
XPC_LOG_OUTDENT();
|
||||
/* void debugDumpEvalInJSStackFrame (in PRUint32 aFrameNumber, in string aSourceText); */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::DebugDumpEvalInJSStackFrame(PRUint32 aFrameNumber, const char *aSourceText)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
JSContext* cx;
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIJSContextStack, stack, "nsThreadJSContextStack", &rv);
|
||||
if(NS_FAILED(rv))
|
||||
printf("failed to get nsIJSContextStack service!\n");
|
||||
else if(NS_FAILED(stack->Peek(&cx)))
|
||||
printf("failed to peek into nsIJSContextStack service!\n");
|
||||
else if(!cx)
|
||||
printf("there is no JSContext on the nsIJSContextStack!\n");
|
||||
else
|
||||
xpc_DumpEvalInJSStackFrame(cx, aFrameNumber, aSourceText);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
/* This is here to be callable from a debugger */
|
||||
/* These are here to be callable from a debugger */
|
||||
JS_BEGIN_EXTERN_C
|
||||
void DumpJSStack()
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIXPConnect, xpc, nsIXPConnect::GetCID(), &rv);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
xpc->DebugDumpJSStack();
|
||||
xpc->DebugDumpJSStack(PR_TRUE, PR_TRUE, PR_FALSE);
|
||||
else
|
||||
printf("failed to get XPConnect service!\n");
|
||||
}
|
||||
|
||||
void DumpJSEval(PRUint32 frameno, const char* text)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIXPConnect, xpc, nsIXPConnect::GetCID(), &rv);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
xpc->DebugDumpEvalInJSStackFrame(frameno, text);
|
||||
else
|
||||
printf("failed to get XPConnect service!\n");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,374 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* John Bandhauer <jband@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "xpcprivate.h"
|
||||
|
||||
#ifdef TAB
|
||||
#undef TAB
|
||||
#endif
|
||||
#define TAB " "
|
||||
|
||||
static const char* JSVAL2String(JSContext* cx, jsval val, JSBool* isString)
|
||||
{
|
||||
const char* value = nsnull;
|
||||
JSString* value_str = JS_ValueToString(cx, val);
|
||||
if(value_str)
|
||||
value = JS_GetStringBytes(value_str);
|
||||
if(value)
|
||||
{
|
||||
const char* found = strstr(value, "function ");
|
||||
if(found && (value == found || value+1 == found || value+2 == found))
|
||||
value = "[function]";
|
||||
}
|
||||
|
||||
if(isString)
|
||||
*isString = JSVAL_IS_STRING(val);
|
||||
return value;
|
||||
}
|
||||
|
||||
static char* FormatJSFrame(JSContext* cx, JSStackFrame* fp,
|
||||
char* buf, int num,
|
||||
JSBool showArgs, JSBool showLocals, JSBool showThisProps)
|
||||
{
|
||||
if(JS_IsNativeFrame(cx, fp))
|
||||
return JS_sprintf_append(buf, "%d [native frame]\n", num);
|
||||
|
||||
JSPropertyDescArray callProps = {0, nsnull};
|
||||
JSPropertyDescArray thisProps = {0, nsnull};
|
||||
JSObject* thisObj = nsnull;
|
||||
JSObject* callObj = nsnull;
|
||||
const char* funname = nsnull;
|
||||
const char* filename = nsnull;
|
||||
PRInt32 lineno = 0;
|
||||
JSFunction* fun = nsnull;
|
||||
uint32 namedArgCount = 0;
|
||||
jsval val;
|
||||
const char* name;
|
||||
const char* value;
|
||||
JSBool isString;
|
||||
|
||||
// get the info for this stack frame
|
||||
|
||||
JSScript* script = JS_GetFrameScript(cx, fp);
|
||||
jsbytecode* pc = JS_GetFramePC(cx, fp);
|
||||
if(script && pc)
|
||||
{
|
||||
filename = JS_GetScriptFilename(cx, script);
|
||||
lineno = (PRInt32) JS_PCToLineNumber(cx, script, pc);
|
||||
fun = JS_GetFrameFunction(cx, fp);
|
||||
if(fun)
|
||||
funname = JS_GetFunctionName(fun);
|
||||
|
||||
if(showArgs || showLocals)
|
||||
{
|
||||
callObj = JS_GetFrameCallObject(cx, fp);
|
||||
if(callObj)
|
||||
if(!JS_GetPropertyDescArray(cx, callObj, &callProps))
|
||||
callProps.array = nsnull; // just to be sure
|
||||
}
|
||||
|
||||
thisObj = JS_GetFrameThis(cx, fp);
|
||||
if(showThisProps)
|
||||
{
|
||||
if(thisObj)
|
||||
if(!JS_GetPropertyDescArray(cx, thisObj, &thisProps))
|
||||
thisProps.array = nsnull; // just to be sure
|
||||
}
|
||||
}
|
||||
|
||||
// print the frame number and function name
|
||||
|
||||
if(funname)
|
||||
buf = JS_sprintf_append(buf, "%d %s(", num, funname);
|
||||
else if(fun)
|
||||
buf = JS_sprintf_append(buf, "%d anonymous(", num);
|
||||
else
|
||||
buf = JS_sprintf_append(buf, "%d <TOP LEVEL>", num);
|
||||
if(!buf) goto out;
|
||||
|
||||
// print the function arguments
|
||||
|
||||
if(showArgs && callObj)
|
||||
{
|
||||
for(uint32 i = 0; i < callProps.length; i++)
|
||||
{
|
||||
JSPropertyDesc* desc = &callProps.array[i];
|
||||
if(desc->flags & JSPD_ARGUMENT)
|
||||
{
|
||||
name = JSVAL2String(cx, desc->id, &isString);
|
||||
if(!isString)
|
||||
name = nsnull;
|
||||
value = JSVAL2String(cx, desc->value, &isString);
|
||||
|
||||
buf = JS_sprintf_append(buf, "%s%s%s%s%s%s",
|
||||
namedArgCount ? ", " : "",
|
||||
name ? name :"",
|
||||
name ? " = " : "",
|
||||
isString ? "\"" : "",
|
||||
value ? value : "?unknown?",
|
||||
isString ? "\"" : "");
|
||||
if(!buf) goto out;
|
||||
namedArgCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// print any unnamed trailing args (found in 'arguments' object)
|
||||
|
||||
if(JS_GetProperty(cx, callObj, "arguments", &val) &&
|
||||
JSVAL_IS_OBJECT(val))
|
||||
{
|
||||
uint32 argCount;
|
||||
JSObject* argsObj = JSVAL_TO_OBJECT(val);
|
||||
if(JS_GetProperty(cx, argsObj, "length", &val) &&
|
||||
JS_ValueToECMAUint32(cx, val, &argCount) &&
|
||||
argCount > namedArgCount)
|
||||
{
|
||||
for(uint32 i = namedArgCount; i < argCount; i++)
|
||||
{
|
||||
char num[8];
|
||||
JS_snprintf(num, 8, "%d", (int) i);
|
||||
|
||||
if(JS_GetProperty(cx, argsObj, num, &val))
|
||||
{
|
||||
value = JSVAL2String(cx, val, &isString);
|
||||
buf = JS_sprintf_append(buf, "%s%s%s%s",
|
||||
i ? ", " : "",
|
||||
isString ? "\"" : "",
|
||||
value ? value : "?unknown?",
|
||||
isString ? "\"" : "");
|
||||
if(!buf) goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print filename and line number
|
||||
|
||||
buf = JS_sprintf_append(buf, "%s [\"%s\":%d]\n",
|
||||
fun ? ")" : "",
|
||||
filename ? filename : "<unknown>",
|
||||
lineno);
|
||||
if(!buf) goto out;
|
||||
|
||||
// print local variables
|
||||
|
||||
if(showLocals && callProps.array)
|
||||
{
|
||||
for(uint32 i = 0; i < callProps.length; i++)
|
||||
{
|
||||
JSPropertyDesc* desc = &callProps.array[i];
|
||||
if(desc->flags & JSPD_VARIABLE)
|
||||
{
|
||||
name = JSVAL2String(cx, desc->id, nsnull);
|
||||
value = JSVAL2String(cx, desc->value, &isString);
|
||||
|
||||
if(name && value)
|
||||
{
|
||||
buf = JS_sprintf_append(buf, TAB "%s = %s%s%s\n",
|
||||
name,
|
||||
isString ? "\"" : "",
|
||||
value,
|
||||
isString ? "\"" : "");
|
||||
if(!buf) goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print the value of 'this'
|
||||
|
||||
if(showLocals && thisObj)
|
||||
{
|
||||
jsval thisJSVal = OBJECT_TO_JSVAL(thisObj);
|
||||
JSString* thisValStr;
|
||||
char* thisVal;
|
||||
|
||||
if(nsnull != (thisValStr = JS_ValueToString(cx, thisJSVal)) &&
|
||||
nsnull != (thisVal = JS_GetStringBytes(thisValStr)))
|
||||
{
|
||||
buf = JS_sprintf_append(buf, TAB "this = %s\n", thisVal);
|
||||
if(!buf) goto out;
|
||||
}
|
||||
}
|
||||
|
||||
// print the properties of 'this'
|
||||
|
||||
if(showThisProps && thisProps.array)
|
||||
{
|
||||
|
||||
for(uint32 i = 0; i < thisProps.length; i++)
|
||||
{
|
||||
JSPropertyDesc* desc = &thisProps.array[i];
|
||||
if(desc->flags & JSPD_ENUMERATE)
|
||||
{
|
||||
|
||||
name = JSVAL2String(cx, desc->id, nsnull);
|
||||
value = JSVAL2String(cx, desc->value, &isString);
|
||||
if(name && value)
|
||||
{
|
||||
buf = JS_sprintf_append(buf, TAB "this.%s = %s%s%s\n",
|
||||
name,
|
||||
isString ? "\"" : "",
|
||||
value,
|
||||
isString ? "\"" : "");
|
||||
if(!buf) goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if(callProps.array)
|
||||
JS_PutPropertyDescArray(cx, &callProps);
|
||||
if(thisProps.array)
|
||||
JS_PutPropertyDescArray(cx, &thisProps);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char* FormatJSStackDump(JSContext* cx, char* buf,
|
||||
JSBool showArgs, JSBool showLocals,
|
||||
JSBool showThisProps)
|
||||
{
|
||||
JSStackFrame* fp;
|
||||
JSStackFrame* iter = nsnull;
|
||||
int num = 0;
|
||||
|
||||
while(nsnull != (fp = JS_FrameIterator(cx, &iter)))
|
||||
{
|
||||
buf = FormatJSFrame(cx, fp, buf, num, showArgs, showLocals, showThisProps);
|
||||
num++;
|
||||
}
|
||||
|
||||
if(!num)
|
||||
buf = JS_sprintf_append(buf, "JavaScript stack is empty\n");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_DumpJSStack(JSContext* cx, JSBool showArgs, JSBool showLocals, JSBool showThisProps)
|
||||
{
|
||||
char* buf;
|
||||
|
||||
buf = FormatJSStackDump(cx, nsnull, showArgs, showLocals, showThisProps);
|
||||
if(buf)
|
||||
{
|
||||
printf(buf);
|
||||
JS_smprintf_free(buf);
|
||||
}
|
||||
else
|
||||
printf("Failed to format JavaScript stack for dump\n");
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void)
|
||||
xpcDumpEvalErrorReporter(JSContext *cx, const char *message,
|
||||
JSErrorReport *report)
|
||||
{
|
||||
printf("Error: %s\n", message);
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_DumpEvalInJSStackFrame(JSContext* cx, JSUint32 frameno, const char* text)
|
||||
{
|
||||
JSStackFrame* fp;
|
||||
JSStackFrame* iter = nsnull;
|
||||
JSUint32 num = 0;
|
||||
|
||||
if(!cx || !text)
|
||||
{
|
||||
printf("invalid params passed to xpc_DumpEvalInJSStackFrame!\n");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
printf("js[%d]> %s\n", frameno, text);
|
||||
|
||||
while(nsnull != (fp = JS_FrameIterator(cx, &iter)))
|
||||
{
|
||||
if(num == frameno)
|
||||
break;
|
||||
num++;
|
||||
}
|
||||
|
||||
if(!fp)
|
||||
{
|
||||
printf("invalid frame number!\n");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSExceptionState* exceptionState = JS_SaveExceptionState(cx);
|
||||
JSErrorReporter older = JS_SetErrorReporter(cx, xpcDumpEvalErrorReporter);
|
||||
|
||||
jsval rval;
|
||||
JSString* str;
|
||||
const char* chars;
|
||||
if(JS_EvaluateInStackFrame(cx, fp, text, strlen(text), "eval", 1, &rval) &&
|
||||
nsnull != (str = JS_ValueToString(cx, rval)) &&
|
||||
nsnull != (chars = JS_GetStringBytes(str)))
|
||||
{
|
||||
printf("%s\n", chars);
|
||||
}
|
||||
else
|
||||
printf("eval failed!\n");
|
||||
JS_SetErrorReporter(cx, older);
|
||||
JS_RestoreExceptionState(cx, exceptionState);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
JSTrapStatus JS_DLL_CALLBACK
|
||||
xpc_DebuggerKeywordHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
jsval *rval, void *closure)
|
||||
{
|
||||
static const char line[] =
|
||||
"------------------------------------------------------------------------\n";
|
||||
printf(line);
|
||||
printf("Hit JavaScript \"debugger\" keyword. JS call stack...\n");
|
||||
xpc_DumpJSStack(cx, JS_TRUE, JS_TRUE, JS_FALSE);
|
||||
printf(line);
|
||||
return JSTRAP_CONTINUE;
|
||||
}
|
||||
|
||||
JSBool xpc_InstallJSDebuggerKeywordHandler(JSRuntime* rt)
|
||||
{
|
||||
return JS_SetDebuggerHandler(rt, xpc_DebuggerKeywordHandler, nsnull);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -53,6 +53,18 @@ const char* XPCJSRuntime::mStrings[] = {
|
|||
|
||||
XPCJSRuntime::~XPCJSRuntime()
|
||||
{
|
||||
#ifdef DEBUG_jband
|
||||
{
|
||||
// count the total JSContexts in use
|
||||
JSContext* iter = nsnull;
|
||||
int count = 0;
|
||||
while(JS_ContextIterator(mJSRuntime, &iter))
|
||||
count ++;
|
||||
if(count)
|
||||
printf("deleting XPCJSRuntime with %d total live JSContexts\n", count);
|
||||
}
|
||||
#endif
|
||||
|
||||
// clean up and destroy maps...
|
||||
|
||||
if(mContextMap)
|
||||
|
@ -61,7 +73,7 @@ XPCJSRuntime::~XPCJSRuntime()
|
|||
#ifdef DEBUG_jband
|
||||
uint32 count = mContextMap->Count();
|
||||
if(count)
|
||||
printf("deleting XPCJSRuntime with %d live JSContexts\n", (int)count);
|
||||
printf("deleting XPCJSRuntime with %d live JSContexts known by xpconnect\n", (int)count);
|
||||
#endif
|
||||
delete mContextMap;
|
||||
}
|
||||
|
@ -119,7 +131,13 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect,
|
|||
{
|
||||
NS_ADDREF(mJSRuntimeService);
|
||||
mJSRuntimeService->GetRuntime(&mJSRuntime);
|
||||
}
|
||||
}
|
||||
|
||||
// Install a JavaScript 'debugger' keyword handler in debug builds only
|
||||
#ifdef DEBUG
|
||||
if(mJSRuntime)
|
||||
xpc_InstallJSDebuggerKeywordHandler(mJSRuntime);
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -1379,14 +1379,26 @@ private:
|
|||
|
||||
/***************************************************************************/
|
||||
|
||||
JSObject*
|
||||
extern JSObject*
|
||||
xpc_NewIDObject(JSContext *cx, JSObject* jsobj, const nsID& aID);
|
||||
|
||||
nsID*
|
||||
extern nsID*
|
||||
xpc_JSObjectToID(JSContext *cx, JSObject* obj);
|
||||
|
||||
/***************************************************************************/
|
||||
// in xpcdebug.cpp
|
||||
|
||||
extern JSBool
|
||||
xpc_DumpJSStack(JSContext* cx, JSBool showArgs, JSBool showLocals,
|
||||
JSBool showThisProps);
|
||||
|
||||
extern JSBool
|
||||
xpc_DumpEvalInJSStackFrame(JSContext* cx, JSUint32 frameno, const char* text);
|
||||
|
||||
extern JSBool
|
||||
xpc_InstallJSDebuggerKeywordHandler(JSRuntime* rt);
|
||||
|
||||
/***************************************************************************/
|
||||
// the include of declarations of the maps comes last because they have
|
||||
// inlines which call methods on classes above.
|
||||
|
||||
|
|
|
@ -307,7 +307,7 @@ xpctestEcho::DebugDumpJSStack()
|
|||
NS_WITH_SERVICE(nsIXPConnect, xpc, nsIXPConnect::GetCID(), &rv);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = xpc->DebugDumpJSStack();
|
||||
rv = xpc->DebugDumpJSStack(JS_TRUE, JS_TRUE, JS_TRUE);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче