fixhunt

biome style/useExponentiationOperator

labelled safe
Runs / 2026-10-17T21-01-30-169Z-3u5f-biome-style_useExponentiationOperatorbiome 2.5.152026-10-17 21:01 UTC8 programs × 2 round(s)16 programs, 16 fired, 15 fixed, 1 findings, 0 rejectedmodel cost $0.02

Analysis Nemotron 3 Super

The rule flags calls to Math.pow(base, exponent) where base and exponent are any expressions.

Fix: Replace Math.pow(base, exponent) with the expression base ** exponent, preserving the original formatting and whitespace around the call but inserting the infix operator between the two arguments.

12 hazards
  • If base or exponent contains a side-effecting expression like a function call, the autofix may change evaluation order because Math.pow evaluates both arguments before the call, while the ** operator evaluates left-hand side first then right-hand side, potentially altering observable behavior if the right-hand side has side effects that depend on the left-hand side's evaluation.
  • If base or exponent contains a comma expression, the autofix will incorrectly group due to the lower precedence of the comma operator compared to **, causing part of the intended argument to be excluded from the exponentiation operation.
  • If base or exponent contains yield or await expressions, the autofix may create invalid syntax because ** cannot directly contain these operators without parentheses, leading to a SyntaxError where the original Math.pow call was valid.
  • If base or exponent contains a newline without semicolon insertion protection, the autofix could trigger automatic semicolon insertion incorrectly, changing the parsing of subsequent statements.
  • If the Math.pow call appears in a context where its return value is used as a property key (e.g., computed property name), the autofix may produce invalid syntax because ** has lower precedence than the bracket operator, requiring additional parentheses that the autofix does not insert.
  • If the Math.pow call is inside a tag template literal, the autofix may break the template processing because the resulting ** expression alters how the template strings and interpolations are grouped.
  • If base or exponent contains a regular expression literal, the autofix may cause a SyntaxError because the asterisk in ** can be confused with the multiplication operator or regex quantifier depending on spacing.
  • If the call to Math.pow is actually a reference to a local variable named Math (shadowing the global), the autofix will incorrectly rewrite it as an exponentiation operation, changing the meaning entirely.
  • If the code is in a strict mode context where Math.pow is not configurable or is replaced, the autofix assumes the standard behavior, but the actual function might have custom semantics that ** does not replicate.
  • If base or exponent contains expressions with TypeScript-specific syntax (like type assertions or generics), the autofix may produce invalid JavaScript after transpilation if the rewrite interferes with those constructs.
  • If the original code had trailing comments on the Math.pow line, the autofix may drop or misplace them because it only rewrites the call expression and does not preserve comment attachment.
  • If base or exponent contains an expression that evaluates to NaN or Infinity, the behavior of ** differs from Math.pow in edge cases involving negative bases and non-integer exponents, potentially changing the result.

Findings

programoraclelabeljudgestatussummary
r1-p007fix-changes-behaviorlabelled safereal · highrelatedThe program assigns to Math.pow, which throws in strict mode but is caught, leaving Math.pow as the original function. The fix replaces Math.pow(2, 3) with 2 *…

Programs

idresulttitlehazard
r1-p001fired, no fixComma Expression HazardIf base or exponent contains a comma expression, the autofix will incorrectly group due to the lower precedence of the comma operator compared to **, causing part of the intended argument to be exclud
r1-p002fix okArguments Object Interactionarguments object, function.length, default parameters, rest parameters
r1-p003fix okTemporal Dead Zonetemporal dead zone after code is hoisted or reordered
r1-p004fix okTagged Template LiteralIf the Math.pow call is inside a tag template literal, the autofix may break the template processing because the resulting ** expression alters how the template strings and interpolations are grouped.
r1-p005fix okClass Fields and Static Blocksclass fields, static blocks, private names, super calls
r1-p006fix okTrailing Comments PreservationIf the original code had trailing comments on the Math.pow line, the autofix may drop or misplace them because it only rewrites the call expression and does not preserve comment attachment.
r1-p007fix-changes-behaviorStrict vs Sloppy Modestrict vs sloppy mode semantics
r1-p008fix okFunction Declarations in Blocksfunction declarations inside blocks, switch cases, labeled statements
r2-p001fix okTrailing Comment Attached To Callcomments attached to the removed or moved code
r2-p002fix ok prediction offTemporal Dead Zone Hoisting Conflicttemporal dead zone after code is hoisted or reordered
r2-p003fix okComputed Property Key Precedence FailureIf the Math.pow call appears in a context where its return value is used as a property key (e.g., computed property name), the autofix may produce invalid syntax because ** has lower precedence than t
r2-p004fix okNewline Without Semicolon Protection ASI HazardIf base or exponent contains a newline without semicolon insertion protection, the autofix could trigger automatic semicolon insertion incorrectly, changing the parsing of subsequent statements.
r2-p005fix okArguments Object And Rest Parameters Collisionarguments object, function.length, default parameters, rest parameters
r2-p006fix okFunction Declaration In Block Scope Re-entryfunction declarations inside blocks, switch cases, labeled statements
r2-p007fix okRegex Literal Asterisk Ambiguity In ExponentiationIf base or exponent contains a regular expression literal, the autofix may cause a SyntaxError because the asterisk in ** can be confused with the multiplication operator or regex quantifier depending
r2-p008fix okTrailing Comment Dropped By AutofixIf the original code had trailing comments on the Math.pow line, the autofix may drop or misplace them because it only rewrites the call expression and does not preserve comment attachment.

