proposal-explicit-resource-management: Possibility of exception handling in the future?
Even though the proposal currently centers the motivation around resource management, the syntax is also an attractive option for performing other patterns that could also clean up JavaScript code. A couple patterns (that will look familiar to Pythonistas) one might want to use in unit tests are:
// Automatic cleanup
using (const spy = jest.withSpy(...)) { // calls `jest.spyOn(...)`
...
} // automatically calls `spy.mockRestore()`
// Error suppression and handling
using (expectToThrow(TypeError)) {
undefined[0];
} // would throw an exception if the block didn't throw a `TypeError`
The latter would require some means of specifying what to do when an exception is thrown. One way this could look is:
function expectToThrow(errorType) {
return {
[Symbol.dispose]: (error) => {
if (error instanceof errorType) {
// Returning `undefined` suppresses the error
return;
}
// Allows the error to be thrown
return error;
}
}
which would behave somewhat like
...
catch ($$error) {
// Need to distinguish between no thrown error vs `undefined` being thrown
$$try.hasBlockError = true;
$$try.blockError = $$error;
}
finally {
while ($$try.stack.length) {
const { value: $$expr, dispose: $$dispose } = $$try.stack.pop();
let $$disposeReturnedError;
try {
$$disposeReturnedError = $$dispose.call($$expr, $$try.lastError);
}
catch ($$error) {
$$try.errors.push($$error);
}
if (typeof $$disposeReturnedError !== 'undefined') {
// Always substitute the error if the dispose function returned one
$$try.hasBlockError = true;
$$try.blockError = $$disposeReturnedError;
} else if ($$dispose.length !== 0) {
// Error is suppressed if the dispose function has an error argument
$$try.hasBlockError = false;
$$try.blockError = undefined;
}
}
if ($$try.hasBlockError) {
$$try.errors.push($$try.blockError);
}
if ($$try.errors.length > 1) {
throw new AggregateError($$try.errors);
}
if ($$try.errors.length === 1) {
throw $$try.errors[0];
}
}
...
Note that this isn’t a request to modify the current proposal to include this behavior. I’m just raising this now to dissuade an API from being shipped that precludes this functionality, should it be desired in the future.
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 5
- Comments: 18
In a way you could consider disposable resources have the following implicit behavior:
Symbol.disposeis present,usingacts as if an implicit[Symbol.enterContext]()method exists (if not found).Symbol.disposeis present,usingacts as if an implicit[Symbol.exitContext]()method exists (if not found).The implied
[Symbol.enterContext]()method would act something like:The implied
[Symbol.exitContext]()method would act something like:Also just wanted to throw out the possibility of being able to do something like:
where
retryadds behavior like: