bug 121192, sr=brendan,r=jst, "Add proper errorHook and debugHook to jsdIDebuggerService"

adds jsdIDebugHook interface, change the meaning of jsdIErrorHook.
error hook is called when an error occurs, and is given information about the error report.
debug hook is called when/if the error hook returns false, and is given information about the ececution state.
This commit is contained in:
rginda%netscape.com 2002-01-29 05:56:02 +00:00
Родитель ffe5b4f9da
Коммит 1fbc1826c1
3 изменённых файлов: 159 добавлений и 16 удалений

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

@ -58,6 +58,7 @@ interface jsdINestCallback;
interface jsdIFilterEnumerator;
interface jsdIScriptEnumerator;
interface jsdIScriptHook;
interface jsdIErrorHook;
interface jsdIExecutionHook;
interface jsdICallHook;
interface jsdIEphemeral;
@ -78,6 +79,11 @@ interface jsdIDebuggerService : nsISupports
/** Internal use only. */
[noscript] readonly attribute JSDContext JSDContext;
/**
* Called when an error or warning occurs.
*/
attribute jsdIErrorHook errorHook;
/**
* Called when a jsdIScript is created or destroyed.
*/
@ -91,9 +97,9 @@ interface jsdIDebuggerService : nsISupports
*/
attribute jsdIExecutionHook debuggerHook;
/**
* Called when an exception goes uncaught.
* Called when the errorHook returns false.
*/
attribute jsdIExecutionHook errorHook;
attribute jsdIExecutionHook debugHook;
/**
* Called before the next PC is executed.
*/
@ -401,6 +407,20 @@ interface jsdICallHook : nsISupports
void onCall (in jsdIStackFrame frame, in unsigned long type);
};
[scriptable, uuid(b7dd3c1c-1dd1-11b2-83eb-8a857d199e0f)]
interface jsdIErrorHook : nsISupports
{
const unsigned long REPORT_ERROR = 0x00;
const unsigned long REPORT_WARNING = 0x01;
const unsigned long REPORT_EXCEPTION = 0x02;
const unsigned long REPORT_STRICT = 0x04;
boolean onError (in string message, in string fileName,
in unsigned long line, in unsigned long pos,
in unsigned long flags, in unsigned long errnum,
in jsdIValue exc);
};
/**
* Hook instances of this interface up to the
* jsdIDebuggerService::breakpointHook, debuggerHook, errorHook, interruptHook,
@ -409,10 +429,25 @@ interface jsdICallHook : nsISupports
[scriptable, uuid(9a7b6ad0-1dd1-11b2-a789-fcfae96356a2)]
interface jsdIExecutionHook : nsISupports
{
/**
* Execution stopped because we're in single step mode.
*/
const unsigned long TYPE_INTERRUPTED = 0;
/**
* Execution stopped by a trap instruction (i.e. breakoint.)
*/
const unsigned long TYPE_BREAKPOINT = 1;
/**
* Error handler returned an "invoke debugger" value.
*/
const unsigned long TYPE_DEBUG_REQUESTED = 2;
/**
* Debugger keyword encountered.
*/
const unsigned long TYPE_DEBUGGER_KEYWORD = 3;
/**
* Exception was thrown.
*/
const unsigned long TYPE_THROW = 4;
/**
@ -429,9 +464,21 @@ interface jsdIExecutionHook : nsISupports
* hooks.
*/
const unsigned long RETURN_CONTINUE = 1;
/**
* Same effect as RETURN_HOOK_ERROR.
*/
const unsigned long RETURN_ABORT = 2;
/**
* Return the value of the |val| parameter.
*/
const unsigned long RETURN_RET_WITH_VAL = 3;
/**
* Throw the value of the |val| parameter.
*/
const unsigned long RETURN_THROW_WITH_VAL = 4;
/**
* Continue the current throw.
*/
const unsigned long RETURN_CONTINUE_THROW = 5;
/**

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

@ -494,11 +494,68 @@ jsds_GCCallbackProc (JSContext *cx, JSGCStatus status)
return JS_TRUE;
}
JS_STATIC_DLL_CALLBACK (uintN)
jsds_ErrorHookProc (JSDContext *jsdc, JSContext *cx, const char *message,
JSErrorReport *report, void *callerdata)
{
static PRBool running = PR_FALSE;
if (running)
return JSD_ERROR_REPORTER_PASS_ALONG;
running = PR_TRUE;
nsCOMPtr<jsdIErrorHook> hook;
gJsds->GetErrorHook(getter_AddRefs(hook));
if (!hook)
return JSD_ERROR_REPORTER_PASS_ALONG;
jsdIValue *val = 0;
if (JS_IsExceptionPending(cx)) {
jsval jv;
JS_GetPendingException(cx, &jv);
JSDValue *jsdv = JSD_NewValue (jsdc, jv);
val = jsdValue::FromPtr(jsdc, jsdv);
}
const char *fileName;
PRUint32 line;
PRUint32 pos;
PRUint32 flags;
PRUint32 errnum;
PRBool rval;
if (report) {
fileName = report->filename;
line = report->lineno;
pos = report->tokenptr - report->linebuf;
flags = report->flags;
errnum = report->errorNumber;
}
else
{
fileName = 0;
line = 0;
pos = 0;
flags = 0;
errnum = 0;
}
gJsds->Pause(nsnull);
hook->OnError (message, fileName, line, pos, flags, errnum, val, &rval);
gJsds->UnPause(nsnull);
running = false;
if (!rval)
return JSD_ERROR_REPORTER_DEBUG;
return JSD_ERROR_REPORTER_PASS_ALONG;
}
JS_STATIC_DLL_CALLBACK (JSBool)
jsds_CallHookProc (JSDContext* jsdc, JSDThreadState* jsdthreadstate,
uintN type, void* callerdata)
{
nsCOMPtr<jsdICallHook> hook(0);
nsCOMPtr<jsdICallHook> hook;
switch (type)
{
@ -548,7 +605,7 @@ jsds_ExecutionHookProc (JSDContext* jsdc, JSDThreadState* jsdthreadstate,
gJsds->GetInterruptHook(getter_AddRefs(hook));
break;
case JSD_HOOK_DEBUG_REQUESTED:
gJsds->GetErrorHook(getter_AddRefs(hook));
gJsds->GetDebugHook(getter_AddRefs(hook));
break;
case JSD_HOOK_DEBUGGER_KEYWORD:
gJsds->GetDebuggerHook(getter_AddRefs(hook));
@ -1345,7 +1402,11 @@ jsdStackFrame::Eval (const nsAReadableString &bytes, const char *fileName,
return NS_ERROR_FAILURE;
JSDValue *jsdv = JSD_NewValue (mCx, jv);
if (!jsdv)
return NS_ERROR_FAILURE;
*_rval = jsdValue::FromPtr (mCx, jsdv);
if (!*_rval)
return NS_ERROR_FAILURE;
return NS_OK;
}
@ -1796,6 +1857,8 @@ jsdService::OnForRuntime (JSRuntime *rt)
/* If any of these mFooHook objects are installed, do the required JSD
* hookup now. See also, jsdService::SetFooHook().
*/
if (mErrorHook)
JSD_SetErrorReporter (mCx, jsds_ErrorHookProc, NULL);
if (mThrowHook)
JSD_SetThrowHook (mCx, jsds_ExecutionHookProc, NULL);
/* can't ignore script callbacks, as we need to |Release| the wrapper
@ -1804,7 +1867,7 @@ jsdService::OnForRuntime (JSRuntime *rt)
JSD_SetInterruptHook (mCx, jsds_ExecutionHookProc, NULL);
if (mDebuggerHook)
JSD_SetDebuggerHook (mCx, jsds_ExecutionHookProc, NULL);
if (mErrorHook)
if (mDebugHook)
JSD_SetDebugBreakHook (mCx, jsds_ExecutionHookProc, NULL);
if (mTopLevelHook)
JSD_SetTopLevelHook (mCx, jsds_CallHookProc, NULL);
@ -1851,6 +1914,7 @@ jsdService::Off (void)
jsdProperty::InvalidateAll();
ClearAllBreakpoints();
JSD_SetErrorReporter (mCx, NULL, NULL);
JSD_ClearThrowHook (mCx);
JSD_ClearInterruptHook (mCx);
JSD_ClearDebuggerHook (mCx);
@ -1875,6 +1939,7 @@ NS_IMETHODIMP
jsdService::Pause(PRUint32 *_rval)
{
if (++mPauseLevel == 1) {
JSD_SetErrorReporter (mCx, NULL, NULL);
JSD_ClearThrowHook (mCx);
JSD_ClearInterruptHook (mCx);
JSD_ClearDebuggerHook (mCx);
@ -1896,13 +1961,15 @@ jsdService::UnPause(PRUint32 *_rval)
return NS_ERROR_NOT_AVAILABLE;
if (--mPauseLevel == 0) {
if (mErrorHook)
JSD_SetErrorReporter (mCx, jsds_ErrorHookProc, NULL);
if (mThrowHook)
JSD_SetThrowHook (mCx, jsds_ExecutionHookProc, NULL);
if (mInterruptHook)
JSD_SetInterruptHook (mCx, jsds_ExecutionHookProc, NULL);
if (mDebuggerHook)
JSD_SetDebuggerHook (mCx, jsds_ExecutionHookProc, NULL);
if (mErrorHook)
if (mDebugHook)
JSD_SetDebugBreakHook (mCx, jsds_ExecutionHookProc, NULL);
if (mTopLevelHook)
JSD_SetTopLevelHook (mCx, jsds_CallHookProc, NULL);
@ -2198,6 +2265,34 @@ jsdService::ExitNestedEventLoop (PRUint32 *_rval)
/* hook attribute get/set functions */
NS_IMETHODIMP
jsdService::SetErrorHook (jsdIErrorHook *aHook)
{
mErrorHook = aHook;
/* if the debugger isn't initialized, that's all we can do for now. The
* OnForRuntime() method will do the rest when the coast is clear.
*/
if (!mCx || mPauseLevel)
return NS_OK;
if (aHook)
JSD_SetErrorReporter (mCx, jsds_ErrorHookProc, NULL);
else
JSD_SetErrorReporter (mCx, NULL, NULL);
return NS_OK;
}
NS_IMETHODIMP
jsdService::GetErrorHook (jsdIErrorHook **aHook)
{
*aHook = mErrorHook;
NS_IF_ADDREF(*aHook);
return NS_OK;
}
NS_IMETHODIMP
jsdService::SetBreakpointHook (jsdIExecutionHook *aHook)
{
@ -2215,9 +2310,9 @@ jsdService::GetBreakpointHook (jsdIExecutionHook **aHook)
}
NS_IMETHODIMP
jsdService::SetErrorHook (jsdIExecutionHook *aHook)
jsdService::SetDebugHook (jsdIExecutionHook *aHook)
{
mErrorHook = aHook;
mDebugHook = aHook;
/* if the debugger isn't initialized, that's all we can do for now. The
* OnForRuntime() method will do the rest when the coast is clear.
@ -2234,9 +2329,9 @@ jsdService::SetErrorHook (jsdIExecutionHook *aHook)
}
NS_IMETHODIMP
jsdService::GetErrorHook (jsdIExecutionHook **aHook)
jsdService::GetDebugHook (jsdIExecutionHook **aHook)
{
*aHook = mErrorHook;
*aHook = mDebugHook;
NS_IF_ADDREF(*aHook);
return NS_OK;

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

@ -274,10 +274,10 @@ class jsdService : public jsdIDebuggerService
NS_DECL_JSDIDEBUGGERSERVICE
jsdService() : mInitAtStartup(triUnknown), mOn(PR_FALSE), mPauseLevel(0),
mNestedLoopLevel(0), mCx(0), mRuntime(0), mBreakpointHook(0),
mErrorHook(0), mDebuggerHook(0), mInterruptHook(0),
mScriptHook(0), mThrowHook(0), mTopLevelHook(0),
mFunctionHook(0)
mNestedLoopLevel(0), mCx(0), mRuntime(0), mErrorHook(0),
mBreakpointHook(0), mDebugHook(0), mDebuggerHook(0),
mInterruptHook(0), mScriptHook(0), mThrowHook(0),
mTopLevelHook(0), mFunctionHook(0)
{
NS_INIT_ISUPPORTS();
}
@ -303,9 +303,10 @@ class jsdService : public jsdIDebuggerService
PRUint32 mNestedLoopLevel;
JSDContext *mCx;
JSRuntime *mRuntime;
nsCOMPtr<jsdIErrorHook> mErrorHook;
nsCOMPtr<jsdIExecutionHook> mBreakpointHook;
nsCOMPtr<jsdIExecutionHook> mErrorHook;
nsCOMPtr<jsdIExecutionHook> mDebugHook;
nsCOMPtr<jsdIExecutionHook> mDebuggerHook;
nsCOMPtr<jsdIExecutionHook> mInterruptHook;
nsCOMPtr<jsdIScriptHook> mScriptHook;