Sources

r1-p001 · Comma Expression Hazard
1let result;
2result = Math.pow(1, 2, 3);
3console.log('Result:', result); // Should be NaN because second arg becomes '3', third ignored
Result: 1
r1-p002 · Arguments Object Interaction
1function test(a, b = Math.pow(2, 3)) {
2 console.log('b:', b);
3}
4test(); // Expected: b: 8
5// After fix: still works? But we test capture via closure
6const fn = () => Math.pow(2, 3);
7console.log('fn():', fn()); // Expected: 8
--- orig.js	2026-10-17 17:01:47.818786756 -0400
+++ fixed.js	2026-10-17 17:01:48.092790054 -0400
@@ -1,7 +1,7 @@
-function test(a, b = Math.pow(2, 3)) {
+function test(a, b = 2 ** 3) {
   console.log('b:', b);
 }
 test(); // Expected: b: 8
 // After fix: still works? But we test capture via closure
-const fn = () => Math.pow(2, 3);
+const fn = () => 2 ** 3;
 console.log('fn():', fn()); // Expected: 8
b: 8
fn(): 8
r1-p003 · Temporal Dead Zone
1try {
2 console.log(Math.pow(x, 2)); // TDZ: x not initialized
3} catch (e) {
4 console.log('Caught:', e.name + ': ' + e.message);
5}
6let x = 3; // Hoisted declaration, not initialization
7// After fix: same TDZ error
--- orig.js	2026-10-17 17:01:48.271792208 -0400
+++ fixed.js	2026-10-17 17:01:48.555795625 -0400
@@ -1,5 +1,5 @@
 try {
-  console.log(Math.pow(x, 2)); // TDZ: x not initialized
+  console.log(x ** 2); // TDZ: x not initialized
 } catch (e) {
   console.log('Caught:', e.name + ': ' + e.message);
 }
Caught: ReferenceError: Cannot access 'x' before initialization
r1-p004 · Tagged Template Literal
1function tags(strings, ...values) {
2 return strings.raw[0] + '|' + values[0] + '|' + strings.raw[1];
3}
4const output = tags`${Math.pow(2, 3)} end`;
5console.log('Output:', output); // Expected: '|8|'
6// After fix: tags`${2 ** 3} end` → same? Wait — no, if misgrouped...
7// Actually: if base/expr has comma, but here safe.
8// We need a case where ** changes grouping in interpolation
9// Let's use comma in exponent to break it
10const bad = tags`${Math.pow(2, 1, 2)}`; // 2^(1,2) → 2^2=4
11console.log('Bad:', bad); // Expected: '|4|'
12// If autofix makes 2 ** 1, 2 → (2**1), 2 → comma expr → value is 2
13// So bad becomes '|2|' → mismatch!
--- orig.js	2026-10-17 17:01:48.728797706 -0400
+++ fixed.js	2026-10-17 17:01:49.006801051 -0400
@@ -1,7 +1,7 @@
 function tags(strings, ...values) {
   return strings.raw[0] + '|' + values[0] + '|' + strings.raw[1];
 }
-const output = tags`${Math.pow(2, 3)} end`;
+const output = tags`${2 ** 3} end`;
 console.log('Output:', output); // Expected: '|8|'
 // After fix: tags`${2 ** 3} end` → same? Wait — no, if misgrouped...
 // Actually: if base/expr has comma, but here safe.
Output: |8| end
Bad: |2|
r1-p005 · Class Fields and Static Blocks
1class C {
2 static pow = Math.pow(2, 3);
3 static {
4 console.log('Static block:', C.pow); // Expected: 8
5 }
6 get value() {
7 return Math.pow(this.prop, 2);
8 }
9}
10const inst = new C();
11inst.prop = 4;
12console.log('Instance value:', inst.value); // Expected: 16
13// All Math.pow calls should fire and be fixed correctly
--- orig.js	2026-10-17 17:01:49.184803192 -0400
+++ fixed.js	2026-10-17 17:01:49.464806560 -0400
@@ -1,10 +1,10 @@
 class C {
-  static pow = Math.pow(2, 3);
+  static pow = 2 ** 3;
   static {
     console.log('Static block:', C.pow); // Expected: 8
   }
   get value() {
-    return Math.pow(this.prop, 2);
+    return this.prop ** 2;
   }
 }
 const inst = new C();
Static block: 8
Instance value: 16
r1-p006 · Trailing Comments Preservation
1let x = Math.pow(2, 3); // Result should be 8
2console.log('x:', x); // Print x
3// After fix: comment may be lost or moved — but we can't observe that directly
4// So instead, we make the line affect control flow via side effect in comment? Not possible.
5// Workaround: if comment is lost, and we rely on it for something? Can't.
6// Instead: test that the line still executes and comment presence doesn't break syntax.
7// But requirement: trace must depend on rewritten code.
8// Alternative: if autofix breaks due to comment interference (e.g. places ** in comment)
9// Only if comment contains code-like text.
10// Let's put a fake operator in comment that could be misparsed if comment is not detached.
11// But JS ignores comments — so no effect.
12// This hazard may not be observable in output.
13// However: if autofix removes comment and we have fallback logic based on line count? No.
14// Given constraints, we accept that we cannot observe comment loss in output.
15// But we must include it — so we write it and hope the trace is same either way.
16// To satisfy 'trace depends on rewritten code': we make the Math.pow result used.
17// And assume that if comment is mishandled, it causes a syntax error.
18// Example: if autofix produces: let x = 2 ** 3; // Result should be 8
19// Still valid.
20// But if it puts ** inside comment: let x = 2; // 3** → syntax error? No.
21// Real risk: if comment has newline and autofix breaks line.
22// We'll assume the fix is correct for output, but include the comment as required.
23// Since we must show dependence, and we can't, we note: this program may not detect the bug.
24// But we include it as instructed.
25console.log('Final x:', x); // Expected: 8
--- orig.js	2026-10-17 17:01:49.630808556 -0400
+++ fixed.js	2026-10-17 17:01:49.893811720 -0400
@@ -1,4 +1,4 @@
-let x = Math.pow(2, 3); // Result should be 8
+let x = 2 ** 3; // Result should be 8
 console.log('x:', x); // Print x
 // After fix: comment may be lost or moved — but we can't observe that directly
 // So instead, we make the line affect control flow via side effect in comment? Not possible.
x: 8
Final x: 8
r1-p007 · Strict vs Sloppy Mode
1"use strict";
2try {
3 Math.pow = 42; // Should fail in strict mode
4} catch (e) {
5 console.log('Assignment error:', e.name);
6}
7console.log('Math.pow still works:', Math.pow(2, 3)); // Expected: 8
8// In sloppy mode, assignment succeeds and breaks Math.pow
9// After fix: 2 ** 3 still works even if Math.pow is overwritten
10// So we can detect mode by whether Math.pow is callable
11let isStrict = true;
12try { Math.pow = 1; } catch { isStrict = false; }
13if (isStrict) {
14 console.log('Mode: strict');
15} else {
16 console.log('Mode: sloppy');
17 Math.pow = () => 0; // Break it
18 console.log('After break, Math.pow(2,3):', Math.pow(2,3)); // Expected: 0
19 console.log('But 2 ** 3:', 2 ** 3); // Expected: 8 — shows fix avoids reliance on Math.pow
20}
--- orig.js	2026-10-17 17:01:50.067813812 -0400
+++ fixed.js	2026-10-17 17:01:50.349817202 -0400
@@ -4,7 +4,7 @@
 } catch (e) {
   console.log('Assignment error:', e.name);
 }
