eslint sort-vars
labelled safe
Analysis Nemotron 3 Super
sort-vars requires variables declared together in var/let/const statements to appear in ascending lexicographic order.
Fix: Reorders the comma-separated variable declarators in the declaration to ascending alphabetical order by identifier name while preserving initializer expressions, 'var'/'let'/'const' kind, and all surrounding tokens and comments attached to those declarators.
10 hazards
- Moving a declarator with an initializer across another declarator changes evaluation order if initializers have side effects, altering program state before subsequent declarators run.
- If a declarator lacks an initializer and relies on hoisting (only relevant for 'var'), moving it after its use creates a ReferenceError because the variable is accessed before declaration.
- When declarators are separated by line comments, the autofix may reposition those comments relative to other code, changing which lines they annotate and potentially misleading readers.
- In a 'for' loop initialization part, reordering variables can affect the sequence of side effects in initializers, which may influence loop behavior if later variables depend on earlier ones.
- In a 'catch' clause parameter list, reordering parameters changes which argument maps to which identifier, breaking error handling if the payload structure is position-sensitive.
- If a variable name is shadowed in an inner scope, moving its declaration could alter the timing of when the shadowing takes effect, affecting variable resolution in intervening code.
- When a declarator includes a trailing comma, the autofix preserves it but may place it after a different identifier, which is syntactically harmless but could conflict with team conventions about trailing commas.
- If the declaration contains spread elements or rest patterns (invalid in var/let/const but possible via parser recovery), the autofix would still reorder tokens, likely producing a SyntaxError.
- Moving a declarator that declares a variable later used as a label (e.g., via a labeled statement) could change when the label is defined, affecting goto-like jumps in rare cases.
- In non-strict mode, a misplaced 'var' declaration might create a property on the global object; reordering could change the timing of that property creation relative to other code.
Programs
| id | result | title | hazard |
|---|---|---|---|
| r1-p001 | fired, no fix | For-loop init side-effect dependency | In a 'for' loop initialization part, reordering variables can affect the sequence of side effects in initializers, which may influence loop behavior if later variables depend on earlier ones. |
| r1-p002 | fired, no fix | Shadowing timing alteration | If a variable name is shadowed in an inner scope, moving its declaration could alter the timing of when the shadowing takes effect, affecting variable resolution in intervening code. |
| r1-p003 | fix ok | Hoisting ReferenceError for var | If a declarator lacks an initializer and relies on hoisting (only relevant for 'var'), moving it after its use creates a ReferenceError because the variable is accessed before declaration. |
| r1-p004 | fired, no fix | Label definition timing | Moving a declarator that declares a variable later used as a label (e.g., via a labeled statement) could change when the label is defined, affecting goto-like jumps in rare cases. |
| r1-p005 | silent | Evaluation order duplication/deletion | Order of evaluation when expressions are merged, duplicated or deleted (side effects run twice or never) |
| r1-p006 | fired, no fix | Coercion edge case | Numeric/string coercion: + vs template literal, objects with toString/valueOf, Symbol, BigInt |
| r1-p007 | invalid | Strict vs sloppy mode | Strict vs sloppy mode semantics |
| r1-p008 | fired, no fix | This binding sensitivity | This binding: arrow vs function, methods extracted from objects, call/apply/bind |
| r2-p001 | fix ok | Label usage affected by var sorting | Moving a declarator that declares a variable later used as a label could change when the label is defined, affecting goto-like jumps. |
| r2-p002 | fix ok | Comments moved with declarators alter annotation target | When declarators are separated by line comments, the autofix may reposition those comments relative to other code, changing which lines they annotate. |
| r2-p003 | invalid | Catch parameter reorder breaks error payload mapping | In a 'catch' clause parameter list, reordering parameters changes which argument maps to which identifier, breaking error handling if the payload structure is position-sensitive. |
| r2-p004 | silent prediction off | Trailing comma moved after sort violates convention | When a declarator includes a trailing comma, the autofix preserves it but may place it after a different identifier, which is syntactically harmless but could conflict with team conventions about trai |
| r2-p005 | silent prediction off | Function length changed by param reorder in sort-vars | arguments object, function.length, default parameters, rest parameters |
| r2-p006 | silent prediction off | Getter/setter side effect order changed by sort | getters, setters and Object.defineProperty side effects |
| r2-p008 | silent prediction off | Generator yield position changed by var sort in block | async/await ordering, generators and yield position |
Sources
r1-p001 · For-loop init side-effect dependency
1function main() {
2 let out = '';
3 for (let b = console.log('B') || 2, a = console.log('A') || b * 2; out += a + ','; ) {
4 break;
5 }
6 return out.slice(0, -1);
7}
8console.log(main());
B A 4
r1-p002 · Shadowing timing alteration
1function outer() {
2 let x = 1;
3 {
4 let y = console.log(x) || 0, x = console.log('shadow') || 2;
5 return x;
6 }
7}
8console.log(outer());
r1-p003 · Hoisting ReferenceError for var
1function test() {
2 try {
3 console.log(typeof x); // 'undefined' due to hoisting
4 var y = 1, x;
5 return typeof x;
6 } catch (e) {
7 return e.name + ': ' + e.message;
8 }
9}
10console.log(test());
--- orig.js 2026-10-22 14:32:21.422533574 -0400 +++ fixed.js 2026-10-22 14:32:25.235566123 -0400 @@ -1,7 +1,7 @@ function test() { try { console.log(typeof x); // 'undefined' due to hoisting - var y = 1, x; + var x, y = 1; return typeof x; } catch (e) { return e.name + ': ' + e.message;
undefined undefined
r1-p004 · Label definition timing
1function test() {
2 try {
3 var lbl = { toString: () => 'L' }, i;
4 lbl: {
5 console.log('enter');
6 break lbl;
7 }
8 return 'ok';
9 } catch (e) {
10 return e.name + ': ' + e.message;
11 }
12}
13console.log(test());
enter ok
r1-p005 · Evaluation order duplication/deletion
1function f() {
2 let a = 1, b = 2;
3 return a + b;
4}
5console.log(f());
3
r1-p006 · Coercion edge case
1function test() {
2 const obj = { valueOf: () => 1, toString: () => '2' };
3 let sym = String(obj), num = Number(obj) + 1;
4 return sym + '-' + num;
5}
6console.log(test());
2-2
r1-p007 · Strict vs sloppy mode (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-32-1)
1"use strict";
2(function() {
3 try {
4 let args = 1, arguments;
5 return typeof arguments;
6 } catch (e) {
7 return e.name + ': ' + e.message;
8 }
9})();
r1-p008 · This binding sensitivity
1const obj = { val: 42, getVal: function() { return this.val; } };
2let fn = obj.getVal, bound = fn.bind(obj);
3console.log(fn(), bound());
undefined 42
r2-p001 · Label usage affected by var sorting
1function test() {
2 var x, L;
3 x = 1;
4 L: console.log(x);
5}
6test();
--- orig.js 2026-10-22 14:32:30.843615531 -0400 +++ fixed.js 2026-10-22 14:32:34.317647052 -0400 @@ -1,5 +1,5 @@ function test() { - var x, L; + var L, x; x = 1; L: console.log(x); }
1
r2-p002 · Comments moved with declarators alter annotation target
1function test() {
2 // comment for y
3 let y,
4 // comment for x
5 x = 1;
6 console.log(x, y);
7}
8test();
--- orig.js 2026-10-22 14:32:30.844615540 -0400 +++ fixed.js 2026-10-22 14:32:34.129645325 -0400 @@ -1,8 +1,8 @@ function test() { // comment for y - let y, + let x = 1, // comment for x - x = 1; + y; console.log(x, y); } test();
1 undefined
r2-p003 · Catch parameter reorder breaks error payload mapping (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-32-1)
1function test() {
2 try {
3 throw {msg: 'error', code: 42};
4 } catch (code, msg) {
5 console.log(`msg=${msg}, code=${code}`);
6 }
7}
8test();
r2-p004 · Trailing comma moved after sort violates convention
1function test() {
2 let a,
3 b,
4 c,
5 d;
6 a = 1; b = 2; c = 3; d = 4;
7 console.log(a + b + c + d);
8}
9test();
10
r2-p005 · Function length changed by param reorder in sort-vars
1function f(z, y, x = 0) {
2 console.log(f.length, arguments.length, x);
3}
4f(1, 2);
2 2 0
r2-p006 · Getter/setter side effect order changed by sort
1let obj = {};
2let log = [];
3Object.defineProperty(obj, 'a', {
4 get() { log.push('get'); return 1; }
5});
6Object.defineProperty(obj, 'b', {
7 set(v) { log.push('set:' + v); }
8});
9obj.b = 2;
10console.log(obj.a, log.join('|'));
1 set:2|get
r2-p008 · Generator yield position changed by var sort in block
1function* gen() {
2 let x, y;
3 y = 1;
4 yield y;
5 x = 2;
6 yield x;
7}
8console.log([...gen()]);
[ 1, 2 ]