1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit-test/tests/debug/Frame-onPop-multiple-01.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,127 @@ 1.4 +// Multiple debuggers all get their onPop handlers called, and see each others' effects. 1.5 + 1.6 +function completionsEqual(c1, c2) { 1.7 + if (c1 && c2) { 1.8 + if (c1.throw) 1.9 + return c1.throw === c2.throw; 1.10 + else 1.11 + return c1.return === c2.return; 1.12 + } 1.13 + return c1 === c2; 1.14 +} 1.15 + 1.16 +function completionString(c) { 1.17 + if (c == null) 1.18 + return 'x'; 1.19 + if (c.return) 1.20 + return 'r' + c.return; 1.21 + if (c.throw) 1.22 + return 't' + c.throw; 1.23 + return '?'; 1.24 +} 1.25 + 1.26 +var g = newGlobal(); // poor thing 1.27 +g.eval('function f() { debugger; return "1"; }'); 1.28 + 1.29 +// We create a bunch of debuggers, but they all consult this global variable 1.30 +// for expectations and responses, so the order in which events get 1.31 +// reported to the debuggers doesn't matter. 1.32 +// 1.33 +// This list includes every pair of transitions, and is of minimal length. 1.34 +// As if opportunity cost were just some theoretical concern. 1.35 +var sequence = [{ expect: { return: '1' }, resume: { return: '2'} }, 1.36 + { expect: { return: '2' }, resume: { throw: '3'} }, 1.37 + { expect: { throw: '3' }, resume: { return: '4'} }, 1.38 + { expect: { return: '4' }, resume: null }, 1.39 + { expect: null, resume: { throw: '5'} }, 1.40 + { expect: { throw: '5' }, resume: { throw: '6'} }, 1.41 + { expect: { throw: '6' }, resume: null }, 1.42 + { expect: null, resume: null }, 1.43 + { expect: null, resume: { return: '7'} }]; 1.44 + 1.45 +// A list of the debuggers' Debugger.Frame instances. When it's all over, 1.46 +// we test that they are all marked as no longer live. 1.47 +var frames = []; 1.48 + 1.49 +// We start off the test via Debugger.Frame.prototype.eval, so if we end 1.50 +// with a termination, we still catch it, instead of aborting the whole 1.51 +// test. (Debugger.Object.prototype.evalInGlobal would simplify this...) 1.52 +var dbg0 = new Debugger(g); 1.53 +dbg0.onEnterFrame = function handleOriginalEnter(frame) { 1.54 + dbg0.log += '('; 1.55 + dbg0.onEnterFrame = undefined; 1.56 + 1.57 + assertEq(frame.live, true); 1.58 + frames.push(frame); 1.59 + 1.60 + var dbgs = []; 1.61 + var log; 1.62 + 1.63 + // Create a separate debugger to carry out each item in sequence. 1.64 + for (s in sequence) { 1.65 + // Each debugger's handlers close over a distinct 'dbg', but 1.66 + // that's the only distinction between them. Otherwise, they're 1.67 + // driven entirely by global data, so the order in which events are 1.68 + // dispatched to them shouldn't matter. 1.69 + let dbg = new Debugger(g); 1.70 + dbgs.push(dbg); 1.71 + 1.72 + dbg.onDebuggerStatement = function handleDebuggerStatement(f) { 1.73 + log += 'd'; 1.74 + assertEq(f.live, true); 1.75 + frames.push(f); 1.76 + }; 1.77 + 1.78 + // First expect the 'eval'... 1.79 + dbg.onEnterFrame = function handleEnterEval(f) { 1.80 + log += 'e'; 1.81 + assertEq(f.type, 'eval'); 1.82 + assertEq(f.live, true); 1.83 + frames.push(f); 1.84 + 1.85 + // Then expect the call. 1.86 + dbg.onEnterFrame = function handleEnterCall(f) { 1.87 + log += '('; 1.88 + assertEq(f.type, 'call'); 1.89 + assertEq(f.live, true); 1.90 + frames.push(f); 1.91 + 1.92 + // Don't expect any further frames. 1.93 + dbg.onEnterFrame = function handleExtraEnter(f) { 1.94 + log += 'z'; 1.95 + }; 1.96 + 1.97 + f.onPop = function handlePop(c) { 1.98 + log += ')' + completionString(c); 1.99 + assertEq(this.live, true); 1.100 + frames.push(this); 1.101 + 1.102 + // Check that this debugger is in the list, and then remove it. 1.103 + var i = dbgs.indexOf(dbg); 1.104 + assertEq(i != -1, true); 1.105 + dbgs.splice(i,1); 1.106 + 1.107 + // Check the frame's completion value against 'sequence'. 1.108 + assertEq(completionsEqual(c, sequence[0].expect), true); 1.109 + 1.110 + // Provide the next resumption value from 'sequence'. 1.111 + return sequence.shift().resume; 1.112 + }; 1.113 + }; 1.114 + }; 1.115 + } 1.116 + 1.117 + log = ''; 1.118 + assertEq(completionsEqual(frame.eval('f()'), { return: '7' }), true); 1.119 + assertEq(log, "eeeeeeeee(((((((((ddddddddd)r1)r2)t3)r4)x)t5)t6)x)x"); 1.120 + 1.121 + dbg0.log += '.'; 1.122 +}; 1.123 + 1.124 +dbg0.log = ''; 1.125 +g.eval('eval'); 1.126 +assertEq(dbg0.log, '(.'); 1.127 + 1.128 +// Check that all Debugger.Frame instances we ran into are now marked as dead. 1.129 +for (var i = 0; i < frames.length; i++) 1.130 + assertEq(frames[i].live, false);