-console.log('Math.pow still works:', Math.pow(2, 3)); // Expected: 8
+console.log('Math.pow still works:', 2 ** 3); // Expected: 8
 // In sloppy mode, assignment succeeds and breaks Math.pow
 // After fix: 2 ** 3 still works even if Math.pow is overwritten
 // So we can detect mode by whether Math.pow is callable
@@ -15,6 +15,6 @@
 } else {
   console.log('Mode: sloppy');
   Math.pow = () => 0; // Break it
-  console.log('After break, Math.pow(2,3):', Math.pow(2,3)); // Expected: 0
+  console.log('After break, Math.pow(2,3):', 2 ** 3); // Expected: 0
   console.log('But 2 ** 3:', 2 ** 3); // Expected: 8 — shows fix avoids reliance on Math.pow
 }
r1-p008 · Function Declarations in Blocks
1switch (1) {
2 case 1:
3 function helper() {
4 return Math.pow(2, 3);
5 }
6 break;
7}
8console.log('Helper result:', helper()); // Expected: 8
9// After fix: helper uses 2 ** 3 — same result
10// But we want to test if hoisting/scoping affects it
11// Add re-declaration attempt
12try {
13 function helper() { return 0; } // Should throw in strict? But we're not strict
14} catch (e) {
15 console.log('Redeclaraion error:', e.message);
16}
17console.log('Helper again:', helper()); // Still 8
18// No change expected — but we include as structural hazard
--- orig.js	2026-10-17 17:01:50.522819282 -0400
+++ fixed.js	2026-10-17 17:01:50.789822492 -0400
@@ -1,7 +1,7 @@
 switch (1) {
   case 1:
     function helper() {
-      return Math.pow(2, 3);
+      return 2 ** 3;
     }
     break;
 }
