tor-browser

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

async-disposable-stack-error-handling.js (3928B)


      1 // |jit-test| skip-if: !getBuildConfiguration("explicit-resource-management"); --enable-explicit-resource-management
      2 
      3 load(libdir + "asserts.js");
      4 
      5 {
      6  const disposed = [];
      7  const errorToThrow = new Error("error");
      8  const stack = new AsyncDisposableStack();
      9  const obj = {
     10    [Symbol.asyncDispose]() {
     11      disposed.push(1);
     12      throw errorToThrow;
     13    },
     14  };
     15  stack.use(obj);
     16  assertEq(stack.disposed, false);
     17  assertThrowsInstanceOfAsync(async () => {
     18    await stack.disposeAsync();
     19  }, Error);
     20  assertArrayEq(disposed, [1]);
     21  assertEq(stack.disposed, true);
     22 }
     23 
     24 {
     25  const disposed = [];
     26  const errorsToThrow = [new Error("error1"), new Error("error2"), new Error("error3")];
     27  const stack = new AsyncDisposableStack();
     28  for (let i = 0; i < 3; i++) {
     29    stack.use({
     30      [Symbol.asyncDispose]() {
     31        disposed.push(i);
     32        throw errorsToThrow[i];
     33      },
     34    });
     35  }
     36  assertEq(stack.disposed, false);
     37  assertSuppressionChainAsync(async () => { await stack.disposeAsync() }, errorsToThrow);
     38  assertEq(stack.disposed, true);
     39  assertArrayEq(disposed, [2, 1, 0]);
     40  stack.disposeAsync();
     41  drainJobQueue();
     42  assertArrayEq(disposed, [2, 1, 0]);
     43 }
     44 
     45 {
     46  const disposed = [];
     47  const errorsToThrow = [new Error("error1"), new Error("error2"), new Error("error3"), new Error("error4")];
     48  async function testStackDisposalWithUsingAndErrors() {
     49    const stack = new AsyncDisposableStack();
     50    for (let i = 0; i < 3; i++) {
     51      stack.use({
     52        [Symbol.asyncDispose]() {
     53          disposed.push(i);
     54          throw errorsToThrow[i];
     55        },
     56      });
     57    }
     58    assertEq(stack.disposed, false);
     59    {
     60      await using stk = stack;
     61      stk.use({
     62        [Symbol.asyncDispose]() {
     63          disposed.push(3);
     64          throw errorsToThrow[3];
     65        },
     66      });
     67    }
     68  }
     69  assertSuppressionChainAsync(testStackDisposalWithUsingAndErrors, errorsToThrow);
     70  assertArrayEq(disposed, [3, 2, 1, 0]);
     71 }
     72 
     73 {
     74  const disposed = [];
     75  const errorsToThrow = [new Error("error1"), new Error("error2"), new Error("error3")];
     76  async function testStackDisposalWithUseAdoptDeferAndErrors() {
     77    const stack = new AsyncDisposableStack();
     78    stack.use({
     79      [Symbol.asyncDispose]() {
     80        disposed.push(1);
     81        throw errorsToThrow[0];
     82      },
     83    });
     84    stack.adopt(2, (v) => {
     85      disposed.push(v);
     86      throw errorsToThrow[1];
     87    });
     88    stack.defer(() => {
     89      disposed.push(3);
     90      throw errorsToThrow[2];
     91    });
     92    assertEq(stack.disposed, false);
     93    await stack.disposeAsync();
     94  }
     95  assertSuppressionChainAsync(testStackDisposalWithUseAdoptDeferAndErrors, errorsToThrow);
     96  assertArrayEq(disposed, [3, 2, 1]);
     97 }
     98 
     99 {
    100  const disposed = [];
    101  const errorsToThrow = [new Error("error1"), new Error("error2"), new Error("error3"), new Error("error4")];
    102  async function testStackDisposalWithUseAdoptDeferAndErrorsAndOutsideError() {
    103    await using stack = new AsyncDisposableStack();
    104    stack.use({
    105      [Symbol.asyncDispose]() {
    106        disposed.push(1);
    107        throw errorsToThrow[0];
    108      },
    109    });
    110    stack.adopt(2, (v) => {
    111      disposed.push(v);
    112      throw errorsToThrow[1];
    113    });
    114    stack.defer(() => {
    115      disposed.push(3);
    116      throw errorsToThrow[2];
    117    });
    118 
    119    throw errorsToThrow[3];
    120  }
    121  let caught = false;
    122  async function test() {
    123    try {
    124      await testStackDisposalWithUseAdoptDeferAndErrorsAndOutsideError();
    125    } catch (err) {
    126      caught = true;
    127      // the error thrown at function end would be suppressed and while
    128      // disposing the stack there would be another suppressed error.
    129      assertEq(err instanceof SuppressedError, true);
    130      assertEq(err.suppressed === errorsToThrow[3], true);
    131      assertSuppressionChain(() => { throw err.error }, [errorsToThrow[0], errorsToThrow[1], errorsToThrow[2]]);
    132    } finally {
    133      assertEq(caught, true);
    134    }
    135  }
    136  test();
    137  drainJobQueue();
    138  assertArrayEq(disposed, [3, 2, 1]);
    139 }