Merge Debug.Function and Debug.Object.
authorJason Orendorff <jorendorff@mozilla.com>
Thu, 05 May 2011 15:37:54 -0500
changeset 74794 012541acc62a95c78dcbd6549f91f52b3ea29db0
parent 74793 9914b62860dc96fc75448f78abd9ecd460beae57
child 74795 18e81fe5abac6810c744012e1236b41a5b83dbbd
push idunknown
push userunknown
push dateunknown
milestone6.0a1
Merge Debug.Function and Debug.Object.
js/src/jit-test/tests/debug/Function-01.js
js/src/jit-test/tests/debug/Function-apply-01.js
js/src/jit-test/tests/debug/Function-apply-02.js
js/src/jit-test/tests/debug/Function-apply-03.js
js/src/jit-test/tests/debug/Function-name-01.js
js/src/jit-test/tests/debug/Object-01.js
js/src/jit-test/tests/debug/Object-apply-01.js
js/src/jit-test/tests/debug/Object-apply-02.js
js/src/jit-test/tests/debug/Object-apply-03.js
js/src/jit-test/tests/debug/Object-name-01.js
js/src/jsdbg.cpp
rename from js/src/jit-test/tests/debug/Function-01.js
rename to js/src/jit-test/tests/debug/Object-01.js
--- a/js/src/jit-test/tests/debug/Function-01.js
+++ b/js/src/jit-test/tests/debug/Object-01.js
@@ -1,21 +1,20 @@
 // |jit-test| debug
-// Debug.Function basics
+// Debug.Object basics
 
 var g = newGlobal('new-compartment');
 var dbg = Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         assertEq(frame.arguments[0], frame.callee);
-        assertEq(Object.getPrototypeOf(frame.arguments[0]), Debug.Function.prototype);
-        assertEq(frame.arguments[0] instanceof Debug.Function, true);
+        assertEq(Object.getPrototypeOf(frame.arguments[0]), Debug.Object.prototype);
         assertEq(frame.arguments[0] instanceof Debug.Object, true);
+        assertEq(frame.arguments[0] !== frame.arguments[1], true);
         assertEq(Object.getPrototypeOf(frame.arguments[1]), Debug.Object.prototype);
-        assertEq(frame.arguments[1] instanceof Debug.Function, false);
         assertEq(frame.arguments[1] instanceof Debug.Object, true);
         hits++;
     }
 };
 
 g.eval("var obj = {}; function f(a, b) { debugger; } f(f, obj);");
 assertEq(hits, 1);
rename from js/src/jit-test/tests/debug/Function-apply-01.js
rename to js/src/jit-test/tests/debug/Object-apply-01.js
--- a/js/src/jit-test/tests/debug/Function-apply-01.js
+++ b/js/src/jit-test/tests/debug/Object-apply-01.js
@@ -1,10 +1,10 @@
 // |jit-test| debug
-// tests calling script functions via Debug.Function.prototype.apply
+// tests calling script functions via Debug.Object.prototype.apply
 
 load(libdir + "asserts.js");
 
 var g = newGlobal("new-compartment");
 g.eval("function f() { debugger; }");
 var dbg = new Debug(g);
 dbg.hooks = {debuggerHandler: function () {}};
 
rename from js/src/jit-test/tests/debug/Function-apply-02.js
rename to js/src/jit-test/tests/debug/Object-apply-02.js
--- a/js/src/jit-test/tests/debug/Function-apply-02.js
+++ b/js/src/jit-test/tests/debug/Object-apply-02.js
@@ -1,10 +1,10 @@
 // |jit-test| debug
-// tests calling native functions via Debug.Function.prototype.apply
+// tests calling native functions via Debug.Object.prototype.apply
 
 load(libdir + "asserts.js");
 
 var g = newGlobal("new-compartment");
 g.eval("function f() { debugger; }");
 var dbg = new Debug(g);
 dbg.hooks = {debuggerHandler: function () {}};
 
rename from js/src/jit-test/tests/debug/Function-apply-03.js
rename to js/src/jit-test/tests/debug/Object-apply-03.js
rename from js/src/jit-test/tests/debug/Function-name-01.js
rename to js/src/jit-test/tests/debug/Object-name-01.js
--- a/js/src/jit-test/tests/debug/Function-name-01.js
+++ b/js/src/jit-test/tests/debug/Object-name-01.js
@@ -1,10 +1,10 @@
 // |jit-test| debug
-// Debug.Function.prototype.name
+// Debug.Object.prototype.name
 
 var g = newGlobal('new-compartment');
 var dbg = Debug(g);
 var name, hits;
 dbg.hooks = {debuggerHandler: function (frame) { hits++; assertEq(frame.callee.name, name); }};
 
 hits = 0;
 name = "f";
