Skip to content

Commit

Permalink
feat(no-regexp-lookbehind): add no-regexp-lookbehind
Browse files Browse the repository at this point in the history
  • Loading branch information
keithamus committed Apr 29, 2020
1 parent fa26dab commit 0d00077
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 1 deletion.
20 changes: 20 additions & 0 deletions docs/no-regexp-lookbehind.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# no-regexp-lookbehind

This prevents the use of the RegExp lookbehind feature

```js
/(?<=a>)b/

new RegExp("/(?<=a)b")
```

These will not be allowed because they are not supported in the following browsers:

- Edge < 79
- Safari (any version at the time of writing)
- Firefox (any version at the time of writing)
- Chrome < 62

## What is the Fix?

You may be able to rewrite your experession using (Negative) Lookaheads, but if not then there is no solution for this, aside from pulling in a custom RegExp library.
3 changes: 2 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ createRule('no-async-iteration', 'edge < 79, safari < 12, firefox < 57, chrome <
createRule('no-async-generator', 'edge < 79, safari < 12, firefox < 57, chrome < 63', 'disallow the use of async generator functions')
createRule('no-object-rest-spread', 'edge < 79, safari < 11.1, firefox < 55, chrome < 60', 'disallow object rest/spread patterns')
createRule('no-regexp-s-flag', 'edge < 79, safari < 11.1, firefox > 0, chrome < 62', 'disallow the use of the RegExp `s` flag')
createRule('no-regexp-lookbehind', 'edge < 79, safari > 0, firefox > 0, chrome < 62', 'disallow the use of RegExp lookbehinds')

// ES2019
createRule('no-optional-catch', 'edge < 79, safari < 11.1, firefox < 58, chrome < 66', 'always require catch() to have an argument')
Expand All @@ -61,7 +62,7 @@ createRule('no-do-expression', 'edge > 0, safari > 0, firefox > 0, chrome > 0',
createRule('no-bind-operator', 'edge > 0, safari > 0, firefox > 0, chrome > 0', 'disallow the :: bind operator')
createRule('no-pipeline-operator', 'edge > 0, safari > 0, firefox > 0, chrome > 0', 'disallow the > pipeline operator')

const v2breakingRules = new Set(['no-nullish-coalescing', 'no-bigint'])
const v2breakingRules = new Set(['no-nullish-coalescing', 'no-bigint', 'no-regexp-lookbehind'])

module.exports.configs.recommended = {
plugins: ['escompat'],
Expand Down
28 changes: 28 additions & 0 deletions lib/rules/no-regexp-lookbehind.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const hasLookbehind = s => s.includes('(?<=') || s.includes('(?<!)')

module.exports = (context, badBrowser) => ({
'Literal[regex]'(node) {
if (hasLookbehind(node.regex.pattern)) {
context.report(node, `RegExp lookbehinds are not supported in ${badBrowser}`)
}
},
'CallExpression[callee.name="RegExp"], NewExpression[callee.name="RegExp"]'(node) {
const [source] = node.arguments;
if (
source &&
(
(
source.type === 'Literal' &&
typeof source.value === 'string' &&
hasLookbehind(source.value)
) ||
(
source.type === 'TemplateLiteral' &&
source.quasis.some(({value: {raw}}) => hasLookbehind(raw))
)
)
) {
context.report(node, `RegExp lookbehinds are not supported in ${badBrowser}`)
}
}
})
49 changes: 49 additions & 0 deletions test/no-regexp-lookbehind.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
var rule = require('../lib/rules/no-regexp-lookbehind')
var RuleTester = require('eslint').RuleTester

var ruleTester = new RuleTester({parserOptions: {ecmaVersion: 2020}})

ruleTester.run('no-regexp-lookbehind', rule, {
valid: [
{code: '/(?:a)b/'},
{code: '/(?:a)b/g'},
{code: '/(?<named_group_not_checked_here>)/'},
{code: 'RegExp("(?:a)b", "g")'},
{code: 'RegExp("(?:a)b", "g")'},
{code: 'RegExp("(?<named-group-not-checked-here>)")'},
],
invalid: [
{
code: '/(?<=a)b/',
errors: [
{
message: 'RegExp lookbehinds are not supported in undefined'
}
]
},
{
code: 'new RegExp("/(?<=a)b")',
errors: [
{
message: 'RegExp lookbehinds are not supported in undefined'
}
]
},
{
code: '/(?<=a)b/g',
errors: [
{
message: 'RegExp lookbehinds are not supported in undefined'
}
]
},
{
code: 'new RegExp("/(?<=a)b", "g")',
errors: [
{
message: 'RegExp lookbehinds are not supported in undefined'
}
]
},
]
})

0 comments on commit 0d00077

Please sign in to comment.