eslint-local-rules.js 2.77 KB
Newer Older
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
/* eslint-disable jsdoc/require-jsdoc, jsdoc/no-undefined-types */
"use strict";

function getPrototypeMethods(prototype) {
    /* eslint-disable local-rules/no-prototype-methods */
    return Object.getOwnPropertyNames(prototype).filter(function(name) {
        return (
            typeof prototype[name] === "function" &&
            prototype.hasOwnProperty(name)
        );
    });
}

var DISALLOWED_ARRAY_PROPS = getPrototypeMethods(Array.prototype);

var DISALLOWED_OBJECT_PROPS = getPrototypeMethods(Object.prototype);

module.exports = {
    // rule to disallow direct use of prototype methods of builtins
    "no-prototype-methods": {
        meta: {
            docs: {
                description: "disallow calling prototype methods directly",
                category: "Possible Errors",
                recommended: false,
                url: "https://eslint.org/docs/rules/no-prototype-builtins"
            },

            schema: []
        },

        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;

                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
                    });
                }
            }

            return {
                CallExpression: disallowBuiltIns
            };
        }
    }
};