Permalink
Cannot retrieve contributors at this time
| /** | |
| * @fileoverview Validate strings passed to the RegExp constructor | |
| * @author Michael Ficarra | |
| */ | |
| "use strict"; | |
| //------------------------------------------------------------------------------ | |
| // Requirements | |
| //------------------------------------------------------------------------------ | |
| const RegExpValidator = require("regexpp").RegExpValidator; | |
| const validator = new RegExpValidator({ ecmaVersion: 2018 }); | |
| const validFlags = /[gimuys]/gu; | |
| const undefined1 = void 0; | |
| //------------------------------------------------------------------------------ | |
| // Rule Definition | |
| //------------------------------------------------------------------------------ | |
| module.exports = { | |
| meta: { | |
| type: "problem", | |
| docs: { | |
| description: "disallow invalid regular expression strings in `RegExp` constructors", | |
| category: "Possible Errors", | |
| recommended: true, | |
| url: "https://eslint.org/docs/rules/no-invalid-regexp" | |
| }, | |
| schema: [{ | |
| type: "object", | |
| properties: { | |
| allowConstructorFlags: { | |
| type: "array", | |
| items: { | |
| type: "string" | |
| } | |
| } | |
| }, | |
| additionalProperties: false | |
| }] | |
| }, | |
| create(context) { | |
| const options = context.options[0]; | |
| let allowedFlags = null; | |
| if (options && options.allowConstructorFlags) { | |
| const temp = options.allowConstructorFlags.join("").replace(validFlags, ""); | |
| if (temp) { | |
| allowedFlags = new RegExp(`[${temp}]`, "giu"); | |
| } | |
| } | |
| /** | |
| * Check if node is a string | |
| * @param {ASTNode} node node to evaluate | |
| * @returns {boolean} True if its a string | |
| * @private | |
| */ | |
| function isString(node) { | |
| return node && node.type === "Literal" && typeof node.value === "string"; | |
| } | |
| /** | |
| * Check syntax error in a given pattern. | |
| * @param {string} pattern The RegExp pattern to validate. | |
| * @param {boolean} uFlag The Unicode flag. | |
| * @returns {string|null} The syntax error. | |
| */ | |
| function validateRegExpPattern(pattern, uFlag) { | |
| try { | |
| validator.validatePattern(pattern, undefined1, undefined1, uFlag); | |
| return null; | |
| } catch (err) { | |
| return err.message; | |
| } | |
| } | |
| /** | |
| * Check syntax error in a given flags. | |
| * @param {string} flags The RegExp flags to validate. | |
| * @returns {string|null} The syntax error. | |
| */ | |
| function validateRegExpFlags(flags) { | |
| try { | |
| validator.validateFlags(flags); | |
| return null; | |
| } catch (err) { | |
| return `Invalid flags supplied to RegExp constructor '${flags}'`; | |
| } | |
| } | |
| return { | |
| "CallExpression, NewExpression"(node) { | |
| if (node.callee.type !== "Identifier" || node.callee.name !== "RegExp" || !isString(node.arguments[0])) { | |
| return; | |
| } | |
| const pattern = node.arguments[0].value; | |
| let flags = isString(node.arguments[1]) ? node.arguments[1].value : ""; | |
| if (allowedFlags) { | |
| flags = flags.replace(allowedFlags, ""); | |
| } | |
| // If flags are unknown, check both are errored or not. | |
| const message = validateRegExpFlags(flags) || ( | |
| flags | |
| ? validateRegExpPattern(pattern, flags.indexOf("u") !== -1) | |
| : validateRegExpPattern(pattern, true) && validateRegExpPattern(pattern, false) | |
| ); | |
| if (message) { | |
| context.report({ | |
| node, | |
| message: "{{message}}.", | |
| data: { message } | |
| }); | |
| } | |
| } | |
| }; | |
| } | |
| }; |