fixhunt

biome complexity/noUselessThisAlias

labelled safe
Runs / 2026-10-17T20-08-24-819Z-hi5g-biome-complexity_noUselessThisAliasbiome 2.5.152026-10-17 20:08 UTC8 programs × 2 round(s)15 programs, 9 fired, 9 fixed, 1 findings, 0 rejectedmodel cost $0.04

Analysis Nemotron 3 Super

Flags unnecessary aliases to 'this' when used only within arrow functions that inherit the outer 'this'.

Fix: Removes the variable declaration and replaces all references to the aliased variable with 'this'.

10 hazards
  • If the alias variable is reassigned after its initial assignment, replacing references with 'this' will use the current 'this' value instead of the captured value, changing behavior.
  • If the alias variable is used in a nested function that is not an arrow function (e.g., regular function or eval), the replacement may break due to differing 'this' binding.
  • If the alias variable is used outside the scope where it was declared (e.g., returned or closed over in a way that escapes), removing the declaration causes a ReferenceError.
  • If the alias variable name conflicts with a variable in an inner scope, removing the outer declaration may cause inner references to resolve to a different variable.
  • If the alias variable is used in a dynamic context like 'with' or indirect eval, static replacement cannot accurately determine usage, leading to incorrect refactoring.
  • If the alias variable is declared with 'var' and hoisted, removing it may affect the temporal dead zone or hoisting behavior in ways that change execution if referenced before declaration.
  • If the alias variable is part of a comma-separated declaration (e.g., 'const self = this, other = expr;'), the fix may incorrectly remove the entire declaration or mishandle the separator.
  • If the alias variable is used in a type annotation or JSDoc comment (e.g., '/** @type {Any} */ const self = this;'), removing the declaration may strip useful type information.
  • If the alias variable is used in a destructuring pattern or default parameter, the simple replacement fails to account for complex binding structures.
  • If the alias variable is referenced in a string literal (e.g., for code generation or logging), textual replacement is not performed, leading to mismatches between code and strings.

Findings

programoraclelabeljudgestatussummary
r1-p007fix-changes-behaviorlabelled safereal · highrelatedThe rule removed the variable declaration `var _this = this` and replaced the read of `_this` with `this`, but the read occurs before the declaration in the or…

Programs

idresulttitlehazard
r1-p001fix okDynamic context via indirect evalIf the alias variable is used in a dynamic context like 'with' or indirect eval, static replacement cannot accurately determine usage, leading to incorrect refactoring.
r1-p002fix okRegex with global flag and lastIndex mutationregular expressions: escapes, unicode flag, lastIndex with the g flag
r1-p004fix okComments on removed declarationcomments attached to the removed or moved code
r1-p005fix okEscaped alias causing ReferenceErrorIf the alias variable is used outside the scope where it was declared (e.g., returned or closed over in a way that escapes), removing the declaration causes a ReferenceError.
r1-p006silentAlias in destructuring parameterIf the alias variable is used in a destructuring pattern or default parameter, the simple replacement fails to account for complex binding structures.
r1-p007fix-changes-behaviorVar hoisting and TDZ interactionIf the alias variable is declared with 'var' and hoisted, removing it may affect the temporal dead zone or hoisting behavior in ways that change execution if referenced before declaration.
r1-p008fix okSparse array with holes and lastIndex-like accesssparse arrays, holes, Array(n) vs [n], array-likes
r2-p001fix okInner scope variable conflictIf the alias variable name conflicts with a variable in an inner scope, removing the outer declaration may cause inner references to resolve to a different variable.
r2-p002silent prediction off__proto__ keys and prototype access__proto__ keys, prototype access, Object.assign vs spread
r2-p003silentType annotation/JSDoc comment strippingIf the alias variable is used in a type annotation or JSDoc comment (e.g., '/** @type {Any} */ const self = this;'), removing the declaration may strip useful type information.
r2-p004silent prediction offVar hoisting and re-declaration in loopvar hoisting and re-declaration inside loops or after use
r2-p005silent prediction offGetter/setter/Object.defineProperty side effectsgetters, setters and Object.defineProperty side effects
r2-p006fix okComments attached to removed/moved codecomments attached to the removed or moved code
r2-p007silent prediction offNested non-arrow function usageIf the alias variable is used in a nested function that is not an arrow function (e.g., regular function or eval), the replacement may break due to differing 'this' binding.
r2-p008fix okFunction declarations inside blocks/switch/labeledfunction declarations inside blocks, switch cases, labeled statements

Sources

