michael@0: // Environments are only inspectable while their globals are debuggees. michael@0: michael@0: load(libdir + 'asserts.js'); michael@0: michael@0: var g1 = newGlobal(); michael@0: var g2 = newGlobal(); michael@0: g2.g1 = g1; michael@0: g1.g2 = g2; michael@0: michael@0: g1.eval('function f(xf) { return function h(xh) { debugger; } }'); michael@0: g1.eval('var h = f("value of xf");'); michael@0: michael@0: // To ensure that xk gets located on the heap, and thus outlives its stack frame, we michael@0: // store a function that captures it here. Kind of a kludge. michael@0: g2.eval('var capture;'); michael@0: g2.eval('function k(xk) { capture = function () { return xk; }; g1.h("value of xh"); }'); michael@0: michael@0: var dbg = new Debugger; michael@0: dbg.addDebuggee(g1); michael@0: dbg.addDebuggee(g2); michael@0: michael@0: dbg.onDebuggerStatement = debuggerHandler; michael@0: michael@0: var log = ''; michael@0: michael@0: g1.eval('g2.k("value of xk");'); michael@0: michael@0: var he, ke, ee; michael@0: michael@0: function debuggerHandler(frame) { michael@0: log += 'd'; michael@0: michael@0: assertEq(frame.type, 'call'); michael@0: he = frame.environment; michael@0: michael@0: assertEq(frame.older.type, 'call'); michael@0: ke = frame.older.environment; michael@0: michael@0: assertEq(frame.older.older.type, 'eval'); michael@0: ee = frame.older.older.environment; michael@0: michael@0: assertEq(he.inspectable, true); michael@0: assertEq(he.getVariable('xh'), 'value of xh'); michael@0: assertEq(he.parent.parent.getVariable('xf'), 'value of xf'); michael@0: assertEq(ke.inspectable, true); michael@0: assertEq(ke.getVariable('xk'), 'value of xk'); michael@0: assertEq(ee.inspectable, true); michael@0: assertEq(ee.type, 'object'); michael@0: michael@0: dbg.removeDebuggee(g2); michael@0: michael@0: assertEq(he.inspectable, true); michael@0: assertEq(he.type, 'declarative'); michael@0: assertEq(ke.inspectable, false); michael@0: assertThrowsInstanceOf(() => ke.getVariable('xk'), Error); michael@0: assertEq(ee.inspectable, true); michael@0: assertEq(ee.type, 'object'); michael@0: michael@0: dbg.removeDebuggee(g1); michael@0: michael@0: assertEq(he.inspectable, false); michael@0: assertThrowsInstanceOf(() => he.getVariable('xh'), Error); michael@0: assertEq(ke.inspectable, false); michael@0: assertThrowsInstanceOf(() => ke.getVariable('xk'), Error); michael@0: assertEq(ee.inspectable, false); michael@0: assertThrowsInstanceOf(() => ee.type, Error); michael@0: } michael@0: michael@0: assertEq(log, 'd'); michael@0: michael@0: dbg.addDebuggee(g2); michael@0: michael@0: assertEq(he.inspectable, false); michael@0: assertThrowsInstanceOf(() => he.getVariable('xh'), Error); michael@0: assertEq(ke.inspectable, true); michael@0: assertEq(ke.getVariable('xk'), 'value of xk'); michael@0: assertEq(ee.inspectable, false); michael@0: assertThrowsInstanceOf(() => ee.type, Error);