Bug 624316 - Unwrap wrapped functions before returning them to JSD to see the contained script and name, r=gal, a=blocker
authorSteve Fink <sfink@mozilla.com>
Tue, 11 Jan 2011 14:24:52 -0800
changeset 60563 a563a4dccc5684960e6199457d21f818edb3684a
parent 60562 98dd962dab2515335b5a726dd46560f3eb79c36d
child 60564 a1d376c7a962df3b0490a167c957374f919b7d50
push id18037
push usercleary@mozilla.com
push dateFri, 14 Jan 2011 17:42:55 +0000
treeherdermozilla-central@4e0501a0c5e5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgal, blocker
bugs624316
milestone2.0b9pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 624316 - Unwrap wrapped functions before returning them to JSD to see the contained script and name, r=gal, a=blocker
js/jsd/jsd.h
js/jsd/jsd_val.c
js/jsd/jsdebug.c
js/jsd/jsdebug.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsdbgapi.cpp
js/src/jsdbgapi.h
--- a/js/jsd/jsd.h
+++ b/js/jsd/jsd.h
@@ -967,16 +967,19 @@ extern jsdouble
 jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval);
 
 extern JSString*
 jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval);
 
 extern JSString*
 jsd_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval);
 
+extern JSFunction*
+jsd_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval);
+
 /**************************************************/
 
 extern uintN
 jsd_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval);
 
 extern JSDProperty*
 jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp);
 