--- a/js/src/jsdbg.cpp
+++ b/js/src/jsdbg.cpp
@@ -57,17 +57,16 @@ extern Class DebugFrame_class;
 
 enum {
     JSSLOT_DEBUGFRAME_OWNER,
     JSSLOT_DEBUGFRAME_ARGUMENTS,
     JSSLOT_DEBUGFRAME_COUNT
 };
 
 extern Class DebugObject_class;
-extern Class DebugFunction_class;
 
 enum {
     JSSLOT_DEBUGOBJECT_OWNER,
     JSSLOT_DEBUGOBJECT_CCW,  // cross-compartment wrapper
     JSSLOT_DEBUGOBJECT_COUNT
 };
 
 // === Utils
@@ -128,17 +127,16 @@ CheckThisClass(JSContext *cx, Value *vp,
         return false;                                                        \
     js::classname *private = (classname *) thisobj->getPrivate();
 
 // === Debug hook dispatch
 
 enum {
     JSSLOT_DEBUG_FRAME_PROTO,
     JSSLOT_DEBUG_OBJECT_PROTO,
-    JSSLOT_DEBUG_FUNCTION_PROTO,
     JSSLOT_DEBUG_COUNT
 };
 
 Debug::Debug(JSObject *dbg, JSObject *hooks, JSCompartment *compartment)
   : object(dbg), debuggeeCompartment(compartment), hooksObject(hooks),
     uncaughtExceptionHook(NULL), enabled(true), hasDebuggerHandler(false)
 {
 }
@@ -149,19 +147,17 @@ Debug::init()
     return frames.init() && objects.init();
 }
 
 JS_STATIC_ASSERT(uintN(JSSLOT_DEBUGFRAME_OWNER) == uintN(JSSLOT_DEBUGOBJECT_OWNER));
 
 Debug *
 Debug::fromChildJSObject(JSObject *obj)
 {
-    JS_ASSERT(obj->clasp == &DebugFrame_class ||
-              obj->clasp == &DebugObject_class ||
-              obj->clasp == &DebugFunction_class);
+    JS_ASSERT(obj->clasp == &DebugFrame_class || obj->clasp == &DebugObject_class);
     JSObject *dbgobj = &obj->getReservedSlot(JSSLOT_DEBUGOBJECT_OWNER).toObject();
     return fromJSObject(dbgobj);
 }
 
 bool
 Debug::getScriptFrame(JSContext *cx, StackFrame *fp, Value *vp)
 {
     JS_ASSERT(fp->isScriptFrame());
@@ -242,24 +238,18 @@ Debug::wrapDebuggeeValue(JSContext *cx, 
         else if (!(cx)->compartment->wrap(cx, &refobj))
             return false;
 
         ObjectMap::AddPtr p = objects.lookupForAdd(ccwobj);
         if (p) {
             vp->setObject(*p->value);
         } else {
             // Create a new Debug.Object for ccwobj.
-            bool fun = refobj->isFunction();
-            uintN slot = fun ? JSSLOT_DEBUG_FUNCTION_PROTO : JSSLOT_DEBUG_OBJECT_PROTO;
-            JSObject *proto = &object->getReservedSlot(slot).toObject();
-            JSObject *dobj =
-                NewNonFunction<WithProto::Given>(cx,
-                                                 fun ? &DebugFunction_class : &DebugObject_class,
-                                                 proto,
-                                                 NULL);
+            JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_OBJECT_PROTO).toObject();
+            JSObject *dobj = NewNonFunction<WithProto::Given>(cx, &DebugObject_class, proto, NULL);
             if (!dobj || !dobj->ensureClassReservedSlots(cx))
                 return false;
             dobj->setReservedSlot(JSSLOT_DEBUGOBJECT_OWNER, ObjectValue(*object));
             dobj->setReservedSlot(JSSLOT_DEBUGOBJECT_CCW, ObjectValue(*ccwobj));
             if (!objects.relookupOrAdd(p, ccwobj, dobj)) {
                 js_ReportOutOfMemory(cx);
                 return false;
             }
@@ -270,17 +260,17 @@ Debug::wrapDebuggeeValue(JSContext *cx, 
 }
 
 bool
 Debug::unwrapDebuggeeValue(JSContext *cx, Value *vp)
 {
     assertSameCompartment(cx, object, *vp);
     if (vp->isObject()) {
         JSObject *dobj = &vp->toObject();
-        if (dobj->clasp != &DebugObject_class && dobj->clasp != &DebugFunction_class) {
+        if (dobj->clasp != &DebugObject_class) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_EXPECTED_TYPE,
                                  "Debug", "Debug.Object", dobj->clasp->name);
             return false;
         }
         *vp = dobj->getReservedSlot(JSSLOT_DEBUGOBJECT_CCW);
     }
     return true;
 }
@@ -859,62 +849,52 @@ static JSPropertySpec DebugFrame_propert
 
 Class DebugObject_class = {
     "Object", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGOBJECT_COUNT),
     PropertyStub, PropertyStub, PropertyStub, StrictPropertyStub,
     EnumerateStub, ResolveStub, ConvertStub, FinalizeStub,
 };
 
 static JSObject *
