Skip to content

Commit 1a0161f

Browse files
brettz9MichaelDeBoey
authored andcommittedOct 9, 2024
feat: add allowThenStrict option; fixes #52
1 parent 3d22840 commit 1a0161f

File tree

3 files changed

+100
-2
lines changed

3 files changed

+100
-2
lines changed
 

‎__tests__/catch-or-return.js

+62
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,37 @@ ruleTester.run('catch-or-return', rule, {
8989
options: [{ allowThen: true }],
9090
},
9191

92+
// allowThenStrict - .then(null, fn)
93+
{
94+
code: 'frank().then(go).then(null, doIt)',
95+
options: [{ allowThenStrict: true }],
96+
},
97+
{
98+
code: 'frank().then(go).then().then().then().then(null, doIt)',
99+
options: [{ allowThenStrict: true }],
100+
},
101+
{
102+
code: 'frank().then(go).then().then(null, function() { /* why bother */ })',
103+
options: [{ allowThenStrict: true }],
104+
},
105+
{
106+
code: 'frank.then(go).then(to).then(null, jail)',
107+
options: [{ allowThenStrict: true }],
108+
},
109+
110+
{
111+
code: 'frank().then(a).then(b).then(null, c)',
112+
options: [{ allowThenStrict: true }],
113+
},
114+
{
115+
code: 'frank().then(a).then(b).then().then().then(null, doIt)',
116+
options: [{ allowThenStrict: true }],
117+
},
118+
{
119+
code: 'frank().then(a).then(b).then(null, function() { /* why bother */ })',
120+
options: [{ allowThenStrict: true }],
121+
},
122+
92123
// allowFinally - .finally(fn)
93124
{
94125
code: 'frank().then(go).catch(doIt).finally(fn)',
@@ -273,5 +304,36 @@ ruleTester.run('catch-or-return', rule, {
273304
code: 'frank.then(go).then(to).then(pewPew, jail)',
274305
errors: [{ message: catchMessage }],
275306
},
307+
308+
{
309+
code: 'frank().then(a, b)',
310+
errors: [{ message: catchMessage }],
311+
options: [{ allowThenStrict: true }],
312+
},
313+
{
314+
code: 'frank().then(go).then(zam, doIt)',
315+
errors: [{ message: catchMessage }],
316+
options: [{ allowThenStrict: true }],
317+
},
318+
{
319+
code: 'frank().then(a).then(b).then(c, d)',
320+
errors: [{ message: catchMessage }],
321+
options: [{ allowThenStrict: true }],
322+
},
323+
{
324+
code: 'frank().then(go).then().then().then().then(wham, doIt)',
325+
errors: [{ message: catchMessage }],
326+
options: [{ allowThenStrict: true }],
327+
},
328+
{
329+
code: 'frank().then(go).then().then(function() {}, function() { /* why bother */ })',
330+
errors: [{ message: catchMessage }],
331+
options: [{ allowThenStrict: true }],
332+
},
333+
{
334+
code: 'frank.then(go).then(to).then(pewPew, jail)',
335+
errors: [{ message: catchMessage }],
336+
options: [{ allowThenStrict: true }],
337+
},
276338
],
277339
})

‎docs/rules/catch-or-return.md

+28
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,34 @@ myPromise.then(null, handleErrors)
5555
myPromise.then(doSomething).catch(handleErrors)
5656
```
5757

58+
##### `allowThenStrict`
59+
60+
`allowThenStrict` is similar to `allowThen` but it only permits `then` when the
61+
fulfillment handler is `null`. This option ensures that the final rejected
62+
handler works like a `catch` and can handle any uncaught errors from the final
63+
`then`.
64+
65+
Examples of **incorrect** code for the default `{ allowThenStrict: false }`
66+
option:
67+
68+
```js
69+
myPromise.then(doSomething, handleErrors)
70+
myPromise.then(null, handleErrors)
71+
```
72+
73+
Examples of **correct** code for the `{ allowThenStrict: true }` option:
74+
75+
```js
76+
myPromise.then(null, handleErrors)
77+
myPromise.then(doSomething).catch(handleErrors)
78+
```
79+
80+
Examples of **incorrect** code for the `{ allowThenStrict: true }` option:
81+
82+
```js
83+
myPromise.then(doSomething, handleErrors)
84+
```
85+
5886
##### `allowFinally`
5987

6088
You can pass an `{ allowFinally: true }` as an option to this rule to allow for

‎rules/catch-or-return.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ module.exports = {
3030
allowThen: {
3131
type: 'boolean',
3232
},
33+
allowThenStrict: {
34+
type: 'boolean',
35+
},
3336
terminationMethod: {
3437
oneOf: [
3538
{ type: 'string' },
@@ -49,6 +52,7 @@ module.exports = {
4952
create(context) {
5053
const options = context.options[0] || {}
5154
const allowThen = options.allowThen
55+
const allowThenStrict = options.allowThenStrict
5256
const allowFinally = options.allowFinally
5357
let terminationMethod = options.terminationMethod || 'catch'
5458

@@ -59,11 +63,15 @@ module.exports = {
5963
function isAllowedPromiseTermination(expression) {
6064
// somePromise.then(a, b)
6165
if (
62-
allowThen &&
66+
(allowThen || allowThenStrict) &&
6367
expression.type === 'CallExpression' &&
6468
expression.callee.type === 'MemberExpression' &&
6569
expression.callee.property.name === 'then' &&
66-
expression.arguments.length === 2
70+
expression.arguments.length === 2 &&
71+
// somePromise.then(null, b)
72+
((allowThen && !allowThenStrict) ||
73+
(expression.arguments[0].type === 'Literal' &&
74+
expression.arguments[0].value === null))
6775
) {
6876
return true
6977
}

0 commit comments

Comments
 (0)