tor-browser

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

job-queue-03.js (4120B)


      1 // Multiple debuggers get their job queues drained after each hook.
      2 // This covers:
      3 // - onDebuggerStatement
      4 // - onStep
      5 // - onEnterFrame
      6 // - onPop
      7 // - onExceptionUnwind
      8 // - breakpoint handlers
      9 // - uncaughtExceptionHook
     10 
     11 const g = newGlobal({ newCompartment: true });
     12 g.parent = this;
     13 
     14 var log = '';
     15 let expected_throws = 0;
     16 
     17 function setup(global, label) {
     18  const dbg = new Debugger;
     19  dbg.gDO = dbg.addDebuggee(global);
     20  dbg.log = '';
     21 
     22  dbg.onDebuggerStatement = function (frame) {
     23    // Exercise the promise machinery: resolve a promise and perform a microtask
     24    // checkpoint. When called from a debugger hook, the debuggee's microtasks
     25    // should not run.
     26    function exercise(name) {
     27      dbg.log += name + ',';
     28      log += `${label}-${name}-handler\n`;
     29      Promise.resolve(42).then(v => {
     30        assertEq(v, 42);
     31        log += `${label}-${name}-tail\n`;
     32      });
     33    }
     34 
     35    exercise('debugger');
     36 
     37    frame.onStep = function () {
     38      this.onStep = undefined;
     39      exercise('step');
     40    };
     41 
     42    dbg.onEnterFrame = function (frame) {
     43      dbg.onEnterFrame = undefined;
     44      frame.onPop = function(completion) {
     45        assertEq(completion.return, 'escutcheon');
     46        exercise('pop');
     47      }
     48 
     49      exercise('enter');
     50    }
     51 
     52    expected_throws++;
     53    dbg.onExceptionUnwind = function(frame, value) {
     54      dbg.onExceptionUnwind = undefined;
     55      assertEq(value, 'myrmidon');
     56      exercise('exception');
     57      if (--expected_throws > 0) {
     58        return undefined;
     59      } else {
     60        return { return: 'escutcheon' };
     61      }
     62    };
     63 
     64    // Set a breakpoint on entry to g.breakpoint_here.
     65    const script = dbg.gDO.getOwnPropertyDescriptor('breakpoint_here').value.script;
     66    const handler = {
     67      hit(frame) {
     68        script.clearAllBreakpoints();
     69        exercise('bp');
     70      }
     71    };
     72    script.setBreakpoint(0, handler);
     73 
     74    dbg.uncaughtExceptionHook = function (ex) {
     75      assertEq(ex, 'turncoat');
     76      exercise('uncaught');
     77    };
     78 
     79    // Throw an uncaught exception from the Debugger handler. This should reach
     80    // uncaughtExceptionHook, but shouldn't affect the debuggee.
     81    throw 'turncoat';
     82  };
     83 
     84  return dbg;
     85 }
     86 
     87 const dbg1 = setup(g, '1');
     88 const dbg2 = setup(g, '2');
     89 const dbg3 = setup(g, '3');
     90 
     91 g.eval(`
     92  function breakpoint_here() {
     93    throw 'myrmidon';
     94  }
     95 
     96  parent.log += 'eval-start\\n';
     97 
     98  // DebuggeeWouldRun detection may prevent this callback from running at all if
     99  // bug 1145201 is present. SpiderMonkey will try to run the promise reaction
    100  // job from the Debugger hook's microtask checkpoint, triggering
    101  // DebuggeeWouldRun. This is a little difficult to observe, since the callback
    102  // never even begins execution. But it should cause the 'then' promise to be
    103  // rejected, which the shell will report (if the assertEq(log, ...) doesn't
    104  // kill the test first).
    105 
    106  Promise.resolve(84).then(function(v) {
    107    assertEq(v, 84);
    108    parent.log += 'eval-react';
    109  });
    110  debugger;
    111  parent.log += 'stuff to step over\\n';
    112  breakpoint_here();
    113  parent.log += 'eval-end\\n';
    114 `);
    115 
    116 log += 'main-drain\n'
    117 drainJobQueue();
    118 log += 'main-drain-done\n';
    119 
    120 const regex = new RegExp(`eval-start
    121 .-debugger-handler
    122 .-uncaught-handler
    123 .-debugger-tail
    124 .-uncaught-tail
    125 .-debugger-handler
    126 .-uncaught-handler
    127 .-debugger-tail
    128 .-uncaught-tail
    129 .-debugger-handler
    130 .-uncaught-handler
    131 .-debugger-tail
    132 .-uncaught-tail
    133 .-step-handler
    134 .-step-tail
    135 .-step-handler
    136 .-step-tail
    137 .-step-handler
    138 .-step-tail
    139 stuff to step over
    140 .-enter-handler
    141 .-enter-tail
    142 .-enter-handler
    143 .-enter-tail
    144 .-enter-handler
    145 .-enter-tail
    146 .-bp-handler
    147 .-bp-tail
    148 .-bp-handler
    149 .-bp-tail
    150 .-bp-handler
    151 .-bp-tail
    152 .-exception-handler
    153 .-exception-tail
    154 .-exception-handler
    155 .-exception-tail
    156 .-exception-handler
    157 .-exception-tail
    158 .-pop-handler
    159 .-pop-tail
    160 .-pop-handler
    161 .-pop-tail
    162 .-pop-handler
    163 .-pop-tail
    164 eval-end
    165 main-drain
    166 eval-reactmain-drain-done
    167 `);
    168 
    169 assertEq(!!log.match(regex), true)
    170 
    171 assertEq(dbg1.log, 'debugger,uncaught,step,enter,bp,exception,pop,');
    172 assertEq(dbg2.log, 'debugger,uncaught,step,enter,bp,exception,pop,');
    173 assertEq(dbg3.log, 'debugger,uncaught,step,enter,bp,exception,pop,');