finally
blocks (no-unsafe-finally)The "extends": "eslint:recommended"
property in a configuration file enables this rule.
JavaScript suspends the control flow statements of try
and catch
blocks until the execution of finally
block finishes. So, when return
, throw
, break
, or continue
is used in finally
, control flow statements inside try
and catch
are overwritten, which is considered as unexpected behavior. Such as:
// We expect this function to return 1; (() => { try { return 1; // 1 is returned but suspended until finally block ends } catch(err) { return 2; } finally { return 3; // 3 is returned before 1, which we did not expect } })(); // > 3
// We expect this function to throw an error, then return (() => { try { throw new Error("Try"); // error is thrown but suspended until finally block ends } finally { return 3; // 3 is returned before the error is thrown, which we did not expect } })(); // > 3
// We expect this function to throw Try(...) error from the catch block (() => { try { throw new Error("Try") } catch(err) { throw err; // The error thrown from try block is caught and rethrown } finally { throw new Error("Finally"); // Finally(...) is thrown, which we did not expect } })(); // > Uncaught Error: Finally(...)
// We expect this function to return 0 from try block. (() => { label: try { return 0; // 0 is returned but suspended until finally block ends } finally { break label; // It breaks out the try-finally block, before 0 is returned. } return 1; })(); // > 1
This rule disallows return
, throw
, break
, and continue
statements inside finally
blocks. It allows indirect usages, such as in function
or class
definitions.
Examples of incorrect code for this rule:
/*eslint no-unsafe-finally: "error"*/ let foo = function() { try { return 1; } catch(err) { return 2; } finally { return 3; } };
/*eslint no-unsafe-finally: "error"*/ let foo = function() { try { return 1; } catch(err) { return 2; } finally { throw new Error; } };
Examples of correct code for this rule:
/*eslint no-unsafe-finally: "error"*/ let foo = function() { try { return 1; } catch(err) { return 2; } finally { console.log("hola!"); } };
/*eslint no-unsafe-finally: "error"*/ let foo = function() { try { return 1; } catch(err) { return 2; } finally { let a = function() { return "hola!"; } } };
/*eslint no-unsafe-finally: "error"*/ let foo = function(a) { try { return 1; } catch(err) { return 2; } finally { switch(a) { case 1: { console.log("hola!") break; } } } };
If you want to allow control flow operations in finally
blocks, you can turn this rule off.
This rule was introduced in ESLint 2.9.0.
© JS Foundation and other contributors
Licensed under the MIT License.
https://eslint.org/docs/rules/no-unsafe-finally