eslint-plugin-unicorn 50.0.0 → 51.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/configs/recommended.js +1 -1
- package/package.json +3 -2
- package/readme.md +5 -5
- package/rules/no-array-method-this-argument.js +113 -77
- package/rules/no-thenable.js +10 -4
- package/rules/no-unnecessary-polyfills.js +1 -1
- package/rules/prefer-module.js +43 -12
- package/rules/prefer-prototype-methods.js +1 -1
- package/rules/shared/abbreviations.js +1 -1
package/configs/recommended.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
module.exports = {
|
|
3
3
|
'unicorn/better-regex': 'error',
|
|
4
4
|
'unicorn/catch-error-name': 'error',
|
|
5
|
-
'unicorn/consistent-destructuring': '
|
|
5
|
+
'unicorn/consistent-destructuring': 'off',
|
|
6
6
|
'unicorn/consistent-function-scoping': 'error',
|
|
7
7
|
'unicorn/custom-error-definition': 'off',
|
|
8
8
|
'unicorn/empty-brace-spaces': 'error',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-unicorn",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "51.0.0",
|
|
4
4
|
"description": "More than 100 powerful ESLint rules",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "sindresorhus/eslint-plugin-unicorn",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"chalk": "^5.3.0",
|
|
78
78
|
"enquirer": "^2.4.1",
|
|
79
79
|
"eslint": "^8.56.0",
|
|
80
|
-
"eslint-ava-rule-tester": "^
|
|
80
|
+
"eslint-ava-rule-tester": "^5.0.1",
|
|
81
81
|
"eslint-doc-generator": "^1.6.1",
|
|
82
82
|
"eslint-plugin-eslint-plugin": "^5.2.1",
|
|
83
83
|
"eslint-plugin-internal-rules": "file:./scripts/internal-rules/",
|
|
@@ -91,6 +91,7 @@
|
|
|
91
91
|
"npm-package-json-lint": "^7.1.0",
|
|
92
92
|
"npm-run-all2": "^6.1.1",
|
|
93
93
|
"outdent": "^0.8.0",
|
|
94
|
+
"pretty-ms": "^8.0.0",
|
|
94
95
|
"typescript": "^5.3.3",
|
|
95
96
|
"vue-eslint-parser": "^9.3.2",
|
|
96
97
|
"xo": "^0.56.0",
|
package/readme.md
CHANGED
|
@@ -112,7 +112,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c
|
|
|
112
112
|
| :----------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :- | :- | :- |
|
|
113
113
|
| [better-regex](docs/rules/better-regex.md) | Improve regexes by making them shorter, consistent, and safer. | ✅ | 🔧 | |
|
|
114
114
|
| [catch-error-name](docs/rules/catch-error-name.md) | Enforce a specific parameter name in catch clauses. | ✅ | 🔧 | |
|
|
115
|
-
| [consistent-destructuring](docs/rules/consistent-destructuring.md) | Use destructured variables over properties. |
|
|
115
|
+
| [consistent-destructuring](docs/rules/consistent-destructuring.md) | Use destructured variables over properties. | | 🔧 | 💡 |
|
|
116
116
|
| [consistent-function-scoping](docs/rules/consistent-function-scoping.md) | Move function definitions to the highest possible scope. | ✅ | | |
|
|
117
117
|
| [custom-error-definition](docs/rules/custom-error-definition.md) | Enforce correct `Error` subclassing. | | 🔧 | |
|
|
118
118
|
| [empty-brace-spaces](docs/rules/empty-brace-spaces.md) | Enforce no spaces between braces. | ✅ | 🔧 | |
|
|
@@ -244,7 +244,7 @@ import eslintPluginUnicorn from 'eslint-plugin-unicorn';
|
|
|
244
244
|
|
|
245
245
|
export default [
|
|
246
246
|
// …
|
|
247
|
-
eslintPluginUnicorn.
|
|
247
|
+
eslintPluginUnicorn.configs['flat/recommended'],
|
|
248
248
|
{
|
|
249
249
|
rules: {
|
|
250
250
|
'unicorn/better-regex': 'warn',
|
|
@@ -261,7 +261,7 @@ const eslintPluginUnicorn = require('eslint-plugin-unicorn');
|
|
|
261
261
|
|
|
262
262
|
module.exports = [
|
|
263
263
|
// …
|
|
264
|
-
eslintPluginUnicorn.
|
|
264
|
+
eslintPluginUnicorn.configs['flat/recommended'],
|
|
265
265
|
{
|
|
266
266
|
rules: {
|
|
267
267
|
'unicorn/better-regex': 'warn',
|
|
@@ -281,7 +281,7 @@ import eslintPluginUnicorn from 'eslint-plugin-unicorn';
|
|
|
281
281
|
|
|
282
282
|
export default [
|
|
283
283
|
// …
|
|
284
|
-
eslintPluginUnicorn.
|
|
284
|
+
eslintPluginUnicorn.configs['flat/all'],
|
|
285
285
|
{
|
|
286
286
|
rules: {
|
|
287
287
|
'unicorn/better-regex': 'warn',
|
|
@@ -298,7 +298,7 @@ const eslintPluginUnicorn = require('eslint-plugin-unicorn');
|
|
|
298
298
|
|
|
299
299
|
module.exports = [
|
|
300
300
|
// …
|
|
301
|
-
eslintPluginUnicorn.
|
|
301
|
+
eslintPluginUnicorn.configs['flat/all'],
|
|
302
302
|
{
|
|
303
303
|
rules: {
|
|
304
304
|
'unicorn/better-regex': 'warn',
|
|
@@ -7,12 +7,14 @@ const {isNodeMatches} = require('./utils/is-node-matches.js');
|
|
|
7
7
|
const {isNodeValueNotFunction} = require('./utils/index.js');
|
|
8
8
|
const {isMethodCall} = require('./ast/index.js');
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const ERROR_PROTOTYPE_METHOD = 'error-prototype-method';
|
|
11
|
+
const ERROR_STATIC_METHOD = 'error-static-method';
|
|
11
12
|
const SUGGESTION_BIND = 'suggestion-bind';
|
|
12
13
|
const SUGGESTION_REMOVE = 'suggestion-remove';
|
|
13
14
|
const messages = {
|
|
14
|
-
[
|
|
15
|
-
[
|
|
15
|
+
[ERROR_PROTOTYPE_METHOD]: 'Do not use the `this` argument in `Array#{{method}}()`.',
|
|
16
|
+
[ERROR_STATIC_METHOD]: 'Do not use the `this` argument in `Array.{{method}}()`.',
|
|
17
|
+
[SUGGESTION_REMOVE]: 'Remove this argument.',
|
|
16
18
|
[SUGGESTION_BIND]: 'Use a bound function.',
|
|
17
19
|
};
|
|
18
20
|
|
|
@@ -70,107 +72,141 @@ const ignored = [
|
|
|
70
72
|
'underscore.some',
|
|
71
73
|
];
|
|
72
74
|
|
|
73
|
-
function removeThisArgument(
|
|
74
|
-
return fixer => removeArgument(fixer,
|
|
75
|
+
function removeThisArgument(thisArgumentNode, sourceCode) {
|
|
76
|
+
return fixer => removeArgument(fixer, thisArgumentNode, sourceCode);
|
|
75
77
|
}
|
|
76
78
|
|
|
77
|
-
function useBoundFunction(
|
|
79
|
+
function useBoundFunction(callbackNode, thisArgumentNode, sourceCode) {
|
|
78
80
|
return function * (fixer) {
|
|
79
|
-
yield removeThisArgument(
|
|
81
|
+
yield removeThisArgument(thisArgumentNode, sourceCode)(fixer);
|
|
80
82
|
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
const callbackParentheses = getParentheses(callback, sourceCode);
|
|
83
|
+
const callbackParentheses = getParentheses(callbackNode, sourceCode);
|
|
84
84
|
const isParenthesized = callbackParentheses.length > 0;
|
|
85
85
|
const callbackLastToken = isParenthesized
|
|
86
86
|
? callbackParentheses.at(-1)
|
|
87
|
-
:
|
|
87
|
+
: callbackNode;
|
|
88
88
|
if (
|
|
89
89
|
!isParenthesized
|
|
90
|
-
&& shouldAddParenthesesToMemberExpressionObject(
|
|
90
|
+
&& shouldAddParenthesesToMemberExpressionObject(callbackNode, sourceCode)
|
|
91
91
|
) {
|
|
92
92
|
yield fixer.insertTextBefore(callbackLastToken, '(');
|
|
93
93
|
yield fixer.insertTextAfter(callbackLastToken, ')');
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
const thisArgumentText = getParenthesizedText(
|
|
96
|
+
const thisArgumentText = getParenthesizedText(thisArgumentNode, sourceCode);
|
|
97
97
|
// `thisArgument` was a argument, no need add extra parentheses
|
|
98
98
|
yield fixer.insertTextAfter(callbackLastToken, `.bind(${thisArgumentText})`);
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
'findLastIndex',
|
|
117
|
-
'flatMap',
|
|
118
|
-
'forEach',
|
|
119
|
-
'map',
|
|
120
|
-
'some',
|
|
121
|
-
],
|
|
122
|
-
argumentsLength: 2,
|
|
123
|
-
optionalCall: false,
|
|
124
|
-
optionalMember: false,
|
|
125
|
-
})
|
|
126
|
-
|| isNodeMatches(callExpression.callee, ignored)
|
|
127
|
-
|| isNodeValueNotFunction(callExpression.arguments[0])
|
|
128
|
-
) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const {callee} = callExpression;
|
|
133
|
-
const method = callee.property.name;
|
|
134
|
-
const [callback, thisArgument] = callExpression.arguments;
|
|
135
|
-
|
|
136
|
-
const problem = {
|
|
137
|
-
node: thisArgument,
|
|
138
|
-
messageId: ERROR,
|
|
139
|
-
data: {method},
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
const thisArgumentHasSideEffect = hasSideEffect(thisArgument, sourceCode);
|
|
143
|
-
const isArrowCallback = callback.type === 'ArrowFunctionExpression';
|
|
144
|
-
|
|
145
|
-
if (isArrowCallback) {
|
|
146
|
-
if (thisArgumentHasSideEffect) {
|
|
147
|
-
problem.suggest = [
|
|
148
|
-
{
|
|
149
|
-
messageId: SUGGESTION_REMOVE,
|
|
150
|
-
fix: removeThisArgument(callExpression, sourceCode),
|
|
151
|
-
},
|
|
152
|
-
];
|
|
153
|
-
} else {
|
|
154
|
-
problem.fix = removeThisArgument(callExpression, sourceCode);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return problem;
|
|
158
|
-
}
|
|
102
|
+
function getProblem({
|
|
103
|
+
sourceCode,
|
|
104
|
+
callExpression,
|
|
105
|
+
callbackNode,
|
|
106
|
+
thisArgumentNode,
|
|
107
|
+
messageId,
|
|
108
|
+
}) {
|
|
109
|
+
const problem = {
|
|
110
|
+
node: thisArgumentNode,
|
|
111
|
+
messageId,
|
|
112
|
+
data: {
|
|
113
|
+
method: callExpression.callee.property.name,
|
|
114
|
+
},
|
|
115
|
+
};
|
|
159
116
|
|
|
117
|
+
const isArrowCallback = callbackNode.type === 'ArrowFunctionExpression';
|
|
118
|
+
if (isArrowCallback) {
|
|
119
|
+
const thisArgumentHasSideEffect = hasSideEffect(thisArgumentNode, sourceCode);
|
|
120
|
+
if (thisArgumentHasSideEffect) {
|
|
160
121
|
problem.suggest = [
|
|
161
122
|
{
|
|
162
123
|
messageId: SUGGESTION_REMOVE,
|
|
163
|
-
fix: removeThisArgument(
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
messageId: SUGGESTION_BIND,
|
|
167
|
-
fix: useBoundFunction(callExpression, sourceCode),
|
|
124
|
+
fix: removeThisArgument(thisArgumentNode, sourceCode),
|
|
168
125
|
},
|
|
169
126
|
];
|
|
127
|
+
} else {
|
|
128
|
+
problem.fix = removeThisArgument(thisArgumentNode, sourceCode);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return problem;
|
|
132
|
+
}
|
|
170
133
|
|
|
171
|
-
|
|
134
|
+
problem.suggest = [
|
|
135
|
+
{
|
|
136
|
+
messageId: SUGGESTION_REMOVE,
|
|
137
|
+
fix: removeThisArgument(thisArgumentNode, sourceCode),
|
|
172
138
|
},
|
|
173
|
-
|
|
139
|
+
{
|
|
140
|
+
messageId: SUGGESTION_BIND,
|
|
141
|
+
fix: useBoundFunction(callbackNode, thisArgumentNode, sourceCode),
|
|
142
|
+
},
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
return problem;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** @param {import('eslint').Rule.RuleContext} context */
|
|
149
|
+
const create = context => {
|
|
150
|
+
const {sourceCode} = context;
|
|
151
|
+
|
|
152
|
+
// Prototype methods
|
|
153
|
+
context.on('CallExpression', callExpression => {
|
|
154
|
+
if (
|
|
155
|
+
!isMethodCall(callExpression, {
|
|
156
|
+
methods: [
|
|
157
|
+
'every',
|
|
158
|
+
'filter',
|
|
159
|
+
'find',
|
|
160
|
+
'findLast',
|
|
161
|
+
'findIndex',
|
|
162
|
+
'findLastIndex',
|
|
163
|
+
'flatMap',
|
|
164
|
+
'forEach',
|
|
165
|
+
'map',
|
|
166
|
+
'some',
|
|
167
|
+
],
|
|
168
|
+
argumentsLength: 2,
|
|
169
|
+
optionalCall: false,
|
|
170
|
+
optionalMember: false,
|
|
171
|
+
})
|
|
172
|
+
|| isNodeMatches(callExpression.callee, ignored)
|
|
173
|
+
|| isNodeValueNotFunction(callExpression.arguments[0])
|
|
174
|
+
) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return getProblem({
|
|
179
|
+
sourceCode,
|
|
180
|
+
callExpression,
|
|
181
|
+
callbackNode: callExpression.arguments[0],
|
|
182
|
+
thisArgumentNode: callExpression.arguments[1],
|
|
183
|
+
messageId: ERROR_PROTOTYPE_METHOD,
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// `Array.from()`
|
|
188
|
+
context.on('CallExpression', callExpression => {
|
|
189
|
+
if (
|
|
190
|
+
!isMethodCall(callExpression, {
|
|
191
|
+
object: 'Array',
|
|
192
|
+
method: 'from',
|
|
193
|
+
argumentsLength: 3,
|
|
194
|
+
optionalCall: false,
|
|
195
|
+
optionalMember: false,
|
|
196
|
+
})
|
|
197
|
+
|| isNodeValueNotFunction(callExpression.arguments[1])
|
|
198
|
+
) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return getProblem({
|
|
203
|
+
sourceCode,
|
|
204
|
+
callExpression,
|
|
205
|
+
callbackNode: callExpression.arguments[1],
|
|
206
|
+
thisArgumentNode: callExpression.arguments[2],
|
|
207
|
+
messageId: ERROR_STATIC_METHOD,
|
|
208
|
+
});
|
|
209
|
+
});
|
|
174
210
|
};
|
|
175
211
|
|
|
176
212
|
/** @type {import('eslint').Rule.RuleModule} */
|
package/rules/no-thenable.js
CHANGED
|
@@ -13,6 +13,15 @@ const messages = {
|
|
|
13
13
|
|
|
14
14
|
const isStringThen = (node, context) =>
|
|
15
15
|
getStaticValue(node, context.sourceCode.getScope(node))?.value === 'then';
|
|
16
|
+
const isPropertyThen = (node, context) => {
|
|
17
|
+
// `getPropertyName` throws on `({[Symbol.prototype]: 0})`
|
|
18
|
+
// https://github.com/eslint-community/eslint-utils/pull/182
|
|
19
|
+
try {
|
|
20
|
+
return getPropertyName(node, context.sourceCode.getScope(node)) === 'then';
|
|
21
|
+
} catch {}
|
|
22
|
+
|
|
23
|
+
return false;
|
|
24
|
+
};
|
|
16
25
|
|
|
17
26
|
const cases = [
|
|
18
27
|
// `{then() {}}`,
|
|
@@ -23,10 +32,7 @@ const cases = [
|
|
|
23
32
|
selector: 'ObjectExpression',
|
|
24
33
|
* getNodes(node, context) {
|
|
25
34
|
for (const property of node.properties) {
|
|
26
|
-
if (
|
|
27
|
-
property.type === 'Property'
|
|
28
|
-
&& getPropertyName(property, context.sourceCode.getScope(property)) === 'then'
|
|
29
|
-
) {
|
|
35
|
+
if (property.type === 'Property' && isPropertyThen(property, context)) {
|
|
30
36
|
yield property.key;
|
|
31
37
|
}
|
|
32
38
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const path = require('node:path');
|
|
3
3
|
const readPkgUp = require('read-pkg-up');
|
|
4
4
|
const coreJsCompat = require('core-js-compat');
|
|
5
|
-
const {camelCase} = require('lodash');
|
|
5
|
+
const {camelCase} = require('./utils/lodash.js');
|
|
6
6
|
const isStaticRequire = require('./ast/is-static-require.js');
|
|
7
7
|
|
|
8
8
|
const {data: compatData, entries: coreJsEntries} = coreJsCompat;
|
package/rules/prefer-module.js
CHANGED
|
@@ -13,8 +13,10 @@ const ERROR_USE_STRICT_DIRECTIVE = 'error/use-strict-directive';
|
|
|
13
13
|
const ERROR_GLOBAL_RETURN = 'error/global-return';
|
|
14
14
|
const ERROR_IDENTIFIER = 'error/identifier';
|
|
15
15
|
const SUGGESTION_USE_STRICT_DIRECTIVE = 'suggestion/use-strict-directive';
|
|
16
|
-
const
|
|
17
|
-
const
|
|
16
|
+
const SUGGESTION_IMPORT_META_DIRNAME = 'suggestion/import-meta-dirname';
|
|
17
|
+
const SUGGESTION_IMPORT_META_URL_TO_DIRNAME = 'suggestion/import-meta-url-to-dirname';
|
|
18
|
+
const SUGGESTION_IMPORT_META_FILENAME = 'suggestion/import-meta-filename';
|
|
19
|
+
const SUGGESTION_IMPORT_META_URL_TO_FILENAME = 'suggestion/import-meta-url-to-filename';
|
|
18
20
|
const SUGGESTION_IMPORT = 'suggestion/import';
|
|
19
21
|
const SUGGESTION_EXPORT = 'suggestion/export';
|
|
20
22
|
const messages = {
|
|
@@ -22,12 +24,43 @@ const messages = {
|
|
|
22
24
|
[ERROR_GLOBAL_RETURN]: '"return" should be used inside a function.',
|
|
23
25
|
[ERROR_IDENTIFIER]: 'Do not use "{{name}}".',
|
|
24
26
|
[SUGGESTION_USE_STRICT_DIRECTIVE]: 'Remove "use strict" directive.',
|
|
25
|
-
[
|
|
26
|
-
[
|
|
27
|
+
[SUGGESTION_IMPORT_META_DIRNAME]: 'Replace `__dirname` with `import.meta.dirname`.',
|
|
28
|
+
[SUGGESTION_IMPORT_META_URL_TO_DIRNAME]: 'Replace `__dirname` with `…(import.meta.url)`.',
|
|
29
|
+
[SUGGESTION_IMPORT_META_FILENAME]: 'Replace `__dirname` with `import.meta.filename`.',
|
|
30
|
+
[SUGGESTION_IMPORT_META_URL_TO_FILENAME]: 'Replace `__filename` with `…(import.meta.url)`.',
|
|
27
31
|
[SUGGESTION_IMPORT]: 'Switch to `import`.',
|
|
28
32
|
[SUGGESTION_EXPORT]: 'Switch to `export`.',
|
|
29
33
|
};
|
|
30
34
|
|
|
35
|
+
const suggestions = new Map([
|
|
36
|
+
[
|
|
37
|
+
'__dirname',
|
|
38
|
+
[
|
|
39
|
+
{
|
|
40
|
+
messageId: SUGGESTION_IMPORT_META_DIRNAME,
|
|
41
|
+
replacement: 'import.meta.dirname',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
messageId: SUGGESTION_IMPORT_META_URL_TO_DIRNAME,
|
|
45
|
+
replacement: 'path.dirname(url.fileURLToPath(import.meta.url))',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
],
|
|
49
|
+
[
|
|
50
|
+
'__filename',
|
|
51
|
+
[
|
|
52
|
+
{
|
|
53
|
+
messageId: SUGGESTION_IMPORT_META_FILENAME,
|
|
54
|
+
replacement: 'import.meta.filename',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
messageId: SUGGESTION_IMPORT_META_URL_TO_FILENAME,
|
|
58
|
+
replacement: 'url.fileURLToPath(import.meta.url)',
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
],
|
|
62
|
+
]);
|
|
63
|
+
|
|
31
64
|
function fixRequireCall(node, sourceCode) {
|
|
32
65
|
if (!isStaticRequire(node.parent) || node.parent.callee !== node) {
|
|
33
66
|
return;
|
|
@@ -277,14 +310,12 @@ function create(context) {
|
|
|
277
310
|
switch (name) {
|
|
278
311
|
case '__filename':
|
|
279
312
|
case '__dirname': {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
fix: fixer => replaceReferenceIdentifier(node, replacement, fixer),
|
|
287
|
-
}];
|
|
313
|
+
problem.suggest = suggestions.get(node.name)
|
|
314
|
+
.map(({messageId, replacement}) => ({
|
|
315
|
+
messageId,
|
|
316
|
+
fix: fixer => replaceReferenceIdentifier(node, replacement, fixer),
|
|
317
|
+
}));
|
|
318
|
+
|
|
288
319
|
return problem;
|
|
289
320
|
}
|
|
290
321
|
|
|
@@ -30,7 +30,7 @@ function create(context) {
|
|
|
30
30
|
// `[].foo.{apply,bind,call}(…)`
|
|
31
31
|
// `({}).foo.{apply,bind,call}(…)`
|
|
32
32
|
isMethodCall(callExpression, {
|
|
33
|
-
|
|
33
|
+
methods: ['apply', 'bind', 'call'],
|
|
34
34
|
optionalCall: false,
|
|
35
35
|
optionalMember: false,
|
|
36
36
|
})
|