2 * @fileoverview Validate strings passed to the RegExp constructor
3 * @author Michael Ficarra
7 //------------------------------------------------------------------------------
9 //------------------------------------------------------------------------------
11 const RegExpValidator = require("regexpp").RegExpValidator;
12 const validator = new RegExpValidator();
13 const validFlags = /[gimuys]/gu;
14 const undefined1 = void 0;
16 //------------------------------------------------------------------------------
18 //------------------------------------------------------------------------------
25 description: "disallow invalid regular expression strings in `RegExp` constructors",
26 category: "Possible Errors",
28 url: "https://eslint.org/docs/rules/no-invalid-regexp"
34 allowConstructorFlags: {
41 additionalProperties: false
45 regexMessage: "{{message}}."
51 const options = context.options[0];
52 let allowedFlags = null;
54 if (options && options.allowConstructorFlags) {
55 const temp = options.allowConstructorFlags.join("").replace(validFlags, "");
58 allowedFlags = new RegExp(`[${temp}]`, "giu");
63 * Check if node is a string
64 * @param {ASTNode} node node to evaluate
65 * @returns {boolean} True if its a string
68 function isString(node) {
69 return node && node.type === "Literal" && typeof node.value === "string";
73 * Gets flags of a regular expression created by the given `RegExp()` or `new RegExp()` call
75 * new RegExp(".") // => ""
76 * new RegExp(".", "gu") // => "gu"
77 * new RegExp(".", flags) // => null
78 * @param {ASTNode} node `CallExpression` or `NewExpression` node
79 * @returns {string|null} flags if they can be determined, `null` otherwise
82 function getFlags(node) {
83 if (node.arguments.length < 2) {
87 if (isString(node.arguments[1])) {
88 return node.arguments[1].value;
95 * Check syntax error in a given pattern.
96 * @param {string} pattern The RegExp pattern to validate.
97 * @param {boolean} uFlag The Unicode flag.
98 * @returns {string|null} The syntax error.
100 function validateRegExpPattern(pattern, uFlag) {
102 validator.validatePattern(pattern, undefined1, undefined1, uFlag);
110 * Check syntax error in a given flags.
111 * @param {string} flags The RegExp flags to validate.
112 * @returns {string|null} The syntax error.
114 function validateRegExpFlags(flags) {
116 validator.validateFlags(flags);
119 return `Invalid flags supplied to RegExp constructor '${flags}'`;
124 "CallExpression, NewExpression"(node) {
125 if (node.callee.type !== "Identifier" || node.callee.name !== "RegExp" || !isString(node.arguments[0])) {
128 const pattern = node.arguments[0].value;
129 let flags = getFlags(node);
131 if (flags && allowedFlags) {
132 flags = flags.replace(allowedFlags, "");
137 flags && validateRegExpFlags(flags)
141 // If flags are unknown, report the regex only if its pattern is invalid both with and without the "u" flag
143 ? validateRegExpPattern(pattern, true) && validateRegExpPattern(pattern, false)
144 : validateRegExpPattern(pattern, flags.includes("u"))
150 messageId: "regexMessage",