fixhunt

biome correctness/noSwitchDeclarations

labelled safe
Runs / 2026-10-17T20-45-26-282Z-047l-biome-correctness_noSwitchDeclarationsbiome 2.5.152026-10-17 20:45 UTC8 programs × 2 round(s)15 programs, 14 fired, 14 fixed, 0 findings, 0 rejectedmodel cost $0.0042

Analysis Nemotron 3 Super

Flags lexical declarations directly inside switch cases without block scope.

Fix: Wraps the lexical declaration in a block by adding { before and } after the declaration statement within the switch case.

8 hazards
  • The inserted block may alter automatic semicolon insertion if the original declaration lacked a terminating semicolon and the following token starts with [, (, /, +, -, or `.`, potentially changing parsing.
  • If the lexical declaration is a function declaration, wrapping it in a block makes it block-scoped instead of function-scoped, altering its visibility outside the switch but within the function.
  • Comments attached to the declaration via trailing comment syntax may be moved inside the block or misplaced if the autofix does not preserve comment attachment points.
  • In strict mode, a block-wrapped function declaration is not allowed and will throw a SyntaxError, whereas the original might have been tolerated in non-strict contexts.
  • If the switch case contains multiple statements and the fix only wraps the first declaration, subsequent statements may fall out of the intended block scope.
  • The rewrite assumes the declaration is a single statement; if it is part of a comma-separated expression or larger statement, wrapping it in a block breaks syntactic validity.
  • Labels preceding the switch case will now apply to the block rather than the declaration, potentially altering break/continue target behavior if labels were used.
  • If the declaration uses `var` (which the rule should not flag but might due to misconfiguration), wrapping it in a block does not change its function-scoping, leading to unnecessary complexity without semantic benefit.

Programs

idresulttitlehazard
r1-p001fix okSparse Arrays and HolesWrapping a const declaration in a block inside a switch changes how we capture variables when processing sparse arrays via iterator-like closure.
r1-p003fix okFunction Decl Visibility Changed by Block ScopeWrap function decl in block → becomes block-scoped → no longer hoisted to function scope → visible only inside case → breaks reuse after switch.
r1-p004fix okNull/Undefined DistinctionBlock wrap alters timing of nullish check evaluation in chain causing different short-circuit path and thrown error.
r1-p005silent prediction offComma Expression Breaks SyntaxRule tries to wrap comma-expr in block → invalid syntax → throws SyntaxError during execution (simulated via eval to avoid parse failure).
r1-p006fix okVar Misconfiguration Unnecessary BlockRule incorrectly flags var → wraps in block → no scoping change → extra block but harmless; we detect block via shadowing attempt.
r1-p007fix okLabel/Break/Continue Control FlowAdded block changes break target: break now exits block not case → fallthrough → wrong value used.
r1-p008fix ok__proto__ Keys and Prototype AccessWrapped decl creates new block scope → closure captures different __proto__ descriptor due to timing of property access in loop.
r2-p001fix okASI Hazard with Open ParenthesisThe inserted block may alter automatic semicolon insertion if the original declaration lacked a terminating semicolon and the following token starts with `(`, `[`, `/`, `+`, `-`, or `` ` ``.
r2-p002fix okFunction Declaration Visibility ChangeIf the lexical declaration is a function declaration, wrapping it in a block makes it block-scoped instead of function-scoped, altering its visibility outside the switch but within the function.
r2-p003fix okSparse Arrays and Holes Mutationsparse arrays, holes, Array(n) vs [n], array-likes
r2-p004fix okVar Hoisting and Redeclaration Conflictvar hoisting and re-declaration inside loops or after use
r2-p005fix okName Collision Across Scopes via Shadowingname collisions across scopes after a move (shadowing)
r2-p006fix okASI and Semicolon-less Code with Leading BracketASI and semicolon-less code, leading ( or [ on the next line
r2-p007fix okNull/Undefined Distinction in Optional Chainingnull/undefined distinction, optional chaining short-circuit, nullish vs falsy
r2-p008fix okGetter Side Effect Altered by Block Scopegetters, setters and Object.defineProperty side effects

Sources

r1-p001 · Sparse Arrays and Holes
1function process(arr) {
2 let total = 0;
3 arr.forEach((v, i) => {
4 switch(i) {
5 case 0:
6 const captured = v + 10;
7 return total += captured;
8 default:
9 const fallback = v || -1;
10 return total -= fallback * 2;
11 }
12 });
13 console.log('Result:', total);
14}
15process([5]); // hole at index 1
--- orig.js	2026-10-17 16:45:42.209197992 -0400
+++ fixed.js	2026-10-17 16:45:42.487205406 -0400
@@ -2,12 +2,14 @@
   let total = 0;
   arr.forEach((v, i) => {
     switch(i) {
-      case 0:
+      case 0: {
         const captured = v + 10;
         return total += captured;
-      default:
+      }
+      default: {
         const fallback = v || -1;
         return total -= fallback * 2;
+      }
     }
   });
   console.log('Result:', total);
Result: 15
r1-p003 · Function Decl Visibility Changed by Block Scope
1function outer() {
2 let result = [];
3 switch(true) {
4 case x > 0:
5 function getVal() { return x * 2; }
6 break;
7 }
8 try {
9 result.push(getVal());
10 } catch(e) {
11 result.push(e.name);
12 }
13 return result.join(':');
14}
15let x = 5;
16console.log(outer());
--- orig.js	2026-10-17 16:45:42.664210126 -0400
+++ fixed.js	2026-10-17 16:45:42.953217834 -0400
@@ -1,9 +1,10 @@
 function outer() {
   let result = [];
   switch(true) {
-    case x > 0:
+    case x > 0: {
       function getVal() { return x * 2; }
       break;
+    }
   }
   try {
     result.push(getVal());
ReferenceError
r1-p004 · Null/Undefined Distinction
1function check(value) {
2 switch(typeof value) {
3 case 'object':
4 const data = value?.prop?.sub;
5 if (data == null) throw 'nullish';
6 return data;
7 default:
8 return undefined;
9 }
10}
11try {
12 console.log(check(null));
13} catch(e) {
14 console.log('Caught:', e);
15}
--- orig.js	2026-10-17 16:45:43.112222070 -0400
+++ fixed.js	2026-10-17 16:45:43.398229688 -0400
@@ -1,9 +1,10 @@
 function check(value) {
   switch(typeof value) {
-    case 'object':
+    case 'object': {
       const data = value?.prop?.sub;
       if (data == null) throw 'nullish';
       return data;
+    }
     default:
       return undefined;
   }
Caught: nullish
r1-p005 · Comma Expression Breaks Syntax
1let x = 1;
2try {
3 eval("switch(x){case 1: const y=2, z=y+1; break}");
4} catch(e) {
5 if (e instanceof SyntaxError) {
6 console.log('SyntaxError as expected');
7 } else {
8 throw e;
9 }
10}
r1-p006 · Var Misconfiguration Unnecessary Block
1function testVar() {
2 switch(1) {
3 case 1:
4 var scoped = 99;
5 if (true) {
6 var scoped = 88; // redeclaration ok in same function scope
7 }
8 console.log(scoped);
9 break;
10 }
11}
12testVar();
--- orig.js	2026-10-17 16:45:43.768239543 -0400
+++ fixed.js	2026-10-17 16:45:44.056247212 -0400
@@ -1,12 +1,13 @@
 function testVar() {
   switch(1) {
-    case 1:
+    case 1: {
       var scoped = 99;
       if (true) {
         var scoped = 88; // redeclaration ok in same function scope
       }
       console.log(scoped);
       break;
+    }
   }
 }
 testVar();
88
r1-p007 · Label/Break/Continue Control Flow
1let out = '';
2lab: {
3 switch(1) {
4 case 1:
5 const msg = 'A';
6 break lab;
7 }
8 out += 'B';
9}
10console.log(out);
--- orig.js	2026-10-17 16:45:44.229251814 -0400
+++ fixed.js	2026-10-17 16:45:44.483258571 -0400
@@ -1,9 +1,10 @@
 let out = '';
 lab: {
   switch(1) {
-    case 1:
+    case 1: {
       const msg = 'A';
       break lab;
+    }
   }
   out += 'B';
 }
r1-p008 · __proto__ Keys and Prototype Access
1const proto = { __proto__: null, toString: () => 'hidden' };
2function makeObj() {
3 switch(true) {
4 case true:
5 const desc = Object.getOwnPropertyDescriptor(proto, '__proto__');
6 return () => desc.get.call({});
7 }
8}
9try {
10 const fn = makeObj();
11 console.log(fn());
12} catch(e) {
13 console.log(e.name);
14}
--- orig.js	2026-10-17 16:45:44.649262987 -0400
+++ fixed.js	2026-10-17 16:45:44.927270383 -0400
@@ -1,9 +1,10 @@
 const proto = { __proto__: null, toString: () => 'hidden' };
 function makeObj() {
   switch(true) {
-    case true:
+    case true: {
       const desc = Object.getOwnPropertyDescriptor(proto, '__proto__');
       return () => desc.get.call({});
+    }
   }
 }
 try {
TypeError
r2-p001 · ASI Hazard with Open Parenthesis
1function f(){
2 switch(0){case 0:
3 const x = () => ({a:1})
4 x().a
5 }
6}
7console.log(f());
--- orig.js	2026-10-17 16:45:49.453390372 -0400
+++ fixed.js	2026-10-17 16:45:49.737397879 -0400
@@ -1,7 +1,7 @@
 function f(){
-  switch(0){case 0:
+  switch(0){case 0: {
     const x = () => ({a:1})
-    x().a
+    x().a}
   }
 }
 console.log(f());
undefined
r2-p002 · Function Declaration Visibility Change
1function outer(){
2 switch(0){case 0:
3 function inner(){ return 'inner' }
4 }
5 try{ return inner() }catch(e){ return e.message }
6}
7console.log(outer());
--- orig.js	2026-10-17 16:45:49.912402505 -0400
+++ fixed.js	2026-10-17 16:45:50.215410508 -0400
@@ -1,6 +1,6 @@
 function outer(){
-  switch(0){case 0:
-    function inner(){ return 'inner' }
+  switch(0){case 0: {
+    function inner(){ return 'inner' }}
   }
   try{ return inner() }catch(e){ return e.message }
 }
inner is not defined
r2-p003 · Sparse Arrays and Holes Mutation
1function test(){
2 let arr = new Array(3);
3 switch(0){case 0:
4 const v = arr[1] = 99
5 }
6 return arr[1];
7}
8console.log(test());
--- orig.js	2026-10-17 16:45:50.397415313 -0400
+++ fixed.js	2026-10-17 16:45:50.658422204 -0400
@@ -1,7 +1,7 @@
 function test(){
   let arr = new Array(3);
-  switch(0){case 0:
-    const v = arr[1] = 99
+  switch(0){case 0: {
+    const v = arr[1] = 99}
   }
   return arr[1];
 }
99
r2-p004 · Var Hoisting and Redeclaration Conflict
1function test(){
2 switch(0){case 0:
3 var x = 1
4 }
5 var x = 2
6 return x;
7}
8console.log(test());
--- orig.js	2026-10-17 16:45:50.806426111 -0400
+++ fixed.js	2026-10-17 16:45:51.093433685 -0400
@@ -1,6 +1,6 @@
 function test(){
-  switch(0){case 0:
-    var x = 1
+  switch(0){case 0: {
+    var x = 1}
   }
   var x = 2
   return x;
2
r2-p005 · Name Collision Across Scopes via Shadowing
1function test(){
2 let y = 'outer';
3 switch(0){case 0:
4 const y = 'inner';
5 return y;
6 }
7}
8console.log(test());
--- orig.js	2026-10-17 16:45:51.272438405 -0400
+++ fixed.js	2026-10-17 16:45:51.559445973 -0400
@@ -1,8 +1,8 @@
 function test(){
   let y = 'outer';
-  switch(0){case 0:
+  switch(0){case 0: {
     const y = 'inner';
-    return y;
+    return y;}
   }
 }
 console.log(test());
inner
r2-p006 · ASI and Semicolon-less Code with Leading Bracket
1function test(){
2 switch(0){case 0:
3 const x = [1,2]
4 [x[0], x[1]] = [x[1], x[0]]
5 return x[0] + ',' + x[1]
6 }
7}
8console.log(test());
--- orig.js	2026-10-17 16:45:51.732450535 -0400
+++ fixed.js	2026-10-17 16:45:52.027458313 -0400
@@ -1,8 +1,8 @@
 function test(){
-  switch(0){case 0:
+  switch(0){case 0: {
     const x = [1,2]
     [x[0], x[1]] = [x[1], x[0]]
-    return x[0] + ',' + x[1]
+    return x[0] + ',' + x[1]}
   }
 }
 console.log(test());
r2-p007 · Null/Undefined Distinction in Optional Chaining
1function test(){
2 switch(0){case 0:
3 const obj = { a: null }
4 return obj.a?.b ?? 'default'
5 }
6}
7console.log(test());
--- orig.js	2026-10-17 16:45:52.206463027 -0400
+++ fixed.js	2026-10-17 16:45:52.497470690 -0400
@@ -1,7 +1,7 @@
 function test(){
-  switch(0){case 0:
+  switch(0){case 0: {
     const obj = { a: null }
-    return obj.a?.b ?? 'default'
+    return obj.a?.b ?? 'default'}
   }
 }
 console.log(test());
default
r2-p008 · Getter Side Effect Altered by Block Scope
1function test(){
2 let log = [];
3 switch(0){case 0:
4 const obj = { get x(){ log.push(1); return 2 } }
5 log.push(obj.x);
6 return log;
7 }
8}
9console.log(test());
--- orig.js	2026-10-17 16:45:52.662475035 -0400
+++ fixed.js	2026-10-17 16:45:52.942482409 -0400
@@ -1,9 +1,9 @@
 function test(){
   let log = [];
-  switch(0){case 0:
+  switch(0){case 0: {
     const obj = { get x(){ log.push(1); return 2 } }
     log.push(obj.x);
-    return log;
+    return log;}
   }
 }
 console.log(test());
[ 1, 2 ]