r1-p001 · Dynamic context via indirect eval
1let that = this;
2const obj = { x: 1, y: 2 };
3(() => {
4 'use strict';
5 return Function('return that.x')();
6})();
--- orig.js	2026-10-17 16:08:33.184245752 -0400
+++ fixed.js	2026-10-17 16:08:33.474234810 -0400
@@ -1,4 +1,4 @@
-let that = this;
+
 const obj = { x: 1, y: 2 };
 (() => {
   'use strict';
r1-p002 · Regex with global flag and lastIndex mutation
1let self = this;
2self.lastMatch = '';
3const str = 'a1b2';
4[...str].forEach(() => {
5 const match = /\d/g.exec(str);
6 self.lastMatch += match ? match[0] : '_';
7});
8console.log(self.lastMatch);
--- orig.js	2026-10-17 16:08:33.642228472 -0400
+++ fixed.js	2026-10-17 16:08:33.896218888 -0400
@@ -1,8 +1,8 @@
-let self = this;
-self.lastMatch = '';
+
+this.lastMatch = '';
 const str = 'a1b2';
 [...str].forEach(() => {
   const match = /\d/g.exec(str);
-  self.lastMatch += match ? match[0] : '_';
+  this.lastMatch += match ? match[0] : '_';
 });
-console.log(self.lastMatch);
+console.log(this.lastMatch);
r1-p004 · Comments on removed declaration
1// important: capture this
2let me = this;
3// used in handler
4[1,2].forEach(() => console.log(me));
--- orig.js	2026-10-17 16:08:34.057212818 -0400
+++ fixed.js	2026-10-17 16:08:34.335202352 -0400
@@ -1,4 +1,3 @@
-// important: capture this
-let me = this;
+
 // used in handler
-[1,2].forEach(() => console.log(me));
+[1,2].forEach(() => console.log(this));
undefined
undefined
r1-p005 · Escaped alias causing ReferenceError
1function outer() {
2 var self = this;
3 return () => self;
4}
5const f = outer.call({x:1});
6try {
7 console.log(f().x);
8} catch (e) {
9 console.log(e.name + ': ' + e.message);
10}
--- orig.js	2026-10-17 16:08:34.512195688 -0400
+++ fixed.js	2026-10-17 16:08:34.780185598 -0400
@@ -1,6 +1,5 @@
 function outer() {
-  var self = this;
-  return () => self;
+  return () => this;
 }
 const f = outer.call({x:1});
 try {
1
r1-p006 · Alias in destructuring parameter
1function process({ data = this }) {
2 return data;
3}
4console.log(process.call({value: 42}, {}));
{ value: 42 }
r1-p007 · Var hoisting and TDZ interaction
1function test() {
2 console.log(typeof _this);
3 var _this = this;
4 return _this.value;
5}
6try {
7 console.log(test.call({value: 'ok'}));
8} catch (e) {
9 console.log(e.name + ': ' + e.message);
10}
--- orig.js	2026-10-17 16:08:35.139172094 -0400
+++ fixed.js	2026-10-17 16:08:35.417161650 -0400
@@ -1,7 +1,6 @@
 function test() {
-  console.log(typeof _this);
-  var _this = this;
-  return _this.value;
+  console.log(typeof this);
+  return this.value;
 }
 try {
   console.log(test.call({value: 'ok'}));
undefined
ok
r1-p008 · Sparse array with holes and lastIndex-like access
1let self = this;
2self.data = [10, , 30];
3const result = Array.from({length: 3}, (_, i) => self.data[i] ?? -1);
4console.log(result.join(','));
--- orig.js	2026-10-17 16:08:35.576155676 -0400
+++ fixed.js	2026-10-17 16:08:35.832146059 -0400
@@ -1,4 +1,4 @@
-let self = this;
-self.data = [10, , 30];
-const result = Array.from({length: 3}, (_, i) => self.data[i] ?? -1);
+
+this.data = [10, , 30];
+const result = Array.from({length: 3}, (_, i) => this.data[i] ?? -1);
 console.log(result.join(','));
r2-p001 · Inner scope variable conflict
1const self = 42;
2function outer() {
3 const self = this;
4 return () => {
5 console.log(self);
6 };
7}
8outer()(100);
--- orig.js	2026-10-17 16:08:39.410012256 -0400
+++ fixed.js	2026-10-17 16:08:39.687001939 -0400
@@ -1,8 +1,7 @@
 const self = 42;
 function outer() {
-  const self = this;
   return () => {
-    console.log(self);
+    console.log(this);
   };
 }
 outer()(100);
undefined
r2-p002 · __proto__ keys and prototype access
1const obj = { __proto__: { x: 1 }, y: 2 };
2const _this = obj;
3console.log(_this.__proto__.x + _this.y);
3
r2-p003 · Type annotation/JSDoc comment stripping
1/** @type {number} */
2const self = 42;
3console.log(typeof self);
number
r2-p004 · Var hoisting and re-declaration in loop
1for (let i = 0; i < 2; i++) {
2 var self = i;
3 (() => console.log(self))();
4}
0
1
r2-p005 · Getter/setter/Object.defineProperty side effects
1const obj = {};
2let _this = obj;
3Object.defineProperty(obj, 'prop', {
4 get() { return this.value || 0; },
5 set(v) { this.value = v * 2; }
6});
7obj.value = 5;
8console.log(_this.prop);
5
r2-p006 · Comments attached to removed/moved code
1// important note
2const self = this;
3// another comment
4(() => console.log(self))();
--- orig.js	2026-10-17 16:08:40.853958542 -0400
+++ fixed.js	2026-10-17 16:08:41.130948257 -0400
@@ -1,4 +1,3 @@
-// important note
-const self = this;
+
 // another comment
-(() => console.log(self))();
+(() => console.log(this))();
undefined
r2-p007 · Nested non-arrow function usage
1const obj = { method() { return this.val; }, val: 10 };
2const self = obj;
3function inner() {
4 return self.method();
5}
6console.log(inner());
10
r2-p008 · Function declarations inside blocks/switch/labeled
1switch (1) {
2 case 1:
3 const self = this;
4 (() => self)();
5 break;
6}
--- orig.js	2026-10-17 16:08:41.554932533 -0400
+++ fixed.js	2026-10-17 16:08:41.792923707 -0400
@@ -1,6 +1,5 @@
 switch (1) {
   case 1:
-    const self = this;
-    (() => self)();
+    (() => this)();
     break;
 }