Skip to content

Commit 53d7508

Browse files
authored
feat: update regex for methods with thisArg (#17439)
* feat: update regex for methods with `thisArg` * rename regex constant
1 parent fcdc85d commit 53d7508

3 files changed

Lines changed: 56 additions & 88 deletions

File tree

lib/rules/utils/ast-utils.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ const {
2626

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

@@ -467,12 +467,12 @@ function isArrayFromMethod(node) {
467467
}
468468

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

478478
/**

tests/lib/rules/no-eval.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ ruleTester.run("no-eval", rule, {
5757
{ code: "class A { field = () => this.eval(); }", parserOptions: { ecmaVersion: 2022 } },
5858
{ code: "class A { static { this.eval(); } }", parserOptions: { ecmaVersion: 2022 } },
5959

60+
// User-defined this.eval in callbacks
61+
"array.findLast(function (x) { return this.eval.includes(x); }, { eval: ['foo', 'bar'] });",
62+
"callbacks.findLastIndex(function (cb) { return cb(this.eval); }, this);",
63+
"['1+1'].flatMap(function (str) { return this.eval(str); }, new Evaluator);",
64+
6065
// Allows indirect eval
6166
{ code: "(0, eval)('foo')", options: [{ allowIndirect: true }] },
6267
{ code: "(0, window.eval)('foo')", options: [{ allowIndirect: true }], env: { browser: true } },
@@ -162,6 +167,25 @@ ruleTester.run("no-eval", rule, {
162167
code: "function foo() { 'use strict'; this.eval(); }",
163168
parserOptions: { ecmaVersion: 3 },
164169
errors: [{ messageId: "unexpected" }]
170+
},
171+
172+
// this.eval in callbacks (not user-defined)
173+
{
174+
code: "array.findLast(x => this.eval.includes(x), { eval: 'abc' });",
175+
parserOptions: { ecmaVersion: 2023 },
176+
errors: [{ messageId: "unexpected" }]
177+
},
178+
{
179+
code: "callbacks.findLastIndex(function (cb) { return cb(eval); }, this);",
180+
errors: [{ messageId: "unexpected" }]
181+
},
182+
{
183+
code: "['1+1'].flatMap(function (str) { return this.eval(str); });",
184+
errors: [{ messageId: "unexpected" }]
185+
},
186+
{
187+
code: "['1'].reduce(function (a, b) { return this.eval(a) ? a : b; }, '0');",
188+
errors: [{ messageId: "unexpected" }]
165189
}
166190
]
167191
});

tests/lib/rules/no-invalid-this.js

Lines changed: 28 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -474,103 +474,47 @@ const patterns = [
474474
valid: [NORMAL],
475475
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
476476
},
477-
{
478-
code: "foo.every(function() { console.log(this); z(x => console.log(x, this)); });",
479-
parserOptions: { ecmaVersion: 6 },
480-
errors,
481-
valid: [NORMAL],
482-
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
483-
},
484-
{
485-
code: "foo.filter(function() { console.log(this); z(x => console.log(x, this)); });",
486-
parserOptions: { ecmaVersion: 6 },
487-
errors,
488-
valid: [NORMAL],
489-
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
490-
},
491-
{
492-
code: "foo.find(function() { console.log(this); z(x => console.log(x, this)); });",
493-
parserOptions: { ecmaVersion: 6 },
494-
errors,
495-
valid: [NORMAL],
496-
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
497-
},
498-
{
499-
code: "foo.findIndex(function() { console.log(this); z(x => console.log(x, this)); });",
500-
parserOptions: { ecmaVersion: 6 },
501-
errors,
502-
valid: [NORMAL],
503-
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
504-
},
505-
{
506-
code: "foo.forEach(function() { console.log(this); z(x => console.log(x, this)); });",
507-
parserOptions: { ecmaVersion: 6 },
508-
errors,
509-
valid: [NORMAL],
510-
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
511-
},
512-
{
513-
code: "foo.map(function() { console.log(this); z(x => console.log(x, this)); });",
514-
parserOptions: { ecmaVersion: 6 },
515-
errors,
516-
valid: [NORMAL],
517-
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
518-
},
519-
{
520-
code: "foo.some(function() { console.log(this); z(x => console.log(x, this)); });",
477+
...[
478+
"every",
479+
"filter",
480+
"find",
481+
"findIndex",
482+
"findLast",
483+
"findLastIndex",
484+
"flatMap",
485+
"forEach",
486+
"map",
487+
"some"
488+
].map(methodName => ({
489+
code: `foo.${methodName}(function() { console.log(this); z(x => console.log(x, this)); });`,
521490
parserOptions: { ecmaVersion: 6 },
522491
errors,
523492
valid: [NORMAL],
524493
invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
525-
},
494+
})),
526495
{
527496
code: "Array.from([], function() { console.log(this); z(x => console.log(x, this)); }, obj);",
528497
parserOptions: { ecmaVersion: 6 },
529498
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
530499
invalid: []
531500
},
532-
{
533-
code: "foo.every(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
534-
parserOptions: { ecmaVersion: 6 },
535-
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
536-
invalid: []
537-
},
538-
{
539-
code: "foo.filter(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
540-
parserOptions: { ecmaVersion: 6 },
541-
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
542-
invalid: []
543-
},
544-
{
545-
code: "foo.find(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
501+
...[
502+
"every",
503+
"filter",
504+
"find",
505+
"findIndex",
506+
"findLast",
507+
"findLastIndex",
508+
"flatMap",
509+
"forEach",
510+
"map",
511+
"some"
512+
].map(methodName => ({
513+
code: `foo.${methodName}(function() { console.log(this); z(x => console.log(x, this)); }, obj);`,
546514
parserOptions: { ecmaVersion: 6 },
547515
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
548516
invalid: []
549-
},
550-
{
551-
code: "foo.findIndex(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
552-
parserOptions: { ecmaVersion: 6 },
553-
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
554-
invalid: []
555-
},
556-
{
557-
code: "foo.forEach(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
558-
parserOptions: { ecmaVersion: 6 },
559-
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
560-
invalid: []
561-
},
562-
{
563-
code: "foo.map(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
564-
parserOptions: { ecmaVersion: 6 },
565-
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
566-
invalid: []
567-
},
568-
{
569-
code: "foo.some(function() { console.log(this); z(x => console.log(x, this)); }, obj);",
570-
parserOptions: { ecmaVersion: 6 },
571-
valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
572-
invalid: []
573-
},
517+
})),
574518
{
575519
code: "foo.forEach(function() { console.log(this); z(x => console.log(x, this)); }, null);",
576520
parserOptions: { ecmaVersion: 6 },

0 commit comments

Comments
 (0)