--- a/js/jsd/jsd_val.c
+++ b/js/jsd/jsd_val.c
@@ -137,50 +137,49 @@ jsd_IsValuePrimitive(JSDContext* jsdc, J
 {
     return JSVAL_IS_PRIMITIVE(jsdval->val);
 }
 
 JSBool
 jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval)
 {
     return !JSVAL_IS_PRIMITIVE(jsdval->val) &&
-           JS_ObjectIsFunction(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
+           JS_ObjectIsCallable(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
 }
 
 JSBool
 jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSContext* cx = jsdc->dumbContext;
-    jsval val = jsdval->val;
     JSFunction* fun;
     JSExceptionState* exceptionState;
     JSCrossCompartmentCall *call = NULL;
 
     if(jsd_IsValueFunction(jsdc, jsdval))
     {
         JSBool ok = JS_FALSE;
         JS_BeginRequest(cx);
-        call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(val));
+        call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
         if(!call) {
             JS_EndRequest(cx);
 
             return JS_FALSE;
         }
 
         exceptionState = JS_SaveExceptionState(cx);
-        fun = JS_ValueToFunction(cx, val);
+        fun = JSD_GetValueFunction(jsdc, jsdval);
         JS_RestoreExceptionState(cx, exceptionState);
         if(fun)
             ok = JS_GetFunctionScript(cx, fun) ? JS_FALSE : JS_TRUE;
         JS_LeaveCrossCompartmentCall(call);
         JS_EndRequest(cx);
         JS_ASSERT(fun);
         return ok;
     }
-    return !JSVAL_IS_PRIMITIVE(val);
+    return !JSVAL_IS_PRIMITIVE(jsdval->val);
 }
 
 /***************************************************************************/
 
 JSBool
 jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
 {
     jsval val = jsdval->val;
@@ -260,17 +259,17 @@ jsd_GetValueFunctionName(JSDContext* jsd
         call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
         if(!call) {
             JS_EndRequest(cx);
 
             return NULL;
         }
 
         exceptionState = JS_SaveExceptionState(cx);
-        fun = JS_ValueToFunction(cx, jsdval->val);
+        fun = JSD_GetValueFunction(jsdc, jsdval);
         JS_RestoreExceptionState(cx, exceptionState);
         JS_LeaveCrossCompartmentCall(call);
         JS_EndRequest(cx);
         if(!fun)
             return NULL;
         jsdval->funName = JS_GetFunctionId(fun);
 
         /* For compatibility we return "anonymous", not an empty string here. */
@@ -632,16 +631,40 @@ jsd_GetValueProperty(JSDContext* jsdc, J
     pd.alias = JSVAL_NULL;
     pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
         | (attrs & JSPROP_READONLY)  ? JSPD_READONLY  : 0
         | (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;
 
     return _newProperty(jsdc, &pd, JSDPD_HINTED);
 }
 
+/*
+ * Retrieve a JSFunction* from a JSDValue*. This differs from
+ * JS_ValueToFunction by fully unwrapping the object first.
+ */
+JSFunction*
+jsd_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval)
+{
+    JSObject *obj;
+    JSFunction *fun;
+    JSCrossCompartmentCall *call = NULL;
+    if (!JSVAL_IS_OBJECT(jsdval->val))
+        return NULL;
+    if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
+        return NULL;
+    obj = JS_UnwrapObject(jsdc->dumbContext, obj);
+
+    call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
+    if (!call)
+        return NULL;
+    fun = JS_ValueToFunction(jsdc->dumbContext, OBJECT_TO_JSVAL(obj));
+    JS_LeaveCrossCompartmentCall(call);
+
+    return fun;
+}
 
 JSDValue*
 jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSCrossCompartmentCall *call = NULL;
 
     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
     {
@@ -792,17 +815,17 @@ jsd_GetScriptForValue(JSDContext* jsdc, 
     call = JS_EnterCrossCompartmentCall(cx, JSVAL_TO_OBJECT(val));
     if (!call) {
         JS_EndRequest(cx);
 
         return NULL;
     }
 
     exceptionState = JS_SaveExceptionState(cx);
-    fun = JS_ValueToFunction(cx, val);
+    fun = JSD_GetValueFunction(jsdc, jsdval);
     JS_RestoreExceptionState(cx, exceptionState);
     if (fun)
         script = JS_GetFunctionScript(cx, fun);
     JS_LeaveCrossCompartmentCall(call);
     JS_EndRequest(cx);
 
     if (!script)
         return NULL;
--- a/js/jsd/jsdebug.c
+++ b/js/jsd/jsdebug.c
@@ -1119,16 +1119,24 @@ JSD_GetValueString(JSDContext* jsdc, JSD
 JSD_PUBLIC_API(JSString *)
 JSD_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     JSD_ASSERT_VALID_VALUE(jsdval);
     return jsd_GetValueFunctionName(jsdc, jsdval);
 }
 
+JSD_PUBLIC_API(JSFunction*)
+JSD_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval)
+{
+    JSD_ASSERT_VALID_CONTEXT(jsdc);
+    JSD_ASSERT_VALID_VALUE(jsdval);
+    return jsd_GetValueFunction(jsdc, jsdval);
+}
+
 /**************************************************/
 
 JSD_PUBLIC_API(uintN)
 JSD_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     JSD_ASSERT_VALID_VALUE(jsdval);
     return jsd_GetCountOfProperties(jsdc, jsdval);
--- a/js/jsd/jsdebug.h
+++ b/js/jsd/jsdebug.h
@@ -1293,16 +1293,24 @@ JSD_GetValueString(JSDContext* jsdc, JSD
 
 /*
 * Return name of function IFF JSDValue represents a function.
 * *** new for version 1.1 ****
 */
 extern JSD_PUBLIC_API(JSString *)
 JSD_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval);
 
+/*
+* Return function object IFF JSDValue represents a function or an object
+* wrapping a function.
+* *** new for version 1.1 ****
+*/
+extern JSD_PUBLIC_API(JSFunction*)
+JSD_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval);
+
 /**************************************************/
 
 /*
 * Return the number of properties for the JSDValue.
 * *** new for version 1.1 ****
 */
 extern JSD_PUBLIC_API(uintN)
 JSD_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4225,16 +4225,22 @@ JS_GetFunctionArity(JSFunction *fun)
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
 {
     return obj->getClass() == &js_FunctionClass;
 }
 
+JS_PUBLIC_API(JSBool)
+JS_ObjectIsCallable(JSContext *cx, JSObject *obj)
+{
+    return obj->isCallable();
+}
+
 static JSBool
 js_generic_native_method_dispatcher(JSContext *cx, uintN argc, Value *vp)
 {
     JSFunctionSpec *fs;
     JSObject *tmp;
     Native native;
 
     fs = (JSFunctionSpec *) vp->toObject().getReservedSlot(0).toPrivate();
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2572,16 +2572,19 @@ JS_GetFunctionArity(JSFunction *fun);
  * comparing obj's class name to "Function", but equivalent unless someone has
  * overwritten the "Function" identifier with a different constructor and then
  * created instances using that constructor that might be passed in as obj).
  */
 extern JS_PUBLIC_API(JSBool)
 JS_ObjectIsFunction(JSContext *cx, JSObject *obj);
 
 extern JS_PUBLIC_API(JSBool)
+JS_ObjectIsCallable(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
 JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs);
 
 extern JS_PUBLIC_API(JSFunction *)
 JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
                   uintN nargs, uintN attrs);
 
 extern JS_PUBLIC_API(JSFunction *)
 JS_DefineUCFunction(JSContext *cx, JSObject *obj,
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -1856,16 +1856,24 @@ JS_PUBLIC_API(JSBool)
 JS_MakeSystemObject(JSContext *cx, JSObject *obj)
 {
     obj->setSystem();
     return true;
 }
 
 /************************************************************************/
 
+JS_PUBLIC_API(JSObject *)
+JS_UnwrapObject(JSContext *cx, JSObject *obj)
+{
+    return obj->unwrap();
+}
+
+/************************************************************************/
+
 JS_FRIEND_API(void)
 js_RevertVersion(JSContext *cx)
 {
     cx->clearVersionOverride();
 }
 
 JS_PUBLIC_API(const JSDebugHooks *)
 JS_GetGlobalDebugHooks(JSRuntime *rt)
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -482,16 +482,21 @@ JS_IsSystemObject(JSContext *cx, JSObjec
  * after allocating the object. A system object is an object for which
  * JS_IsSystemObject returns true.
  */
 extern JS_PUBLIC_API(JSBool)
 JS_MakeSystemObject(JSContext *cx, JSObject *obj);
 
 /************************************************************************/
 
+extern JS_PUBLIC_API(JSObject *)
+JS_UnwrapObject(JSContext *cx, JSObject *obj);
+
+/************************************************************************/
+
 extern JS_FRIEND_API(void)
 js_RevertVersion(JSContext *cx);
 
 extern JS_PUBLIC_API(const JSDebugHooks *)
 JS_GetGlobalDebugHooks(JSRuntime *rt);
 
 extern JS_PUBLIC_API(JSDebugHooks *)
 JS_SetContextDebugHooks(JSContext *cx, const JSDebugHooks *hooks);