no-new-func.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /**
  2. * @fileoverview Rule to flag when using new Function
  3. * @author Ilya Volodin
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Requirements
  8. //------------------------------------------------------------------------------
  9. const astUtils = require("./utils/ast-utils");
  10. //------------------------------------------------------------------------------
  11. // Helpers
  12. //------------------------------------------------------------------------------
  13. const callMethods = new Set(["apply", "bind", "call"]);
  14. //------------------------------------------------------------------------------
  15. // Rule Definition
  16. //------------------------------------------------------------------------------
  17. /** @type {import('../types').Rule.RuleModule} */
  18. module.exports = {
  19. meta: {
  20. type: "suggestion",
  21. docs: {
  22. description: "Disallow `new` operators with the `Function` object",
  23. recommended: false,
  24. url: "https://eslint.org/docs/latest/rules/no-new-func",
  25. },
  26. schema: [],
  27. messages: {
  28. noFunctionConstructor: "The Function constructor is eval.",
  29. },
  30. },
  31. create(context) {
  32. const sourceCode = context.sourceCode;
  33. return {
  34. "Program:exit"(node) {
  35. const globalScope = sourceCode.getScope(node);
  36. const variable = globalScope.set.get("Function");
  37. if (variable && variable.defs.length === 0) {
  38. variable.references.forEach(ref => {
  39. const idNode = ref.identifier;
  40. const { parent } = idNode;
  41. let evalNode;
  42. if (parent) {
  43. if (
  44. idNode === parent.callee &&
  45. (parent.type === "NewExpression" ||
  46. parent.type === "CallExpression")
  47. ) {
  48. evalNode = parent;
  49. } else if (
  50. parent.type === "MemberExpression" &&
  51. idNode === parent.object &&
  52. callMethods.has(
  53. astUtils.getStaticPropertyName(parent),
  54. )
  55. ) {
  56. const maybeCallee =
  57. parent.parent.type === "ChainExpression"
  58. ? parent.parent
  59. : parent;
  60. if (
  61. maybeCallee.parent.type ===
  62. "CallExpression" &&
  63. maybeCallee.parent.callee === maybeCallee
  64. ) {
  65. evalNode = maybeCallee.parent;
  66. }
  67. }
  68. }
  69. if (evalNode) {
  70. context.report({
  71. node: evalNode,
  72. messageId: "noFunctionConstructor",
  73. });
  74. }
  75. });
  76. }
  77. },
  78. };
  79. },
  80. };