Blame view

node_modules/eslint/lib/rules/no-await-in-loop.js 2.69 KB
ce4c83ff   wxy   初始提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  /**
   * @fileoverview Rule to disallow uses of await inside of loops.
   * @author Nat Mote (nmote)
   */
  "use strict";
  
  /**
   * Check whether it should stop traversing ancestors at the given node.
   * @param {ASTNode} node A node to check.
   * @returns {boolean} `true` if it should stop traversing.
   */
  function isBoundary(node) {
      const t = node.type;
  
      return (
          t === "FunctionDeclaration" ||
          t === "FunctionExpression" ||
          t === "ArrowFunctionExpression" ||
  
          /*
           * Don't report the await expressions on for-await-of loop since it's
           * asynchronous iteration intentionally.
           */
          (t === "ForOfStatement" && node.await === true)
      );
  }
  
  /**
   * Check whether the given node is in loop.
   * @param {ASTNode} node A node to check.
   * @param {ASTNode} parent A parent node to check.
   * @returns {boolean} `true` if the node is in loop.
   */
  function isLooped(node, parent) {
      switch (parent.type) {
          case "ForStatement":
              return (
                  node === parent.test ||
                  node === parent.update ||
                  node === parent.body
              );
  
          case "ForOfStatement":
          case "ForInStatement":
              return node === parent.body;
  
          case "WhileStatement":
          case "DoWhileStatement":
              return node === parent.test || node === parent.body;
  
          default:
              return false;
      }
  }
  
  module.exports = {
      meta: {
          docs: {
              description: "disallow `await` inside of loops",
              category: "Possible Errors",
              recommended: false,
              url: "https://eslint.org/docs/rules/no-await-in-loop"
          },
          schema: [],
          messages: {
              unexpectedAwait: "Unexpected `await` inside a loop."
          }
      },
      create(context) {
  
          /**
           * Validate an await expression.
           * @param {ASTNode} awaitNode An AwaitExpression or ForOfStatement node to validate.
           * @returns {void}
           */
          function validate(awaitNode) {
              if (awaitNode.type === "ForOfStatement" && !awaitNode.await) {
                  return;
              }
  
              let node = awaitNode;
              let parent = node.parent;
  
              while (parent && !isBoundary(parent)) {
                  if (isLooped(node, parent)) {
                      context.report({
                          node: awaitNode,
                          messageId: "unexpectedAwait"
                      });
                      return;
                  }
                  node = parent;
                  parent = parent.parent;
              }
          }
  
          return {
              AwaitExpression: validate,
              ForOfStatement: validate
          };
      }
  };