-DebugObject_checkThis(JSContext *cx, Value *vp, const char *fnname, bool funflag)
+DebugObject_checkThis(JSContext *cx, Value *vp, const char *fnname)
 {
     if (!vp[1].isObject()) {
         ReportObjectRequired(cx);
         return NULL;
     }
     JSObject *thisobj = &vp[1].toObject();
-    if (thisobj->clasp != &DebugFunction_class &&
-        (funflag || thisobj->clasp != &DebugObject_class))
-    {
+    if (thisobj->clasp != &DebugObject_class) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
-                             funflag ? "Debug.Function" : "Debug.Object", fnname,
-                             thisobj->getClass()->name);
+                             "Debug.Object", fnname, thisobj->getClass()->name);
         return NULL;
     }
 
-    // Check for Debug.Object.prototype and Debug.Function.prototype, which are
-    // of class Debug{Object,Function}_class but aren't real Debug.Objects.
+    // Check for Debug.Object.prototype, which is of class DebugObject_class
+    // but isn't a real working Debug.Object.
     if (thisobj->getReservedSlot(JSSLOT_DEBUGOBJECT_CCW).isUndefined()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
-                             funflag ? "Debug.Function" : "Debug.Object", fnname,
-                             "prototype object");
+                             "Debug.Object", fnname, "prototype object");
         return NULL;
     }
     return thisobj;
 }
 
-#define THIS_DEBUGOBJECT_CCW_FUNFLAG(cx, vp, fnname, ccwobj, funflag)        \
-    JSObject *ccwobj = DebugObject_checkThis(cx, vp, fnname, funflag);       \
+#define THIS_DEBUGOBJECT_CCW(cx, vp, fnname, ccwobj)                         \
+    JSObject *ccwobj = DebugObject_checkThis(cx, vp, fnname);                \
     if (!ccwobj)                                                             \
         return false;                                                        \
     ccwobj = &ccwobj->getReservedSlot(JSSLOT_DEBUGOBJECT_CCW).toObject()
 
-#define THIS_DEBUGOBJECT_CCW(cx, vp, fnname, ccwobj)                         \
-    THIS_DEBUGOBJECT_CCW_FUNFLAG(cx, vp, fnname, ccwobj, false)
-
-#define THIS_DEBUGOBJECT_REFERENT_FUNFLAG(cx, vp, fnname, refobj, funflag)   \
-    THIS_DEBUGOBJECT_CCW_FUNFLAG(cx, vp, fnname, refobj, funflag);           \
+#define THIS_DEBUGOBJECT_REFERENT(cx, vp, fnname, refobj)                    \
+    THIS_DEBUGOBJECT_CCW(cx, vp, fnname, refobj);                            \
     if (refobj->isWrapper()) /* XXX TODO would love to assert instead */     \
         refobj = JSWrapper::wrappedObject(refobj);                           \
     else if (!(cx)->compartment->wrap(cx, &refobj))                          \
         return false
 
-#define THIS_DEBUGOBJECT_REFERENT(cx, vp, fnname, refobj)                    \
-    THIS_DEBUGOBJECT_REFERENT_FUNFLAG(cx, vp, fnname, refobj, false)
-
 static JSBool
 DebugObject_construct(JSContext *cx, uintN argc, Value *vp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR, "Debug.Object");
     return false;
 }
 
 static JSBool
@@ -924,63 +904,41 @@ DebugObject_getClass(JSContext *cx, uint
     const char *s = refobj->clasp->name;
     JSAtom *str = js_Atomize(cx, s, strlen(s), 0);
     if (!str)
         return false;
     vp->setString(str);
     return true;
 }
 
-static JSFunctionSpec DebugObject_methods[] = {
-    JS_FN("getClass", DebugObject_getClass, 0, 0),
-    JS_FS_END
-};
-
-// === Debug.Function
-
-Class DebugFunction_class = {
-    "Function", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGOBJECT_COUNT),
-    PropertyStub, PropertyStub, PropertyStub, StrictPropertyStub,
-    EnumerateStub, ResolveStub, ConvertStub, FinalizeStub,
-};
-
-#define THIS_DEBUGFUNCTION_REFERENT(cx, vp, fnname, refobj)                  \
-    THIS_DEBUGOBJECT_REFERENT_FUNFLAG(cx, vp, fnname, refobj, true)
-
 static JSBool
