fixhunt

eslint no-else-return

labelled safe
Runs / 2026-10-22T18-15-37-418Z-3i3d-eslint-no-else-returneslint 9.39.52026-10-22 18:15 UTC8 programs × 2 round(s)16 programs, 12 fired, 12 fixed, 0 findings, 3 rejectedmodel cost $0.0038

Analysis Nemotron 3 Super

The rule flags `else` blocks immediately following an `if` block that contains a `return` statement.

Fix: Removes the `else` block and places its contents directly after the `if` block, preserving indentation and statements.

8 hazards
  • The rewrite fails when the `else` block contains a `break` or `continue` statement, as these are only valid inside loops and would cause a syntax error when moved outside.
  • Moving a `throw` statement from the `else` block changes control flow by skipping any `finally` blocks that would have been executed had the `else` remained within the original function scope.
  • If the `else` block declares a function using a function declaration, hoisting behavior changes because the function is no longer conditionally defined and may be accessible earlier than intended.
  • When the `else` block contains a `var` declaration, the variable becomes function-scoped and may be accessed before the `if` block due to hoisting, altering timing-dependent behavior.
  • Labels inside the `else` block become invalid after the rewrite if the surrounding context is not a loop or switch, causing a syntax error due to misplaced label usage.
  • The rewrite incorrectly handles empty `else` blocks by leaving an unnecessary empty block or semicolon, which may affect automatic semicolon insertion in edge cases involving line breaks.
  • If the `else` block contains a `debugger` statement, its execution timing relative to prior expressions in the `if` block remains the same, but surrounding tooling or profiling that depends on block structure may behave differently.
  • Comments attached to the `else` keyword or braces may be lost during the rewrite, as the autofix typically operates on syntactic tokens and does not preserve comment attachment in all formatter contexts.

Programs

idresulttitlehazard
r1-p001invalidHoisting vulnerability from var redeclarationvar hoisting and re-declaration inside loops or after use
r1-p002fix okComment loss on else keywordComments attached to the `else` keyword or braces may be lost during the rewrite
r1-p003silent prediction offEmpty else block semicolon hazardThe rewrite incorrectly handles empty `else` blocks by leaving an unnecessary empty block or semicolon
r1-p004fix okLabel interaction with nested returnlabel/break/continue control flow, finally blocks, early returns in nested blocks
r1-p005fix okVar hoisting timing alterationWhen the `else` block contains a `var` declaration, the variable becomes function-scoped and may be accessed before the `if` block due to hoisting
r1-p006fix okComment attachment on moved codecomments attached to the removed or moved code
r1-p007fix okSparse array interaction with else rewritesparse arrays, holes, Array(n) vs [n], array-likes
r1-p008fix ok__proto__ key interference in object mutation__proto__ keys, prototype access, Object.assign vs spread
r2-p001fix okStrict vs Sloppy Mode Semantics Hazardstrict vs sloppy mode semantics
r2-p002fix okThis Binding: Arrow vs Function Hazardthis binding: arrow vs function, methods extracted from objects, call/apply/bind
r2-p003invalidBreak/Continue Outside Loop HazardThe rewrite fails when the `else` block contains a `break` or `continue` statement, as these are only valid inside loops and would cause a syntax error when moved outside.
r2-p004fix okRegular Expressions: Escapes, Unicode Flag, LastIndex Hazardregular expressions: escapes, unicode flag, lastIndex with the g flag
r2-p005fix okDebugger Statement Timing HazardIf the `else` block contains a `debugger` statement, its execution timing relative to prior expressions in the `if` block remains the same, but surrounding tooling or profiling that depends on block s
r2-p006invalidEmpty Else Block Semicolon Insertion HazardThe rewrite incorrectly handles empty `else` blocks by leaving an unnecessary empty block or semicolon, which may affect automatic semicolon insertion in edge cases involving line breaks.
r2-p007fix okGetters, Setters and Object.defineProperty Side Effects Hazardgetters, setters and Object.defineProperty side effects
r2-p008fix okNumeric/String Coercion: + vs Template Literal Hazardnumeric/string coercion: + vs template literal, objects with toString/valueOf, Symbol, BigInt

Sources

