Debugger-onEnterFrame-resumption-05.js (3177B)
1 // Exercise the call to ScriptDebugPrologue in js_InternalInterpret. 2 3 // This may change, but as of this writing, inline caches (ICs) are 4 // disabled in debug mode, and those are the only users of the out-of-line entry 5 // points for JIT code (arityCheckEntry, argsCheckEntry, fastEntry); debug 6 // mode uses only invokeEntry. This means most of the bytecode tails in 7 // js_InternalInterpret that might call ScriptPrologue or ScriptEpilogue are 8 // unreachable in debug mode: they're only called from the out-of-line entry 9 // points. 10 // 11 // The exception is REJOIN_THIS_PROTOTYPE, which can be reached reliably if you 12 // add a JS_GC call to stubs::GetPropNoCache. JIT code calls that stub to 13 // retrieve the 'prototype' property of a function called as a constructor, if 14 // TI can't establish the exact identity of that prototype's value at compile 15 // time. Thus the preoccupation with constructors here. 16 17 load(libdir + "asserts.js"); 18 19 var debuggee = newGlobal({newCompartment: true}); 20 var dbg = Debugger(debuggee); 21 var hits, savedFrame; 22 23 // Allow the constructor to return normally. 24 dbg.onEnterFrame = function (frame) { 25 hits++; 26 if (frame.constructing) { 27 savedFrame = frame; 28 assertEq(savedFrame.onStack, true); 29 return undefined; 30 } 31 return undefined; 32 }; 33 hits = 0; 34 debuggee.hits = 0; 35 savedFrame = undefined; 36 assertEq(typeof debuggee.eval("function f(){ hits++; } f.prototype = {}; new f;"), "object"); 37 assertEq(hits, 2); 38 assertEq(savedFrame.onStack, false); 39 assertEq(debuggee.hits, 1); 40 41 // Force an early return from the constructor. 42 dbg.onEnterFrame = function (frame) { 43 hits++; 44 if (frame.constructing) { 45 savedFrame = frame; 46 assertEq(savedFrame.onStack, true); 47 return { return: "pass" }; 48 } 49 return undefined; 50 }; 51 hits = 0; 52 debuggee.hits = 0; 53 savedFrame = undefined; 54 assertEq(typeof debuggee.eval("function f(){ hits++; } f.prototype = {}; new f;"), "object"); 55 assertEq(hits, 2); 56 assertEq(savedFrame.onStack, false); 57 assertEq(debuggee.hits, 0); 58 59 // Force the constructor to throw an exception. 60 dbg.onEnterFrame = function (frame) { 61 hits++; 62 if (frame.constructing) { 63 savedFrame = frame; 64 assertEq(savedFrame.onStack, true); 65 return { throw: "pass" }; 66 } 67 return undefined; 68 }; 69 hits = 0; 70 debuggee.hits = 0; 71 savedFrame = undefined; 72 assertThrowsValue(function () { 73 debuggee.eval("function f(){ hits++ } f.prototype = {}; new f;"); 74 }, "pass"); 75 assertEq(hits, 2); 76 assertEq(savedFrame.onStack, false); 77 assertEq(debuggee.hits, 0); 78 79 // Ensure that forcing an early return only returns from one JS call. 80 debuggee.eval("function g() { var result = new f; g_hits++; return result; }"); 81 dbg.onEnterFrame = function (frame) { 82 hits++; 83 if (frame.constructing) { 84 savedFrame = frame; 85 assertEq(savedFrame.onStack, true); 86 return { return: "pass" }; 87 } 88 return undefined; 89 }; 90 hits = 0; 91 debuggee.hits = 0; 92 debuggee.g_hits = 0; 93 savedFrame = undefined; 94 assertEq(typeof debuggee.eval("g();"), "object"); 95 assertEq(hits, 3); 96 assertEq(savedFrame.onStack, false); 97 assertEq(debuggee.hits, 0); 98 assertEq(debuggee.g_hits, 1);