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 }