no-new-func.js 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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('../shared/types').Rule} */
  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/rules/no-new-func"
  25. },
  26. schema: [],
  27. messages: {
  28. noFunctionConstructor: "The Function constructor is eval."
  29. }
  30. },
  31. create(context) {
  32. return {
  33. "Program:exit"() {
  34. const globalScope = context.getScope();
  35. const variable = globalScope.set.get("Function");
  36. if (variable && variable.defs.length === 0) {
  37. variable.references.forEach(ref => {
  38. const node = ref.identifier;
  39. const { parent } = node;
  40. let evalNode;
  41. if (parent) {
  42. if (node === parent.callee && (
  43. parent.type === "NewExpression" ||
  44. parent.type === "CallExpression"
  45. )) {
  46. evalNode = parent;
  47. } else if (
  48. parent.type === "MemberExpression" &&
  49. node === parent.object &&
  50. callMethods.has(astUtils.getStaticPropertyName(parent))
  51. ) {
  52. const maybeCallee = parent.parent.type === "ChainExpression" ? parent.parent : parent;
  53. if (maybeCallee.parent.type === "CallExpression" && maybeCallee.parent.callee === maybeCallee) {
  54. evalNode = maybeCallee.parent;
  55. }
  56. }
  57. }
  58. if (evalNode) {
  59. context.report({
  60. node: evalNode,
  61. messageId: "noFunctionConstructor"
  62. });
  63. }
  64. });
  65. }
  66. }
  67. };
  68. }
  69. };