The prefer-array-from-map fixer incorrectly converts Array.from({ length: N }, mapper) to Array.from({ length: N }).fill(mapper()). This is semantically wrong in two ways:
1. Mapper with side effects — called once instead of N times
// Before — creates N independent worker coroutines
await Promise.all(Array.from({ length: concurrency }, () => worker()));
// After autofix — BROKEN
await Promise.all(Array.from({ length: concurrency }).fill(worker()));
// worker() is called ONCE, and the same promise fills all slots.
// Instead of N concurrent workers, you get 1 worker and N-1 duplicates.
2. Mapper producing unique values — all slots get same reference
// Before — each element gets unique random values
const bars = Array.from({ length: barCount }, () => ({
delay: Math.random(),
scale: Math.random() * 0.6 + 0.4,
}));
// After autofix — BROKEN
const bars = Array.from({ length: barCount }).fill({
delay: Math.random(),
scale: Math.random() * 0.6 + 0.4,
});
// All elements share the same object reference with the same random values.
// Mutating one mutates all.
Root cause
.fill(expr) evaluates expr once and fills every slot with that single value. Array.from(iterable, mapper) calls mapper once per element. These are not equivalent when the mapper has side effects or returns unique values.
Suggested fix
The rule should not flag Array.from({ length: N }, mapper) (with an object literal as the first argument) at all, since there's no [...{ length: N }] equivalent — it's a fundamentally different use of Array.from that creates arrays of a given length with a factory function.
Suggested test case (valid — should not flag)
// Mapper with side effects
'const workers = Array.from({ length: 4 }, () => startWorker())'
// Mapper producing unique objects
'const items = Array.from({ length: 10 }, () => ({ id: Math.random() }))'
// Mapper using index
'const indices = Array.from({ length: 5 }, (_, i) => i * 2)'
Note: #71 addressed a related issue (non-constant callbacks) but the fix appears incomplete — these cases still trigger and autofix incorrectly.
The
prefer-array-from-mapfixer incorrectly convertsArray.from({ length: N }, mapper)toArray.from({ length: N }).fill(mapper()). This is semantically wrong in two ways:1. Mapper with side effects — called once instead of N times
2. Mapper producing unique values — all slots get same reference
Root cause
.fill(expr)evaluatesexpronce and fills every slot with that single value.Array.from(iterable, mapper)callsmapperonce per element. These are not equivalent when the mapper has side effects or returns unique values.Suggested fix
The rule should not flag
Array.from({ length: N }, mapper)(with an object literal as the first argument) at all, since there's no[...{ length: N }]equivalent — it's a fundamentally different use ofArray.fromthat creates arrays of a given length with a factory function.Suggested test case (valid — should not flag)
Note: #71 addressed a related issue (non-constant callbacks) but the fix appears incomplete — these cases still trigger and autofix incorrectly.