Skip to content

Commit 10f26f1

Browse files
committed
fix: crash in from-map rule with identifiers as callbacks and some invalid fix suggestions. (fixes #344)
1 parent e8c486b commit 10f26f1

File tree

2 files changed

+35
-10
lines changed

2 files changed

+35
-10
lines changed

rules/from-map.js

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
*/
55
"use strict";
66

7-
const { ARROW_FUNCTION_EXPRESSION } = require("../lib/type");
7+
const { ARROW_FUNCTION_EXPRESSION } = require("../lib/type"),
8+
ALL_PARAMS = [
9+
{ name: 'item' },
10+
{ name: 'index' }
11+
];
812

913
module.exports = {
1014
meta: {
@@ -21,11 +25,22 @@ module.exports = {
2125
},
2226
create(context) {
2327
return {
24-
'CallExpression[callee.type="MemberExpression"] > MemberExpression[property.name="map"] > CallExpression[callee.type="MemberExpression"][callee.property.name="from"][callee.object.type="Identifier"][callee.object.name="Array"]'(node) {
28+
'CallExpression[callee.type="MemberExpression"] > MemberExpression[property.name="map"][property] > CallExpression[callee.type="MemberExpression"][callee.property.name="from"][callee.object.type="Identifier"][callee.object.name="Array"]'(node) {
2529
const parent = node,
26-
callee = node.parent;
30+
callee = node.parent,
31+
[
32+
mapCallback,
33+
mapThisArgument
34+
] = callee.parent.arguments;
2735
node = callee.parent;
2836

37+
if(mapCallback.type === "Identifier" ||
38+
mapCallback.params.length > ALL_PARAMS.length ||
39+
mapCallback.params.some((parameter) => parameter.type === "RestElement")
40+
) {
41+
return;
42+
}
43+
2944
context.report({
3045
node: callee.property,
3146
loc: {
@@ -42,17 +57,14 @@ module.exports = {
4257
// Merge the from and map callbacks
4358
if(parent.arguments.length >= HAS_CBK) {
4459
const OMIT_ITEM = 1,
45-
[
46-
mapCallback,
47-
mapThisArgument
48-
] = node.arguments,
4960
[
5061
_, // eslint-disable-line no-unused-vars
5162
callback,
5263
thisArgument
5364
] = parent.arguments,
54-
// Get the params names from the callback that has the most params (since the signature is identical).
55-
parameters = callback.params.length > mapCallback.params.length ? callback.params : mapCallback.params,
65+
parameters = callback.type !== "Identifier"
66+
? callback.params.length > mapCallback.params.length ? callback.params : mapCallback.params
67+
: ALL_PARAMS,
5668
parameterString = parameters.map((p) => p.name).join(PARAM_SEPARATOR),
5769
getCallback = (cbk, targ, ps) => {
5870
const source = `(${sourceCode.getText(cbk)})`;

test/helpers/from-map-test-cases.mjs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ export default {
22
valid: [
33
'array.map((t) => t.id)',
44
'Array.from(iterable).some((t) => t !== "a")',
5-
'Array.from(iterable, (t) => t.id)'
5+
'Array.from(iterable, (t) => t.id)',
6+
'Array.from(iterable, callback)',
7+
'Array.from(iterable).map((u, i, a) => a[i])',
8+
'Array.from(iterable).map(callback)',
9+
'Array.from(iterable).map((...args) => args)'
610
],
711
invalid: [
812
{
@@ -58,6 +62,15 @@ export default {
5862
line: 1
5963
} ],
6064
output: 'Array.from(iterable, function(u, i) { return (function(t) { return t[0]; }).call(b, (function(u, i) { return u.id; }).call(this, u, i), i); }, a)'
65+
},
66+
{
67+
code: 'Array.from(iterable, mapper).map((u, i) => u.name)',
68+
errors: [ {
69+
messageId: 'useMapCb',
70+
column: 1,
71+
line: 1
72+
} ],
73+
output: 'Array.from(iterable, (item, index) => ((u, i) => u.name)((mapper).call(this, item, index), index))'
6174
}
6275
]
6376
};

0 commit comments

Comments
 (0)