tor-browser

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

disposable-stack-error-handling.js (3571B)


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