Skip to content

Commit

Permalink
feat: update regex for methods with thisArg (#17439)
Browse files Browse the repository at this point in the history
* feat: update regex for methods with `thisArg`

* rename regex constant
  • Loading branch information
fasttime committed Aug 2, 2023
1 parent fcdc85d commit 53d7508
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 88 deletions.
8 changes: 4 additions & 4 deletions lib/rules/utils/ast-utils.js
Expand Up @@ -26,8 +26,8 @@ const {

const anyFunctionPattern = /^(?:Function(?:Declaration|Expression)|ArrowFunctionExpression)$/u;
const anyLoopPattern = /^(?:DoWhile|For|ForIn|ForOf|While)Statement$/u;
const arrayMethodWithThisArgPattern = /^(?:every|filter|find(?:Last)?(?:Index)?|flatMap|forEach|map|some)$/u;
const arrayOrTypedArrayPattern = /Array$/u;
const arrayMethodPattern = /^(?:every|filter|find|findIndex|forEach|map|some)$/u;
const bindOrCallOrApplyPattern = /^(?:bind|call|apply)$/u;
const thisTagPattern = /^[\s*]*@this/mu;

Expand Down Expand Up @@ -467,12 +467,12 @@ function isArrayFromMethod(node) {
}

/**
* Checks whether or not a node is a method which has `thisArg`.
* Checks whether or not a node is a method which expects a function as a first argument, and `thisArg` as a second argument.
* @param {ASTNode} node A node to check.
* @returns {boolean} Whether or not the node is a method which has `thisArg`.
* @returns {boolean} Whether or not the node is a method which expects a function as a first argument, and `thisArg` as a second argument.
*/
function isMethodWhichHasThisArg(node) {
return isSpecificMemberAccess(node, null, arrayMethodPattern);
return isSpecificMemberAccess(node, null, arrayMethodWithThisArgPattern);
}

/**
Expand Down
24 changes: 24 additions & 0 deletions tests/lib/rules/no-eval.js
Expand Up @@ -57,6 +57,11 @@ ruleTester.run("no-eval", rule, {
{ code: "class A { field = () => this.eval(); }", parserOptions: { ecmaVersion: 2022 } },
{ code: "class A { static { this.eval(); } }", parserOptions: { ecmaVersion: 2022 } },

// User-defined this.eval in callbacks
"array.findLast(function (x) { return this.eval.includes(x); }, { eval: ['foo', 'bar'] });",
"callbacks.findLastIndex(function (cb) { return cb(this.eval); }, this);",
"['1+1'].flatMap(function (str) { return this.eval(str); }, new Evaluator);",

// Allows indirect eval
{ code: "(0, eval)('foo')", options: [{ allowIndirect: true }] },
{ code: "(0, window.eval)('foo')", options: [{ allowIndirect: true }], env: { browser: true } },
Expand Down Expand Up @@ -162,6 +167,25 @@ ruleTester.run("no-eval", rule, {
code: "function foo() { 'use strict'; this.eval(); }",
parserOptions: { ecmaVersion: 3 },
errors: [{ messageId: "unexpected" }]
},

// this.eval in callbacks (not user-defined)
{
code: "array.findLast(x => this.eval.includes(x), { eval: 'abc' });",
parserOptions: { ecmaVersion: 2023 },
errors: [{ messageId: "unexpected" }]
},
{
code: "callbacks.findLastIndex(function (cb) { return cb(eval); }, this);",
errors: [{ messageId: "unexpected" }]
},
{
code: "['1+1'].flatMap(function (str) { return this.eval(str); });",
errors: [{ messageId: "unexpected" }]
},
{
code: "['1'].reduce(function (a, b) { return this.eval(a) ? a : b; }, '0');",
errors: [{ messageId: "unexpected" }]
}
]
});
112 changes: 28 additions & 84 deletions tests/lib/rules/no-invalid-this.js
Expand Up @@ -474,103 +474,47 @@ const patterns = [
valid: [NORMAL],
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
},
{
code: "foo.every(function() { console.log(this); z(x => console.log(x, this)); });",
parserOptions: { ecmaVersion: 6 },
errors,
valid: [NORMAL],
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
},
{
code: "foo.filter(function() { console.log(this); z(x => console.log(x, this)); });",
parserOptions: { ecmaVersion: 6 },
errors,
valid: [NORMAL],
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
},
{
code: "foo.find(function() { console.log(this); z(x => console.log(x, this)); });",
parserOptions: { ecmaVersion: 6 },
errors,
valid: [NORMAL],
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
},
{
code: "foo.findIndex(function() { console.log(this); z(x => console.log(x, this)); });",
parserOptions: { ecmaVersion: 6 },
errors,
valid: [NORMAL],
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
},
{
code: "foo.forEach(function() { console.log(this); z(x => console.log(x, this)); });",
parserOptions: { ecmaVersion: 6 },
errors,
valid: [NORMAL],
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
},
{
code: "foo.map(function() { console.log(this); z(x => console.log(x, this)); });",
parserOptions: { ecmaVersion: 6 },
errors,
valid: [NORMAL],
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
},
{
code: "foo.some(function() { console.log(this); z(x => console.log(x, this)); });",
...[
"every",
"filter",
"find",
"findIndex",
"findLast",
"findLastIndex",
"flatMap",
"forEach",
"map",
"some"
].map(methodName => ({
code: `foo.${methodName}(function() { console.log(this); z(x => console.log(x, this)); });`,
parserOptions: { ecmaVersion: 6 },
errors,
valid: [NORMAL],
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
},
})),
{
code: "Array.from([], function() { console.log(this); z(x => console.log(x, this)); }, obj);",
parserOptions: { ecmaVersion: 6 },
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
invalid: []
},
{
code: "foo.every(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
parserOptions: { ecmaVersion: 6 },
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
invalid: []
},
{
code: "foo.filter(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
parserOptions: { ecmaVersion: 6 },
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
invalid: []
},
{
code: "foo.find(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
...[
"every",
"filter",
"find",
"findIndex",
"findLast",
"findLastIndex",
"flatMap",
"forEach",
"map",
"some"
].map(methodName => ({
code: `foo.${methodName}(function() { console.log(this); z(x => console.log(x, this)); }, obj);`,
parserOptions: { ecmaVersion: 6 },
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
invalid: []
},
{
code: "foo.findIndex(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
parserOptions: { ecmaVersion: 6 },
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
invalid: []
},
{
code: "foo.forEach(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
parserOptions: { ecmaVersion: 6 },
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
invalid: []
},
{
code: "foo.map(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
parserOptions: { ecmaVersion: 6 },
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
invalid: []
},
{
code: "foo.some(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
parserOptions: { ecmaVersion: 6 },
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
invalid: []
},
})),
{
code: "foo.forEach(function() { console.log(this); z(x => console.log(x, this)); }, null);",
parserOptions: { ecmaVersion: 6 },
Expand Down

0 comments on commit 53d7508

Please sign in to comment.