Bug 741615: Replace Debugger.prototype.wrap with Debugger.Object.prototype.makeDebuggeeValue. r=jorendorff

This commit is contained in:
Jim Blandy 2012-04-05 12:30:35 -07:00
parent b36c773a23
commit 1c14d48cab
4 changed files with 80 additions and 58 deletions

View File

@ -1,34 +0,0 @@
// Debugger.prototype.wrap creates only one Debugger.Object instance for each debuggee object.
var g = newGlobal('new-compartment');
var dbg = new Debugger(g);
g.eval("var x = { 'now playing': 'Joy Division' };");
g.eval("var y = { 'mood': 'bleak' };");
wx = dbg.wrap(g.x);
assertEq(wx, dbg.wrap(g.x));
assertEq(wx === g.x, false);
assertEq("now playing" in wx, false);
assertEq(wx.getOwnPropertyNames().indexOf("now playing"), 0);
wx.commentary = "deconstruction";
assertEq("deconstruction" in g.x, false);
wy = dbg.wrap(g.y);
assertEq(wy === wx, false);
wy.commentary = "reconstruction";
assertEq(wx.commentary, "deconstruction");
// Separate debuggers get separate wrappers, but they both view the same underlying object.
var dbg2 = new Debugger(g);
w2x = dbg2.wrap(g.x);
assertEq(wx === w2x, false);
w2x.defineProperty("breadcrumb", { value: "pumpernickel" });
assertEq(wx.getOwnPropertyDescriptor("breadcrumb").value, "pumpernickel");
// Trying to wrap things that aren't objects should pass them through unchanged.
assertEq(dbg.wrap("foonting turlingdromes"), "foonting turlingdromes");
assertEq(dbg.wrap(true), true);
assertEq(dbg.wrap(false), false);
assertEq(dbg.wrap(null), null);
assertEq(dbg.wrap(1729), 1729);
assertEq(dbg.wrap(undefined), undefined);

View File

@ -0,0 +1,40 @@
// Debugger.Object.prototype.makeDebuggeeValue creates only one
// Debugger.Object instance for each debuggee object.
var g = newGlobal('new-compartment');
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
g.eval("var x = { 'now playing': 'Joy Division' };");
g.eval("var y = { 'mood': 'bleak' };");
wx = gw.makeDebuggeeValue(g.x);
assertEq(wx, gw.makeDebuggeeValue(g.x));
assertEq(wx === g.x, false);
assertEq("now playing" in wx, false);
assertEq(wx.getOwnPropertyNames().indexOf("now playing"), 0);
wx.commentary = "deconstruction";
assertEq("deconstruction" in g.x, false);
wy = gw.makeDebuggeeValue(g.y);
assertEq(wy === wx, false);
wy.commentary = "reconstruction";
assertEq(wx.commentary, "deconstruction");
// Separate debuggers get separate Debugger.Object instances, but both
// instances' referents are the same underlying object.
var dbg2 = new Debugger();
var gw2 = dbg2.addDebuggee(g);
w2x = gw2.makeDebuggeeValue(g.x);
assertEq(wx === w2x, false);
w2x.defineProperty("breadcrumb", { value: "pumpernickel" });
assertEq(wx.getOwnPropertyDescriptor("breadcrumb").value, "pumpernickel");
// Non-objects are already debuggee values.
assertEq(gw.makeDebuggeeValue("foonting turlingdromes"), "foonting turlingdromes");
assertEq(gw.makeDebuggeeValue(true), true);
assertEq(gw.makeDebuggeeValue(false), false);
assertEq(gw.makeDebuggeeValue(null), null);
assertEq(gw.makeDebuggeeValue(1729), 1729);
assertEq(gw.makeDebuggeeValue(Math.PI), Math.PI);
assertEq(gw.makeDebuggeeValue(undefined), undefined);

View File

@ -0,0 +1,12 @@
// Debugger.Object.prototype.makeDebuggeeValue returns the object wrapped
// the same way as Debugger.Frame.prototype.eval, etc.
var g = newGlobal('new-compartment');
g.eval("function f() { debugger; }");
var dbg = Debugger();
var gw = dbg.addDebuggee(g);
var jsonw;
dbg.onDebuggerStatement = function (frame) {
jsonw = frame.eval("JSON").return;
};
g.eval("debugger;");
assertEq(gw.makeDebuggeeValue(g.JSON), jsonw);

View File

@ -2053,29 +2053,6 @@ Debugger::findScripts(JSContext *cx, unsigned argc, Value *vp)
return true;
}
JSBool
Debugger::wrap(JSContext *cx, unsigned argc, Value *vp)
{
REQUIRE_ARGC("Debugger.prototype.wrap", 1);
THIS_DEBUGGER(cx, argc, vp, "wrap", args, dbg);
/* Wrapping a non-object returns the value unchanged. */
if (!args[0].isObject()) {
args.rval() = args[0];
return true;
}
JSObject *obj = dbg->unwrapDebuggeeArgument(cx, args[0]);
if (!obj)
return false;
args.rval() = args[0];
if (!dbg->wrapDebuggeeValue(cx, &args.rval()))
return false;
return true;
}
JSPropertySpec Debugger::properties[] = {
JS_PSGS("enabled", Debugger::getEnabled, Debugger::setEnabled, 0),
JS_PSGS("onDebuggerStatement", Debugger::getOnDebuggerStatement,
@ -2097,7 +2074,6 @@ JSFunctionSpec Debugger::methods[] = {
JS_FN("getNewestFrame", Debugger::getNewestFrame, 0, 0),
JS_FN("clearAllBreakpoints", Debugger::clearAllBreakpoints, 1, 0),
JS_FN("findScripts", Debugger::findScripts, 1, 0),
JS_FN("wrap", Debugger::wrap, 1, 0),
JS_FS_END
};
@ -3858,6 +3834,33 @@ DebuggerObject_call(JSContext *cx, unsigned argc, Value *vp)
return ApplyOrCall(cx, argc, vp, CallMode);
}
static JSBool
DebuggerObject_makeDebuggeeValue(JSContext *cx, unsigned argc, Value *vp)
{
REQUIRE_ARGC("Debugger.Object.prototype.makeDebuggeeValue", 1);
THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "makeDebuggeeValue", args, dbg, referent);
/* Non-objects are already debuggee values. */
if (args[0].isObject()) {
// Enter this Debugger.Object's referent's compartment, and wrap the
// argument as appropriate for references from there.
{
AutoCompartment ac(cx, referent);
if (!ac.enter() ||
!cx->compartment->wrap(cx, &args[0]))
return false;
}
// Back in the debugger's compartment, produce a new Debugger.Object
// instance referring to the wrapped argument.
if (!dbg->wrapDebuggeeValue(cx, &args[0]))
return false;
}
args.rval() = args[0];
return true;
}
static JSPropertySpec DebuggerObject_properties[] = {
JS_PSG("proto", DebuggerObject_getProto, 0),
JS_PSG("class", DebuggerObject_getClass, 0),
@ -3883,6 +3886,7 @@ static JSFunctionSpec DebuggerObject_methods[] = {
JS_FN("isExtensible", DebuggerObject_isExtensible, 0, 0),
JS_FN("apply", DebuggerObject_apply, 0, 0),
JS_FN("call", DebuggerObject_call, 0, 0),
JS_FN("makeDebuggeeValue", DebuggerObject_makeDebuggeeValue, 1, 0),
JS_FS_END
};