Bug 521010. Expose a .script on jsdIValue, r=brendan
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 07 Oct 2009 21:19:54 -0400
changeset 33644 6958e86eead0f2f8034309cc754d6772887daa5e
parent 33643 63c6082e6230064ddc3b89227d3227da81fd25ca
child 33645 0eee0c1d69a853e1ba5e33df9dcdfa9ce942db6f
push id9605
push userbzbarsky@mozilla.com
push dateThu, 08 Oct 2009 01:20:13 +0000
treeherdermozilla-central@6958e86eead0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbrendan
bugs521010
milestone1.9.3a1pre
Bug 521010. Expose a .script on jsdIValue, r=brendan
js/jsd/idl/jsdIDebuggerService.idl
js/jsd/jsd.h
js/jsd/jsd_val.c
js/jsd/jsd_xpc.cpp
js/jsd/jsdebug.c
js/jsd/jsdebug.h
--- 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 */