forked from eslint/eslint
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New: Disallow use of Object.prototype methods on objects (fixes eslin…
- Loading branch information
Showing
5 changed files
with
177 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Disallow use of Object.prototypes builtins directly (no-prototype-builtins) | ||
|
||
In ECMAScript 5.1, `Object.create` was added, which enables the creation of objects with a specified `[[Prototype]]`. `Object.create(null)` is a common pattern used to create objects that will be used as a Map. This can lead to errors when it is assumed that objects will have properties from `Object.prototype`. This rule prevents calling `Object.prototype` methods directly from an object. | ||
|
||
## Rule Details | ||
|
||
This rule disallows calling some `Object.prototype` methods directly on object instances. | ||
|
||
Examples of **incorrect** code for this rule: | ||
|
||
```js | ||
/*eslint no-prototype-built-ins: "error"*/ | ||
|
||
var hasBarProperty = foo.hasOwnProperty("bar"); | ||
|
||
var isPrototypeOfBar = foo.isPrototypeOf(bar); | ||
|
||
var barIsEnumerable = foo.propertyIsEnumerable("bar"); | ||
``` | ||
|
||
Examples of **correct** code for this rule: | ||
|
||
```js | ||
/*eslint no-prototype-built-ins: "error"*/ | ||
|
||
var hasBarProperty = {}.hasOwnProperty.call(foo, "bar"); | ||
|
||
var isPrototypeOfBar = {}.isPrototypeOf.call(foo, bar); | ||
|
||
var barIsEnumerable = {}.propertyIsEnumerable.call(foo, "bar"); | ||
``` | ||
|
||
## When Not To Use It | ||
|
||
You may want to turn this rule off if you will never use an object that shadows an `Object.prototype` method or which does not inherit from `Object.prototype`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/** | ||
* @fileoverview Rule to disallow use of Object.prototype builtins on objects | ||
* @author Andrew Levine | ||
*/ | ||
"use strict"; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
|
||
module.exports = { | ||
meta: { | ||
docs: { | ||
description: "disallow calling some Object.prototype methods directly on objects", | ||
category: "Possible Errors", | ||
recommended: false | ||
} | ||
}, | ||
|
||
create: function(context) { | ||
var DISALLOWED_PROPS = [ | ||
"hasOwnProperty", | ||
"isPrototypeOf", | ||
"propertyIsEnumerable" | ||
]; | ||
|
||
/** | ||
* Reports if a disallowed property is used in a CallExpression | ||
* @param {ASTNode} node The CallExpression node. | ||
* @returns {void} | ||
*/ | ||
function disallowBuiltIns(node) { | ||
if (node.callee.type !== "MemberExpression" || node.callee.computed) { | ||
return; | ||
} | ||
var propName = node.callee.property.name; | ||
|
||
if (DISALLOWED_PROPS.indexOf(propName) > -1) { | ||
context.report({ | ||
message: "Do not access Object.prototype method '{{prop}}' from target object.", | ||
loc: node.callee.property.loc.start, | ||
data: {prop: propName}, | ||
node: node | ||
}); | ||
} | ||
} | ||
|
||
return { | ||
CallExpression: disallowBuiltIns | ||
}; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/** | ||
* @fileoverview Tests for no-prototype-built-ins | ||
* @author Andrew Levine | ||
*/ | ||
|
||
"use strict"; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Requirements | ||
//------------------------------------------------------------------------------ | ||
|
||
var rule = require("../../../lib/rules/no-prototype-builtins"), | ||
RuleTester = require("../../../lib/testers/rule-tester"); | ||
|
||
//------------------------------------------------------------------------------ | ||
// Tests | ||
//------------------------------------------------------------------------------ | ||
var ruleTester = new RuleTester(); | ||
|
||
var valid = [ | ||
{ code: "Object.prototype.hasOwnProperty.call(foo, 'bar')" }, | ||
{ code: "Object.prototype.isPrototypeOf.call(foo, 'bar')" }, | ||
{ code: "Object.prototype.propertyIsEnumerable.call(foo, 'bar')" }, | ||
{ code: "Object.prototype.hasOwnProperty.apply(foo, ['bar'])" }, | ||
{ code: "Object.prototype.isPrototypeOf.apply(foo, ['bar'])" }, | ||
{ code: "Object.prototype.propertyIsEnumerable.apply(foo, ['bar'])" }, | ||
{ code: "hasOwnProperty(foo, 'bar')" }, | ||
{ code: "isPrototypeOf(foo, 'bar')" }, | ||
{ code: "propertyIsEnumerable(foo, 'bar')" }, | ||
{ code: "({}.hasOwnProperty.call(foo, 'bar'))" }, | ||
{ code: "({}.isPrototypeOf.call(foo, 'bar'))" }, | ||
{ code: "({}.propertyIsEnumerable.call(foo, 'bar'))" }, | ||
{ code: "({}.hasOwnProperty.apply(foo, ['bar']))" }, | ||
{ code: "({}.isPrototypeOf.apply(foo, ['bar']))" }, | ||
{ code: "({}.propertyIsEnumerable.apply(foo, ['bar']))" } | ||
]; | ||
|
||
var invalid = [ | ||
{ | ||
code: "foo.hasOwnProperty('bar')", | ||
errors: [{ | ||
line: 1, | ||
column: 5, | ||
message: "Do not access Object.prototype method 'hasOwnProperty' from target object.", | ||
type: "CallExpression" | ||
}] | ||
}, | ||
{ | ||
code: "foo.isPrototypeOf('bar')", | ||
errors: [{ | ||
line: 1, | ||
column: 5, | ||
message: "Do not access Object.prototype method 'isPrototypeOf' from target object.", | ||
type: "CallExpression" | ||
}] | ||
}, | ||
{ | ||
code: "foo.propertyIsEnumerable('bar')", | ||
errors: [{ | ||
line: 1, | ||
column: 5, | ||
message: "Do not access Object.prototype method 'propertyIsEnumerable' from target object." | ||
}] | ||
}, | ||
{ | ||
code: "foo.bar.hasOwnProperty('bar')", | ||
errors: [{ | ||
line: 1, | ||
column: 9, | ||
message: "Do not access Object.prototype method 'hasOwnProperty' from target object.", | ||
type: "CallExpression" | ||
}] | ||
}, | ||
{ | ||
code: "foo.bar.baz.isPrototypeOf('bar')", | ||
errors: [{ | ||
line: 1, | ||
column: 13, | ||
message: "Do not access Object.prototype method 'isPrototypeOf' from target object.", | ||
type: "CallExpression" | ||
}] | ||
} | ||
]; | ||
|
||
ruleTester.run("no-prototype-builtins", rule, { | ||
valid: valid, | ||
invalid: invalid | ||
}); |