r1-p001 · Hoisting vulnerability from var redeclaration (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-15-3)
1function test() {
2 let result = [];
3 for (let i = 0; i;; break) {
4 var x = 1;
5 if (i === 0) { return x; } // Line A
6 else { // Hazard: else with var decl
7 console.log('else', x);
8 var x = 99; // Redeclaration - hoisted!
9 x++;
10 }
11 result.push(x);
12 if (result.length > 2) break;
13 i++;
14 }
15 return result.join(',');
16}
17console.log(test());
r1-p002 · Comment loss on else keyword
1function logValue(flag) {
2 const out = [];
3 if (flag) { // Enter condition
4 return 42; // Magic number
5 } /* ignore */ // Comment on brace
6 else // <- Critical: comment on else keyword
7 { // Brace with potential comment loss
8 /* preserved */ // This should survive
9 out.push('hi');
10 }
11 out.push(flag ? 't' : 'f');
12 return out.join('|');
13}
14console.log(logValue(true));
15console.log(logValue(false));
--- orig.js	2026-10-22 14:15:49.613714250 -0400
+++ fixed.js	2026-10-22 14:15:53.579829312 -0400
@@ -3,11 +3,10 @@
   if (flag) {                  // Enter condition
     return 42;                 // Magic number
   } /* ignore */               // Comment on brace
-  else                         // <- Critical: comment on else keyword
-  {                            // Brace with potential comment loss
+                              // Brace with potential comment loss
     /* preserved */            // This should survive
     out.push('hi');
-  }
+  
   out.push(flag ? 't' : 'f');
   return out.join('|');
 }
42
hi|f
r1-p003 · Empty else block semicolon hazard
1function checkEmpty(a) {
2 try {
3 if (a < 0) { throw 'neg'; }
4 else {} // Hazard: empty else
5 return 'ok' + a;
6 } catch (e) {
7 return 'bad' + typeof e;
8 }
9}
10console.log(checkEmpty(-1));
11console.log(checkEmpty(5));
badstring
ok5
r1-p004 · Label interaction with nested return
1function process(data) {
2 outer: for (let i = 0; i < 3; i++) {
3 if (data[i] === undefined) { continue outer; }
4 if (data[i] === null) { // Trigger point
5 return i * 2; // Returns from loop
6 }
7 else { // Hazard: else after return
8 break outer; // Breaks labeled loop
9 }
10 console.log('skipped', i); // Should not print
11 }
12 return -1;
13}
14console.log(process([1, null, 3]));
--- orig.js	2026-10-22 14:15:49.615714307 -0400
+++ fixed.js	2026-10-22 14:15:53.018812963 -0400
@@ -4,9 +4,9 @@
     if (data[i] === null) {    // Trigger point
       return i * 2;            // Returns from loop
     }                          
-    else {                     // Hazard: else after return
+                         // Hazard: else after return
       break outer;             // Breaks labeled loop
-    }
+    
     console.log('skipped', i); // Should not print
   }
   return -1;
-1
r1-p005 · Var hoisting timing alteration
1function timingTest(val) {
2 console.log('start:', typeof y); // Hazard: accessing hoisted var
3 if (val > 0) { // Trigger: if with return
4 return y * 2;
5 }
6 else { // Else with var decl
7 var y = 5; // Hoisted to top
8 y += val;
9 return y;
10 }
11}
12console.log(timingTest(3));
13console.log(timingTest(-1));
--- orig.js	2026-10-22 14:15:49.616714336 -0400
+++ fixed.js	2026-10-22 14:15:53.593829720 -0400
@@ -3,11 +3,11 @@
   if (val > 0) {                   // Trigger: if with return
     return y * 2;
   }                                
-  else {                           // Else with var decl
+                             // Else with var decl
     var y = 5;                     // Hoisted to top
     y += val;
     return y;
-  }
+  
 }
 console.log(timingTest(3));
 console.log(timingTest(-1));
