зеркало из https://github.com/mozilla/gecko-dev.git
Bug 833817 part 3 - Replace JSStackFrame with JSAbstractFramePtr. r=luke
This commit is contained in:
Родитель
9bf0337f71
Коммит
7799c058c4
15
js/jsd/jsd.h
15
js/jsd/jsd.h
|
@ -210,7 +210,8 @@ struct JSDStackFrameInfo
|
|||
JSDThreadState* jsdthreadstate;
|
||||
JSDScript* jsdscript;
|
||||
uintptr_t pc;
|
||||
JSStackFrame* fp;
|
||||
bool isConstructing;
|
||||
JSAbstractFramePtr frame;
|
||||
};
|
||||
|
||||
#define GOT_PROTO ((short) (1 << 0))
|
||||
|
@ -347,7 +348,7 @@ extern JSDScript*
|
|||
jsd_FindOrCreateJSDScript(JSDContext *jsdc,
|
||||
JSContext *cx,
|
||||
JSScript *script,
|
||||
JSStackFrame *fp);
|
||||
JSAbstractFramePtr frame);
|
||||
|
||||
extern JSDProfileData*
|
||||
jsd_GetScriptProfileData(JSDContext* jsdc, JSDScript *script);
|
||||
|
@ -978,12 +979,12 @@ jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop);
|
|||
/* Stepping Functions */
|
||||
|
||||
extern void *
|
||||
jsd_FunctionCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
|
||||
JSBool *ok, void *closure);
|
||||
jsd_FunctionCallHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
|
||||
JSBool before, JSBool *ok, void *closure);
|
||||
|
||||
extern void *
|
||||
jsd_TopLevelCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
|
||||
JSBool *ok, void *closure);
|
||||
jsd_TopLevelCallHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
|
||||
JSBool before, JSBool *ok, void *closure);
|
||||
|
||||
/**************************************************/
|
||||
/* Object Functions */
|
||||
|
@ -999,7 +1000,7 @@ jsd_DestroyObjects(JSDContext* jsdc);
|
|||
|
||||
extern void
|
||||
jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
|
||||
JSStackFrame *fp);
|
||||
JSAbstractFramePtr frame);
|
||||
|
||||
extern JSDObject*
|
||||
jsd_IterateObjects(JSDContext* jsdc, JSDObject** iterp);
|
||||
|
|
|
@ -34,7 +34,7 @@ jsd_InterruptHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rva
|
|||
return JSTRAP_CONTINUE;
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
|
||||
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
if( ! jsdscript )
|
||||
return JSTRAP_CONTINUE;
|
||||
|
@ -72,7 +72,7 @@ jsd_DebuggerHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|||
return JSTRAP_CONTINUE;
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
|
||||
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
if( ! jsdscript )
|
||||
return JSTRAP_CONTINUE;
|
||||
|
@ -106,7 +106,7 @@ jsd_ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|||
return JSTRAP_CONTINUE;
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
|
||||
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, JSNullFramePtr());
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
if( ! jsdscript )
|
||||
return JSTRAP_CONTINUE;
|
||||
|
|
|
@ -80,7 +80,7 @@ _destroyJSDObject(JSDContext* jsdc, JSDObject* jsdobj)
|
|||
|
||||
void
|
||||
jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
|
||||
JSStackFrame *fp)
|
||||
JSAbstractFramePtr frame)
|
||||
{
|
||||
JSDObject* jsdobj;
|
||||
JSScript* script;
|
||||
|
@ -93,7 +93,7 @@ jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
|
|||
jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj);
|
||||
if( jsdobj && !jsdobj->ctorURL )
|
||||
{
|
||||
script = JS_GetFrameScript(cx, fp);
|
||||
script = frame.script();
|
||||
if( script )
|
||||
{
|
||||
ctorURL = JS_GetScriptFilename(cx, script);
|
||||
|
@ -101,7 +101,7 @@ jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
|
|||
jsdobj->ctorURL = jsd_AddAtom(jsdc, ctorURL);
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, fp);
|
||||
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, frame);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
if( jsdscript && (ctorNameStr = jsd_GetScriptFunctionId(jsdc, jsdscript)) ) {
|
||||
if( (ctorName = JS_EncodeString(cx, ctorNameStr)) ) {
|
||||
|
|
|
@ -278,7 +278,7 @@ JSDScript *
|
|||
jsd_FindOrCreateJSDScript(JSDContext *jsdc,
|
||||
JSContext *cx,
|
||||
JSScript *script,
|
||||
JSStackFrame *fp)
|
||||
JSAbstractFramePtr frame)
|
||||
{
|
||||
JSDScript *jsdscript;
|
||||
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
||||
|
@ -288,9 +288,12 @@ jsd_FindOrCreateJSDScript(JSDContext *jsdc,
|
|||
return jsdscript;
|
||||
|
||||
/* Fallback for unknown scripts: create a new script. */
|
||||
if (!fp)
|
||||
JS_BrokenFrameIterator(cx, &fp);
|
||||
if (fp)
|
||||
if (!frame) {
|
||||
JSBrokenFrameIterator iter(cx);
|
||||
if (!iter.done())
|
||||
frame = iter.abstractFramePtr();
|
||||
}
|
||||
if (frame)
|
||||
jsdscript = _newJSDScript(jsdc, cx, script);
|
||||
|
||||
return jsdscript;
|
||||
|
|
|
@ -29,7 +29,8 @@ _addNewFrame(JSDContext* jsdc,
|
|||
JSDThreadState* jsdthreadstate,
|
||||
JSScript* script,
|
||||
uintptr_t pc,
|
||||
JSStackFrame* fp)
|
||||
bool isConstructing,
|
||||
JSAbstractFramePtr frame)
|
||||
{
|
||||
JSDStackFrameInfo* jsdframe;
|
||||
JSDScript* jsdscript = NULL;
|
||||
|
@ -52,8 +53,9 @@ _addNewFrame(JSDContext* jsdc,
|
|||
|
||||
jsdframe->jsdthreadstate = jsdthreadstate;
|
||||
jsdframe->jsdscript = jsdscript;
|
||||
jsdframe->isConstructing = isConstructing;
|
||||
jsdframe->pc = pc;
|
||||
jsdframe->fp = fp;
|
||||
jsdframe->frame = frame;
|
||||
|
||||
JS_APPEND_LINK(&jsdframe->links, &jsdthreadstate->stack);
|
||||
jsdthreadstate->stackDepth++;
|
||||
|
@ -74,8 +76,6 @@ JSDThreadState*
|
|||
jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
|
||||
{
|
||||
JSDThreadState* jsdthreadstate;
|
||||
JSStackFrame * iter = NULL;
|
||||
JSStackFrame * fp;
|
||||
|
||||
jsdthreadstate = (JSDThreadState*)calloc(1, sizeof(JSDThreadState));
|
||||
if( ! jsdthreadstate )
|
||||
|
@ -87,10 +87,13 @@ jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
|
|||
jsdthreadstate->stackDepth = 0;
|
||||
|
||||
JS_BeginRequest(jsdthreadstate->context);
|
||||
while( NULL != (fp = JS_BrokenFrameIterator(cx, &iter)) )
|
||||
|
||||
JSBrokenFrameIterator iter(cx);
|
||||
while(!iter.done())
|
||||
{
|
||||
JSScript* script = JS_GetFrameScript(cx, fp);
|
||||
uintptr_t pc = (uintptr_t) JS_GetFramePC(cx, fp);
|
||||
JSAbstractFramePtr frame = iter.abstractFramePtr();
|
||||
JSScript* script = frame.script();
|
||||
uintptr_t pc = (uintptr_t)iter.pc();
|
||||
jsval dummyThis;
|
||||
|
||||
/*
|
||||
|
@ -98,15 +101,14 @@ jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
|
|||
* |this| object, or native frames, if JSD_INCLUDE_NATIVE_FRAMES
|
||||
* isn't set.
|
||||
*/
|
||||
if (JS_GetFrameThis(cx, fp, &dummyThis))
|
||||
if (frame.getThisValue(cx, &dummyThis))
|
||||
{
|
||||
JSDStackFrameInfo *frame;
|
||||
bool isConstructing = iter.isConstructing();
|
||||
JSDStackFrameInfo *frameInfo = _addNewFrame( jsdc, jsdthreadstate, script, pc, isConstructing, frame );
|
||||
|
||||
frame = _addNewFrame( jsdc, jsdthreadstate, script, pc, fp );
|
||||
|
||||
if ((jsdthreadstate->stackDepth == 0 && !frame) ||
|
||||
(jsdthreadstate->stackDepth == 1 && frame &&
|
||||
frame->jsdscript && !JSD_IS_DEBUG_ENABLED(jsdc, frame->jsdscript)))
|
||||
if ((jsdthreadstate->stackDepth == 0 && !frameInfo) ||
|
||||
(jsdthreadstate->stackDepth == 1 && frameInfo &&
|
||||
frameInfo->jsdscript && !JSD_IS_DEBUG_ENABLED(jsdc, frameInfo->jsdscript)))
|
||||
{
|
||||
/*
|
||||
* if we failed to create the first frame, or the top frame
|
||||
|
@ -118,6 +120,8 @@ jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
++iter;
|
||||
}
|
||||
JS_EndRequest(jsdthreadstate->context);
|
||||
|
||||
|
@ -262,7 +266,7 @@ jsd_GetCallObjectForStackFrame(JSDContext* jsdc,
|
|||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
{
|
||||
obj = JS_GetFrameCallObject(jsdthreadstate->context, jsdframe->fp);
|
||||
obj = jsdframe->frame.callObject(jsdthreadstate->context);
|
||||
if(obj)
|
||||
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
|
||||
}
|
||||
|
@ -285,10 +289,10 @@ jsd_GetScopeChainForStackFrame(JSDContext* jsdc,
|
|||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
{
|
||||
JS_BeginRequest(jsdthreadstate->context);
|
||||
obj = JS_GetFrameScopeChain(jsdthreadstate->context, jsdframe->fp);
|
||||
obj = jsdframe->frame.scopeChain(jsdthreadstate->context);
|
||||
JS_EndRequest(jsdthreadstate->context);
|
||||
if(obj)
|
||||
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
|
||||
if(obj)
|
||||
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
|
||||
}
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
@ -309,7 +313,7 @@ jsd_GetThisForStackFrame(JSDContext* jsdc,
|
|||
JSBool ok;
|
||||
jsval thisval;
|
||||
JS_BeginRequest(jsdthreadstate->context);
|
||||
ok = JS_GetFrameThis(jsdthreadstate->context, jsdframe->fp, &thisval);
|
||||
ok = jsdframe->frame.getThisValue(jsdthreadstate->context, &thisval);
|
||||
JS_EndRequest(jsdthreadstate->context);
|
||||
if(ok)
|
||||
jsdval = JSD_NewValue(jsdc, thisval);
|
||||
|
@ -330,8 +334,7 @@ jsd_GetIdForStackFrame(JSDContext* jsdc,
|
|||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
{
|
||||
JSFunction *fun = JS_GetFrameFunction (jsdthreadstate->context,
|
||||
jsdframe->fp);
|
||||
JSFunction *fun = jsdframe->frame.maybeFun();
|
||||
if( fun )
|
||||
{
|
||||
rv = JS_GetFunctionId (fun);
|
||||
|
@ -359,7 +362,7 @@ jsd_IsStackFrameDebugger(JSDContext* jsdc,
|
|||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
{
|
||||
rv = JS_IsDebuggerFrame(jsdthreadstate->context, jsdframe->fp);
|
||||
rv = jsdframe->frame.isDebuggerFrame();
|
||||
}
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
@ -376,7 +379,7 @@ jsd_IsStackFrameConstructing(JSDContext* jsdc,
|
|||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
{
|
||||
rv = JS_IsConstructorFrame(jsdthreadstate->context, jsdframe->fp);
|
||||
rv = jsdframe->isConstructing;
|
||||
}
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
@ -412,8 +415,8 @@ jsd_EvaluateUCScriptInStackFrame(JSDContext* jsdc,
|
|||
exceptionState = JS_SaveExceptionState(cx);
|
||||
JS_ClearPendingException(cx);
|
||||
jsd_StartingEvalUsingFilename(jsdc, filename);
|
||||
retval = JS_EvaluateUCInStackFrame(cx, jsdframe->fp, bytes, length,
|
||||
filename, lineno, rval);
|
||||
retval = jsdframe->frame.evaluateUCInStackFrame(cx, bytes, length, filename, lineno,
|
||||
rval);
|
||||
jsd_FinishedEvalUsingFilename(jsdc, filename);
|
||||
if (eatExceptions)
|
||||
JS_RestoreExceptionState(cx, exceptionState);
|
||||
|
@ -450,8 +453,8 @@ jsd_EvaluateScriptInStackFrame(JSDContext* jsdc,
|
|||
exceptionState = JS_SaveExceptionState(cx);
|
||||
JS_ClearPendingException(cx);
|
||||
jsd_StartingEvalUsingFilename(jsdc, filename);
|
||||
retval = JS_EvaluateInStackFrame(cx, jsdframe->fp, bytes, length,
|
||||
filename, lineno, rval);
|
||||
retval = jsdframe->frame.evaluateInStackFrame(cx, bytes, length, filename, lineno,
|
||||
rval);
|
||||
jsd_FinishedEvalUsingFilename(jsdc, filename);
|
||||
if (eatExceptions)
|
||||
JS_RestoreExceptionState(cx, exceptionState);
|
||||
|
|
|
@ -31,19 +31,19 @@ _indentSpaces(int i)
|
|||
}
|
||||
|
||||
static void
|
||||
_interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
|
||||
JSBool before)
|
||||
_interpreterTrace(JSDContext* jsdc, JSContext *cx, JSAbstractFramePtr frame,
|
||||
bool isConstructing, JSBool before)
|
||||
{
|
||||
JSDScript* jsdscript = NULL;
|
||||
JSScript * script;
|
||||
static indent = 0;
|
||||
JSString* funName = NULL;
|
||||
|
||||
script = JS_GetFrameScript(cx, fp);
|
||||
script = frame.script();
|
||||
if(script)
|
||||
{
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, fp);
|
||||
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, frame);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
if(jsdscript)
|
||||
funName = JSD_GetScriptFunctionId(jsdc, jsdscript);
|
||||
|
@ -63,9 +63,9 @@ _interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
|
|||
{
|
||||
jsval thisVal;
|
||||
|
||||
printf("%s this: ", JS_IsConstructorFrame(cx, fp) ? "constructing":"");
|
||||
printf("%s this: ", isConstructing ? "constructing":"");
|
||||
|
||||
if (JS_GetFrameThis(cx, fp, &thisVal))
|
||||
if (JS_GetFrameThis(cx, frame, &thisVal))
|
||||
printf("0x%0llx", (uintptr_t) thisVal);
|
||||
else
|
||||
puts("<unavailable>");
|
||||
|
@ -76,8 +76,8 @@ _interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
|
|||
#endif
|
||||
|
||||
JSBool
|
||||
_callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
|
||||
unsigned type, JSD_CallHookProc hook, void *hookData)
|
||||
_callHook(JSDContext *jsdc, JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
|
||||
JSBool before, unsigned type, JSD_CallHookProc hook, void *hookData)
|
||||
{
|
||||
JSDScript* jsdscript;
|
||||
JSScript* jsscript;
|
||||
|
@ -93,19 +93,19 @@ _callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
|
|||
*/
|
||||
return hookresult;
|
||||
}
|
||||
|
||||
if (before && JS_IsConstructorFrame(cx, fp)) {
|
||||
|
||||
if (before && isConstructing) {
|
||||
jsval newObj;
|
||||
if (!JS_GetFrameThis(cx, fp, &newObj))
|
||||
if (!frame.getThisValue(cx, &newObj))
|
||||
return JS_FALSE;
|
||||
jsd_Constructing(jsdc, cx, JSVAL_TO_OBJECT(newObj), fp);
|
||||
jsd_Constructing(jsdc, cx, JSVAL_TO_OBJECT(newObj), frame);
|
||||
}
|
||||
|
||||
jsscript = JS_GetFrameScript(cx, fp);
|
||||
jsscript = frame.script();
|
||||
if (jsscript)
|
||||
{
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, jsscript, fp);
|
||||
jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, jsscript, frame);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
|
||||
if (jsdscript)
|
||||
|
@ -223,7 +223,7 @@ _callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
|
|||
}
|
||||
|
||||
#ifdef JSD_TRACE
|
||||
_interpreterTrace(jsdc, cx, fp, before);
|
||||
_interpreterTrace(jsdc, cx, frame, isConstructing, before);
|
||||
return JS_TRUE;
|
||||
#else
|
||||
return hookresult;
|
||||
|
@ -232,8 +232,8 @@ _callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
|
|||
}
|
||||
|
||||
void *
|
||||
jsd_FunctionCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
|
||||
JSBool *ok, void *closure)
|
||||
jsd_FunctionCallHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
|
||||
JSBool before, JSBool *ok, void *closure)
|
||||
{
|
||||
JSDContext* jsdc;
|
||||
JSD_CallHookProc hook;
|
||||
|
@ -247,7 +247,7 @@ jsd_FunctionCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
|
|||
hookData = jsdc->functionHookData;
|
||||
JSD_UNLOCK();
|
||||
|
||||
if (_callHook (jsdc, cx, fp, before,
|
||||
if (_callHook (jsdc, cx, frame, isConstructing, before,
|
||||
(before) ? JSD_HOOK_FUNCTION_CALL : JSD_HOOK_FUNCTION_RETURN,
|
||||
hook, hookData))
|
||||
{
|
||||
|
@ -258,8 +258,8 @@ jsd_FunctionCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
|
|||
}
|
||||
|
||||
void *
|
||||
jsd_TopLevelCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
|
||||
JSBool *ok, void *closure)
|
||||
jsd_TopLevelCallHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
|
||||
JSBool before, JSBool *ok, void *closure)
|
||||
{
|
||||
JSDContext* jsdc;
|
||||
JSD_CallHookProc hook;
|
||||
|
@ -273,7 +273,7 @@ jsd_TopLevelCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
|
|||
hookData = jsdc->toplevelHookData;
|
||||
JSD_UNLOCK();
|
||||
|
||||
if (_callHook (jsdc, cx, fp, before,
|
||||
if (_callHook (jsdc, cx, frame, isConstructing, before,
|
||||
(before) ? JSD_HOOK_TOPLEVEL_START : JSD_HOOK_TOPLEVEL_END,
|
||||
hook, hookData))
|
||||
{
|
||||
|
|
|
@ -13,12 +13,13 @@
|
|||
static int callCount[2] = {0, 0};
|
||||
|
||||
static void *
|
||||
callCountHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
|
||||
callCountHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, JSBool before,
|
||||
JSBool *ok, void *closure)
|
||||
{
|
||||
callCount[before]++;
|
||||
|
||||
jsval thisv;
|
||||
JS_GetFrameThis(cx, fp, &thisv); // assert if fp is incomplete
|
||||
frame.getThisValue(cx, &thisv); // assert if fp is incomplete
|
||||
|
||||
return cx; // any non-null value causes the hook to be called again after
|
||||
}
|
||||
|
@ -38,12 +39,13 @@ BEGIN_TEST(testDebugger_bug519719)
|
|||
END_TEST(testDebugger_bug519719)
|
||||
|
||||
static void *
|
||||
nonStrictThisHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
|
||||
nonStrictThisHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, JSBool before,
|
||||
JSBool *ok, void *closure)
|
||||
{
|
||||
if (before) {
|
||||
bool *allWrapped = (bool *) closure;
|
||||
js::RootedValue thisv(cx);
|
||||
JS_GetFrameThis(cx, fp, thisv.address());
|
||||
frame.getThisValue(cx, thisv.address());
|
||||
*allWrapped = *allWrapped && !JSVAL_IS_PRIMITIVE(thisv);
|
||||
}
|
||||
return NULL;
|
||||
|
@ -76,12 +78,13 @@ BEGIN_TEST(testDebugger_getThisNonStrict)
|
|||
END_TEST(testDebugger_getThisNonStrict)
|
||||
|
||||
static void *
|
||||
strictThisHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
|
||||
strictThisHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, JSBool before,
|
||||
JSBool *ok, void *closure)
|
||||
{
|
||||
if (before) {
|
||||
bool *anyWrapped = (bool *) closure;
|
||||
js::RootedValue thisv(cx);
|
||||
JS_GetFrameThis(cx, fp, thisv.address());
|
||||
frame.getThisValue(cx, thisv.address());
|
||||
*anyWrapped = *anyWrapped || !JSVAL_IS_PRIMITIVE(thisv);
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -71,6 +71,14 @@ JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug)
|
|||
rt->debugMode = !!debug;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsTopFrameConstructing(JSContext *cx, AbstractFramePtr frame)
|
||||
{
|
||||
ScriptFrameIter iter(cx);
|
||||
JS_ASSERT(iter.abstractFramePtr() == frame);
|
||||
return iter.isConstructing();
|
||||
}
|
||||
|
||||
JSTrapStatus
|
||||
js::ScriptDebugPrologue(JSContext *cx, AbstractFramePtr frame)
|
||||
{
|
||||
|
@ -78,12 +86,12 @@ js::ScriptDebugPrologue(JSContext *cx, AbstractFramePtr frame)
|
|||
|
||||
if (frame.isFramePushedByExecute()) {
|
||||
if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
|
||||
frame.setHookData(hook(cx, Jsvalify(frame.asStackFrame()), true, 0,
|
||||
cx->runtime->debugHooks.executeHookData));
|
||||
frame.setHookData(hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame),
|
||||
true, 0, cx->runtime->debugHooks.executeHookData));
|
||||
} else {
|
||||
if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
|
||||
frame.setHookData(hook(cx, Jsvalify(frame.asStackFrame()), true, 0,
|
||||
cx->runtime->debugHooks.callHookData));
|
||||
frame.setHookData(hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame),
|
||||
true, 0, cx->runtime->debugHooks.callHookData));
|
||||
}
|
||||
|
||||
RootedValue rval(cx);
|
||||
|
@ -115,10 +123,10 @@ js::ScriptDebugEpilogue(JSContext *cx, AbstractFramePtr frame, bool okArg)
|
|||
if (void *hookData = frame.maybeHookData()) {
|
||||
if (frame.isFramePushedByExecute()) {
|
||||
if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
|
||||
hook(cx, Jsvalify(frame.asStackFrame()), false, &ok, hookData);
|
||||
hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame), false, &ok, hookData);
|
||||
} else {
|
||||
if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
|
||||
hook(cx, Jsvalify(frame.asStackFrame()), false, &ok, hookData);
|
||||
hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame), false, &ok, hookData);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -537,103 +545,6 @@ JS_GetScriptOriginPrincipals(JSScript *script)
|
|||
|
||||
/************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(JSStackFrame *)
|
||||
JS_BrokenFrameIterator(JSContext *cx, JSStackFrame **iteratorp)
|
||||
{
|
||||
StackFrame *fp = Valueify(*iteratorp);
|
||||
if (!fp) {
|
||||
#ifdef JS_METHODJIT
|
||||
js::mjit::ExpandInlineFrames(cx->compartment);
|
||||
#endif
|
||||
fp = cx->maybefp();
|
||||
} else {
|
||||
fp = fp->prev();
|
||||
}
|
||||
|
||||
// settle on the next non-ion frame as it is not considered safe to inspect
|
||||
// Ion's activation StackFrame.
|
||||
while (fp && fp->runningInIon())
|
||||
fp = fp->prev();
|
||||
|
||||
*iteratorp = Jsvalify(fp);
|
||||
return *iteratorp;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFrameScript(JSContext *cx, JSStackFrame *fpArg)
|
||||
{
|
||||
return Valueify(fpArg)->script();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(jsbytecode *)
|
||||
JS_GetFramePC(JSContext *cx, JSStackFrame *fpArg)
|
||||
{
|
||||
/*
|
||||
* This API is used to compute the line number for jsd and XPConnect
|
||||
* exception handling backtraces. Once the stack gets really deep, the
|
||||
* overall cost can become quadratic. This can hang the browser (eventually
|
||||
* terminated by a slow-script dialog) when content causes infinite
|
||||
* recursion and a backtrace.
|
||||
*/
|
||||
return Valueify(fpArg)->pcQuadratic(cx->stack, 100);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fpArg)
|
||||
{
|
||||
StackFrame *fp = Valueify(fpArg);
|
||||
JS_ASSERT(cx->stack.space().containsSlow(fp));
|
||||
AutoCompartment ac(cx, fp->scopeChain());
|
||||
return GetDebugScopeForFrame(cx, fp);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fpArg)
|
||||
{
|
||||
StackFrame *fp = Valueify(fpArg);
|
||||
JS_ASSERT(cx->stack.space().containsSlow(fp));
|
||||
|
||||
if (!fp->isFunctionFrame())
|
||||
return NULL;
|
||||
|
||||
JSObject *o = GetDebugScopeForFrame(cx, fp);
|
||||
|
||||
/*
|
||||
* Given that fp is a function frame and GetDebugScopeForFrame always fills
|
||||
* in missing scopes, we can expect to find fp's CallObject on 'o'. Note:
|
||||
* - GetDebugScopeForFrame wraps every ScopeObject (missing or not) with
|
||||
* a DebugScopeObject proxy.
|
||||
* - If fp is an eval-in-function, then fp has no callobj of its own and
|
||||
* JS_GetFrameCallObject will return the innermost function's callobj.
|
||||
*/
|
||||
while (o) {
|
||||
ScopeObject &scope = o->asDebugScope().scope();
|
||||
if (scope.isCall())
|
||||
return o;
|
||||
o = o->enclosingScope();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_GetFrameThis(JSContext *cx, JSStackFrame *fpArg, jsval *thisv)
|
||||
{
|
||||
StackFrame *fp = Valueify(fpArg);
|
||||
|
||||
js::AutoCompartment ac(cx, fp->scopeChain());
|
||||
if (!ComputeThis(cx, fp))
|
||||
return false;
|
||||
|
||||
*thisv = fp->thisValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFunction *)
|
||||
JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return Valueify(fp)->maybeScriptFunction();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFunction *)
|
||||
JS_GetScriptFunction(JSContext *cx, JSScript *script)
|
||||
{
|
||||
|
@ -646,12 +557,6 @@ JS_GetParentOrScopeChain(JSContext *cx, JSObject *obj)
|
|||
return obj->enclosingScope();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return Valueify(fp)->isConstructing();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(const char *)
|
||||
JS_GetDebugClassName(JSObject *obj)
|
||||
{
|
||||
|
@ -660,18 +565,6 @@ JS_GetDebugClassName(JSObject *obj)
|
|||
return obj->getClass()->name;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return Valueify(fp)->isDebuggerFrame();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_IsGlobalFrame(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return Valueify(fp)->isGlobalFrame();
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(const char *)
|
||||
|
@ -737,56 +630,6 @@ JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
|
|||
|
||||
/***************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fpArg,
|
||||
const jschar *chars, unsigned length,
|
||||
const char *filename, unsigned lineno,
|
||||
jsval *rval)
|
||||
{
|
||||
if (!CheckDebugMode(cx))
|
||||
return false;
|
||||
|
||||
Rooted<Env*> env(cx, JS_GetFrameScopeChain(cx, fpArg));
|
||||
if (!env)
|
||||
return false;
|
||||
|
||||
StackFrame *fp = Valueify(fpArg);
|
||||
|
||||
if (!ComputeThis(cx, fp))
|
||||
return false;
|
||||
RootedValue thisv(cx, fp->thisValue());
|
||||
|
||||
js::AutoCompartment ac(cx, env);
|
||||
return EvaluateInEnv(cx, env, thisv, fp, StableCharPtr(chars, length), length,
|
||||
filename, lineno, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
|
||||
const char *bytes, unsigned length,
|
||||
const char *filename, unsigned lineno,
|
||||
jsval *rval)
|
||||
{
|
||||
jschar *chars;
|
||||
JSBool ok;
|
||||
size_t len = length;
|
||||
|
||||
if (!CheckDebugMode(cx))
|
||||
return JS_FALSE;
|
||||
|
||||
chars = InflateString(cx, bytes, &len);
|
||||
if (!chars)
|
||||
return JS_FALSE;
|
||||
length = (unsigned) len;
|
||||
ok = JS_EvaluateUCInStackFrame(cx, fp, chars, length, filename, lineno,
|
||||
rval);
|
||||
js_free(chars);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* This all should be reworked to avoid requiring JSScopeProperty types. */
|
||||
|
||||
static JSBool
|
||||
|
@ -1293,7 +1136,8 @@ FormatFrame(JSContext *cx, const ScriptFrameIter &iter, char *buf, int num,
|
|||
AutoPropertyDescArray callProps(cx);
|
||||
|
||||
if (!iter.isIon() && (showArgs || showLocals)) {
|
||||
callObj = JS_GetFrameCallObject(cx, Jsvalify(iter.interpFrame()));
|
||||
JSAbstractFramePtr frame(Jsvalify(iter.abstractFramePtr()));
|
||||
callObj = frame.callObject(cx);
|
||||
if (callObj)
|
||||
callProps.fetch(callObj);
|
||||
}
|
||||
|
@ -1461,3 +1305,175 @@ JS::FormatStackDump(JSContext *cx, char *buf,
|
|||
return buf;
|
||||
}
|
||||
|
||||
JSAbstractFramePtr::JSAbstractFramePtr(void *raw)
|
||||
: ptr_(uintptr_t(raw))
|
||||
{ }
|
||||
|
||||
JSObject *
|
||||
JSAbstractFramePtr::scopeChain(JSContext *cx)
|
||||
{
|
||||
AbstractFramePtr frame = Valueify(*this);
|
||||
JS_ASSERT_IF(frame.isStackFrame(),
|
||||
cx->stack.space().containsSlow(frame.asStackFrame()));
|
||||
RootedObject scopeChain(cx, frame.scopeChain());
|
||||
AutoCompartment ac(cx, scopeChain);
|
||||
return GetDebugScopeForFrame(cx, frame);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
JSAbstractFramePtr::callObject(JSContext *cx)
|
||||
{
|
||||
AbstractFramePtr frame = Valueify(*this);
|
||||
JS_ASSERT_IF(frame.isStackFrame(),
|
||||
cx->stack.space().containsSlow(frame.asStackFrame()));
|
||||
|
||||
if (!frame.isFunctionFrame())
|
||||
return NULL;
|
||||
|
||||
JSObject *o = GetDebugScopeForFrame(cx, frame);
|
||||
|
||||
/*
|
||||
* Given that fp is a function frame and GetDebugScopeForFrame always fills
|
||||
* in missing scopes, we can expect to find fp's CallObject on 'o'. Note:
|
||||
* - GetDebugScopeForFrame wraps every ScopeObject (missing or not) with
|
||||
* a DebugScopeObject proxy.
|
||||
* - If fp is an eval-in-function, then fp has no callobj of its own and
|
||||
* JS_GetFrameCallObject will return the innermost function's callobj.
|
||||
*/
|
||||
while (o) {
|
||||
ScopeObject &scope = o->asDebugScope().scope();
|
||||
if (scope.isCall())
|
||||
return o;
|
||||
o = o->enclosingScope();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSFunction *
|
||||
JSAbstractFramePtr::maybeFun()
|
||||
{
|
||||
AbstractFramePtr frame = Valueify(*this);
|
||||
return frame.maybeFun();
|
||||
}
|
||||
|
||||
JSScript *
|
||||
JSAbstractFramePtr::script()
|
||||
{
|
||||
AbstractFramePtr frame = Valueify(*this);
|
||||
return frame.script();
|
||||
}
|
||||
|
||||
bool
|
||||
JSAbstractFramePtr::getThisValue(JSContext *cx, jsval *thisv)
|
||||
{
|
||||
AbstractFramePtr frame = Valueify(*this);
|
||||
|
||||
RootedObject scopeChain(cx, frame.scopeChain());
|
||||
js::AutoCompartment ac(cx, scopeChain);
|
||||
if (!ComputeThis(cx, frame))
|
||||
return false;
|
||||
|
||||
*thisv = frame.thisValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSAbstractFramePtr::isDebuggerFrame()
|
||||
{
|
||||
AbstractFramePtr frame = Valueify(*this);
|
||||
return frame.isDebuggerFrame();
|
||||
}
|
||||
|
||||
bool
|
||||
JSAbstractFramePtr::evaluateInStackFrame(JSContext *cx,
|
||||
const char *bytes, unsigned length,
|
||||
const char *filename, unsigned lineno,
|
||||
jsval *rval)
|
||||
{
|
||||
if (!CheckDebugMode(cx))
|
||||
return false;
|
||||
|
||||
size_t len = length;
|
||||
jschar *chars = InflateString(cx, bytes, &len);
|
||||
if (!chars)
|
||||
return false;
|
||||
length = (unsigned) len;
|
||||
|
||||
bool ok = evaluateUCInStackFrame(cx, chars, length, filename, lineno, rval);
|
||||
js_free(chars);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool
|
||||
JSAbstractFramePtr::evaluateUCInStackFrame(JSContext *cx,
|
||||
const jschar *chars, unsigned length,
|
||||
const char *filename, unsigned lineno,
|
||||
jsval *rval)
|
||||
{
|
||||
if (!CheckDebugMode(cx))
|
||||
return false;
|
||||
|
||||
RootedObject scope(cx, scopeChain(cx));
|
||||
Rooted<Env*> env(cx, scope);
|
||||
if (!env)
|
||||
return false;
|
||||
|
||||
AbstractFramePtr frame = Valueify(*this);
|
||||
if (!ComputeThis(cx, frame))
|
||||
return false;
|
||||
RootedValue thisv(cx, frame.thisValue());
|
||||
|
||||
js::AutoCompartment ac(cx, env);
|
||||
return EvaluateInEnv(cx, env, thisv, frame, StableCharPtr(chars, length), length,
|
||||
filename, lineno, rval);
|
||||
}
|
||||
|
||||
JSBrokenFrameIterator::JSBrokenFrameIterator(JSContext *cx)
|
||||
{
|
||||
ScriptFrameIter iter(cx);
|
||||
data_ = iter.copyData();
|
||||
}
|
||||
|
||||
JSBrokenFrameIterator::~JSBrokenFrameIterator()
|
||||
{
|
||||
js_free((StackIter::Data *)data_);
|
||||
}
|
||||
|
||||
bool
|
||||
JSBrokenFrameIterator::done() const
|
||||
{
|
||||
ScriptFrameIter iter(*(StackIter::Data *)data_);
|
||||
return iter.done();
|
||||
}
|
||||
|
||||
JSBrokenFrameIterator &
|
||||
JSBrokenFrameIterator::operator++()
|
||||
{
|
||||
StackIter::Data *data = (StackIter::Data *)data_;
|
||||
ScriptFrameIter iter(*data);
|
||||
++iter;
|
||||
*data = iter.data_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSAbstractFramePtr
|
||||
JSBrokenFrameIterator::abstractFramePtr() const
|
||||
{
|
||||
ScriptFrameIter iter(*(StackIter::Data *)data_);
|
||||
return Jsvalify(iter.abstractFramePtr());
|
||||
}
|
||||
|
||||
jsbytecode *
|
||||
JSBrokenFrameIterator::pc() const
|
||||
{
|
||||
ScriptFrameIter iter(*(StackIter::Data *)data_);
|
||||
return iter.pc();
|
||||
}
|
||||
|
||||
bool
|
||||
JSBrokenFrameIterator::isConstructing() const
|
||||
{
|
||||
ScriptFrameIter iter(*(StackIter::Data *)data_);
|
||||
return iter.isConstructing();
|
||||
}
|
||||
|
|
|
@ -191,53 +191,12 @@ JS_GetScriptPrincipals(JSScript *script);
|
|||
extern JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_GetScriptOriginPrincipals(JSScript *script);
|
||||
|
||||
/*
|
||||
* This function does not work when IonMonkey is active. It remains for legacy
|
||||
* code: caps/principal clamping, which will be removed shortly after
|
||||
* compartment-per-global, and jsd, which can only be used when IonMonkey is
|
||||
* disabled.
|
||||
*
|
||||
* To find the calling script and line number, use JS_DescribeSciptedCaller.
|
||||
* To summarize the call stack, use JS::DescribeStack.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSStackFrame *)
|
||||
JS_BrokenFrameIterator(JSContext *cx, JSStackFrame **iteratorp);
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFrameScript(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(jsbytecode *)
|
||||
JS_GetFramePC(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp, jsval *thisv);
|
||||
|
||||
extern JS_PUBLIC_API(JSFunction *)
|
||||
JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
JS_PUBLIC_API(JSFunction *)
|
||||
JS_GetScriptFunction(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetParentOrScopeChain(JSContext *cx, JSObject *obj);
|
||||
|
||||
/* XXXrginda Initially published with typo */
|
||||
#define JS_IsContructorFrame JS_IsConstructorFrame
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsGlobalFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
|
@ -291,20 +250,6 @@ JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
|
|||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
|
||||
const jschar *chars, unsigned length,
|
||||
const char *filename, unsigned lineno,
|
||||
jsval *rval);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
|
||||
const char *bytes, unsigned length,
|
||||
const char *filename, unsigned lineno,
|
||||
jsval *rval);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
typedef struct JSPropertyDesc {
|
||||
jsval id; /* primary id, atomized string, or int */
|
||||
jsval value; /* property value */
|
||||
|
@ -337,6 +282,135 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
|
|||
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
* JSAbstractFramePtr is the public version of AbstractFramePtr, a pointer to a
|
||||
* StackFrame or baseline JIT frame.
|
||||
*/
|
||||
class JS_PUBLIC_API(JSAbstractFramePtr)
|
||||
{
|
||||
uintptr_t ptr_;
|
||||
|
||||
protected:
|
||||
JSAbstractFramePtr()
|
||||
: ptr_(0)
|
||||
{ }
|
||||
|
||||
public:
|
||||
explicit JSAbstractFramePtr(void *raw);
|
||||
|
||||
uintptr_t raw() const { return ptr_; }
|
||||
|
||||
operator bool() const { return !!ptr_; }
|
||||
|
||||
JSObject *scopeChain(JSContext *cx);
|
||||
JSObject *callObject(JSContext *cx);
|
||||
|
||||
JSFunction *maybeFun();
|
||||
JSScript *script();
|
||||
|
||||
bool getThisValue(JSContext *cx, jsval *thisv);
|
||||
|
||||
bool isDebuggerFrame();
|
||||
|
||||
bool evaluateInStackFrame(JSContext *cx,
|
||||
const char *bytes, unsigned length,
|
||||
const char *filename, unsigned lineno,
|
||||
jsval *rval);
|
||||
|
||||
bool evaluateUCInStackFrame(JSContext *cx,
|
||||
const jschar *chars, unsigned length,
|
||||
const char *filename, unsigned lineno,
|
||||
jsval *rval);
|
||||
};
|
||||
|
||||
class JS_PUBLIC_API(JSNullFramePtr) : public JSAbstractFramePtr
|
||||
{
|
||||
public:
|
||||
JSNullFramePtr()
|
||||
: JSAbstractFramePtr()
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* This class does not work when IonMonkey is active. It's only used by jsd,
|
||||
* which can only be used when IonMonkey is disabled.
|
||||
*
|
||||
* To find the calling script and line number, use JS_DescribeSciptedCaller.
|
||||
* To summarize the call stack, use JS::DescribeStack.
|
||||
*/
|
||||
class JS_PUBLIC_API(JSBrokenFrameIterator)
|
||||
{
|
||||
void *data_;
|
||||
|
||||
public:
|
||||
JSBrokenFrameIterator(JSContext *cx);
|
||||
~JSBrokenFrameIterator();
|
||||
|
||||
bool done() const;
|
||||
JSBrokenFrameIterator& operator++();
|
||||
|
||||
JSAbstractFramePtr abstractFramePtr() const;
|
||||
jsbytecode *pc() const;
|
||||
|
||||
bool isConstructing() const;
|
||||
};
|
||||
|
||||
/*
|
||||
* This hook captures high level script execution and function calls (JS or
|
||||
* native). It is used by JS_SetExecuteHook to hook top level scripts and by
|
||||
* JS_SetCallHook to hook function calls. It will get called twice per script
|
||||
* or function call: just before execution begins and just after it finishes.
|
||||
* In both cases the 'current' frame is that of the executing code.
|
||||
*
|
||||
* The 'before' param is JS_TRUE for the hook invocation before the execution
|
||||
* and JS_FALSE for the invocation after the code has run.
|
||||
*
|
||||
* The 'ok' param is significant only on the post execution invocation to
|
||||
* signify whether or not the code completed 'normally'.
|
||||
*
|
||||
* The 'closure' param is as passed to JS_SetExecuteHook or JS_SetCallHook
|
||||
* for the 'before'invocation, but is whatever value is returned from that
|
||||
* invocation for the 'after' invocation. Thus, the hook implementor *could*
|
||||
* allocate a structure in the 'before' invocation and return a pointer to that
|
||||
* structure. The pointer would then be handed to the hook for the 'after'
|
||||
* invocation. Alternately, the 'before' could just return the same value as
|
||||
* in 'closure' to cause the 'after' invocation to be called with the same
|
||||
* 'closure' value as the 'before'.
|
||||
*
|
||||
* Returning NULL in the 'before' hook will cause the 'after' hook *not* to
|
||||
* be called.
|
||||
*/
|
||||
typedef void *
|
||||
(* JSInterpreterHook)(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
|
||||
JSBool before, JSBool *ok, void *closure);
|
||||
|
||||
typedef JSBool
|
||||
(* JSDebugErrorHook)(JSContext *cx, const char *message, JSErrorReport *report,
|
||||
void *closure);
|
||||
|
||||
typedef struct JSDebugHooks {
|
||||
JSInterruptHook interruptHook;
|
||||
void *interruptHookData;
|
||||
JSNewScriptHook newScriptHook;
|
||||
void *newScriptHookData;
|
||||
JSDestroyScriptHook destroyScriptHook;
|
||||
void *destroyScriptHookData;
|
||||
JSDebuggerHandler debuggerHandler;
|
||||
void *debuggerHandlerData;
|
||||
JSSourceHandler sourceHandler;
|
||||
void *sourceHandlerData;
|
||||
JSInterpreterHook executeHook;
|
||||
void *executeHookData;
|
||||
JSInterpreterHook callHook;
|
||||
void *callHookData;
|
||||
JSThrowHook throwHook;
|
||||
void *throwHookData;
|
||||
JSDebugErrorHook debugErrorHook;
|
||||
void *debugErrorHookData;
|
||||
} JSDebugHooks;
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler hook, void *closure);
|
||||
|
||||
|
|
|
@ -283,60 +283,6 @@ typedef void
|
|||
(* JSSourceHandler)(const char *filename, unsigned lineno, const jschar *str,
|
||||
size_t length, void **listenerTSData, void *closure);
|
||||
|
||||
/*
|
||||
* This hook captures high level script execution and function calls (JS or
|
||||
* native). It is used by JS_SetExecuteHook to hook top level scripts and by
|
||||
* JS_SetCallHook to hook function calls. It will get called twice per script
|
||||
* or function call: just before execution begins and just after it finishes.
|
||||
* In both cases the 'current' frame is that of the executing code.
|
||||
*
|
||||
* The 'before' param is JS_TRUE for the hook invocation before the execution
|
||||
* and JS_FALSE for the invocation after the code has run.
|
||||
*
|
||||
* The 'ok' param is significant only on the post execution invocation to
|
||||
* signify whether or not the code completed 'normally'.
|
||||
*
|
||||
* The 'closure' param is as passed to JS_SetExecuteHook or JS_SetCallHook
|
||||
* for the 'before'invocation, but is whatever value is returned from that
|
||||
* invocation for the 'after' invocation. Thus, the hook implementor *could*
|
||||
* allocate a structure in the 'before' invocation and return a pointer to that
|
||||
* structure. The pointer would then be handed to the hook for the 'after'
|
||||
* invocation. Alternately, the 'before' could just return the same value as
|
||||
* in 'closure' to cause the 'after' invocation to be called with the same
|
||||
* 'closure' value as the 'before'.
|
||||
*
|
||||
* Returning NULL in the 'before' hook will cause the 'after' hook *not* to
|
||||
* be called.
|
||||
*/
|
||||
typedef void *
|
||||
(* JSInterpreterHook)(JSContext *cx, JSStackFrame *fp, JSBool before,
|
||||
JSBool *ok, void *closure);
|
||||
|
||||
typedef JSBool
|
||||
(* JSDebugErrorHook)(JSContext *cx, const char *message, JSErrorReport *report,
|
||||
void *closure);
|
||||
|
||||
typedef struct JSDebugHooks {
|
||||
JSInterruptHook interruptHook;
|
||||
void *interruptHookData;
|
||||
JSNewScriptHook newScriptHook;
|
||||
void *newScriptHookData;
|
||||
JSDestroyScriptHook destroyScriptHook;
|
||||
void *destroyScriptHookData;
|
||||
JSDebuggerHandler debuggerHandler;
|
||||
void *debuggerHandlerData;
|
||||
JSSourceHandler sourceHandler;
|
||||
void *sourceHandlerData;
|
||||
JSInterpreterHook executeHook;
|
||||
void *executeHookData;
|
||||
JSInterpreterHook callHook;
|
||||
void *callHookData;
|
||||
JSThrowHook throwHook;
|
||||
void *throwHookData;
|
||||
JSDebugErrorHook debugErrorHook;
|
||||
void *debugErrorHookData;
|
||||
} JSDebugHooks;
|
||||
|
||||
/* js::ObjectOps function pointer typedefs. */
|
||||
|
||||
/*
|
||||
|
|
|
@ -181,7 +181,6 @@ typedef struct JSPropertyName JSPropertyName;
|
|||
typedef struct JSPropertySpec JSPropertySpec;
|
||||
typedef struct JSRuntime JSRuntime;
|
||||
typedef struct JSSecurityCallbacks JSSecurityCallbacks;
|
||||
typedef struct JSStackFrame JSStackFrame;
|
||||
typedef struct JSStructuredCloneCallbacks JSStructuredCloneCallbacks;
|
||||
typedef struct JSStructuredCloneReader JSStructuredCloneReader;
|
||||
typedef struct JSStructuredCloneWriter JSStructuredCloneWriter;
|
||||
|
|
|
@ -1539,7 +1539,7 @@ TrapHandler(JSContext *cx, RawScript, jsbytecode *pc, jsval *rval,
|
|||
JS_ASSERT(!iter.done());
|
||||
|
||||
/* Debug-mode currently disables Ion compilation. */
|
||||
JSStackFrame *caller = Jsvalify(iter.interpFrame());
|
||||
JSAbstractFramePtr frame(Jsvalify(iter.abstractFramePtr()));
|
||||
RootedScript script(cx, iter.script());
|
||||
|
||||
size_t length;
|
||||
|
@ -1547,10 +1547,11 @@ TrapHandler(JSContext *cx, RawScript, jsbytecode *pc, jsval *rval,
|
|||
if (!chars)
|
||||
return JSTRAP_ERROR;
|
||||
|
||||
if (!JS_EvaluateUCInStackFrame(cx, caller, chars, length,
|
||||
script->filename,
|
||||
script->lineno,
|
||||
rval)) {
|
||||
if (!frame.evaluateUCInStackFrame(cx, chars, length,
|
||||
script->filename,
|
||||
script->lineno,
|
||||
rval))
|
||||
{
|
||||
return JSTRAP_ERROR;
|
||||
}
|
||||
if (!JSVAL_IS_VOID(*rval))
|
||||
|
@ -2635,13 +2636,13 @@ EvalInFrame(JSContext *cx, unsigned argc, jsval *vp)
|
|||
if (!chars)
|
||||
return false;
|
||||
|
||||
StackFrame *fp = fi.interpFrame();
|
||||
RootedScript fpscript(cx, fp->script());
|
||||
bool ok = !!JS_EvaluateUCInStackFrame(cx, Jsvalify(fp), chars, length,
|
||||
fpscript->filename,
|
||||
JS_PCToLineNumber(cx, fpscript,
|
||||
fi.pc()),
|
||||
vp);
|
||||
JSAbstractFramePtr frame(Jsvalify(fi.abstractFramePtr()));
|
||||
RootedScript fpscript(cx, frame.script());
|
||||
bool ok = !!frame.evaluateUCInStackFrame(cx, chars, length,
|
||||
fpscript->filename,
|
||||
JS_PCToLineNumber(cx, fpscript,
|
||||
fi.pc()),
|
||||
vp);
|
||||
|
||||
if (saved)
|
||||
JS_RestoreFrameChain(cx);
|
||||
|
|
|
@ -795,6 +795,14 @@ AbstractFramePtr::fun() const
|
|||
JS_NOT_REACHED("Invalid frame");
|
||||
return NULL;
|
||||
}
|
||||
inline JSFunction *
|
||||
AbstractFramePtr::maybeFun() const
|
||||
{
|
||||
if (isStackFrame())
|
||||
return asStackFrame()->maybeFun();
|
||||
JS_NOT_REACHED("Invalid frame");
|
||||
return NULL;
|
||||
}
|
||||
inline JSFunction &
|
||||
AbstractFramePtr::callee() const
|
||||
{
|
||||
|
|
|
@ -238,6 +238,11 @@ class AbstractFramePtr
|
|||
JS_ASSERT((uintptr_t(fp) & 1) == 0);
|
||||
}
|
||||
|
||||
explicit AbstractFramePtr(JSAbstractFramePtr frame)
|
||||
: ptr_(uintptr_t(frame.raw()))
|
||||
{
|
||||
}
|
||||
|
||||
bool isStackFrame() const {
|
||||
return ptr_ & 0x1;
|
||||
}
|
||||
|
@ -274,6 +279,7 @@ class AbstractFramePtr
|
|||
|
||||
inline UnrootedScript script() const;
|
||||
inline JSFunction *fun() const;
|
||||
inline JSFunction *maybeFun() const;
|
||||
inline JSFunction &callee() const;
|
||||
inline Value calleev() const;
|
||||
inline Value &thisValue() const;
|
||||
|
@ -761,7 +767,7 @@ class StackFrame
|
|||
* All function frames have an associated interpreted JSFunction. The
|
||||
* function returned by fun() and maybeFun() is not necessarily the
|
||||
* original canonical function which the frame's script was compiled
|
||||
* against. To get this function, use maybeScriptFunction().
|
||||
* against.
|
||||
*/
|
||||
|
||||
JSFunction* fun() const {
|
||||
|
@ -773,15 +779,6 @@ class StackFrame
|
|||
return isFunctionFrame() ? fun() : NULL;
|
||||
}
|
||||
|
||||
JSFunction* maybeScriptFunction() const {
|
||||
if (!isFunctionFrame())
|
||||
return NULL;
|
||||
const StackFrame *fp = this;
|
||||
while (fp->isEvalFrame())
|
||||
fp = fp->prev();
|
||||
return fp->script()->function();
|
||||
}
|
||||
|
||||
/*
|
||||
* This value
|
||||
*
|
||||
|
@ -1222,8 +1219,8 @@ InitialFrameFlagsAreLowered(InitialFrameFlags initial)
|
|||
return !!(initial & INITIAL_LOWERED);
|
||||
}
|
||||
|
||||
inline StackFrame * Valueify(JSStackFrame *fp) { return (StackFrame *)fp; }
|
||||
static inline JSStackFrame * Jsvalify(StackFrame *fp) { return (JSStackFrame *)fp; }
|
||||
inline AbstractFramePtr Valueify(JSAbstractFramePtr frame) { return AbstractFramePtr(frame); }
|
||||
static inline JSAbstractFramePtr Jsvalify(AbstractFramePtr frame) { return JSAbstractFramePtr(frame.raw()); }
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
@ -1879,6 +1876,7 @@ class StackIter
|
|||
};
|
||||
|
||||
friend class ContextStack;
|
||||
friend class ::JSBrokenFrameIterator;
|
||||
private:
|
||||
Data data_;
|
||||
#ifdef JS_ION
|
||||
|
|
|
@ -71,10 +71,6 @@ xpcDumpEvalErrorReporter(JSContext *cx, const char *message,
|
|||
JSBool
|
||||
xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text)
|
||||
{
|
||||
JSStackFrame* fp;
|
||||
JSStackFrame* iter = nullptr;
|
||||
uint32_t num = 0;
|
||||
|
||||
if (!cx || !text) {
|
||||
DebugDump("%s", "invalid params passed to xpc_DumpEvalInJSStackFrame!\n");
|
||||
return false;
|
||||
|
@ -82,13 +78,21 @@ xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text)
|
|||
|
||||
DebugDump("js[%d]> %s\n", frameno, text);
|
||||
|
||||
while (nullptr != (fp = JS_BrokenFrameIterator(cx, &iter))) {
|
||||
if (num == frameno)
|
||||
uint32_t num = 0;
|
||||
|
||||
JSAbstractFramePtr frame = JSNullFramePtr();
|
||||
|
||||
JSBrokenFrameIterator iter(cx);
|
||||
while (!iter.done()) {
|
||||
if (num == frameno) {
|
||||
frame = iter.abstractFramePtr();
|
||||
break;
|
||||
}
|
||||
++iter;
|
||||
num++;
|
||||
}
|
||||
|
||||
if (!fp) {
|
||||
if (!frame) {
|
||||
DebugDump("%s", "invalid frame number!\n");
|
||||
return false;
|
||||
}
|
||||
|
@ -101,7 +105,7 @@ xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text)
|
|||
jsval rval;
|
||||
JSString* str;
|
||||
JSAutoByteString bytes;
|
||||
if (JS_EvaluateInStackFrame(cx, fp, text, strlen(text), "eval", 1, &rval) &&
|
||||
if (frame.evaluateInStackFrame(cx, text, strlen(text), "eval", 1, &rval) &&
|
||||
nullptr != (str = JS_ValueToString(cx, rval)) &&
|
||||
bytes.encode(cx, str)) {
|
||||
DebugDump("%s\n", bytes.ptr());
|
||||
|
|
Загрузка…
Ссылка в новой задаче