fixhunt

eslint curly

labelled safe
Runs / 2026-10-22T18-12-12-228Z-mbq6-eslint-curlyeslint 9.39.52026-10-22 18:12 UTC8 programs × 2 round(s)16 programs, 14 fired, 14 fixed, 0 findings, 1 rejectedmodel cost $0.0034

Analysis Nemotron 3 Super

The curly rule flags missing braces around single-statement bodies of if, else, for, while, and do-while statements.

Fix: Wraps the single-statement body in curly braces, preserving indentation and formatting where possible.

8 hazards
  • Rewriting 'if (x) y();' to 'if (x) { y(); }' changes nothing semantically but may affect automatic semicolon insertion if the original relied on ASI across a line break—though rare, adding braces could prevent a newline from being interpreted as a statement terminator in edge cases involving line-break-sensitive expressions.
  • If the single statement is a labeled statement like 'label: break;', wrapping it in braces creates a new block scope, which does not affect the label's validity but could confuse readers expecting the label to function outside the block—though the label remains function-scoped, the block may mislead about scope boundaries.
  • In a 'with' statement context (deprecated but still parsable), adding braces around the body could alter scope resolution if the original relied on the with object being implicitly available—though braces don't change with behavior, the visual nesting might mislead maintainers about scope, potentially causing bugs if they refactor based on perceived scope.
  • If the statement contains a trailing comment on the same line (e.g., 'if (x) y++; // comment'), the fix may reposition the comment inside the braces, which is harmless syntactically but could break tools or conventions that expect comments to remain at specific column positions or outside control structures.
  • In a macro-like preprocessing environment (non-standard), tools that scan for patterns like 'if (cond) stmt;' might fail to match the braced version, breaking build-time instrumentation or code generation that depends on the unbraceled form.
  • If the single statement is a directive prologue like '"use strict";' inside a function, wrapping it in braces does not change its effect, but if mistakenly applied to a non-function block, it could create a block-scoped strict directive—which has no effect, so no behavioral change, though it may confuse linters expecting directives only at function or script top level.
  • In rare cases where the statement is an empty statement (';'), rewriting 'if (x);' to 'if (x) {}' is functionally identical, but some minifiers or parsers might treat the empty block differently in terms of byte output or syntax tree structure, though execution remains unchanged.
  • If the code relies on dynamic scope inspection via non-standard APIs (e.g., examining the call stack or function.caller), adding a block introduces an additional lexical environment, which could alter the depth of scopes inspected—though such APIs are obsolete and unreliable, this represents a theoretical hazard in legacy environments.

Programs

