fixhunt

biome complexity/noUselessUndefined

labelled safe
Runs / 2026-10-17T20-09-08-973Z-61rc-biome-complexity_noUselessUndefinedbiome 2.5.152026-10-17 20:09 UTC8 programs × 2 round(s)15 programs, 10 fired, 10 fixed, 2 findings, 1 rejectedmodel cost $0.05

Analysis Nemotron 3 Super

Flags explicit uses of `undefined` where it is redundant because it is already the implicit default.

Fix: Removes the explicit `= undefined` initializer or argument default, or replaces `return undefined;`/`yield undefined;` with `return;`/`yield;` respectively.

10 hazards
  • Rewriting `let x = undefined;` to `let x;` changes behavior if the variable is read before assignment due to TDZ—though both initialize to `undefined`, the temporal dead zone semantics differ slightly in edge cases involving indirect eval or with statements.
  • In destructuring like `const {a = undefined} = obj;`, removing `= undefined` alters behavior when `obj.a` is `null` because the default only applies if the property is missing, not if it is present but `null`.
  • For function parameters like `function f(a = undefined)`, removing the default changes behavior when `f()` is called with no argument vs. `f(undefined)`—though both result in `a` being `undefined`, the former triggers the default parameter initialization which may have side effects if the default expression is not a literal (but here it is, so low risk; still, spec-wise distinct).
  • In object destructuring parameters like `function f({a = undefined})`, omitting the default breaks when the argument is `{a: null}` because the default does not apply, preserving `null` instead of converting to `undefined`.
  • Replacing `return undefined;` with `return;` in a function that is used as a constructor changes behavior because `new f()` returns the instance when the return value is not an object, and `undefined` is not an object, so both behave the same—however, if the function is called via `Reflect.construct` with a `newTarget`, the return value handling is identical, so no actual hazard; but per spec, any non-object return is ignored, so safe.
  • Replacing `yield undefined;` with `yield;` in a generator changes behavior if the generator's return value is inspected via `{value, done}` because `yield` produces `{value: undefined, done: false}` just like `yield undefined;`, so equivalent—no hazard.
  • If the code relies on the length of the function's parameter list for reflection (e.g., `f.length`), removing a default parameter does not change the length because parameters with defaults still count toward length—so no hazard.
  • In strict mode, if `undefined` is reassigned globally, the literal `undefined` might not refer to the actual undefined value, but the rule only flags syntactic defaults, and the autofix removes the reference entirely, so if `undefined` was shadowed, removing the use avoids relying on the possibly mutated binding—this could fix unintended behavior, not break it.
  • The autofix may drop comments attached to the `undefined` token, such as `let x = /* TODO */ undefined;`, which would be lost during rewriting.
  • In rare cases involving `with` statements or indirect `eval`, the scope resolution of a bare variable in `let x;` vs. an initializer could differ if `undefined` is not resolvable in the expected scope, but since the initializer is removed and the variable is still declared, the behavior remains consistent.

Findings

programoraclelabeljudgestatussummary
r1-p006fix-changes-behaviorlabelled safereal · highrelatedThe rule removes the initializer `undefined` from `let x = undefined`, turning it into `let x;`. In the program, a local variable named `undefined` shadows the…
r2-p005fix-changes-behaviorlabelled safereal · highduplicateThe rule removes the default parameter `= undefined`, which changes the function's `length` property from 0 to 2 because trailing parameters without defaults a…

Programs