-DebugFunction_construct(JSContext *cx, uintN argc, Value *vp)
+DebugObject_getName(JSContext *cx, uintN argc, Value *vp)
 {
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR, "Debug.Function");
-    return false;
-}
-
-static JSBool
-DebugFunction_getName(JSContext *cx, uintN argc, Value *vp)
-{
-    THIS_DEBUGFUNCTION_REFERENT(cx, vp, "get name", funobj);
-    if (JSString *name = funobj->getFunctionPrivate()->atom) {
-        vp->setString(name);
-        return Debug::fromChildJSObject(&vp[1].toObject())->wrapDebuggeeValue(cx, vp);
+    THIS_DEBUGOBJECT_REFERENT(cx, vp, "get name", obj);
+    if (obj->isFunction()) {
+        if (JSString *name = obj->getFunctionPrivate()->atom) {
+            vp->setString(name);
+            return Debug::fromChildJSObject(&vp[1].toObject())->wrapDebuggeeValue(cx, vp);
+        }
     }
     vp->setNull();
     return true;
 }
 
 static JSBool
-DebugFunction_apply(JSContext *cx, uintN argc, Value *vp)
+DebugObject_apply(JSContext *cx, uintN argc, Value *vp)
 {
-    // Don't require a Debug.Function. Any Debug.Object might be callable.
-    // Check callability using JSObject::isCallable below.
     THIS_DEBUGOBJECT_REFERENT(cx, vp, "apply", obj);
     Debug *dbg = Debug::fromChildJSObject(&vp[1].toObject());
 
     // Any JS exceptions thrown must be in the debugger compartment, so do
     // sanity checks and fallible conversions before entering the debuggee.
     if (!obj->isCallable()) {
-        ReportIncompatibleMethod(cx, vp, &DebugFunction_class);
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
+                             "Debug.Object", "apply", obj->getClass()->name);
         return false;
     }
 
     // Unwrap Debug.Objects. This happens in the debugger's compartment since
     // that is where any exceptions must be reported.
     Value calleev = vp[1];
     Value thisv = argc > 0 ? vp[2] : UndefinedValue();
     AutoValueVector argv(cx);
@@ -1017,23 +975,24 @@ DebugFunction_apply(JSContext *cx, uintN
 
     // Call the function. Use newCompletionValue to return to the debugger
     // compartment and populate *vp.
     Value rval;
     bool ok = ExternalInvoke(cx, thisv, calleev, argv.length(), argv.begin(), &rval);
     return dbg->newCompletionValue(ac, ok, rval, vp);
 }
 
-static JSPropertySpec DebugFunction_properties[] = {
-    JS_PSG("name", DebugFunction_getName, 0),
+static JSPropertySpec DebugObject_properties[] = {
+    JS_PSG("name", DebugObject_getName, 0),
     JS_PS_END
 };
 
-static JSFunctionSpec DebugFunction_methods[] = {
-    JS_FN("apply", DebugFunction_apply, 0, 0),
+static JSFunctionSpec DebugObject_methods[] = {
+    JS_FN("getClass", DebugObject_getClass, 0, 0),
+    JS_FN("apply", DebugObject_apply, 0, 0),
     JS_FS_END
 };
 
 // === Glue
 
 extern JS_PUBLIC_API(JSBool)
 JS_DefineDebugObject(JSContext *cx, JSObject *obj)
 {
@@ -1051,24 +1010,16 @@ JS_DefineDebugObject(JSContext *cx, JSOb
     JSObject *frameProto = js_InitClass(cx, debugCtor, objProto, &DebugFrame_class,
                                         DebugFrame_construct, 0,
                                         DebugFrame_properties, NULL, NULL, NULL, &frameCtor);
     if (!frameProto)
         return false;
 
     JSObject *objectProto = js_InitClass(cx, debugCtor, objProto, &DebugObject_class,
                                          DebugObject_construct, 0,
-                                         NULL, DebugObject_methods, NULL, NULL);
+                                         DebugObject_properties, DebugObject_methods, NULL, NULL);
     if (!objectProto)
         return false;
 
-    JSObject *functionProto = js_InitClass(cx, debugCtor, objectProto, &DebugFunction_class,
-                                           DebugFunction_construct, 0,
-                                           DebugFunction_properties, DebugFunction_methods,
-                                           NULL, NULL);
-    if (!functionProto)
-        return false;
-
     debugProto->setReservedSlot(JSSLOT_DEBUG_FRAME_PROTO, ObjectValue(*frameProto));
     debugProto->setReservedSlot(JSSLOT_DEBUG_OBJECT_PROTO, ObjectValue(*objectProto));
-    debugProto->setReservedSlot(JSSLOT_DEBUG_FUNCTION_PROTO, ObjectValue(*functionProto));
     return true;
 }