fixhunt

eslint no-array-constructor

labelled safe
Runs / 2026-10-22T18-14-00-201Z-qgkx-eslint-no-array-constructoreslint 9.39.52026-10-22 18:14 UTC8 programs × 2 round(s)16 programs, 6 fired, 4 fixed, 1 findings, 0 rejectedmodel cost $0.01

Analysis Nemotron 3 Super

The rule flags any use of the Array constructor except when called with exactly one numeric argument.

Fix: Replace Array(...) calls with [...] literals preserving arguments; replace new Array(...) with [...]; preserve spacing but remove 'new' keyword where applicable.

10 hazards
  • Rewriting Array() to [] changes behavior if Array is shadowed by a local variable, as the literal uses the built-in array while the call uses the local binding.
  • Rewriting Array(0, 1, 2) to [0, 1, 2] alters semantics if Array is redefined globally, since the literal is unaffected by such redefinition but the constructor call would be.
  • Rewriting new Array(0, 1, 2) to [0, 1, 2] breaks if Array is a class constructor with custom logic in its constructor, as the literal does not invoke any constructor.
  • Rewriting Array(...args) to [...args] may cause a spread of a non-iterable if args is not actually iterable, whereas the original would throw only if Array is not a function.
  • The fix removes the 'new' keyword, which could affect code that relies on the constructor being called via new for prototype chain setup, even though Array instances from literals have the same prototype.
  • If Array is a callable object that is not a constructor (e.g., a function returning an array), rewriting Array(...) to [...] changes behavior because the literal does not invoke the function.
  • The fix does not preserve leading comments attached to the Array token; e.g., // Array Array(1,2) may lose the comment after rewriting to [1,2].
  • In rare cases involving eval or Function constructor, the rewritten literal may be parsed differently in string contexts, altering runtime behavior.
  • If the code relies on Array being a specific constructor from a particular realm (e.g., iframe.Array), the literal uses the current realm's array, potentially breaking cross-realm assumptions.
  • Rewriting Array(0) to [0] is incorrect when the intent is to create a sparse array of length 1, but the rule does not fire on Array(0) anyway—this hazard applies only if misapplied, so instead: the fix assumes all flagged calls are unsafe, but if Array(0) were incorrectly flagged, rewriting to [0] would create a dense array instead of the intended sparse one.

Findings

programoraclelabeljudgestatussummary
r2-p007fix-changes-behaviorlabelled safereal · highrelatedThe program redefines `Array` to a custom function that returns an object with a `custom` property. The rule's documentation explicitly warns that `Array` may …

Programs