idresulttitlehazard
r1-p001fix okVar Hoisting & Redeclaration Inside Loopsvar hoisting and re-declaration inside loops or after use
r1-p002fix ok prediction offDirective Prologue MisapplicationIf the single statement is a directive prologue like \"use strict\" inside a function, wrapping it in braces does not change its effect, but if mistakenly applied to a non-function block, it could cre
r1-p003fix okEmpty Statement RewritingIn rare cases where the statement is an empty statement (';'), rewriting 'if (x);' to 'if (x) {}' is functionally identical, but some minifiers or parsers might treat the empty block differently in te
r1-p004fix ok__proto__ Keys & Prototype Access__proto__ keys, prototype access, Object.assign vs spread
r1-p005fix okThis Binding: Arrow vs Functionthis binding: arrow vs function, methods extracted from objects, call/apply/bind
r1-p006fix okClass Fields, Static Blocks, Private Namesclass fields, static blocks, private names, super calls
r1-p007silent prediction offASI and Semicolon-less CodeASI and semicolon-less code, leading ( or [ on the next line
r1-p008fix okNumeric/String Coercionnumeric/string coercion: + vs template literal, objects with toString/valueOf, Symbol, BigInt
r2-p001fix okEmpty statement rewriting affects JSDoc parsingIn rare cases where the statement is an empty statement (';'), rewriting 'if (x)' to 'if (x) {}' changes how trailing comments or docblocks attach syntactically.
r2-p002fix okASI hazard with leading parenthesis after if-bodySemicolon-less code with leading '(' on next line causes misparse when body is braced due to altered ASI boundaries.
r2-p003fix ok prediction offGetter/setter side effect timing changed by block wrapWrapping a getter access in braces doesn't change value but alters microtask timing if getter has async side effects.
r2-p004fix okNon-standard stack inspection depth altered by new blockAdding a block introduces a new lexical environment, increasing stack depth observed by legacy .caller chains.
r2-p005fix okarguments object capture shifted by block scopeBracing a one-line loop body creates a new scope, causing closures to capture different arguments objects.
r2-p006invalidTDZ interaction with re-declaration after braced loopRe-declaring a var after a braced loop vs unbraced affects hoisting visibility in TDZ-sensitive contexts.
r2-p007fix okSparse array mutation via braced loop bodyBracing a loop body doesn't change iteration but altering comment attachment may affect tooling-dependent codegen.
r2-p008fix okNumeric/string coercion altered by brace-induced newline handlingBrace wrapping changes how JS engines handle newline-dependent coercion in edge-case expressions.

Sources

r1-p001 · Var Hoisting & Redeclaration Inside Loops
1function f() {
2 for (var i = 0; i < 2; i++)
3 if (i === 0)
4 var x = 1;
5 console.log(x);
6}
7f();
--- orig.js	2026-10-22 14:12:19.494673111 -0400
+++ fixed.js	2026-10-22 14:12:21.890689273 -0400
@@ -1,7 +1,7 @@
 function f() {
   for (var i = 0; i < 2; i++)
-    if (i === 0)
-      var x = 1;
+    {if (i === 0)
+      {var x = 1;}}
     console.log(x);
 }
 f();
1
r1-p002 · Directive Prologue Misapplication
1(function () {
2 if (false)
3 "use strict";
4 return typeof x;
5})();
--- orig.js	2026-10-22 14:12:19.496673124 -0400
+++ fixed.js	2026-10-22 14:12:22.642694543 -0400
@@ -1,5 +1,5 @@
 (function () {
   if (false)
-    "use strict";
+    {"use strict";}
   return typeof x;
 })();
r1-p003 · Empty Statement Rewriting
1let count = 0;
2for (let i = 0; i < 2; i++)
3 if (i === 0);
4 count++;
5console.log(count);
--- orig.js	2026-10-22 14:12:19.496673124 -0400
+++ fixed.js	2026-10-22 14:12:23.171698288 -0400
@@ -1,5 +1,5 @@
 let count = 0;
 for (let i = 0; i < 2; i++)
-  if (i === 0);
+  {if (i === 0){;}}
   count++;
 console.log(count);
1
r1-p004 · __proto__ Keys & Prototype Access
1const obj = {};
2for (let k of ['a', '__proto__'])
3 if (k === '__proto__')
4 obj[k] = { toString: () => 'hijacked' };
5console.log(obj.toString());
--- orig.js	2026-10-22 14:12:19.497673130 -0400
+++ fixed.js	2026-10-22 14:12:22.695694915 -0400
@@ -1,5 +1,5 @@
 const obj = {};
 for (let k of ['a', '__proto__'])
-  if (k === '__proto__')
-    obj[k] = { toString: () => 'hijacked' };
+  {if (k === '__proto__')
+    {obj[k] = { toString: () => 'hijacked' };}}
 console.log(obj.toString());
hijacked
r1-p005 · This Binding: Arrow vs Function
1const o = { m() { return this.x; }, x: 1 };
2let f;
3if (true)
4 f = o.m;
5console.log(f(), f.call(o));
--- orig.js	2026-10-22 14:12:19.498673137 -0400
+++ fixed.js	2026-10-22 14:12:22.604694276 -0400
@@ -1,5 +1,5 @@
 const o = { m() { return this.x; }, x: 1 };
 let f;
 if (true)
-  f = o.m;
+  {f = o.m;}
 console.log(f(), f.call(o));
undefined 1
r1-p006 · Class Fields, Static Blocks, Private Names
1class B { constructor() { this.x = 1; } }
2class D extends B {
3 constructor() {
4 super();
5 if (true)
6 this.y = 2;
7 }
8}
9console.log(new D().y);
--- orig.js	2026-10-22 14:12:19.499673143 -0400
+++ fixed.js	2026-10-22 14:12:22.631694465 -0400
@@ -3,7 +3,7 @@
   constructor() {
     super();
     if (true)
-      this.y = 2;
+      {this.y = 2;}
   }
 }
 console.log(new D().y);
2
r1-p007 · ASI and Semicolon-less Code
1let val = 1
2[
3 2, 3
4].forEach(v => val += v)
5console.log(val)
r1-p008 · Numeric/String Coercion
1const obj = { valueOf: () => 2, toString: () => '3' };
2let sum = 0;
3if (true)
4 sum += obj;
5console.log(sum, typeof sum);
--- orig.js	2026-10-22 14:12:23.861703245 -0400
+++ fixed.js	2026-10-22 14:12:27.474730404 -0400
@@ -1,5 +1,5 @@
 const obj = { valueOf: () => 2, toString: () => '3' };
 let sum = 0;
 if (true)
-  sum += obj;
+  {sum += obj;}
 console.log(sum, typeof sum);
2 number
r2-p001 · Empty statement rewriting affects JSDoc parsing
1// @ts-ignore
2let x = 0;
3function f() {
4 // pre-directive-like comment
5 if (x++ === 0)
6 ; // <-- triggers curly: empty stmt
7}
8f();
9f();
10console.log(x);
--- orig.js	2026-10-22 14:12:33.197777425 -0400
+++ fixed.js	2026-10-22 14:12:36.022802418 -0400
@@ -3,7 +3,7 @@
 function f() {
   // pre-directive-like comment
   if (x++ === 0)
-    ; // <-- triggers curly: empty stmt
+    {;} // <-- triggers curly: empty stmt
 }
 f();
 f();
2
r2-p002 · ASI hazard with leading parenthesis after if-body
1let n = 0
2function g() {
3 if (n < 2)
4 console.log('a')
5 (function(){ n++; return })()
6}
7g();
8g();
9console.log(n)
--- orig.js	2026-10-22 14:12:33.198777433 -0400
+++ fixed.js	2026-10-22 14:12:36.057802737 -0400
@@ -1,8 +1,8 @@
 let n = 0
 function g() {
   if (n < 2)
-    console.log('a')
-    (function(){ n++; return })()
+    {console.log('a')
+    (function(){ n++; return })()}
 }
 g();
 g();
a
r2-p003 · Getter/setter side effect timing changed by block wrap
1const obj = { get val() { return side++; }, side: 0 }
2let captured;
3if (true)
4 captured = obj.val
5console.log(captured)
--- orig.js	2026-10-22 14:12:33.200777451 -0400
+++ fixed.js	2026-10-22 14:12:36.112803239 -0400
@@ -1,5 +1,5 @@
 const obj = { get val() { return side++; }, side: 0 }
 let captured;
 if (true)
-  captured = obj.val
+  {captured = obj.val}
 console.log(captured)
r2-p004 · Non-standard stack inspection depth altered by new block
1function outer() {
2 if (true)
3 return inner()
4}
5function inner() {
6 try { throw new Error() } catch (e) {
7 let depth = 0
8 let f = arguments.callee.caller
9 while (f && f !== outer) { depth++; f = f.caller }
10 console.log(depth)
11 }
12}
13outer()
--- orig.js	2026-10-22 14:12:33.201777459 -0400
+++ fixed.js	2026-10-22 14:12:36.194803988 -0400
@@ -1,6 +1,6 @@
 function outer() {
   if (true)
-    return inner()
+    {return inner()}
 }
 function inner() {
   try { throw new Error() } catch (e) {
0
r2-p005 · arguments object capture shifted by block scope
1function h(...args) {
2 let fns = []
3 for (let i = 0; i < args.length; i++)
4 fns.push(() => args[i])
5 return fns.map(fn => fn())
6}
7console.log(h(10, 20))
--- orig.js	2026-10-22 14:12:33.202777468 -0400
+++ fixed.js	2026-10-22 14:12:36.063802792 -0400
@@ -1,7 +1,7 @@
 function h(...args) {
   let fns = []
   for (let i = 0; i < args.length; i++)
-    fns.push(() => args[i])
+    {fns.push(() => args[i])}
   return fns.map(fn => fn())
 }
 console.log(h(10, 20))
[ 10, 20 ]
r2-p006 · TDZ interaction with re-declaration after braced loop (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-12-1)
1function tdztest() {
2 if (false)
3 ; // dummy to avoid warning
4 for (var i = 0; i < 1; i++)
5 let tmp = i
6 console.log(typeof i, typeof tmp)
7 var i = 99
8}
9tdztest()
r2-p007 · Sparse array mutation via braced loop body
1let arr = Array(3)
2arr[1] = 1
3let sum = 0
4for (let i = 0; i < arr.length; i++)
5 if (arr[i] !== undefined) sum += arr[i]
6console.log(sum)
--- orig.js	2026-10-22 14:12:33.246777850 -0400
+++ fixed.js	2026-10-22 14:12:36.623807904 -0400
@@ -2,5 +2,5 @@
 arr[1] = 1
 let sum = 0
 for (let i = 0; i < arr.length; i++)
-  if (arr[i] !== undefined) sum += arr[i]
+  {if (arr[i] !== undefined) {sum += arr[i]}}
 console.log(sum)
1
r2-p008 · Numeric/string coercion altered by brace-induced newline handling
1let val = '5'
2if (+val == 5)
3 console.log('loose eq true')
4else
5 console.log('loose eq false')
6console.log(String(+val))
--- orig.js	2026-10-22 14:12:37.203813227 -0400
+++ fixed.js	2026-10-22 14:12:41.168850958 -0400
@@ -1,6 +1,6 @@
 let val = '5'
 if (+val == 5)
-  console.log('loose eq true')
+  {console.log('loose eq true')}
 else
-  console.log('loose eq false')
+  {console.log('loose eq false')}
 console.log(String(+val))
loose eq true
5