start: undefined
NaN
start: undefined
4
r1-p006 · Comment attachment on moved code
1function processFlag(mode) {
2 const log = [];
3 if (mode === 'fast') { // fast path
4 return 100; // <- value 100
5 }
6 else { // <- Hazard: comment-rich else
7 /* step 1 */ // Comment on statement
8 log.push('start'); // inline comment
9 /* step 2 */
10 mode.toUpperCase(); // side effect
11 return log.join('|');
12 }
13 log.push('end'); // Should not execute
14 return log.length;
15}
16console.log(processFlag('fast'));
17console.log(processFlag('slow'));
--- orig.js	2026-10-22 14:15:49.616714336 -0400
+++ fixed.js	2026-10-22 14:15:51.979782756 -0400
@@ -3,13 +3,13 @@
   if (mode === 'fast') {         // fast path
     return 100;                  // <- value 100
   }                              
-  else {                         // <- Hazard: comment-rich else
+                           // <- Hazard: comment-rich else
     /* step 1 */                 // Comment on statement
     log.push('start');           // inline comment
     /* step 2 */                 
     mode.toUpperCase();          // side effect
     return log.join('|');        
-  }
+  
   log.push('end');               // Should not execute
   return log.length;
 }
100
start
r1-p007 · Sparse array interaction with else rewrite
1function sparseCheck(arr) {
2 let sum = 0;
3 for (let i = 0; i < arr.length; i++) {
4 if (arr[i] === undefined) { // Trigger: hole detection
5 return sum; // Returns early on hole
6 }
7 else { // Hazard: else after return
8 sum += arr[i] || 0; // Would skip if rewritten poorly
9 }
10 }
11 return sum;
12}
13const sparse = [1, , 3]; // Hole at index 1
14console.log(sparseCheck(sparse));
15console.log(sparseCheck([1,2,3]));
--- orig.js	2026-10-22 14:15:49.660715606 -0400
+++ fixed.js	2026-10-22 14:15:53.567828962 -0400
@@ -4,9 +4,9 @@
     if (arr[i] === undefined) {  // Trigger: hole detection
       return sum;                // Returns early on hole
     }                            
-    else {                       // Hazard: else after return
+                           // Hazard: else after return
       sum += arr[i] || 0;        // Would skip if rewritten poorly
-    }
+    
   }
   return sum;
 }
1
6
r1-p008 · __proto__ key interference in object mutation
1function protoTest(obj) {
2 if ('__proto__' in obj) { // Trigger: proto check
3 return obj.__proto__; // Returns prototype
4 }
5 else { // Hazard: else block
6 obj.custom = 'added'; // Mutates input
7 return obj;
8 }
9}
10const map = { a: 1 };
11console.log('before:', map.custom);
12const result = protoTest(map); // Modifies map
13console.log('after:', map.custom);
14console.log('result:', result.custom);
--- orig.js	2026-10-22 14:15:52.255790779 -0400
+++ fixed.js	2026-10-22 14:15:56.205906079 -0400
@@ -2,10 +2,10 @@
   if ('__proto__' in obj) {      // Trigger: proto check
     return obj.__proto__;        // Returns prototype
   }                              
-  else {                         // Hazard: else block
+                           // Hazard: else block
     obj.custom = 'added';        // Mutates input
     return obj;                  
-  }
+  
 }
 const map = { a: 1 };
 console.log('before:', map.custom);
before: undefined
after: undefined
result: undefined
r2-p001 · Strict vs Sloppy Mode Semantics Hazard
1"use strict";
2let result = [];
3function test(x) {
4 if (x === 0) { return "zero"; }
5 else {
6 try { eval("arguments[0] = 99"); }
7 catch(e) { result.push(e.message); }
8 result.push(x);
9 }
10}
11test(5);
12test(0);
13console.log(result.join("|"));
--- orig.js	2026-10-22 14:16:07.021227045 -0400
+++ fixed.js	2026-10-22 14:16:10.442330153 -0400
@@ -2,11 +2,11 @@
 let result = [];
 function test(x) {
   if (x === 0) { return "zero"; }
-  else { 
+   
     try { eval("arguments[0] = 99"); }
     catch(e) { result.push(e.message); }
     result.push(x);
-  }
+  
 }
 test(5);
 test(0);
