tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

job-queue-01.js (3247B)


      1 // Debuggee promise reaction jobs should not run from debugger callbacks.
      2 // This covers:
      3 // - onDebuggerStatement
      4 // - onStep
      5 // - onEnterFrame
      6 // - onPop
      7 // - onExceptionUnwind
      8 // - breakpoint handlers
      9 // - uncaughtExceptionHook
     10 
     11 var g = newGlobal({ newCompartment: true });
     12 g.parent = this;
     13 var dbg = new Debugger;
     14 var gDO = dbg.addDebuggee(g);
     15 var log = '';
     16 
     17 // Exercise the promise machinery: resolve a promise and drain the job queue (or
     18 // in HTML terms, perform a microtask checkpoint). When called from a debugger
     19 // hook, the debuggee's microtasks should not run.
     20 function exercise(name) {
     21  log += `${name}-handler`;
     22  Promise.resolve(42).then(v => {
     23    assertEq(v, 42);
     24    log += `${name}-react`;
     25  });
     26  log += `(`;
     27  drainJobQueue();
     28  log += `)`;
     29 
     30  // This should be run by the implicit microtask checkpoint after each Debugger
     31  // hook call.
     32  Promise.resolve(42).then(v => {
     33    assertEq(v, 42);
     34    log += `(${name}-tail)`;
     35  });
     36 }
     37 
     38 dbg.onDebuggerStatement = function (frame) {
     39  exercise('debugger');
     40 
     41  frame.onStep = function () {
     42    this.onStep = undefined;
     43    exercise('step');
     44  };
     45 
     46  dbg.onEnterFrame = function (frame) {
     47    dbg.onEnterFrame = undefined;
     48    frame.onPop = function(completion) {
     49      assertEq(completion.return, 'recompense');
     50      exercise('pop');
     51    }
     52 
     53    exercise('enter');
     54  }
     55 
     56  dbg.onExceptionUnwind = function(frame, value) {
     57    dbg.onExceptionUnwind = undefined;
     58    assertEq(value, 'recidivism');
     59    exercise('exception');
     60    return { return: 'recompense' };
     61  };
     62 
     63  // Set a breakpoint on entry to g.breakpoint_here.
     64  const script = gDO.getOwnPropertyDescriptor('breakpoint_here').value.script;
     65  const handler = {
     66    hit(frame) {
     67      script.clearAllBreakpoints();
     68      exercise('bp');
     69    }
     70  };
     71  script.setBreakpoint(0, handler);
     72 
     73  dbg.uncaughtExceptionHook = function (ex) {
     74    assertEq(ex, 'turncoat');
     75    exercise('uncaught');
     76  };
     77 
     78  // Throw an uncaught exception from the Debugger handler. This should reach
     79  // uncaughtExceptionHook, but shouldn't affect the debuggee.
     80  throw 'turncoat';
     81 };
     82 
     83 g.eval(`
     84  function breakpoint_here() {
     85    throw 'recidivism';
     86  }
     87 
     88  parent.log += 'eval(';
     89 
     90  // DebuggeeWouldRun detection may prevent this callback from running at all if
     91  // bug 1145201 is present. SpiderMonkey will try to run the promise reaction
     92  // job from the Debugger hook's microtask checkpoint, triggering
     93  // DebuggeeWouldRun. This is a little difficult to observe, since the callback
     94  // never even begins execution. But it should cause the 'then' promise to be
     95  // rejected, which the shell will report (if the assertEq(log, ...) doesn't
     96  // kill the test first).
     97 
     98  Promise.resolve(84).then(function(v) {
     99    assertEq(v, 84);
    100    parent.log += 'eval-react';
    101  });
    102  debugger;
    103  parent.log += '...';
    104  breakpoint_here();
    105  parent.log += ')';
    106 `);
    107 
    108 log += 'main-drain('
    109 drainJobQueue();
    110 log += ')';
    111 
    112 assertEq(log, `eval(\
    113 debugger-handler(debugger-react)\
    114 uncaught-handler((debugger-tail)uncaught-react)(uncaught-tail)\
    115 step-handler(step-react)(step-tail)\
    116 ...\
    117 enter-handler(enter-react)(enter-tail)\
    118 bp-handler(bp-react)(bp-tail)\
    119 exception-handler(exception-react)(exception-tail)\
    120 pop-handler(pop-react)(pop-tail)\
    121 )\
    122 main-drain(eval-react)`);