Blame view

node_modules/eslint/lib/rules/no-extend-native.js 3.83 KB
f7563de62   Palak Handa   first commit
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  /**
   * @fileoverview Rule to flag adding properties to native object's prototypes.
   * @author David Nelson
   */
  
  "use strict";
  
  //------------------------------------------------------------------------------
  // Requirements
  //------------------------------------------------------------------------------
  
  const globals = require("globals");
  
  //------------------------------------------------------------------------------
  // Rule Definition
  //------------------------------------------------------------------------------
  
  module.exports = {
      meta: {
          docs: {
              description: "disallow extending native types",
              category: "Best Practices",
              recommended: false
          },
  
          schema: [
              {
                  type: "object",
                  properties: {
                      exceptions: {
                          type: "array",
                          items: {
                              type: "string"
                          },
                          uniqueItems: true
                      }
                  },
                  additionalProperties: false
              }
          ]
      },
  
      create(context) {
  
          const config = context.options[0] || {};
          const exceptions = config.exceptions || [];
          let modifiedBuiltins = Object.keys(globals.builtin).filter(builtin => builtin[0].toUpperCase() === builtin[0]);
  
          if (exceptions.length) {
              modifiedBuiltins = modifiedBuiltins.filter(builtIn => exceptions.indexOf(builtIn) === -1);
          }
  
          return {
  
              // handle the Array.prototype.extra style case
              AssignmentExpression(node) {
                  const lhs = node.left;
  
                  if (lhs.type !== "MemberExpression" || lhs.object.type !== "MemberExpression") {
                      return;
                  }
  
                  const affectsProto = lhs.object.computed
                      ? lhs.object.property.type === "Literal" && lhs.object.property.value === "prototype"
                      : lhs.object.property.name === "prototype";
  
                  if (!affectsProto) {
                      return;
                  }
  
                  modifiedBuiltins.forEach(builtin => {
                      if (lhs.object.object.name === builtin) {
                          context.report({
                              node,
                              message: "{{builtin}} prototype is read only, properties should not be added.",
                              data: {
                                  builtin
                              }
                          });
                      }
                  });
              },
  
              // handle the Object.definePropert[y|ies](Array.prototype) case
              CallExpression(node) {
  
                  const callee = node.callee;
  
                  // only worry about Object.definePropert[y|ies]
                  if (callee.type === "MemberExpression" &&
                      callee.object.name === "Object" &&
                      (callee.property.name === "defineProperty" || callee.property.name === "defineProperties")) {
  
                      // verify the object being added to is a native prototype
                      const subject = node.arguments[0];
                      const object = subject && subject.object;
  
                      if (object &&
                          object.type === "Identifier" &&
                          (modifiedBuiltins.indexOf(object.name) > -1) &&
                          subject.property.name === "prototype") {
  
                          context.report({
                              node,
                              message: "{{objectName}} prototype is read only, properties should not be added.",
                              data: {
                                  objectName: object.name
                              }
                          });
                      }
                  }
  
              }
          };
  
      }
  };