source: imaps-frontend/node_modules/eslint/lib/rules/no-invalid-regexp.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/**
2 * @fileoverview Validate strings passed to the RegExp constructor
3 * @author Michael Ficarra
4 */
5"use strict";
6
7//------------------------------------------------------------------------------
8// Requirements
9//------------------------------------------------------------------------------
10
11const RegExpValidator = require("@eslint-community/regexpp").RegExpValidator;
12const validator = new RegExpValidator();
13const validFlags = /[dgimsuvy]/gu;
14const undefined1 = void 0;
15
16//------------------------------------------------------------------------------
17// Rule Definition
18//------------------------------------------------------------------------------
19
20/** @type {import('../shared/types').Rule} */
21module.exports = {
22 meta: {
23 type: "problem",
24
25 docs: {
26 description: "Disallow invalid regular expression strings in `RegExp` constructors",
27 recommended: true,
28 url: "https://eslint.org/docs/latest/rules/no-invalid-regexp"
29 },
30
31 schema: [{
32 type: "object",
33 properties: {
34 allowConstructorFlags: {
35 type: "array",
36 items: {
37 type: "string"
38 }
39 }
40 },
41 additionalProperties: false
42 }],
43
44 messages: {
45 regexMessage: "{{message}}."
46 }
47 },
48
49 create(context) {
50
51 const options = context.options[0];
52 let allowedFlags = null;
53
54 if (options && options.allowConstructorFlags) {
55 const temp = options.allowConstructorFlags.join("").replace(validFlags, "");
56
57 if (temp) {
58 allowedFlags = new RegExp(`[${temp}]`, "giu");
59 }
60 }
61
62 /**
63 * Reports error with the provided message.
64 * @param {ASTNode} node The node holding the invalid RegExp
65 * @param {string} message The message to report.
66 * @returns {void}
67 */
68 function report(node, message) {
69 context.report({
70 node,
71 messageId: "regexMessage",
72 data: { message }
73 });
74 }
75
76 /**
77 * Check if node is a string
78 * @param {ASTNode} node node to evaluate
79 * @returns {boolean} True if its a string
80 * @private
81 */
82 function isString(node) {
83 return node && node.type === "Literal" && typeof node.value === "string";
84 }
85
86 /**
87 * Gets flags of a regular expression created by the given `RegExp()` or `new RegExp()` call
88 * Examples:
89 * new RegExp(".") // => ""
90 * new RegExp(".", "gu") // => "gu"
91 * new RegExp(".", flags) // => null
92 * @param {ASTNode} node `CallExpression` or `NewExpression` node
93 * @returns {string|null} flags if they can be determined, `null` otherwise
94 * @private
95 */
96 function getFlags(node) {
97 if (node.arguments.length < 2) {
98 return "";
99 }
100
101 if (isString(node.arguments[1])) {
102 return node.arguments[1].value;
103 }
104
105 return null;
106 }
107
108 /**
109 * Check syntax error in a given pattern.
110 * @param {string} pattern The RegExp pattern to validate.
111 * @param {Object} flags The RegExp flags to validate.
112 * @param {boolean} [flags.unicode] The Unicode flag.
113 * @param {boolean} [flags.unicodeSets] The UnicodeSets flag.
114 * @returns {string|null} The syntax error.
115 */
116 function validateRegExpPattern(pattern, flags) {
117 try {
118 validator.validatePattern(pattern, undefined1, undefined1, flags);
119 return null;
120 } catch (err) {
121 return err.message;
122 }
123 }
124
125 /**
126 * Check syntax error in a given flags.
127 * @param {string|null} flags The RegExp flags to validate.
128 * @returns {string|null} The syntax error.
129 */
130 function validateRegExpFlags(flags) {
131 if (!flags) {
132 return null;
133 }
134 try {
135 validator.validateFlags(flags);
136 } catch {
137 return `Invalid flags supplied to RegExp constructor '${flags}'`;
138 }
139
140 /*
141 * `regexpp` checks the combination of `u` and `v` flags when parsing `Pattern` according to `ecma262`,
142 * but this rule may check only the flag when the pattern is unidentifiable, so check it here.
143 * https://tc39.es/ecma262/multipage/text-processing.html#sec-parsepattern
144 */
145 if (flags.includes("u") && flags.includes("v")) {
146 return "Regex 'u' and 'v' flags cannot be used together";
147 }
148 return null;
149 }
150
151 return {
152 "CallExpression, NewExpression"(node) {
153 if (node.callee.type !== "Identifier" || node.callee.name !== "RegExp") {
154 return;
155 }
156
157 let flags = getFlags(node);
158
159 if (flags && allowedFlags) {
160 flags = flags.replace(allowedFlags, "");
161 }
162
163 let message = validateRegExpFlags(flags);
164
165 if (message) {
166 report(node, message);
167 return;
168 }
169
170 if (!isString(node.arguments[0])) {
171 return;
172 }
173
174 const pattern = node.arguments[0].value;
175
176 message = (
177
178 // If flags are unknown, report the regex only if its pattern is invalid both with and without the "u" flag
179 flags === null
180 ? (
181 validateRegExpPattern(pattern, { unicode: true, unicodeSets: false }) &&
182 validateRegExpPattern(pattern, { unicode: false, unicodeSets: true }) &&
183 validateRegExpPattern(pattern, { unicode: false, unicodeSets: false })
184 )
185 : validateRegExpPattern(pattern, { unicode: flags.includes("u"), unicodeSets: flags.includes("v") })
186 );
187
188 if (message) {
189 report(node, message);
190 }
191 }
192 };
193 }
194};
Note: See TracBrowser for help on using the repository browser.