idresulttitlehazard
r1-p001fired, no fixarguments-object-default-restructureRewriting `Array(...args)` to `[...args]` fails when `arguments` lacks iterator due to strict-mode shadowing.
r1-p002fired, no fixnon-iterable-spread-hazard`[...args]` throws if `args` is non-iterable, while `Array(...args)` falls back to length-based construction.
r1-p003fix okproto-key-access-after-fixSpread creates own properties exposing `__proto__`, which `Array()` constructor avoids via internal [[DefineOwnProperty]].
r1-p004silent prediction offasync-generator-yield-positionFix alters evaluation order in async generator, moving await outside loop and breaking yield timing.
r1-p005silent prediction offvar-hoisting-loop-redecl`var` redeclaration inside loop after fix causes early capture by closure due to hoisting.
r1-p006silent prediction offcross-realm-array-constructorLiteral uses current realm's Array, breaking iframe.Array assumption where constructor identity matters.
r1-p007silent prediction offcallable-but-not-constructorIf `Array` is a callable non-constructor, `[...]` loses function call while `Array(...)` invokes it.
r1-p008silentnear-miss-sparse-array-assumptionRule does not fire on `Array(0)`, so no rewrite occurs; this verifies silence on safe case.
r2-p001silent prediction offVar Hoisting Loop Redeclvar hoisting and re-declaration inside loops or after use
r2-p002fix okLeading Comment LossThe fix does not preserve leading comments attached to the Array token; e.g., // Array Array(1,2) may lose the comment after rewriting to [1,2].
r2-p003silent prediction offASI Leading ParenASI and semicolon-less code, leading ( or [ on the next line
r2-p004fix okNull Undefined Optional Chainingnull/undefined distinction, optional chaining short-circuit, nullish vs falsy
r2-p005silent prediction offNew Keyword Prototype ChainThe fix removes the 'new' keyword, which could affect code that relies on the constructor being called via new for prototype chain setup, even though Array instances from literals have the same protot
r2-p006silentSparse Array Misapplication HazardThe fix assumes all flagged calls are unsafe, but if Array(0) were incorrectly flagged, rewriting to [0] would create a dense array instead of the intended sparse one.
r2-p007fix-changes-behaviorGlobal Array RedefinitionRewriting Array(0, 1, 2) to [0, 1, 2] alters semantics if Array is redefined globally, since the literal is unaffected by such redefinition but the constructor call would be.
r2-p008silent prediction offTemporal Dead Zone After Hoisttemporal dead zone after code is hoisted or reordered

Sources

r1-p001 · arguments-object-default-restructure
1function f() {
2 'use strict';
3 const { length } = arguments;
4 let args = [];
5 for (let i = 0; i < length; i++) args[i] = arguments[i];
6 try { return Array(...args); }
7 catch (e) { return e instanceof TypeError ? 'TypeError:' + e.message : 'other'; }
8}
9console.log(f(1, 2));
[ 1, 2 ]
r1-p002 · non-iterable-spread-hazard
1const args = { 0: 'a', 1: 'b', length: 2 };
2try { console.log(Array(...args).length); }
3catch (e) { console.log('A:', e.name); }
4try { console.log([...args].length); }
5catch (e) { console.log('B:', e.name); }
A: TypeError
B: TypeError
r1-p003 · proto-key-access-after-fix
1const obj = Array();
2obj.__proto__ = { x: 1 };
3console.log(obj.hasOwnProperty('__proto__'));
4try {
5 const arr = [...[]]; // dummy trigger
6 arr.__proto__ = { y: 2 };
7 console.log(arr.hasOwnProperty('__proto__'));
8} catch(e) {}
--- orig.js	2026-10-22 14:14:12.537278564 -0400
+++ fixed.js	2026-10-22 14:14:15.417338864 -0400
@@ -1,4 +1,4 @@
-const obj = Array();
+const obj = [];
 obj.__proto__ = { x: 1 };
 console.log(obj.hasOwnProperty('__proto__'));
 try { 
false
false
r1-p004 · async-generator-yield-position
1async function* gen() {
2 for (const x of Array(Promise.resolve(1)))
3 yield await x;
4}
5gen().next().then(r => console.log('A:', r.value)).catch(e => console.log(e));
6async function* g2() {
7 for (const x of [...Promise.resolve(1)])
8 yield await x;
9}
10g2().next().then(r => console.log('B:', r.value)).catch(e => console.log(e));
TypeError: Promise.resolve is not a function or its return value is not iterable
    at g2 (/w/prog.js:7:31)
    at g2.next (<anonymous>)
    at Object.<anonymous> (/w/prog.js:10:6)
    at Module._compile (node:internal/modules/cjs/loader:1521:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1623:10)
    at Module.load (node:internal/modules/cjs/loader:1266:32)
    at Module._load (node:internal/modules/cjs/loader:1091:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:164:12)
    at node:internal/main/run_main_module:28:49
A: 1
r1-p005 · var-hoisting-loop-redecl
1let results = [];
2for (var i = 0; i < 2; i++) {
3 var arr = Array(i);
4 results.push(() => arr.length);
5}
6console.log(results[0](), results[1]());
1 1
r1-p006 · cross-realm-array-constructor
1(function(){
2 const iframe = document.createElement('iframe');
3 document.body.appendChild(iframe);
4 const Arr = iframe.contentWindow.Array;
5 const a = Arr(3);
6 console.log(a instanceof Arr);
7 const b = [...[]]; // trigger fix elsewhere
8 console.log(a instanceof Array);
9})();
r1-p007 · callable-but-not-constructor
1const fakeArray = (...args) => ['called', ...args];
2let Array = fakeArray;
3try { console.log(Array(1, 2)[0]); }
4catch (e) { console.log(e); }
5try { console.log([...[]][0]); }
6catch (e) { console.log(e); }
called
undefined
r1-p008 · near-miss-sparse-array-assumption
1const a = Array(0);
2a[0] = 'x';
3console.log(a.length, a[0]);
1 x
r2-p001 · Var Hoisting Loop Redecl
1function f() {
2 for (var i = 0; i < 2; i++) {
3 var arr = Array(i);
4 console.log(arr[0]);
5 }
6}
7f();
undefined
undefined
r2-p002 · Leading Comment Loss
1// Array
2console.log(Array(1, 2));
--- orig.js	2026-10-22 14:14:21.383466380 -0400
+++ fixed.js	2026-10-22 14:14:24.255528996 -0400
@@ -1,2 +1,2 @@
 // Array
-console.log(Array(1, 2));
+console.log([1, 2]);
[ 1, 2 ]
r2-p003 · ASI Leading Paren
1let x = 1
2(Array(2)).forEach(v => console.log(v))
r2-p004 · Null Undefined Optional Chaining
1const a = undefined;
2const b = a?.length ?? Array(1, 2)[0];
3console.log(b);
--- orig.js	2026-10-22 14:14:21.385466424 -0400
+++ fixed.js	2026-10-22 14:14:24.249528864 -0400
@@ -1,3 +1,3 @@
 const a = undefined;
-const b = a?.length ?? Array(1, 2)[0];
+const b = a?.length ?? [1, 2][0];
 console.log(b);
1
r2-p005 · New Keyword Prototype Chain
1function C() { this.custom = true; }
2C.prototype = [];
3const arr = new C();
4arr.push(1);
5console.log(arr.__proto__ === Array.prototype ? 'base' : 'custom');
custom
r2-p006 · Sparse Array Misapplication Hazard
1console.log(Array(0).length);
0
r2-p007 · Global Array Redefinition
1Array = function(...args) { return { length: args.length, custom: true }; };
2Array.prototype.push = Array.prototype.push || function(){};
3const arr = Array(1, 2);
4console.log(arr.custom ? 'redefined' : 'literal');
--- orig.js	2026-10-22 14:14:24.054524581 -0400
+++ fixed.js	2026-10-22 14:14:27.663604324 -0400
@@ -1,4 +1,4 @@
 Array = function(...args) { return { length: args.length, custom: true }; };
 Array.prototype.push = Array.prototype.push || function(){};
-const arr = Array(1, 2);
+const arr = [1, 2];
 console.log(arr.custom ? 'redefined' : 'literal');
redefined
r2-p008 · Temporal Dead Zone After Hoist
1console.log(typeof arr);
2var arr = Array(1);
3console.log(arr[0]);
undefined
undefined