Example #1
0
void CThreadDebugger::SaveStackFrameData(STACK_INFO stackInfo, uint nestingLevel)
{
	ENSURE(GetIsInBreak());
	
	CScopeLock lock(m->m_Mutex);
	JSStackFrame *fp;
	JSStackFrame *iter = 0;
	uint counter = 0;
	jsval val;
	
	if (stackInfo == STACK_INFO_GLOBALOBJECT)
	{
		JSObject* obj;
		obj = JS_GetGlobalForScopeChain(m->m_pScriptInterface->GetContext());
		m->m_StackFrameData[stackInfo][nestingLevel] = StringifyCyclicJSON(OBJECT_TO_JSVAL(obj), false);
	}
	else
	{
		fp = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
		while (fp)
		{
			if (counter == nestingLevel)
			{
				if (stackInfo == STACK_INFO_LOCALS)
				{
					JSObject* obj;
					obj = JS_GetFrameCallObject(m->m_pScriptInterface->GetContext(), fp);
					//obj = JS_GetFrameScopeChain(m->m_pScriptInterface->GetContext(), fp);
					m->m_StackFrameData[stackInfo][nestingLevel] = StringifyCyclicJSON(OBJECT_TO_JSVAL(obj), false);
				}
				else if (stackInfo == STACK_INFO_THIS)
				{
					if (JS_GetFrameThis(m->m_pScriptInterface->GetContext(), fp, &val))
						m->m_StackFrameData[stackInfo][nestingLevel] = StringifyCyclicJSON(val, false);
					else
						m->m_StackFrameData[stackInfo][nestingLevel] = "";
				}
			}
			
			counter++;
			fp = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
		}
	}
}
Example #2
0
JSDValue*
jsd_GetCallObjectForStackFrame(JSDContext* jsdc, 
                               JSDThreadState* jsdthreadstate,
                               JSDStackFrameInfo* jsdframe)
{
    JSObject* obj;
    JSDValue* jsdval = NULL;

    JSD_LOCK_THREADSTATES(jsdc);

    if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
    {
        obj = JS_GetFrameCallObject(jsdthreadstate->context, jsdframe->fp); 
        if(obj)                                                             
            jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));              
    }

    JSD_UNLOCK_THREADSTATES(jsdc);

    return jsdval;
}
Example #3
0
static void
format_frame(JSContext* cx, JSStackFrame* fp,
             GString *buf, int num)
{
    JSPropertyDescArray call_props = { 0, NULL };
    JSObject* call_obj = NULL;
    char* funname_str = NULL;
    const char* filename = NULL;
    guint32 lineno = 0;
    guint32 named_arg_count = 0;
    JSFunction* fun = NULL;
    JSScript* script;
    guchar* pc;
    guint32 i;
    gboolean is_string;
    jsval val;

    (void)JS_EnterLocalRootScope(cx);

    if (!JS_IsScriptFrame(cx, fp)) {
        g_string_append_printf(buf, "%d [native frame]\n", num);
        goto out;
    }

    /* get the info for this stack frame */

    script = JS_GetFrameScript(cx, fp);
    pc = JS_GetFramePC(cx, fp);

    if (script && pc) {
        filename = JS_GetScriptFilename(cx, script);
        lineno =  (guint32) JS_PCToLineNumber(cx, script, pc);
        fun = JS_GetFrameFunction(cx, fp);
        if (fun) {
	    JSString* funname = JS_GetFunctionId(fun);
            if (funname)
                funname_str = gjs_string_get_ascii(cx, STRING_TO_JSVAL(funname));
	}

        call_obj = JS_GetFrameCallObject(cx, fp);
        if (call_obj) {
            if (!JS_GetPropertyDescArray(cx, call_obj, &call_props))
                call_props.array = NULL;
        }

    }

    /* print the frame number and function name */

    if (funname_str) {
        g_string_append_printf(buf, "%d %s(", num, funname_str);
        g_free(funname_str);
    }
    else if (fun)
        g_string_append_printf(buf, "%d anonymous(", num);
    else
        g_string_append_printf(buf, "%d <TOP LEVEL>", num);

    for (i = 0; i < call_props.length; i++) {
        char *name = NULL;
        char *value = NULL;
        JSPropertyDesc* desc = &call_props.array[i];
        if(desc->flags & JSPD_ARGUMENT) {
            name = jsvalue_to_string(cx, desc->id, &is_string);
            if(!is_string) {
                g_free(name);
                name = NULL;
            }
            value = jsvalue_to_string(cx, desc->value, &is_string);

            g_string_append_printf(buf, "%s%s%s%s%s%s",
                                   named_arg_count ? ", " : "",
                                   name ? name :"",
                                   name ? " = " : "",
                                   is_string ? "\"" : "",
                                   value ? value : "?unknown?",
                                   is_string ? "\"" : "");
            named_arg_count++;
        }
        g_free(name);
        g_free(value);
    }

    /* print any unnamed trailing args (found in 'arguments' object) */

    if (call_obj != NULL &&
        JS_GetProperty(cx, call_obj, "arguments", &val) &&
        JSVAL_IS_OBJECT(val)) {
        guint32 k;
        guint32 arg_count;
        JSObject* args_obj = JSVAL_TO_OBJECT(val);
        if (JS_GetArrayLength(cx, args_obj, &arg_count) &&
            arg_count > named_arg_count) {
            for (k = named_arg_count; k < arg_count; k++) {
                if (JS_GetElement(cx, args_obj, k, &val)) {
                    char *value = jsvalue_to_string(cx, val, &is_string);
                    g_string_append_printf(buf, "%s%s%s%s",
                                           k ? ", " : "",
                                           is_string ? "\"" : "",
                                           value ? value : "?unknown?",
                                           is_string ? "\"" : "");
                    g_free(value);
                }
            }
        }
    }

    /* print filename and line number */

    g_string_append_printf(buf, "%s@%s:%d\n",
                           fun ? ")" : "",
                           filename ? filename : "",
                           lineno);

  out:
    if (call_props.array)
      JS_PutPropertyDescArray(cx, &call_props);

    JS_LeaveLocalRootScope(cx);
}
Example #4
0
static char* FormatJSFrame(JSContext* cx, JSStackFrame* fp,
                           char* buf, int num,
                           JSBool showArgs, JSBool showLocals, JSBool showThisProps)
{
    JSPropertyDescArray callProps = {0, nsnull};
    JSPropertyDescArray thisProps = {0, nsnull};
    JSBool gotThisVal = JS_FALSE;
    jsval thisVal;
    JSObject* callObj = nsnull;
    JSString* funname = nsnull;
    JSAutoByteString funbytes;
    const char* filename = nsnull;
    PRInt32 lineno = 0;
    JSFunction* fun = nsnull;
    uint32 namedArgCount = 0;
    jsval val;
    JSBool isString;

    // get the info for this stack frame

    JSScript* script = JS_GetFrameScript(cx, fp);
    jsbytecode* pc = JS_GetFramePC(cx, fp);

    JSAutoRequest ar(cx);
    JSAutoEnterCompartment ac;
    if(!ac.enter(cx, JS_GetFrameScopeChain(cx, fp)))
        return buf;

    if(script && pc)
    {
        filename = JS_GetScriptFilename(cx, script);
        lineno =  (PRInt32) JS_PCToLineNumber(cx, script, pc);
        fun = JS_GetFrameFunction(cx, fp);
        if(fun)
            funname = JS_GetFunctionId(fun);

        if(showArgs || showLocals)
        {
            callObj = JS_GetFrameCallObject(cx, fp);
            if(callObj)
                if(!JS_GetPropertyDescArray(cx, callObj, &callProps))
                    callProps.array = nsnull;  // just to be sure
        }

        gotThisVal = JS_GetFrameThis(cx, fp, &thisVal);
        if (!gotThisVal ||
            !showThisProps ||
            JSVAL_IS_PRIMITIVE(thisVal) ||
            !JS_GetPropertyDescArray(cx, JSVAL_TO_OBJECT(thisVal),
                                     &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, funbytes.encode(cx, 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)
            {
                JSAutoByteString nameBytes;
                const char* name = JSVAL2String(cx, desc->id, &isString, &nameBytes);
                if(!isString)
                    name = nsnull;
                JSAutoByteString valueBytes;
                const char* value = JSVAL2String(cx, desc->value, &isString, &valueBytes);
                
                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 k = namedArgCount; k < argCount; k++)
                {
                    char number[8];
                    JS_snprintf(number, 8, "%d", (int) k);

                    if(JS_GetProperty(cx, argsObj, number, &val))
                    {
                        JSAutoByteString valueBytes;
                        const char *value = JSVAL2String(cx, val, &isString, &valueBytes);
                        buf = JS_sprintf_append(buf, "%s%s%s%s",
                                        k ? ", " : "",
                                        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)
            {
                JSAutoByteString nameBytes;
                JSAutoByteString valueBytes;
                const char *name = JSVAL2String(cx, desc->id, nsnull, &nameBytes);
                const char *value = JSVAL2String(cx, desc->value, &isString, &valueBytes);

                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)
    {
        if(gotThisVal)
        {
            JSString* thisValStr;
            JSAutoByteString thisValBytes;

            if(nsnull != (thisValStr = JS_ValueToString(cx, thisVal)) &&
               thisValBytes.encode(cx, thisValStr))
            {
                buf = JS_sprintf_append(buf, TAB "this = %s\n", thisValBytes.ptr());
                if(!buf) goto out;
            }
        }
        else
            buf = JS_sprintf_append(buf, TAB "<failed to get 'this' value>\n");
    }

    // print the properties of 'this', if it is an object

    if(showThisProps && thisProps.array)
    {

        for(uint32 i = 0; i < thisProps.length; i++)
        {
            JSPropertyDesc* desc = &thisProps.array[i];
            if(desc->flags & JSPD_ENUMERATE)
            {
                JSAutoByteString nameBytes;
                JSAutoByteString valueBytes;
                const char *name = JSVAL2String(cx, desc->id, nsnull, &nameBytes);
                const char *value = JSVAL2String(cx, desc->value, &isString, &valueBytes);
                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;
}
Example #5
0
JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp)
{
    /* Force creation of argument and call objects if not yet created */
    (void) JS_GetFrameCallObject(cx, fp);
    return fp->scopeChain;
}