-
Notifications
You must be signed in to change notification settings - Fork 29.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tools: add linting rule for async IIFEs
The result of an async IIFE should always be handled in our tests, typically by adding `.then(common.mustCall())` to verify that the async function actually finishes executing at some point. PR-URL: #34363 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Richard Lau <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]>
- Loading branch information
Showing
3 changed files
with
90 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
if (!common.hasCrypto) | ||
common.skip('missing crypto'); | ||
common.skipIfEslintMissing(); | ||
|
||
const RuleTester = require('../../tools/node_modules/eslint').RuleTester; | ||
const rule = require('../../tools/eslint-rules/async-iife-no-unused-result'); | ||
|
||
const message = 'The result of an immediately-invoked async function needs ' + | ||
'to be used (e.g. with `.then(common.mustCall())`)'; | ||
|
||
const tester = new RuleTester({ parserOptions: { ecmaVersion: 8 } }); | ||
tester.run('async-iife-no-unused-result', rule, { | ||
valid: [ | ||
'(() => {})()', | ||
'(async () => {})', | ||
'(async () => {})().then()', | ||
'(async () => {})().catch()', | ||
'(function () {})()', | ||
'(async function () {})', | ||
'(async function () {})().then()', | ||
'(async function () {})().catch()', | ||
], | ||
invalid: [ | ||
{ | ||
code: '(async () => {})()', | ||
errors: [{ message }], | ||
output: '(async () => {})()', | ||
}, | ||
{ | ||
code: '(async function() {})()', | ||
errors: [{ message }], | ||
output: '(async function() {})()', | ||
}, | ||
{ | ||
code: "const common = require('../common');(async () => {})()", | ||
errors: [{ message }], | ||
output: "const common = require('../common');(async () => {})()" + | ||
'.then(common.mustCall())', | ||
}, | ||
{ | ||
code: "const common = require('../common');(async function() {})()", | ||
errors: [{ message }], | ||
output: "const common = require('../common');(async function() {})()" + | ||
'.then(common.mustCall())', | ||
}, | ||
] | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
'use strict'; | ||
const { isCommonModule } = require('./rules-utils.js'); | ||
|
||
function isAsyncIIFE(node) { | ||
const { callee: { type, async } } = node; | ||
const types = ['FunctionExpression', 'ArrowFunctionExpression']; | ||
return types.includes(type) && async; | ||
} | ||
|
||
const message = | ||
'The result of an immediately-invoked async function needs to be used ' + | ||
'(e.g. with `.then(common.mustCall())`)'; | ||
|
||
module.exports = { | ||
meta: { | ||
fixable: 'code' | ||
}, | ||
create: function(context) { | ||
let hasCommonModule = false; | ||
return { | ||
CallExpression: function(node) { | ||
if (isCommonModule(node) && node.parent.type === 'VariableDeclarator') { | ||
hasCommonModule = true; | ||
} | ||
|
||
if (!isAsyncIIFE(node)) return; | ||
if (node.parent && node.parent.type === 'ExpressionStatement') { | ||
context.report({ | ||
node, | ||
message, | ||
fix: (fixer) => { | ||
if (hasCommonModule) | ||
return fixer.insertTextAfter(node, '.then(common.mustCall())'); | ||
} | ||
}); | ||
} | ||
} | ||
}; | ||
} | ||
}; |