diff options
Diffstat (limited to 'js/src/jit-test/tests/debug/job-queue-03.js')
-rw-r--r-- | js/src/jit-test/tests/debug/job-queue-03.js | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/debug/job-queue-03.js b/js/src/jit-test/tests/debug/job-queue-03.js new file mode 100644 index 0000000000..7e3ce27ea4 --- /dev/null +++ b/js/src/jit-test/tests/debug/job-queue-03.js @@ -0,0 +1,173 @@ +// Multiple debuggers get their job queues drained after each hook. +// This covers: +// - onDebuggerStatement +// - onStep +// - onEnterFrame +// - onPop +// - onExceptionUnwind +// - breakpoint handlers +// - uncaughtExceptionHook + +const g = newGlobal({ newCompartment: true }); +g.parent = this; + +var log = ''; +let expected_throws = 0; + +function setup(global, label) { + const dbg = new Debugger; + dbg.gDO = dbg.addDebuggee(global); + dbg.log = ''; + + dbg.onDebuggerStatement = function (frame) { + // Exercise the promise machinery: resolve a promise and perform a microtask + // checkpoint. When called from a debugger hook, the debuggee's microtasks + // should not run. + function exercise(name) { + dbg.log += name + ','; + log += `${label}-${name}-handler\n`; + Promise.resolve(42).then(v => { + assertEq(v, 42); + log += `${label}-${name}-tail\n`; + }); + } + + exercise('debugger'); + + frame.onStep = function () { + this.onStep = undefined; + exercise('step'); + }; + + dbg.onEnterFrame = function (frame) { + dbg.onEnterFrame = undefined; + frame.onPop = function(completion) { + assertEq(completion.return, 'escutcheon'); + exercise('pop'); + } + + exercise('enter'); + } + + expected_throws++; + dbg.onExceptionUnwind = function(frame, value) { + dbg.onExceptionUnwind = undefined; + assertEq(value, 'myrmidon'); + exercise('exception'); + if (--expected_throws > 0) { + return undefined; + } else { + return { return: 'escutcheon' }; + } + }; + + // Set a breakpoint on entry to g.breakpoint_here. + const script = dbg.gDO.getOwnPropertyDescriptor('breakpoint_here').value.script; + const handler = { + hit(frame) { + script.clearAllBreakpoints(); + exercise('bp'); + } + }; + script.setBreakpoint(0, handler); + + dbg.uncaughtExceptionHook = function (ex) { + assertEq(ex, 'turncoat'); + exercise('uncaught'); + }; + + // Throw an uncaught exception from the Debugger handler. This should reach + // uncaughtExceptionHook, but shouldn't affect the debuggee. + throw 'turncoat'; + }; + + return dbg; +} + +const dbg1 = setup(g, '1'); +const dbg2 = setup(g, '2'); +const dbg3 = setup(g, '3'); + +g.eval(` + function breakpoint_here() { + throw 'myrmidon'; + } + + parent.log += 'eval-start\\n'; + + // DebuggeeWouldRun detection may prevent this callback from running at all if + // bug 1145201 is present. SpiderMonkey will try to run the promise reaction + // job from the Debugger hook's microtask checkpoint, triggering + // DebuggeeWouldRun. This is a little difficult to observe, since the callback + // never even begins execution. But it should cause the 'then' promise to be + // rejected, which the shell will report (if the assertEq(log, ...) doesn't + // kill the test first). + + Promise.resolve(84).then(function(v) { + assertEq(v, 84); + parent.log += 'eval-react'; + }); + debugger; + parent.log += 'stuff to step over\\n'; + breakpoint_here(); + parent.log += 'eval-end\\n'; +`); + +log += 'main-drain\n' +drainJobQueue(); +log += 'main-drain-done\n'; + +const regex = new RegExp(`eval-start +.-debugger-handler +.-uncaught-handler +.-debugger-tail +.-uncaught-tail +.-debugger-handler +.-uncaught-handler +.-debugger-tail +.-uncaught-tail +.-debugger-handler +.-uncaught-handler +.-debugger-tail +.-uncaught-tail +.-step-handler +.-step-tail +.-step-handler +.-step-tail +.-step-handler +.-step-tail +stuff to step over +.-enter-handler +.-enter-tail +.-enter-handler +.-enter-tail +.-enter-handler +.-enter-tail +.-bp-handler +.-bp-tail +.-bp-handler +.-bp-tail +.-bp-handler +.-bp-tail +.-exception-handler +.-exception-tail +.-exception-handler +.-exception-tail +.-exception-handler +.-exception-tail +.-pop-handler +.-pop-tail +.-pop-handler +.-pop-tail +.-pop-handler +.-pop-tail +eval-end +main-drain +eval-reactmain-drain-done +`); + +assertEq(!!log.match(regex), true) + +assertEq(dbg1.log, 'debugger,uncaught,step,enter,bp,exception,pop,'); +assertEq(dbg2.log, 'debugger,uncaught,step,enter,bp,exception,pop,'); +assertEq(dbg3.log, 'debugger,uncaught,step,enter,bp,exception,pop,'); |