michael@0: // Debugger.prototype.{addDebuggee,hasDebuggee,removeDebuggee} recognize globals michael@0: // regardless of how they are specified. michael@0: michael@0: var dbg = new Debugger; michael@0: michael@0: // Assert that dbg's debuggees are exactly the set passed as arguments. michael@0: // The arguments are assumed to be Debugger.Object instances referring to michael@0: // globals without wrappers --- which is the sort returned by addDebuggee. michael@0: function assertDebuggees() { michael@0: print("assertDebuggees([" + [g.toSource() for each (g in arguments)] + "])"); michael@0: var debuggees = dbg.getDebuggees(); michael@0: assertEq(arguments.length, debuggees.length); michael@0: for each (g in arguments) michael@0: assertEq(debuggees.indexOf(g) != -1, true); michael@0: } michael@0: michael@0: var g1 = newGlobal(); g1.toSource = function () { return "[global g1]"; }; michael@0: var g2 = newGlobal(); g2.toSource = function () { return "[global g2]"; }; michael@0: michael@0: assertDebuggees(); michael@0: michael@0: // Produce every possible way to designate g1, for us to play with. michael@0: // Globals can be designated by any of the following: michael@0: // michael@0: // - "CCW": a Cross-Compartment Wrapper (CCW) of a global object michael@0: // - "D.O": a Debugger.Object whose referent is a global object michael@0: // - "D.O of CCW": a Debugger.Object whose referent is a CCW of a michael@0: // global object, where the CCW can be securely unwrapped michael@0: // michael@0: // There's no direct "G", since globals are always in their own michael@0: // compartments, never the debugger's; if we ever viewed them directly, michael@0: // that would be a compartment violation. michael@0: michael@0: // "dg1" means "Debugger.Object referring (directly) to g1". michael@0: var dg1 = dbg.addDebuggee(g1); michael@0: dg1.toSource = function() { return "[Debugger.Object for global g1]"; }; michael@0: assertEq(dg1.global, dg1); michael@0: assertEq(dg1.unwrap(), dg1); michael@0: assertDebuggees(dg1); michael@0: michael@0: // We need to add g2 as a debuggee; that's the only way to get a D.O referring michael@0: // to it without a wrapper. michael@0: var dg2 = dbg.addDebuggee(g2); michael@0: dg2.toSource = function() { return "[Debugger.Object for global g2]"; }; michael@0: assertEq(dg2.global, dg2); michael@0: assertEq(dg2.unwrap(), dg2); michael@0: assertDebuggees(dg1, dg2); michael@0: michael@0: // "dwg1" means "Debugger.Object referring to CCW of g1". michael@0: var dwg1 = dg2.makeDebuggeeValue(g1); michael@0: assertEq(dwg1.global, dg2); michael@0: assertEq(dwg1.unwrap(), dg1); michael@0: dwg1.toSource = function() { return "[Debugger.Object for CCW of global g1]"; }; michael@0: michael@0: assertDebuggees(dg1, dg2); michael@0: assertEq(dbg.removeDebuggee(g1), undefined); michael@0: assertEq(dbg.removeDebuggee(g2), undefined); michael@0: assertDebuggees(); michael@0: michael@0: // Systematically cover all the single-global possibilities: michael@0: // michael@0: // | added as | designated as | addDebuggee | hasDebuggee | removeDebuggee | michael@0: // |-------------+---------------+-------------+-------------+----------------| michael@0: // | (not added) | CCW | X | X | X | michael@0: // | | D.O | X | X | X | michael@0: // | | D.O of CCW | X | X | X | michael@0: // |-------------+---------------+-------------+-------------+----------------| michael@0: // | CCW | CCW | X | X | X | michael@0: // | | D.O | X | X | X | michael@0: // | | D.O of CCW | X | X | X | michael@0: // |-------------+---------------+-------------+-------------+----------------| michael@0: // | D.O | CCW | X | X | X | michael@0: // | | D.O | X | X | X | michael@0: // | | D.O of CCW | X | X | X | michael@0: // |-------------+---------------+-------------+-------------+----------------| michael@0: // | D.O of CCW | CCW | X | X | X | michael@0: // | | D.O | X | X | X | michael@0: // | | D.O of CCW | X | X | X | michael@0: michael@0: // Cover the "(not added)" section of the table, other than "addDebuggee": michael@0: assertEq(dbg.hasDebuggee(g1), false); michael@0: assertEq(dbg.hasDebuggee(dg1), false); michael@0: assertEq(dbg.hasDebuggee(dwg1), false); michael@0: michael@0: assertEq(dbg.removeDebuggee(g1), undefined); assertDebuggees(); michael@0: assertEq(dbg.removeDebuggee(dg1), undefined); assertDebuggees(); michael@0: assertEq(dbg.removeDebuggee(dwg1), undefined); assertDebuggees(); michael@0: michael@0: // Try all operations adding the debuggee using |addAs|, and operating on it michael@0: // using |designateAs|, thereby covering one row of the table (outside the '(not michael@0: // added)' section), and one case in the '(not added)', 'designated as' section. michael@0: // michael@0: // |Direct| should be the Debugger.Object referring directly to the debuggee michael@0: // global, for checking the results from addDebuggee and getDebuggees. michael@0: function combo(addAs, designateAs, direct) { michael@0: print("combo(" + uneval(addAs) + ", " + uneval(designateAs) + ")"); michael@0: assertDebuggees(); michael@0: assertEq(dbg.addDebuggee(addAs), direct); michael@0: assertDebuggees(direct); michael@0: assertEq(dbg.addDebuggee(designateAs), direct); michael@0: assertDebuggees(direct); michael@0: assertEq(dbg.hasDebuggee(designateAs), true); michael@0: assertEq(dbg.removeDebuggee(designateAs), undefined); michael@0: assertDebuggees(); michael@0: } michael@0: michael@0: combo(g1, g1, dg1); michael@0: combo(dg1, g1, dg1); michael@0: combo(dwg1, g1, dg1); michael@0: michael@0: combo(g1, dg1, dg1); michael@0: combo(dg1, dg1, dg1); michael@0: combo(dwg1, dg1, dg1); michael@0: michael@0: combo(g1, dwg1, dg1); michael@0: combo(dg1, dwg1, dg1); michael@0: combo(dwg1, dwg1, dg1);