idresulttitlehazard
r1-p001fix okDestructuring assignment with undefined default overwriting nullIn destructuring like `const {a = undefined} = obj;`, removing `= undefined` alters behavior when `obj.a` is `null` because the default only applies if the property is missing, not if it is present bu
r1-p002fix okFunction parameter default with undefined changing init timingFor function parameters like `function f(a = undefined)`, removing the default changes behavior when `f()` is called with no argument vs. `f(undefined)`—though both result in `a` being `undefined`, th
r1-p003fix okObject destructuring parameter preserving null vs undefinedIn object destructuring parameters like `function f({a = undefined})`, omitting the default breaks when the argument is `{a: null}` because the default does not apply, preserving `null` instead of con
r1-p004silentBlock-scoped function declaration hoisting differencesfunction declarations inside blocks, switch cases, labeled statements
r1-p005fix okYield undefined equivalence verified by inspectionReplacing `yield undefined;` with `yield;` in a generator changes behavior if the generator's return value is inspected via `{value, done}` because `yield` produces `{value: undefined, done: false}` j
r1-p006fix-changes-behaviorStrict mode undefined shadowing made safe by removalIn strict mode, if `undefined` is reassigned globally, the literal `undefined` might not refer to the actual undefined value, but the rule only flags syntactic defaults, and the autofix removes the re
r1-p007invalidControl flow interaction with labeled breaks and finallylabel/break/continue control flow, finally blocks, early returns in nested blocks
r1-p008silentProto key access unaffected by undefined removal__proto__ keys, prototype access, Object.assign vs spread
r2-p001fix okFunction Parameter Default Undefined - Initialization TimingRemoving default parameter '= undefined' changes when the default is evaluated versus when argument is passed explicitly.
r2-p002fix okConstructor Return Undefined vs Empty Return - Reflect.constructReplacing 'return undefined;' with 'return;' in a constructor has no behavioral difference per spec, but we trace the return value to show equivalence.
r2-p003silent prediction offASI Hazard with Leading Parenthesis After Return UndefinedRemoving 'undefined' from 'return undefined' can cause ASI to misinterpret the next line starting with '(' as a function call.
r2-p004fix okGetter/Setter with Undefined Return and Side EffectsReplacing 'return undefined;' in a getter with 'return;' may affect side effects if the getter is defined via Object.defineProperty and called multiple times.
r2-p005fix-changes-behavior prediction offFunction Length Reflection - No Change ExpectedRemoving '= undefined' from parameter does not change function.length, so no behavioral difference in reflection-based code.
r2-p006silentClass Fields and Static Blocks - No InteractionThe rule does not apply to class fields or static blocks, so this is a near-miss to confirm no trigger.
r2-p008fix ok prediction offTemporal Dead Zone - Let Redeclaration After LoopThe rule does not cause hoisting or reordering, so no TDZ hazard. We show a loop that reenters a scope with let to prove no interference.

Sources

