biome complexity/useArrowFunction
labelled safe
Analysis Nemotron 3 Super
Flags function expressions without 'this' usage, generator markers, named identifiers, arguments references, or explicit 'this' type annotations.
Fix: Replaces each flagged function expression with an arrow function having the same parameters and function body, preserving formatting and comments where possible.
10 hazards
- Rewriting a function used as a constructor with 'new' changes behavior because arrow functions cannot be instantiated and will throw TypeError.
- If the function expression appears before its variable declaration due to hoisting, replacing it with an arrow function creates a temporal dead zone error when accessed earlier.
- When the function is referenced via arguments.callee (e.g., for recursion), the arrow function lacks this property, breaking self-reference.
- If the function expression is wrapped in parentheses and immediately invoked, the arrow function may parse differently due to precedence, causing syntax errors.
- In sequences like '0, function(){}', replacing with arrow function alters comma operator evaluation if the arrow function is misparsed.
- If the function expression is a label target (e.g., 'label: function(){}'), the arrow function cannot be labeled, causing a syntax error.
- When the function expression is a method in an object literal and the object is used in a super() call, the arrow function's lexical this breaks method inheritance.
- If the function expression contains a trailing comment on the closing brace, the autofix may drop it during transformation.
- In TypeScript, if the function expression has a return type annotation like 'function(): number', removing it breaks type checking.
- If the function expression is part of a larger destructuring pattern, the rewrite may disrupt indentation or alignment, hiding syntax errors.
Programs
| id | result | title | hazard |
|---|---|---|---|
| r1-p001 | fix ok | Hoisting Temporal Dead Zone | If the function expression appears before its variable declaration due to hoisting, replacing it with an arrow function creates a temporal dead zone error when accessed earlier. |
| r1-p002 | silent prediction off | Strict vs Sloppy Mode Semantics | strict vs sloppy mode semantics |
| r1-p003 | fix ok | Parenthesized IIFE Precedence | If the function expression is wrapped in parentheses and immediately invoked, the arrow function may parse differently due to precedence, causing syntax errors. |
| r1-p004 | fix ok | Sparse Arrays and Holes | sparse arrays, holes, Array(n) vs [n], array-likes |
| r1-p005 | invalid | Block-Scoped Function Declarations | function declarations inside blocks, switch cases, labeled statements |
| r1-p006 | fix ok | Name Collisions Across Scopes After Move | name collisions across scopes after a move (shadowing) |
| r1-p007 | invalid | Label/Break/Continue Control Flow | label/break/continue control flow, finally blocks, early returns in nested blocks |
| r1-p008 | fix ok | Temporal Dead Zone After Hoisting/Reordering | temporal dead zone after code is hoisted or reordered |
| r2-p001 | invalid | TypeScript return type annotation lost | In TypeScript, if the function expression has a return type annotation like 'function(): number', removing it breaks type checking. |
| r2-p002 | invalid | Destructuring pattern indentation disruption | If the function expression is part of a larger destructuring pattern, the rewrite may disrupt indentation or alignment, hiding syntax errors. |
| r2-p003 | fix ok | Comma operator evaluation altered | In sequences like '0, function(){}', replacing with arrow function alters comma operator evaluation if the arrow function is misparsed. |
| r2-p004 | invalid | Label/break/continue with finally and early return | label/break/continue control flow, finally blocks, early returns in nested blocks |
| r2-p005 | silent prediction off | arguments.callee recursion broken | When the function is referenced via arguments.callee (e.g., for recursion), the arrow function lacks this property, breaking self-reference. |
| r2-p006 | fix ok | null/undefined distinction with optional chaining | null/undefined distinction, optional chaining short-circuit, nullish vs falsy |
| r2-p007 | fix ok | ASI with leading paren on next line | ASI and semicolon-less code, leading ( or [ on the next line |
| r2-p008 | fix ok | Exception thrown inside rewritten function | exceptions thrown inside the code the fix removes or rewrites |
Sources
r1-p001 · Hoisting Temporal Dead Zone
1function test() {
2 try { f(); } catch (e) { console.log(e.name + ': ' + e.message); }
3 var f = function() { return 42; };
4}
5test();
--- orig.js 2026-10-17 16:11:50.385194347 -0400 +++ fixed.js 2026-10-17 16:11:50.662187572 -0400 @@ -1,5 +1,5 @@ function test() { try { f(); } catch (e) { console.log(e.name + ': ' + e.message); } - var f = function() { return 42; }; + var f = () => 42; } test();
TypeError: f is not a function
r1-p002 · Strict vs Sloppy Mode Semantics
1'use strict';
2const f = function() { return arguments.length; };
3console.log(f());
4
5(() => {
6 const g = function() { return arguments.length; };
7 console.log(g());
8})();
0 0
r1-p003 · Parenthesized IIFE Precedence
1(function () {
2 return (function(x) { return x * 2; })(5);
3})();
--- orig.js 2026-10-17 16:11:51.054177986 -0400 +++ fixed.js 2026-10-17 16:11:51.308171787 -0400 @@ -1,3 +1 @@ -(function () { - return (function(x) { return x * 2; })(5); -})(); +(() => ((x) => x * 2)(5))();
r1-p004 · Sparse Arrays and Holes
1const arr = Array(3);
2arr[0] = 10;
3arr[2] = 30;
4const result = arr.map(function(v) { return v === undefined ? -1 : v * 2; });
5console.log(result.join(','));
--- orig.js 2026-10-17 16:11:51.457168151 -0400 +++ fixed.js 2026-10-17 16:11:51.727161561 -0400 @@ -1,5 +1,5 @@ const arr = Array(3); arr[0] = 10; arr[2] = 30; -const result = arr.map(function(v) { return v === undefined ? -1 : v * 2; }); +const result = arr.map((v) => v === undefined ? -1 : v * 2); console.log(result.join(','));
20,,60
r1-p005 · Block-Scoped Function Declarations (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-11-4)
1{ let x = 1;
2 if (true) {
3 function f() { return x; }
4 console.log(f());
5 let f = function() { return x + 1; };
6 console.log(f());
7 }
8}
r1-p006 · Name Collisions Across Scopes After Move
1let f = function() { return 'outer'; };
2{
3 let f = function() { return 'inner'; };
4 console.log(f()); // inner
5 console.log((function() { return f(); })()); // outer
6}
--- orig.js 2026-10-17 16:11:51.923156778 -0400 +++ fixed.js 2026-10-17 16:11:52.170150759 -0400 @@ -1,6 +1,6 @@ -let f = function() { return 'outer'; }; +let f = () => 'outer'; { - let f = function() { return 'inner'; }; + let f = () => 'inner'; console.log(f()); // inner - console.log((function() { return f(); })()); // outer + console.log((() => f())()); // outer }
inner inner
r1-p007 · Label/Break/Continue Control Flow (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-11-4)
1outer: {
2 try {
3 (function() {
4 if (true) break outer;
5 console.log('unreachable');
6 })();
7 console.log('after break');
8 } finally {
9 console.log('finally');
10 }
11}
r1-p008 · Temporal Dead Zone After Hoisting/Reordering
1function test() {
2 console.log(typeof f);
3 let f = function() { return 42; };
4}
5test();
--- orig.js 2026-10-17 16:11:52.377145718 -0400 +++ fixed.js 2026-10-17 16:11:52.620139801 -0400 @@ -1,5 +1,5 @@ function test() { console.log(typeof f); - let f = function() { return 42; }; + let f = () => 42; } test();
r2-p001 · TypeScript return type annotation lost (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-11-4)
1// @ts-check
2const f = function(): number {
3 return 42;
4};
5console.log(typeof f === 'function' && f());
r2-p002 · Destructuring pattern indentation disruption (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-11-4)
1const [
2 a,
3 { b: function() { return 1; } }
4] = [0, { b: () => {} }];
5console.log(a, typeof b);
r2-p003 · Comma operator evaluation altered
1let result = 0,
2 value = (0, function() { return 5; })();
3console.log(result, value);
--- orig.js 2026-10-17 16:11:58.647994050 -0400 +++ fixed.js 2026-10-17 16:11:58.923987419 -0400 @@ -1,3 +1,3 @@ let result = 0, - value = (0, function() { return 5; })(); + value = (0, () => 5)(); console.log(result, value);
0 5
r2-p004 · Label/break/continue with finally and early return (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-11-4)
1outer: {
2 try {
3 (function() {
4 if (true) break outer;
5 return 1;
6 })();
7 console.log('unreachable');
8 } finally {
9 console.log('finally');
10 }
11}
12console.log('after');
r2-p005 · arguments.callee recursion broken
1let count = 0;
2const fact = function(n) {
3 if (n <= 1) return 1;
4 return n * arguments.callee(n - 1);
5};
6try {
7 console.log(fact(4));
8} catch (e) {
9 console.log(e.name, e.message);
10}
TypeError 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
r2-p006 · null/undefined distinction with optional chaining
1const obj = { prop: null };
2const getValue = function() {
3 return obj.prop?.length ?? 'empty';
4};
5console.log(getValue());
6obj.prop = undefined;
7console.log(getValue());
--- orig.js 2026-10-17 16:11:59.360976941 -0400 +++ fixed.js 2026-10-17 16:11:59.632970422 -0400 @@ -1,7 +1,5 @@ const obj = { prop: null }; -const getValue = function() { - return obj.prop?.length ?? 'empty'; -}; +const getValue = () => obj.prop?.length ?? 'empty'; console.log(getValue()); obj.prop = undefined; console.log(getValue());
empty empty
r2-p007 · ASI with leading paren on next line
1let x = 1
2const f = function() {
3 return x++
4}()
5;(function(){
6 x = 10
7})()
8console.log(x)
--- orig.js 2026-10-17 16:11:59.794966539 -0400 +++ fixed.js 2026-10-17 16:12:00.070959927 -0400 @@ -1,8 +1,6 @@ let x = 1 -const f = function() { - return x++ -}() -;(function(){ +const f = (() => x++)() +;(()=> { x = 10 })() console.log(x)
10
r2-p008 · Exception thrown inside rewritten function
1const risky = function() {
2 throw new Error('intentional');
3};
4try {
5 risky();
6} catch (e) {
7 console.log(e.name, e.message);
8}
--- orig.js 2026-10-17 16:12:00.240955862 -0400 +++ fixed.js 2026-10-17 16:12:00.504949549 -0400 @@ -1,4 +1,4 @@ -const risky = function() { +const risky = () => { throw new Error('intentional'); }; try {
Error intentional