5
r2-p002 · This Binding: Arrow vs Function Hazard
1const obj = { val: 42, method() { return this.val; }, arrow: () => this.val };
2let logs = [];
3function wrapper(fn) {
4 if (typeof fn === "function") { return fn.call({val: 99}); }
5 else { logs.push(fn()); }
6}
7wrapper(obj.method);
8wrapper(obj.arrow);
9console.log(logs.length ? logs[0] : "none");
--- orig.js	2026-10-22 14:16:07.022227075 -0400
+++ fixed.js	2026-10-22 14:16:10.444330214 -0400
@@ -2,7 +2,7 @@
 let logs = [];
 function wrapper(fn) {
   if (typeof fn === "function") { return fn.call({val: 99}); }
-  else { logs.push(fn()); }
+   logs.push(fn()); 
 }
 wrapper(obj.method);
 wrapper(obj.arrow);
none
r2-p003 · Break/Continue Outside Loop Hazard (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-15-3)
1try {
2 if (false) { return 1; }
3 else { break; }
4} catch (e) {
5 console.log(e.name + ":" + e.message);
6}
r2-p004 · Regular Expressions: Escapes, Unicode Flag, LastIndex Hazard
1let str = "aßç🌟d", logs = [], re = /[a-zßç🌟]/gu;
2function testChar(ch) {
3 if (!re.test(ch)) { return false; }
4 else { logs.push(re.lastIndex); re.lastIndex = 0; }
5}
6for (const c of str) testChar(c);
7console.log(logs.join(","));
--- orig.js	2026-10-22 14:16:07.023227105 -0400
+++ fixed.js	2026-10-22 14:16:09.856312436 -0400
@@ -1,7 +1,7 @@
 let str = "aßç🌟d", logs = [], re = /[a-zßç🌟]/gu;
 function testChar(ch) {
   if (!re.test(ch)) { return false; }
-  else { logs.push(re.lastIndex); re.lastIndex = 0; }
+   logs.push(re.lastIndex); re.lastIndex = 0; 
 }
 for (const c of str) testChar(c);
 console.log(logs.join(","));
1,1,1,2,1
r2-p005 · Debugger Statement Timing Hazard
1let log = "";
2function check(val) {
3 if (val < 0) { log += "neg"; return; }
4 else { debugger; log += "pos"; }
5}
6check(-1);
7check(1);
8console.log(log);
--- orig.js	2026-10-22 14:16:07.024227135 -0400
+++ fixed.js	2026-10-22 14:16:11.531363129 -0400
@@ -1,7 +1,7 @@
 let log = "";
 function check(val) {
   if (val < 0) { log += "neg"; return; }
-  else { debugger; log += "pos"; }
+   debugger; log += "pos"; 
 }
 check(-1);
 check(1);
negpos
r2-p006 · Empty Else Block Semicolon Insertion Hazard (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-15-3)
1let x = 1
2;
3if (x === 1) { return } else {}
4console.log("reached");
r2-p007 · Getters, Setters and Object.defineProperty Side Effects Hazard
1const obj = {};
2let log = [], val = 10;
3Object.defineProperty(obj, "prop", {
4 get() { log.push("get"); return val; },
5 set(v) { log.push("set:" + v); val = v; }
6});
7function test() {
8 if (obj.prop > 5) { return obj.prop; }
9 else { obj.prop = 20; }
10}
11test();
12console.log(log.join("|") + "|" + val);
--- orig.js	2026-10-22 14:16:07.064228337 -0400
+++ fixed.js	2026-10-22 14:16:11.613365615 -0400
@@ -6,7 +6,7 @@
 });
 function test() {
   if (obj.prop > 5) { return obj.prop; }
-  else { obj.prop = 20; }
+   obj.prop = 20; 
 }
 test();
 console.log(log.join("|") + "|" + val);
get|get|10
r2-p008 · Numeric/String Coercion: + vs Template Literal Hazard
1const obj = { valueOf() { return 2; }, toString() { return "2" } };
2let results = [];
3function add(x) {
4 if (x === 2) { return x + 3; }
5 else { results.push(String(x) + 3); }
6}
7results.push(add(2));
8add(obj);
9console.log(results.join(""));
--- orig.js	2026-10-22 14:16:07.079228788 -0400
+++ fixed.js	2026-10-22 14:16:11.734369283 -0400
@@ -2,7 +2,7 @@
 let results = [];
 function add(x) {
   if (x === 2) { return x + 3; }
-  else { results.push(String(x) + 3); }
+   results.push(String(x) + 3); 
 }
 results.push(add(2));
 add(obj);
523