From 55f009e71efa3e53db127dc46f5d39bed510e2ff Mon Sep 17 00:00:00 2001 From: Josh Chisholm Date: Mon, 22 Oct 2018 19:41:30 +0100 Subject: [PATCH 1/4] Allow loops containing await --- lib/no-loops.js | 33 ++++++++++++++++++++++++++++----- package.json | 4 ++-- tests/index.js | 20 +++++++++++++++++++- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/lib/no-loops.js b/lib/no-loops.js index 5f53f6a..c6418bd 100644 --- a/lib/no-loops.js +++ b/lib/no-loops.js @@ -5,11 +5,34 @@ module.exports = function (context) { context.report(node, 'loops are not allowed', { identifier: node.name }); } + var loopDepth = 0 + var isAsyncLoop = false + + function enterLoop(node) { + if (loopDepth === 0) isAsyncLoop = false; + } + + function exitLoop(node) { + if (!isAsyncLoop) { + reportLoopPresence(node); + } + } + + function foundAwait() { + isAsyncLoop = true; + } + return { - ForStatement: reportLoopPresence, - ForInStatement: reportLoopPresence, - WhileStatement: reportLoopPresence, - DoWhileStatement: reportLoopPresence, - ForOfStatement: reportLoopPresence + ForStatement: enterLoop, + 'ForStatement:exit': exitLoop, + ForInStatement: enterLoop, + 'ForInStatement:exit': exitLoop, + WhileStatement: enterLoop, + 'WhileStatement:exit': exitLoop, + DoWhileStatement: enterLoop, + 'DoWhileStatement:exit': exitLoop, + ForOfStatement: enterLoop, + 'ForOfStatement:exit': exitLoop, + AwaitExpression: foundAwait }; }; diff --git a/package.json b/package.json index 3b84a0f..4d4dd37 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ }, "homepage": "https://github.com/buildo/eslint-plugin-no-loops#readme", "devDependencies": { - "babel-eslint": "^6.1.0", - "eslint": "^2.0.0" + "babel-eslint": "8", + "eslint": "5" }, "peerDependencies": { "eslint": ">=2.0.0" diff --git a/tests/index.js b/tests/index.js index 78f788c..dd29dd5 100644 --- a/tests/index.js +++ b/tests/index.js @@ -3,11 +3,29 @@ var rule = require('../lib/no-loops.js'); var RuleTester = require('eslint').RuleTester; -var ruleTester = new RuleTester(); +var ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2018 } }); ruleTester.run('no-loops', rule, { valid: [ { code: '[1, 2, 3].map(function (i) { console.log(i); });' + }, + { + code: 'async function ok() { for (var i = 0; i < n; i++) { await x[i]() } }' + }, + { + code: 'const ok = async () => { for (const x of y) { for (const z of y) { await z() } } }' + }, + { + code: 'async function ok() { for (const x of y) { await x() } }' + }, + { + code: 'async function ok() { while (true) { await x() } }' + }, + { + code: 'async function ok() { do { await x() } while (true) }' + }, + { + code: 'const ok = async () => { for (const x of y) { for (const z in y) { await z() } } }' } ], From e982100705e894026aea5b7e277e1c6f9357e86f Mon Sep 17 00:00:00 2001 From: Josh Chisholm Date: Mon, 22 Oct 2018 20:30:20 +0100 Subject: [PATCH 2/4] Better examples --- lib/no-loops.js | 16 ++++++++-------- tests/index.js | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/lib/no-loops.js b/lib/no-loops.js index c6418bd..9d7cb40 100644 --- a/lib/no-loops.js +++ b/lib/no-loops.js @@ -5,21 +5,21 @@ module.exports = function (context) { context.report(node, 'loops are not allowed', { identifier: node.name }); } - var loopDepth = 0 - var isAsyncLoop = false + var awaits = [] - function enterLoop(node) { - if (loopDepth === 0) isAsyncLoop = false; + function enterLoop() { + awaits.unshift(false) } function exitLoop(node) { - if (!isAsyncLoop) { - reportLoopPresence(node); - } + var await = awaits.shift() + if (!await) reportLoopPresence(node) } function foundAwait() { - isAsyncLoop = true; + for (var i = 0; i < awaits.length; i++) { + awaits[i] = true + } } return { diff --git a/tests/index.js b/tests/index.js index dd29dd5..44e2440 100644 --- a/tests/index.js +++ b/tests/index.js @@ -50,6 +50,21 @@ ruleTester.run('no-loops', rule, { code: 'for (i of [1, 2, 3]) { console.log(i) }', parser: 'babel-eslint', errors: [ { message: 'loops are not allowed' } ] + }, + { + code: 'async function bad() { while (true) { x() } }', + parser: 'babel-eslint', + errors: [ { message: 'loops are not allowed' } ] + }, + { + code: 'async function bad() { while (true) { x() } }', + parser: 'babel-eslint', + errors: [ { message: 'loops are not allowed' } ] + }, + { + code: 'const ok = async () => { for (const x of y) { await x(); for (const z in y) { z() } } }', + parser: 'babel-eslint', + errors: [ { message: 'loops are not allowed' } ] } ] }); From d8a1f7a88e94fdab8199a864c895494e4665fb7b Mon Sep 17 00:00:00 2001 From: Josh Chisholm Date: Mon, 22 Oct 2018 20:31:58 +0100 Subject: [PATCH 3/4] Remove duplicate example --- tests/index.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/index.js b/tests/index.js index 44e2440..76690a1 100644 --- a/tests/index.js +++ b/tests/index.js @@ -56,11 +56,6 @@ ruleTester.run('no-loops', rule, { parser: 'babel-eslint', errors: [ { message: 'loops are not allowed' } ] }, - { - code: 'async function bad() { while (true) { x() } }', - parser: 'babel-eslint', - errors: [ { message: 'loops are not allowed' } ] - }, { code: 'const ok = async () => { for (const x of y) { await x(); for (const z in y) { z() } } }', parser: 'babel-eslint', From 758e19617c286d44bf167feae9b6e2cb3d6b84f3 Mon Sep 17 00:00:00 2001 From: Josh Chisholm Date: Mon, 22 Oct 2018 20:34:31 +0100 Subject: [PATCH 4/4] Simplify --- lib/no-loops.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/no-loops.js b/lib/no-loops.js index 9d7cb40..a110347 100644 --- a/lib/no-loops.js +++ b/lib/no-loops.js @@ -5,20 +5,19 @@ module.exports = function (context) { context.report(node, 'loops are not allowed', { identifier: node.name }); } - var awaits = [] + var loopsContainAwait = [] function enterLoop() { - awaits.unshift(false) + loopsContainAwait.unshift(false) } function exitLoop(node) { - var await = awaits.shift() - if (!await) reportLoopPresence(node) + if (!loopsContainAwait.shift()) reportLoopPresence(node) } function foundAwait() { - for (var i = 0; i < awaits.length; i++) { - awaits[i] = true + for (var i = 0; i < loopsContainAwait.length; i++) { + loopsContainAwait[i] = true } }