eslint one-var
labelled safe
Analysis Nemotron 3 Super
Enforces consistent grouping of variable declarations within a function or block by requiring them to be declared together or separately.
Fix: Combines consecutive variable declarations of the same kind (`var`, `let`, `const`, etc.) within the same scope into a single declaration with comma-separated declarators, preserving initialization expressions and removing redundant keywords.
10 hazards
- Moving a `var` declaration across a function boundary changes its scope from block-scoped (in strict mode) to function-scoped, potentially exposing the variable to unintended parts of the function.
- Rewriting `let` declarations that are separated by non-declaration statements (e.g., loops or conditionals) alters temporal dead zone behavior, causing early accesses to throw ReferenceError instead of using undefined.
- Combining `const` declarations with initializers that have side effects (e.g., function calls) changes evaluation order if the original declarations were interleaved with other statements.
- Dropping comments attached to individual `var` or `let` declarators during the merge loses developer intent and may break documentation or tooling that relies on those comments.
- Merging declarations across different blocks (e.g., in separate `case` clauses of a `switch`) incorrectly combines variables that were meant to be scoped to individual blocks, leading to redeclaration errors or unintended sharing.
- If a declaration includes a destructuring pattern with a default value that references a later variable in the same original group, merging changes the evaluation order and may cause a ReferenceError.
- Rewriting `var` declarations inside a `try` block to merge with those in a `catch` block incorrectly shares variables between scopes, violating isolation and potentially leaking error-specific state.
- Combining declarations in a `for`-loop initializer that are separated by other statements (though rare due to syntax constraints) would break the loop's structure if the autofix incorrectly assumes consecutiveness.
- Merging declarations that are separated by a `debugger;` statement alters the debugging experience by removing the ability to pause between declarations.
- If a declaration contains a trailing comment on the same line (e.g., `var x; // comment`), the autofix may discard it when joining lines, changing the source text without affecting behavior but violating comment preservation expectations.
Programs
| id | result | title | hazard |
|---|---|---|---|
| r1-p001 | silent prediction off | Var Scope Crossing Function Boundary | Moving a var declaration across a function boundary changes its scope from block-scoped (strict mode) to function-scoped |
| r1-p002 | fix ok | Null/Undefined Distinction with Optional Chaining | null/undefined distinction, optional chaining short-circuit, nullish vs falsy |
| r1-p003 | fix ok | Comments Attached to Removed Code | comments attached to the removed or moved code |
| r1-p004 | fix ok | Exceptions Inside Rewritten Var Declarations | exceptions thrown inside the code the fix removes or rewrites |
| r1-p005 | fired, no fix | Sparse Arrays and Array Literal Holes | sparse arrays, holes, Array(n) vs [n], array-likes |
| r1-p006 | fired, no fix | Try-Catch Var Merging Across Blocks | Rewriting var declarations inside a try block to merge with those in a catch block incorrectly shares variables between scopes |
| r1-p007 | fix ok | ASI and Semicolon-Less Leading Parenthesis | ASI and semicolon-less code, leading ( or [ on the next line |
| r1-p008 | invalid | Arguments Object and Default Parameters | arguments object, function.length, default parameters, rest parameters |
| r2-p001 | fired, no fix | Switch case declarations merged causing redeclaration error | Merging declarations across different blocks (e.g., in separate `case` clauses of a `switch`) incorrectly combines variables that were meant to be scoped to individual blocks, leading to redeclaration |
| r2-p002 | silent prediction off | Destructuring default referencing later variable broken by merge | If a declaration includes a destructuring pattern with a default value that references a later variable in the same original group, merging changes the evaluation order and may cause a ReferenceError. |
| r2-p003 | fired, no fix | Function declaration inside case clause affected by var merge | function declarations inside blocks, switch cases, labeled statements |
| r2-p004 | fix ok | Regex lastIndex shared across merged declarations causing incorrect match | regular expressions: escapes, unicode flag, lastIndex with the g flag |
| r2-p005 | silent prediction off | Var hoisted across function boundary exposing to outer scope | Moving a `var` declaration across a function boundary changes its scope from block-scoped (in strict mode) to function-scoped, potentially exposing the variable to unintended parts of the function. |
| r2-p006 | invalid | Strict mode var merge changes semantics of delete | strict vs sloppy mode semantics |
| r2-p007 | fix ok | Symbol primitive coerced differently in template vs plus after merge | numeric/string coercion: + vs template literal, objects with toString/valueOf, Symbol, BigInt |
| r2-p008 | fired, no fix | Var declaration merged across case clauses with comment on removed code | Comments Attached to Removed Code |
Sources
r1-p001 · Var Scope Crossing Function Boundary
1"use strict";function outer(){if(true){var x=1;}}outer();console.log(typeof x);
undefined
r1-p002 · Null/Undefined Distinction with Optional Chaining
1function f(){let a=null;let b=void 0;console.log(a?.x ?? 'a-null', b?.y ?? 'b-undefined');}f();
--- orig.js 2026-10-22 14:24:03.700799657 -0400 +++ fixed.js 2026-10-22 14:24:07.485965646 -0400 @@ -1 +1 @@ -function f(){let a=null;let b=void 0;console.log(a?.x ?? 'a-null', b?.y ?? 'b-undefined');}f(); +function f(){let a=null, b=void 0;console.log(a?.x ?? 'a-null', b?.y ?? 'b-undefined');}f();
a-null b-undefined
r1-p003 · Comments Attached to Removed Code
1function g(){// note: important
2var a=1;// init
3var b=2;// calc
4return a+b;}console.log(g());
--- orig.js 2026-10-22 14:24:03.701799700 -0400 +++ fixed.js 2026-10-22 14:24:06.926941122 -0400 @@ -1,4 +1,4 @@ function g(){// note: important -var a=1;// init -var b=2;// calc +var a=1,// init + b=2;// calc return a+b;}console.log(g());
3
r1-p004 · Exceptions Inside Rewritten Var Declarations
1function h(){try{var x=JSON.parse('{');var y=5;}catch(e){console.log(e.name+':'+e.message);}return y;}console.log(h());
--- orig.js 2026-10-22 14:24:03.701799700 -0400 +++ fixed.js 2026-10-22 14:24:06.918940771 -0400 @@ -1 +1 @@ -function h(){try{var x=JSON.parse('{');var y=5;}catch(e){console.log(e.name+':'+e.message);}return y;}console.log(h()); +function h(){try{var x=JSON.parse('{'), y=5;}catch(e){console.log(e.name+':'+e.message);}return y;}console.log(h());
SyntaxError:Expected property name or '}' in JSON at position 1 undefined
r1-p005 · Sparse Arrays and Array Literal Holes
1function i(){var a=Array(3);a[2]=9;var b=[, , 9];console.log(a.length,b.length,a[1]===b[1]);}i();
3 3 true
r1-p006 · Try-Catch Var Merging Across Blocks
1function j(){try{var e=1;throw 'err';}catch(e){console.log(e);var e=2;console.log(e);}}j();
err 2
r1-p007 · ASI and Semicolon-Less Leading Parenthesis
1function k(){var a=1
2var b=2
3;(function(){console.log(a+b);})()}k();
--- orig.js 2026-10-22 14:24:06.221910198 -0400 +++ fixed.js 2026-10-22 14:24:09.932072988 -0400 @@ -1,3 +1,3 @@ -function k(){var a=1 -var b=2 +function k(){var a=1, + b=2 ;(function(){console.log(a+b);})()}k();
3
r1-p008 · Arguments Object and Default Parameters (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-23-5)
1function l(a=1, b=2){var c=a+b;var d=arguments.length;return {return [c,d];}}console.log(l(10));
r2-p001 · Switch case declarations merged causing redeclaration error
1function f() {
2 switch (x) {
3 case 1:
4 var a = 1;
5 break;
6 case 2:
7 var a = 2;
8 console.log(a);
9 break;
10 }
11}
12f();
r2-p002 · Destructuring default referencing later variable broken by merge
1function f() {
2 let [x = y, y] = [];
3 console.log(x, y);
4}
5try { f(); } catch (e) { console.log(e.name + ': ' + e.message); }
ReferenceError: Cannot access 'y' before initialization
r2-p003 · Function declaration inside case clause affected by var merge
1function outer() {
2 switch (x) {
3 case 1:
4 var a = 1;
5 function inner() { return a; }
6 break;
7 case 2:
8 var a = 2;
9 console.log(inner());
10 break;
11 }
12}
13outer();
r2-p004 · Regex lastIndex shared across merged declarations causing incorrect match
1function f() {
2 let re1 = /a/g;
3 let re2 = /b/g;
4 re1.test('ab');
5 console.log(re2.test('ab'));
6}
7f();
--- orig.js 2026-10-22 14:24:16.662368631 -0400 +++ fixed.js 2026-10-22 14:24:21.045561401 -0400 @@ -1,6 +1,6 @@ function f() { - let re1 = /a/g; - let re2 = /b/g; + let re1 = /a/g, + re2 = /b/g; re1.test('ab'); console.log(re2.test('ab')); }
true
r2-p005 · Var hoisted across function boundary exposing to outer scope
1function outer() {
2 'use strict';
3 if (true) {
4 var x = 1;
5 }
6 function inner() {
7 console.log(typeof x);
8 }
9 inner();
10}
11outer();
number
r2-p006 · Strict mode var merge changes semantics of delete (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-23-5)
1'use strict';
2function f() {
3 var x = 1;
4 var y = 2;
5 try { delete x; } catch (e) { console.log(e.name); }
6 try { delete y; } catch (e) { console.log(e.name); }
7}
8f();
r2-p007 · Symbol primitive coerced differently in template vs plus after merge
1function f() {
2 let s = Symbol('test');
3 let t = 42;
4 console.log(s + t);
5 console.log(`${s}${t}`);
6}
7f();
--- orig.js 2026-10-22 14:24:16.684369598 -0400 +++ fixed.js 2026-10-22 14:24:20.978558452 -0400 @@ -1,6 +1,6 @@ function f() { - let s = Symbol('test'); - let t = 42; + let s = Symbol('test'), + t = 42; console.log(s + t); console.log(`${s}${t}`); }
r2-p008 · Var declaration merged across case clauses with comment on removed code
1function f() {
2 switch (x) {
3 case 1:
4 var a = 1; // initialized in case 1
5 break;
6 case 2:
7 var a = 2; // initialized in case 2
8 console.log(a);
9 break;
10 }
11}
12f();