Bug 521010. Expose a .script on jsdIValue, r=brendan
--- a/js/jsd/idl/jsdIDebuggerService.idl
+++ b/js/jsd/idl/jsdIDebuggerService.idl
@@ -1015,17 +1015,17 @@ interface jsdIScript : jsdIEphemeral
};
/**
* Value objects. Represents typeless JavaScript values (jsval in SpiderMonkey
* terminology.) These are valid until the debugger is turned off. Holding a
* jsdIValue adds a root for the underlying JavaScript value, so don't keep it
* if you don't need to.
*/
-[scriptable, uuid(f39204c5-4e67-4fd0-9c70-0bd8d14e6511)]
+[scriptable, uuid(9cab158f-dc78-41dd-9d11-79e05cb3f2bd)]
interface jsdIValue : jsdIEphemeral
{
/** Internal use only. */
[noscript] readonly attribute JSDContext JSDContext;
/** Internal use only. */
[noscript] readonly attribute JSDValue JSDValue;
/**
@@ -1144,16 +1144,22 @@ interface jsdIValue : jsdIEphemeral
/**
* When called from JavaScript, this method returns the JavaScript value
* wrapped by this jsdIValue. The calling script is free to use the result
* as it would any other JavaScript value.
* When called from another language this method returns an xpconnect
* defined error code.
*/
void getWrappedValue();
+
+ /**
+ * If this is a function value, return its associated jsdIScript.
+ * Otherwise, return null.
+ */
+ readonly attribute jsdIScript script;
};
/**
* Properties specific to values which are also objects.
* XXX We don't add roots for these yet, so make sure you hold on to the
* jsdIValue from whence your jsdIObject instance came for at least as long as
* you hold the jsdIObject.
* XXX Maybe the jsClassName, jsConstructorName, and property related attribute/
--- a/js/jsd/jsd.h
+++ b/js/jsd/jsd.h
@@ -987,16 +987,19 @@ extern JSDValue*
jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval);
extern JSDValue*
jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval);
extern const char*
jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval);
+extern JSDScript*
+jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval);
+
/**************************************************/
extern void
jsd_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop);
extern JSDValue*
jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop);
--- a/js/jsd/jsd_val.c
+++ b/js/jsd/jsd_val.c
@@ -652,16 +652,47 @@ jsd_GetValueClassName(JSDContext* jsdc,
JS_BeginRequest(jsdc->dumbContext);
if(JS_GET_CLASS(jsdc->dumbContext, obj))
jsdval->className = JS_GET_CLASS(jsdc->dumbContext, obj)->name;
JS_EndRequest(jsdc->dumbContext);
}
return jsdval->className;
}
+JSDScript*
+jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval)
+{
+ JSContext* cx = jsdc->dumbContext;
+ jsval val = jsdval->val;
+ JSFunction* fun;
+ JSExceptionState* exceptionState;
+ JSScript* script = NULL;
+ JSDScript* jsdscript;
+
+ if (!jsd_IsValueFunction(jsdc, jsdval))
+ return NULL;
+
+ JS_BeginRequest(cx);
+ exceptionState = JS_SaveExceptionState(cx);
+ fun = JS_ValueToFunction(cx, val);
+ JS_RestoreExceptionState(cx, exceptionState);
+ if (fun)
+ script = JS_GetFunctionScript(cx, fun);
+ JS_EndRequest(cx);
+
+ if (!script)
+ return NULL;
+
+ JSD_LOCK_SCRIPTS(jsdc);
+ jsdscript = jsd_FindJSDScript(jsdc, script);
+ JSD_UNLOCK_SCRIPTS(jsdc);
+ return jsdscript;
+}
+
+
/***************************************************************************/
/***************************************************************************/
JSDValue*
jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop)
{
jsdprop->name->nref++;
return jsdprop->name;
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -2258,16 +2258,25 @@ jsdValue::GetWrappedValue()
{
*result = JSD_GetValueWrappedJSVal (mCx, mValue);
cc->SetReturnValueWasSet(PR_TRUE);
}
return NS_OK;
}
+NS_IMETHODIMP
+jsdValue::GetScript(jsdIScript **_rval)
+{
+ ASSERT_VALID_EPHEMERAL;
+ JSDScript *script = JSD_GetScriptForValue(mCx, mValue);
+ *_rval = jsdScript::FromPtr(mCx, script);
+ return NS_OK;
+}
+
/******************************************************************************
* debugger service implementation
******************************************************************************/
NS_IMPL_THREADSAFE_ISUPPORTS1(jsdService, jsdIDebuggerService)
NS_IMETHODIMP
jsdService::GetJSDContext(JSDContext **_rval)
{
--- a/js/jsd/jsdebug.c
+++ b/js/jsd/jsdebug.c
@@ -1161,16 +1161,22 @@ JSD_GetValueConstructor(JSDContext* jsdc
JSD_PUBLIC_API(const char*)
JSD_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
JSD_ASSERT_VALID_VALUE(jsdval);
return jsd_GetValueClassName(jsdc, jsdval);
}
+JSD_PUBLIC_API(JSDScript*)
+JSD_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval)
+{
+ JSD_ASSERT_VALID_CONTEXT(jsdc);
+ return jsd_GetScriptForValue(jsdc, jsdval);
+}
/**************************************************/
JSD_PUBLIC_API(void)
JSD_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop)
{
JSD_ASSERT_VALID_CONTEXT(jsdc);
JSD_ASSERT_VALID_PROPERTY(jsdprop);
jsd_DropProperty(jsdc, jsdprop);
--- a/js/jsd/jsdebug.h
+++ b/js/jsd/jsdebug.h
@@ -1331,16 +1331,23 @@ JSD_GetValueConstructor(JSDContext* jsdc
/*
* Get the name of the class for this object.
* *** new for version 1.1 ****
*/
extern JSD_PUBLIC_API(const char*)
JSD_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval);
+/*
+* Get the script for the given value if the given value represents a
+* scripted function. Otherwise, return null.
+*/
+extern JSD_PUBLIC_API(JSDScript*)
+JSD_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval);
+
/**************************************************/
/* possible or'd together bitflags returned by JSD_GetPropertyFlags
*
* XXX these must stay the same as the JSPD_ flags in jsdbgapi.h
*/
#define JSDPD_ENUMERATE JSPD_ENUMERATE /* visible to for/in loop */
#define JSDPD_READONLY JSPD_READONLY /* assignment is error */