January 19, 2023
TestsSource
- Use try+finally without catch?
- execution order of try+finally
- What happens when a block returns?
- What happens when a block throws?
Source Code
The source code we wrote during the event.
try-finally.spec.js
import {strict as assert} from 'assert';
describe('Use try+finally without catch?', () => {
it('using try+finally without catch is valid syntax', () => {
assert.doesNotThrow(function() {
eval(`
try {}
finally {}
`);
});
});
it('using try without catch+finally is invalid syntax', () => {
assert.throws(function() {
eval(`try{}`);
}, SyntaxError);
});
});
describe('execution order of try+finally', () => {
it('try block is executed before finally block, if there is no exception thrown', () => {
const executedBlocks = [];
try {
executedBlocks.push('try');
} finally {
executedBlocks.push('finally');
}
assert.deepEqual(executedBlocks, ['try', 'finally']);
});
it('finally block is also executed after the try block, when it throws', () => {
const executedBlocks = []
assert.throws(() => {
try {
executedBlocks.push('try');
throw Error('an error');
} finally {
executedBlocks.push('finally');
}
})
assert.deepEqual(executedBlocks, ['try', 'finally']);
});
});
describe('What happens when a block returns?', () => {
it('returns from inside a finally block, also when there is a return inside try block', () => {
function functionThatReturnsFromTryAndFinally() {
try {
return 'returned from try';
} finally {
return 'returned from finally';
}
}
assert.equal(functionThatReturnsFromTryAndFinally(), 'returned from finally');
});
it('returns from inside the try block, when there is no return inside the finally block', () => {
function returnFromTry() {
try {
return 'from try';
} finally {
// do not return
}
}
assert.equal(returnFromTry(), 'from try');
});
it('returns from inside the finally block, even when undefined is returned by it', () => {
function returnsHopefully() {
try {
return 'from try';
} finally {
return undefined;
}
}
assert.equal(returnsHopefully(), undefined);
});
it('returns throwing in the try block and returning in the finally block', () => {
function fn() {
try {
throw 'in try';
} finally {
return 'from finally'
}
}
assert.equal(fn(), 'from finally');
});
});
describe('What happens when a block throws?', () => {
it('throws even when there is a finally block that does not return or throw', () => {
function fn() {
try {
throw 'in try';
} finally {
// do nothing
}
}
assert.throws(fn);
});
it('throwing inside finally is what is returned, even when try throws', () => {
class TryError extends Error {};
class FinallyError extends Error {};
function fn() {
try {
throw new TryError();
} finally {
throw new FinallyError();
}
}
assert.throws(fn, FinallyError);
});
});