diff --git a/lib/rules/no-async-in-computed-properties.js b/lib/rules/no-async-in-computed-properties.js index 53dd83e6e..ba34e1f82 100644 --- a/lib/rules/no-async-in-computed-properties.js +++ b/lib/rules/no-async-in-computed-properties.js @@ -73,6 +73,7 @@ module.exports = { create (context) { const forbiddenNodes = [] + const allowedScopes = [] const expressionTypes = { promise: 'asynchronous action', @@ -88,6 +89,8 @@ module.exports = { node: node, type: 'async' }) + } else if (node.parent.type === 'ReturnStatement') { + allowedScopes.push(node) } } @@ -105,6 +108,8 @@ module.exports = { node: node, type: 'new' }) + } else if (node.parent.type === 'ReturnStatement') { + allowedScopes.push(node) } }, @@ -114,12 +119,13 @@ module.exports = { node: node, type: 'promise' }) - } - if (isTimedFunction(node)) { + } else if (isTimedFunction(node)) { forbiddenNodes.push({ node: node, type: 'timed' }) + } else if (node.parent.type === 'ReturnStatement') { + allowedScopes.push(node) } }, @@ -128,6 +134,15 @@ module.exports = { node: node, type: 'await' }) + }, + + 'ReturnStatement' (node) { + if ( + node.argument.type === 'ObjectExpression' || + node.argument.type === 'ArrayExpression' + ) { + allowedScopes.push(node.argument) + } } }, utils.executeOnVue(context, (obj) => { @@ -138,7 +153,11 @@ module.exports = { if ( cp.value && el.node.loc.start.line >= cp.value.loc.start.line && - el.node.loc.end.line <= cp.value.loc.end.line + el.node.loc.end.line <= cp.value.loc.end.line && + !allowedScopes.some(scope => + scope.range[0] < el.node.range[0] && + scope.range[1] > el.node.range[1] + ) ) { context.report({ node: el.node, diff --git a/tests/lib/rules/no-async-in-computed-properties.js b/tests/lib/rules/no-async-in-computed-properties.js index 23f59965b..39cef9f9e 100644 --- a/tests/lib/rules/no-async-in-computed-properties.js +++ b/tests/lib/rules/no-async-in-computed-properties.js @@ -71,6 +71,103 @@ ruleTester.run('no-async-in-computed-properties', rule, { } `, parserOptions + }, + { + filename: 'test.vue', + code: ` + export default { + computed: { + foo() { + return { + async bar() { + const data = await baz(this.a) + return data + } + } + } + } + } + `, + parserOptions + }, + { + filename: 'test.vue', + code: ` + export default { + computed: { + foo() { + const a = 'test' + return [ + async () => { + const baz = await bar(a) + return baz + }, + 'b', + {} + ] + } + } + } + `, + parserOptions + }, + { + filename: 'test.vue', + code: ` + export default { + computed: { + foo() { + return function () { + return async () => await bar() + } + }, + } + } + `, + parserOptions + }, + { + filename: 'test.vue', + code: ` + export default { + computed: { + foo() { + return new Promise.resolve() + }, + } + } + `, + parserOptions + }, + { + filename: 'test.vue', + code: ` + export default { + computed: { + foo() { + return new Bar(async () => await baz()) + }, + } + } + `, + parserOptions + }, + { + filename: 'test.vue', + code: ` + export default { + computed: { + foo() { + return someFunc.doSomething({ + async bar() { + return await baz() + } + }) + }, + } + } + `, + parserOptions } ],