2 * @fileoverview Rule to disallow certain object properties
3 * @author Will Klein & Eli White
8 const astUtils
= require("./utils/ast-utils");
10 //------------------------------------------------------------------------------
12 //------------------------------------------------------------------------------
19 description
: "disallow certain properties on certain objects",
20 category
: "Best Practices",
22 url
: "https://eslint.org/docs/rules/no-restricted-properties"
28 anyOf
: [ // `object` and `property` are both optional, but at least one of them must be provided.
42 additionalProperties
: false,
58 additionalProperties
: false,
59 required
: ["property"]
67 // eslint-disable-next-line eslint-plugin/report-message-format
68 restrictedObjectProperty
: "'{{objectName}}.{{propertyName}}' is restricted from being used.{{message}}",
69 // eslint-disable-next-line eslint-plugin/report-message-format
70 restrictedProperty
: "'{{propertyName}}' is restricted from being used.{{message}}"
75 const restrictedCalls
= context
.options
;
77 if (restrictedCalls
.length
=== 0) {
81 const restrictedProperties
= new Map();
82 const globallyRestrictedObjects
= new Map();
83 const globallyRestrictedProperties
= new Map();
85 restrictedCalls
.forEach(option
=> {
86 const objectName
= option
.object
;
87 const propertyName
= option
.property
;
89 if (typeof objectName
=== "undefined") {
90 globallyRestrictedProperties
.set(propertyName
, { message
: option
.message
});
91 } else if (typeof propertyName
=== "undefined") {
92 globallyRestrictedObjects
.set(objectName
, { message
: option
.message
});
94 if (!restrictedProperties
.has(objectName
)) {
95 restrictedProperties
.set(objectName
, new Map());
98 restrictedProperties
.get(objectName
).set(propertyName
, {
99 message
: option
.message
105 * Checks to see whether a property access is restricted, and reports it if so.
106 * @param {ASTNode} node The node to report
107 * @param {string} objectName The name of the object
108 * @param {string} propertyName The name of the property
109 * @returns {undefined}
111 function checkPropertyAccess(node
, objectName
, propertyName
) {
112 if (propertyName
=== null) {
115 const matchedObject
= restrictedProperties
.get(objectName
);
116 const matchedObjectProperty
= matchedObject
? matchedObject
.get(propertyName
) : globallyRestrictedObjects
.get(objectName
);
117 const globalMatchedProperty
= globallyRestrictedProperties
.get(propertyName
);
119 if (matchedObjectProperty
) {
120 const message
= matchedObjectProperty
.message
? ` ${matchedObjectProperty.message}` : "";
124 messageId
: "restrictedObjectProperty",
131 } else if (globalMatchedProperty
) {
132 const message
= globalMatchedProperty
.message
? ` ${globalMatchedProperty.message}` : "";
136 messageId
: "restrictedProperty",
146 * Checks property accesses in a destructuring assignment expression, e.g. `var foo; ({foo} = bar);`
147 * @param {ASTNode} node An AssignmentExpression or AssignmentPattern node
148 * @returns {undefined}
150 function checkDestructuringAssignment(node
) {
151 if (node
.right
.type
=== "Identifier") {
152 const objectName
= node
.right
.name
;
154 if (node
.left
.type
=== "ObjectPattern") {
155 node
.left
.properties
.forEach(property
=> {
156 checkPropertyAccess(node
.left
, objectName
, astUtils
.getStaticPropertyName(property
));
163 MemberExpression(node
) {
164 checkPropertyAccess(node
, node
.object
&& node
.object
.name
, astUtils
.getStaticPropertyName(node
));
166 VariableDeclarator(node
) {
167 if (node
.init
&& node
.init
.type
=== "Identifier") {
168 const objectName
= node
.init
.name
;
170 if (node
.id
.type
=== "ObjectPattern") {
171 node
.id
.properties
.forEach(property
=> {
172 checkPropertyAccess(node
.id
, objectName
, astUtils
.getStaticPropertyName(property
));
177 AssignmentExpression
: checkDestructuringAssignment
,
178 AssignmentPattern
: checkDestructuringAssignment