tor-browser

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

bug1644699-terminated-generator.js (2435B)


      1 // |jit-test| exitstatus:6
      2 // Ensure that a frame terminated due to an interrupt in the generator
      3 // builtin will properly be treated as terminated.
      4 
      5 const g = newGlobal({ newCompartment: true });
      6 const dbg = new Debugger(g);
      7 g.eval(`
      8 var done = false;
      9 async function* f() {
     10  await null;
     11  await null;
     12  await null;
     13  await null;
     14  done = true;
     15 }
     16 `);
     17 
     18 dbg.onEnterFrame = f => {
     19  frame = f;
     20  dbg.onEnterFrame = undefined;
     21 };
     22 
     23 setInterruptCallback(function() {
     24  const stack = saveStack();
     25 
     26  // We want to explicitly terminate inside the AsyncGeneratorNext builtin
     27  // when it tries to resume execution at the 'await' in the async generator.
     28  // Terminating inside AsyncGeneratorNext causes the generator to be closed,
     29  // and for this test case we specifically need that to happen without
     30  // entering the async generator frame because we're aiming to trigger the
     31  // case where DebugAPI::onLeaveFrame does not having the opportunity to
     32  // clean up the generator information associated with the Debugger.Frame.
     33  if (
     34    stack.parent &&
     35    stack.parent.source === "self-hosted" &&
     36    stack.parent.functionDisplayName === "AsyncGeneratorNext" &&
     37    stack.parent.parent &&
     38    stack.parent.parent.source === stack.source &&
     39    stack.parent.parent.line === DRAIN_QUEUE_LINE
     40  ) {
     41    return false;
     42  }
     43 
     44  // Keep interrupting until we find the right place.
     45  interruptIf(true);
     46  return true;
     47 });
     48 
     49 // Run the async generator and suspend at the first await.
     50 const it = g.f();
     51 let promise = it.next();
     52 
     53 // Queue the interrupt so that it will start trying to terminate inside the
     54 // generator builtin.
     55 interruptIf(true);
     56 
     57 // Explicitly drain the queue to run the async generator to completion.
     58 const DRAIN_QUEUE_LINE = saveStack().line + 1;
     59 drainJobQueue();
     60 
     61 let threw = false;
     62 try {
     63  // In the original testcase for this bug, this call would cause
     64  // an assertion failure because the generator was closed.
     65  frame.environment;
     66 } catch (err) {
     67  threw = true;
     68 }
     69 assertEq(threw, true);
     70 
     71 // The frame here still has a GeneratorInfo datastructure because the
     72 // termination interrupt will cause the generator to be closed without
     73 // clearing that data. The frame must still be treated as terminated in
     74 // this case in order for the Debugger API to behave consistently.
     75 assertEq(frame.terminated, true);
     76 
     77 // We should never reach the end of the async generator because it will
     78 // have been terminated.
     79 assertEq(g.done, false);