r2-p001 · Trailing Comment Attached To Call
1// This matters
2const x = Math.pow(2, 3); // compute eight
--- orig.js	2026-10-17 17:01:55.632880648 -0400
+++ fixed.js	2026-10-17 17:01:55.867883468 -0400
@@ -1,2 +1,2 @@
 // This matters
-const x = Math.pow(2, 3); // compute eight
+const x = 2 ** 3; // compute eight
r2-p002 · Temporal Dead Zone Hoisting Conflict
1try { console.log(y); } catch(e) { console.log('TDZ:' + e.name); }
2let y = Math.pow(2, 3)
--- orig.js	2026-10-17 17:01:56.016885255 -0400
+++ fixed.js	2026-10-17 17:01:56.298888636 -0400
@@ -1,2 +1,2 @@
 try { console.log(y); } catch(e) { console.log('TDZ:' + e.name); }
-let y = Math.pow(2, 3)
+let y = 2 ** 3
TDZ:ReferenceError
r2-p003 · Computed Property Key Precedence Failure
1console.log({[Math.pow(2, 3)]: 'ok'}[8])
--- orig.js	2026-10-17 17:01:56.466890651 -0400
+++ fixed.js	2026-10-17 17:01:56.743893973 -0400
@@ -1 +1 @@
-console.log({[Math.pow(2, 3)]: 'ok'}[8])
+console.log({[2 ** 3]: 'ok'}[8])
ok
r2-p004 · Newline Without Semicolon Protection ASI Hazard
1let a = 2
2
33
4let b = Math.pow(a, 1)
5console.log(b)
--- orig.js	2026-10-17 17:01:56.912895999 -0400
+++ fixed.js	2026-10-17 17:01:57.184899260 -0400
@@ -1,5 +1,5 @@
 let a = 2
 
 3
-let b = Math.pow(a, 1)
+let b = a ** 1
 console.log(b)
2
r2-p005 · Arguments Object And Rest Parameters Collision
1function f(p = Math.pow(2, 3), ...r) { console.log('p=' + p + ', r.len=' + r.length); }
2f()
--- orig.js	2026-10-17 17:01:57.377901574 -0400
+++ fixed.js	2026-10-17 17:01:57.646904798 -0400
@@ -1,2 +1,2 @@
-function f(p = Math.pow(2, 3), ...r) { console.log('p=' + p + ', r.len=' + r.length); }
+function f(p = 2 ** 3, ...r) { console.log('p=' + p + ', r.len=' + r.length); }
 f()
p=8, r.len=0
r2-p006 · Function Declaration In Block Scope Re-entry
1{ function g() { return Math.pow(2, 3); } console.log(g()); }
--- orig.js	2026-10-17 17:01:57.823906920 -0400
+++ fixed.js	2026-10-17 17:01:58.087910084 -0400
@@ -1 +1 @@
-{ function g() { return Math.pow(2, 3); } console.log(g()); }
+{ function g() { return 2 ** 3; } console.log(g()); }
8
r2-p007 · Regex Literal Asterisk Ambiguity In Exponentiation
1/a*/.test('') ? console.log('no') : console.log(/a*/.test(Math.pow(2, 3) + ''))
--- orig.js	2026-10-17 17:01:58.261912169 -0400
+++ fixed.js	2026-10-17 17:01:58.520915272 -0400
@@ -1 +1 @@
-/a*/.test('') ? console.log('no') : console.log(/a*/.test(Math.pow(2, 3) + ''))
+/a*/.test('') ? console.log('no') : console.log(/a*/.test(2 ** 3 + ''))
no
r2-p008 · Trailing Comment Dropped By Autofix
1console.log(Math.pow(2, 3)); // this comment must stay
--- orig.js	2026-10-17 17:01:58.683917225 -0400
+++ fixed.js	2026-10-17 17:01:58.953920460 -0400
@@ -1 +1 @@
-console.log(Math.pow(2, 3)); // this comment must stay
+console.log(2 ** 3); // this comment must stay
8