r1-p001 · Destructuring assignment with undefined default overwriting null
1let log = [];
2function capture(v){ log.push(v); }
3
4// Hazardous pattern: default in destructuring
5data = {a: null}; // note: value is null, not missing
6try {
7 const {a = undefined} = data;
8 capture('got ' + String(a));
9} catch(e) {
10 capture(e.name + ': ' + e.message);
11}
12
13console.log(log.join(' | '));
--- orig.js	2026-10-17 16:09:21.099526993 -0400
+++ fixed.js	2026-10-17 16:09:21.370517776 -0400
@@ -4,7 +4,7 @@
 // Hazardous pattern: default in destructuring
 data = {a: null}; // note: value is null, not missing
 try {
-  const {a = undefined} = data;
+  const {a } = data;
   capture('got ' + String(a));
 } catch(e) {
   capture(e.name + ': ' + e.message);
r1-p002 · Function parameter default with undefined changing init timing
1let callLog = [];
2function sideEffect(){
3 callLog.push('init');
4 return undefined;
5}
6
7function f(a = sideEffect()){ // rule triggers here
8 callLog.push('body: ' + (a === undefined ? 'undef' : 'def'));
9}
10
11f(); // triggers default param init
12f(undefined); // does NOT trigger default param init
13
14console.log(callLog.join(' | '));
--- orig.js	2026-10-17 16:09:21.531512300 -0400
+++ fixed.js	2026-10-17 16:09:21.810502811 -0400
@@ -1,7 +1,7 @@
 let callLog = [];
 function sideEffect(){
   callLog.push('init');
-  return undefined;
+  return ;
 }
 
 function f(a = sideEffect()){ // rule triggers here
init | body: undef | init | body: undef
r1-p003 · Object destructuring parameter preserving null vs undefined
1let result = [];
2function test(val){
3 result.push(String(val));
4}
5
6// Hazard: default in parameter destructuring
7function g({a = undefined}){
8 test(a);
9}
10
11g({a: null}); // should preserve null -> logs 'null'
12g({a: undefined});// logs 'undefined'
13g({}); // missing -> default -> logs 'undefined'
14
15g = null; // redeclaration after use
16
17console.log(result.join(' | '));
--- orig.js	2026-10-17 16:09:21.969497403 -0400
+++ fixed.js	2026-10-17 16:09:22.249487898 -0400
@@ -4,7 +4,7 @@
 }
 
 // Hazard: default in parameter destructuring
-function g({a = undefined}){
+function g({a }){
   test(a);
 }
 
null | undefined | undefined
r1-p004 · Block-scoped function declaration hoisting differences
1let out = [];
2{
3 function h(){ out.push('block'); }
4 if(true){ function h(){ out.push('redeclared'); } }
5 h();
6}
7
8switch(0){
9 case 0:
10 function h(){ out.push('case'); }
11 break;
12}
13
14h();
15
16label: {
17 function h(){ out.push('label'); }
18 break label;
19}
20
21h();
22
23console.log(out.join(' | '));
r1-p005 · Yield undefined equivalence verified by inspection
1function* gen(){
2 yield undefined; // triggers rule
3 yield; // equivalent, no trigger
4}
5
6const it = gen();
7let log = [];
8log.push(JSON.stringify(it.next()));
9log.push(JSON.stringify(it.next()));
10log.push(JSON.stringify(it.next()));
11
12console.log(log.join(' | '));
--- orig.js	2026-10-17 16:09:22.645474458 -0400
+++ fixed.js	2026-10-17 16:09:22.919465160 -0400
@@ -1,5 +1,5 @@
 function* gen(){
-  yield undefined; // triggers rule
+  yield ; // triggers rule
   yield;         // equivalent, no trigger
 }
 
{"done":false} | {"done":false} | {"done":true}
r1-p006 · Strict mode undefined shadowing made safe by removal
1"use strict";
2let log = [];
3(function(){
4 var undefined = 42; // shadowing
5 let x = undefined; // rule triggers: removes this line
6 log.push(String(x));
7})();
8
9// After fix: x is undeclared -> ReferenceError
10try {
11 (function(){
12 var undefined = 42;
13 let x; // autofixed version
14 log.push(String(x));
15 })();
16} catch(e) {
17 log.push(e.name + ': ' + e.message);
18}
19
20console.log(log.join(' | '));
--- orig.js	2026-10-17 16:09:23.083459600 -0400
+++ fixed.js	2026-10-17 16:09:23.355450389 -0400
@@ -2,7 +2,7 @@
 let log = [];
 (function(){ 
   var undefined = 42; // shadowing
-  let x = undefined;  // rule triggers: removes this line
+  let x ;  // rule triggers: removes this line
   log.push(String(x));
 })();
 
42 | undefined
r1-p007 · Control flow interaction with labeled breaks and finally (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-09-0)
1let trace = [];
2outer: for(let i=0; i<2; i++){
3 try{
4 if(i===0){
5 trace.push('a');
6 break outer;
7 }
8 trace.push('b');
9 return undefined; // rule triggers
10 } finally{
11 trace.push('finally');
12 }
13}
14
15function inner(){
16 trace.push('inner start');
17 if(true) yield undefined; // rule triggers
18 trace.push('inner end');
19}
20
21for(const v of inner()){ trace.push('yielded: '+v); }
22
23console.log(trace.join(' | '));
r1-p008 · Proto key access unaffected by undefined removal
1let obj = {__proto__: {toString(){return 'proto'}}};
2let copy = {...obj, a: undefined}; // rule triggers on 'a: undefined'
3
4let log = [];
5log.push(String(copy.a));
6log.push(String(copy.toString()));
7log.push(String(Object.getPrototypeOf(copy)));
8
9// Re-assign after use
10data = {x:1};
11copy = {...data, y: undefined}; // another trigger
12log.push(String(copy.y));
13
14console.log(log.join(' | '));
r2-p001 · Function Parameter Default Undefined - Initialization Timing
1let log = [];
2function side() { log.push('side'); return undefined; }
3function f(a = side()) {
4 return a;
5}
6f(); // call with no arg -> evaluates side()
7f(undefined); // call with undefined arg -> does NOT evaluate side()
8console.log(log.join(','));
--- orig.js	2026-10-17 16:09:29.560241608 -0400
+++ fixed.js	2026-10-17 16:09:29.835232417 -0400
@@ -1,5 +1,5 @@
 let log = [];
-function side() { log.push('side'); return undefined; }
+function side() { log.push('side'); return ; }
 function f(a = side()) {
   return a;
 }
side,side
r2-p002 · Constructor Return Undefined vs Empty Return - Reflect.construct
1function F() {
2 this.x = 1;
3 return undefined;
4}
5let o1 = Reflect.construct(F, [], F);
6console.log(o1.x);
7function G() {
8 this.x = 2;
9 return;
10}
11let o2 = Reflect.construct(G, [], G);
12console.log(o2.x);
--- orig.js	2026-10-17 16:09:30.008226634 -0400
+++ fixed.js	2026-10-17 16:09:30.276217696 -0400
@@ -1,6 +1,6 @@
 function F() {
   this.x = 1;
-  return undefined;
+  return ;
 }
 let o1 = Reflect.construct(F, [], F);
 console.log(o1.x);
1
2
r2-p003 · ASI Hazard with Leading Parenthesis After Return Undefined
1function f() {
2 return
3 [
4 function() { return 1; },
5 function() { return 2; }
6 ]
7}
8try {
9 let arr = f();
10 console.log(arr[0]());
11} catch (e) {
12 console.log(e.name + ': ' + e.message);
13}
TypeError: Cannot read properties of undefined (reading '0')
r2-p004 · Getter/Setter with Undefined Return and Side Effects
1let log = [];
2const obj = {};
3Object.defineProperty(obj, 'prop', {
4 get() {
5 log.push('get');
6 return undefined;
7 }
8});
9x = obj.prop;
10y = obj.prop;
11console.log(log.join(','));
12// After fix: getter still returns undefined implicitly, but we trace call count
--- orig.js	2026-10-17 16:09:30.656205022 -0400
+++ fixed.js	2026-10-17 16:09:30.921196184 -0400
@@ -3,7 +3,7 @@
 Object.defineProperty(obj, 'prop', {
   get() {
     log.push('get');
-    return undefined;
+    return ;
   }
 });
 x = obj.prop;
r2-p005 · Function Length Reflection - No Change Expected
1function f(a = undefined, b) {}
2console.log(f.length); // should be 2 regardless of default
--- orig.js	2026-10-17 16:09:31.089190587 -0400
+++ fixed.js	2026-10-17 16:09:31.345182068 -0400
@@ -1,2 +1,2 @@
-function f(a = undefined, b) {}
+function f(a , b) {}
 console.log(f.length); // should be 2 regardless of default
0
r2-p006 · Class Fields and Static Blocks - No Interaction
1class C {
2 static field = undefined;
3 static {
4 console.log(C.field);
5 }
6 method() {}
7}
8// No output expected from rule, but static block runs
undefined
r2-p008 · Temporal Dead Zone - Let Redeclaration After Loop
1for (let i = 0; i < 2; i++) {
2 let x = undefined;
3 if (i === 0) {
4 x = 'first';
5 } else {
6 x = 'second';
7 }
8 console.log(x);
9}
--- orig.js	2026-10-17 16:09:31.730169255 -0400
+++ fixed.js	2026-10-17 16:09:32.006160070 -0400
@@ -1,5 +1,5 @@
 for (let i = 0; i < 2; i++) {
-  let x = undefined;
+  let x ;
   if (i === 0) {
     x = 'first';
   } else {
first
second