Skip to content

Commit 3bbe027

Browse files
authored
prefer-string-replace-all: Don't crash on invalid pattern (#2011)
1 parent 8cd1ded commit 3bbe027

8 files changed

+60
-6
lines changed

rules/better-regex.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ const {newExpressionSelector} = require('./selectors/index.js');
66
const {isStringLiteral} = require('./ast/index.js');
77

88
const MESSAGE_ID = 'better-regex';
9+
const MESSAGE_ID_PARSE_ERROR = 'better-regex/parse-error';
910
const messages = {
1011
[MESSAGE_ID]: '{{original}} can be optimized to {{optimized}}.',
12+
[MESSAGE_ID_PARSE_ERROR]: 'Problem parsing {{original}}: {{error}}',
1113
};
1214

1315
const newRegExp = newExpressionSelector({name: 'RegExp', minimumArguments: 1});
@@ -39,11 +41,11 @@ const create = context => {
3941
} catch (error) {
4042
return {
4143
node,
44+
messageId: MESSAGE_ID_PARSE_ERROR,
4245
data: {
4346
original,
4447
error: error.message,
4548
},
46-
message: 'Problem parsing {{original}}: {{error}}',
4749
};
4850
}
4951

rules/prefer-string-replace-all.js

+11-5
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,17 @@ function getPatternReplacement(node) {
2727
return;
2828
}
2929

30-
const tree = parseRegExp(pattern, flags, {
31-
unicodePropertyEscape: true,
32-
namedGroups: true,
33-
lookbehind: true,
34-
});
30+
let tree;
31+
32+
try {
33+
tree = parseRegExp(pattern, flags, {
34+
unicodePropertyEscape: true,
35+
namedGroups: true,
36+
lookbehind: true,
37+
});
38+
} catch {
39+
return;
40+
}
3541

3642
const parts = tree.type === 'alternative' ? tree.body : [tree];
3743
if (parts.some(part => part.type !== 'value')) {

test/better-regex.mjs

+8
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,11 @@ test({
323323
},
324324
],
325325
});
326+
327+
test.snapshot({
328+
valid: [],
329+
invalid: [
330+
// Invalid RegExp
331+
'/(?!a)+/g',
332+
],
333+
});

test/prefer-string-replace-all.mjs

+3
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,8 @@ test.snapshot({
103103
'foo.replaceAll(/a]/g, _)',
104104
'foo.replaceAll(/\\r\\n\\u{1f600}/gu, _)',
105105
`foo.replaceAll(/a${' very'.repeat(30)} long string/g, _)`,
106+
107+
// Invalid RegExp #2010
108+
'foo.replace(/(?!a)+/g, "")',
106109
],
107110
});

test/snapshots/better-regex.mjs.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Snapshot report for `test/better-regex.mjs`
2+
3+
The actual snapshot is saved in `better-regex.mjs.snap`.
4+
5+
Generated by [AVA](https://avajs.dev).
6+
7+
## Invalid #1
8+
1 | /(?!a)+/g
9+
10+
> Error 1/1
11+
12+
`␊
13+
> 1 | /(?!a)+/g␊
14+
| ^^^^^^^^^ Problem parsing /(?!a)+/g: ␊
15+
16+
/(?!a)+/g␊
17+
^␊
18+
Unexpected token: "+" at 1:6.␊
19+
`

test/snapshots/better-regex.mjs.snap

175 Bytes
Binary file not shown.

test/snapshots/prefer-string-replace-all.mjs.md

+16
Original file line numberDiff line numberDiff line change
@@ -613,3 +613,19 @@ Generated by [AVA](https://avajs.dev).
613613
> 1 | foo.replaceAll(/a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long string/g, _)␊
614614
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This pattern can be replaced with a string literal.␊
615615
`
616+
617+
## Invalid #38
618+
1 | foo.replace(/(?!a)+/g, "")
619+
620+
> Output
621+
622+
`␊
623+
1 | foo.replaceAll(/(?!a)+/g, "")␊
624+
`
625+
626+
> Error 1/1
627+
628+
`␊
629+
> 1 | foo.replace(/(?!a)+/g, "")␊
630+
| ^^^^^^^ Prefer \`String#replaceAll()\` over \`String#replace()\`.␊
631+
`
48 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)