@sinonjs/eslint-plugin-no-prototype-methods
Advanced tools
| extends: | ||
| - sinon | ||
| - plugin:prettier/recommended | ||
| plugins: | ||
| - prettier | ||
| rules: | ||
| prettier/prettier: error | ||
| overrides: | ||
| - files: "*.test.*" | ||
| plugins: | ||
| - mocha | ||
| env: | ||
| mocha: true | ||
| rules: | ||
| jsdoc/check-alignment: off | ||
| jsdoc/check-examples: off | ||
| jsdoc/check-indentation: off | ||
| jsdoc/check-param-names: off | ||
| jsdoc/check-syntax: off | ||
| jsdoc/check-tag-names: off | ||
| jsdoc/check-types: off | ||
| jsdoc/implements-on-classes: off | ||
| jsdoc/match-description: off | ||
| jsdoc/newline-after-description: off | ||
| jsdoc/no-types: off | ||
| jsdoc/no-undefined-types: off | ||
| jsdoc/require-description: off | ||
| jsdoc/require-description-complete-sentence: off | ||
| jsdoc/require-example: off | ||
| jsdoc/require-hyphen-before-param-description: off | ||
| jsdoc/require-jsdoc: off | ||
| jsdoc/require-param: off | ||
| jsdoc/require-param-description: off | ||
| jsdoc/require-param-name: off | ||
| jsdoc/require-param-type: off | ||
| jsdoc/require-returns: off | ||
| jsdoc/require-returns-check: off | ||
| jsdoc/require-returns-description: off | ||
| jsdoc/require-returns-type: off | ||
| jsdoc/valid-types: off | ||
| max-nested-callbacks: | ||
| - warn | ||
| - 6 | ||
| mocha/handle-done-callback: error | ||
| mocha/no-exclusive-tests: error | ||
| mocha/no-global-tests: error | ||
| mocha/no-hooks-for-single-case: off | ||
| mocha/no-identical-title: error | ||
| mocha/no-mocha-arrows: error | ||
| mocha/no-nested-tests: error | ||
| mocha/no-return-and-callback: error | ||
| mocha/no-sibling-hooks: error | ||
| mocha/no-skipped-tests: error | ||
| mocha/no-top-level-hooks: error |
| "use strict"; | ||
| /** | ||
| * getPrototypeMethods | ||
| * | ||
| * @param {object} prototype | ||
| * @returns {Array} Array of method names from the prototype | ||
| */ | ||
| function getPrototypeMethods(prototype) { | ||
| return Object.getOwnPropertyNames(prototype).filter(function (name) { | ||
| return ( | ||
| typeof prototype[name] === "function" && prototype.hasOwnProperty(name) | ||
| ); | ||
| }); | ||
| } | ||
| module.exports = getPrototypeMethods; |
| "use strict"; | ||
| var assert = require("@sinonjs/referee-sinon").assert; | ||
| var getPrototypeMethods = require("../../lib/get-prototype-methods"); | ||
| describe("getPrototypeMethods", function () { | ||
| it("returns only own methods", function () { | ||
| var obj = { | ||
| // eslint-disable-next-line no-empty-function | ||
| hello: function () {}, | ||
| // eslint-disable-next-line no-empty-function | ||
| world: function () {}, | ||
| apple: "pie", | ||
| }; | ||
| var actual = getPrototypeMethods(obj); | ||
| assert.equals(actual, ["hello", "world"]); | ||
| }); | ||
| }); |
| "use strict"; | ||
| var rule = require("../../../lib/rules/no-prototype-methods"); | ||
| var RuleTester = require("eslint").RuleTester; | ||
| var getPrototypeMethods = require("../../../lib/get-prototype-methods"); | ||
| var ruleTester = new RuleTester(); | ||
| var arrayMethods = getPrototypeMethods(Array.prototype); | ||
| var INVALID_ARRAY_EXAMPLES = [].concat( | ||
| arrayMethods.map(createInvalidArrayPrototypeExample), | ||
| arrayMethods.map(createInvalidArrayLiteralExample) | ||
| ); | ||
| function createInvalidArrayPrototypeExample(propertyName) { | ||
| // Array.prototype.constructor has a function name of `Array` not `constructor` | ||
| if (propertyName === "constructor") { | ||
| return { | ||
| code: "Array.prototype.constructor()", | ||
| errors: [ | ||
| { | ||
| message: | ||
| "Do not access Array prototype method 'constructor' from target object.", | ||
| type: "CallExpression", | ||
| }, | ||
| ], | ||
| }; | ||
| } | ||
| return { | ||
| code: "Array.prototype." + propertyName + "()", | ||
| errors: [ | ||
| { | ||
| message: | ||
| "Do not access Array prototype method '" + | ||
| propertyName + | ||
| "' from target object.", | ||
| type: "CallExpression", | ||
| }, | ||
| ], | ||
| }; | ||
| } | ||
| function createInvalidArrayLiteralExample(propertyName) { | ||
| // Array.prototype.constructor has a function name of `Array` not `constructor` | ||
| if (propertyName === "constructor") { | ||
| return { | ||
| code: "[].constructor()", | ||
| errors: [ | ||
| { | ||
| message: | ||
| "Do not access Array prototype method 'constructor' from target object.", | ||
| type: "CallExpression", | ||
| }, | ||
| ], | ||
| }; | ||
| } | ||
| return { | ||
| code: "[]." + propertyName + "()", | ||
| errors: [ | ||
| { | ||
| message: | ||
| "Do not access Array prototype method '" + | ||
| propertyName + | ||
| "' from target object.", | ||
| type: "CallExpression", | ||
| }, | ||
| ], | ||
| }; | ||
| } | ||
| var objectMethods = getPrototypeMethods(Object.prototype); | ||
| var INVALID_OBJECT_EXAMPLES = [].concat( | ||
| objectMethods.map(createInvalidObjectPrototypeExample) | ||
| ); | ||
| function createInvalidObjectPrototypeExample(propertyName) { | ||
| return { | ||
| code: "Object.prototype." + propertyName + "()", | ||
| errors: [ | ||
| { | ||
| message: | ||
| "Do not access Object prototype method '" + | ||
| propertyName + | ||
| "' from target object.", | ||
| type: "CallExpression", | ||
| }, | ||
| ], | ||
| }; | ||
| } | ||
| ruleTester.run("no-prototype-methods", rule, { | ||
| valid: [], | ||
| invalid: INVALID_OBJECT_EXAMPLES.concat(INVALID_ARRAY_EXAMPLES), | ||
| }); |
+8
-0
| # Changes | ||
| ## 0.1.1 | ||
| - [`507c254`](https://github.com/sinonjs/eslint-plugin-no-prototype-methods/commit/507c254d5e535b4e7a0ab8925767b7d3a27de91b) | ||
| Add tests for no-prototype-methods | ||
| This also fixes a bug, where arrays were not always detected, because of the overlap in prototype methods with object | ||
| _Released on 2020-11-26._ | ||
| ## 0.1.0 | ||
@@ -4,0 +12,0 @@ |
+1
-5
| /** | ||
| * @fileoverview Disallow direct use of prototype methods of builtins | ||
| * @file Disallow direct use of prototype methods of builtins | ||
| * @author Morgan Roderick | ||
@@ -17,7 +17,3 @@ */ | ||
| // import all rules in lib/rules | ||
| module.exports.rules = requireIndex(__dirname + "/rules"); | ||
| "use strict"; | ||
| function getPrototypeMethods(prototype) { | ||
| return Object.getOwnPropertyNames(prototype).filter(function(name) { | ||
| return typeof prototype[name] === "function" && prototype.hasOwnProperty(name); | ||
| }); | ||
| } | ||
| var getPrototypeMethods = require("../get-prototype-methods"); | ||
@@ -13,57 +9,67 @@ var DISALLOWED_ARRAY_PROPS = getPrototypeMethods(Array.prototype); | ||
| module.exports = { | ||
| meta: { | ||
| docs: { | ||
| description: "disallow calling prototype methods directly", | ||
| category: "Possible Errors", | ||
| recommended: false, | ||
| url: "https://github.com/sinonjs/no-prototype-builtins" | ||
| }, | ||
| schema: [], | ||
| type: 'problem' | ||
| meta: { | ||
| docs: { | ||
| description: "disallow calling prototype methods directly", | ||
| category: "Possible Errors", | ||
| recommended: false, | ||
| url: "https://github.com/sinonjs/no-prototype-builtins", | ||
| }, | ||
| create: function(context) { | ||
| /** | ||
| * 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 || | ||
| // allow static method calls | ||
| node.callee.object.name === "Array" || | ||
| node.callee.object.name === "Object" | ||
| ) { | ||
| return; | ||
| } | ||
| var propName = node.callee.property.name; | ||
| schema: [], | ||
| type: "problem", | ||
| }, | ||
| create: function (context) { | ||
| /** | ||
| * Reports if a disallowed property is used in a CallExpression | ||
| * | ||
| * @param {object} node The CallExpression node. | ||
| * @returns {void} | ||
| */ | ||
| function disallowBuiltIns(node) { | ||
| if ( | ||
| node.callee.type !== "MemberExpression" || | ||
| node.callee.computed || | ||
| // allow static method calls | ||
| node.callee.object.name === "Array" || | ||
| node.callee.object.name === "Object" | ||
| ) { | ||
| return; | ||
| } | ||
| var propName = node.callee.property.name; | ||
| var isArray = | ||
| (node.callee.object.object && | ||
| node.callee.object.object.name === "Array") || | ||
| node.callee.object.type === "ArrayExpression"; | ||
| var isObject = | ||
| node.callee.object.object && | ||
| node.callee.object.object.name === "Object"; | ||
| if (DISALLOWED_OBJECT_PROPS.indexOf(propName) > -1) { | ||
| context.report({ | ||
| message: "Do not access {{obj}} prototype method '{{prop}}' from target object.", | ||
| loc: node.callee.property.loc.start, | ||
| data: { | ||
| obj: "Object", | ||
| prop: propName | ||
| }, | ||
| node: node | ||
| }); | ||
| } else if (DISALLOWED_ARRAY_PROPS.indexOf(propName) > -1) { | ||
| context.report({ | ||
| message: "Do not access {{obj}} prototype method '{{prop}}' from target object.", | ||
| loc: node.callee.property.loc.start, | ||
| data: { | ||
| obj: "Array", | ||
| prop: propName | ||
| }, | ||
| node: node | ||
| }); | ||
| } | ||
| } | ||
| if (isObject && DISALLOWED_OBJECT_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 | ||
| }; | ||
| if (isArray && DISALLOWED_ARRAY_PROPS.indexOf(propName) > -1) { | ||
| context.report({ | ||
| message: | ||
| "Do not access Array prototype method '{{prop}}' from target object.", | ||
| loc: node.callee.property.loc.start, | ||
| data: { | ||
| prop: propName, | ||
| }, | ||
| node: node, | ||
| }); | ||
| } | ||
| } | ||
| return { | ||
| CallExpression: disallowBuiltIns, | ||
| }; | ||
| }, | ||
| }; |
+11
-3
| { | ||
| "name": "@sinonjs/eslint-plugin-no-prototype-methods", | ||
| "version": "0.1.0", | ||
| "version": "0.1.1", | ||
| "description": "Disallow direct use of prototype methods of builtins", | ||
@@ -17,3 +17,4 @@ "keywords": [ | ||
| "scripts": { | ||
| "test": "mocha tests --recursive", | ||
| "lint": "eslint .", | ||
| "test": "mocha tests --recursive --reporter dot", | ||
| "version": "changes --commits --footer", | ||
@@ -26,5 +27,12 @@ "postversion": "git push --follow-tags && npm publish --access public" | ||
| "devDependencies": { | ||
| "@sinonjs/referee-sinon": "^8.0.0", | ||
| "@studio/changes": "^2.0.1", | ||
| "eslint": "^7.1.0", | ||
| "mocha": "^7.2.0" | ||
| "eslint-config-prettier": "^6.9.0", | ||
| "eslint-config-sinon": "^4.0.0", | ||
| "eslint-plugin-jsdoc": "^30.7.6", | ||
| "eslint-plugin-mocha": "^6.1.0", | ||
| "eslint-plugin-prettier": "^3.1.0", | ||
| "mocha": "^7.2.0", | ||
| "prettier": "^2.1.2" | ||
| }, | ||
@@ -31,0 +39,0 @@ "engines": { |
11892
83.41%10
66.67%199
158.44%10
233.33%