biome style/useExponentiationOperator
labelled safe
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
| program | oracle | label | judge | status | summary |
|---|---|---|---|---|---|
| r1-p007 | fix-changes-behavior | labelled safe | real · high | related | The 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
| id | result | title | hazard |
|---|---|---|---|
| r1-p001 | fired, no fix | Comma Expression Hazard | 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 exclud |
| r1-p002 | fix ok | Arguments Object Interaction | arguments object, function.length, default parameters, rest parameters |
| r1-p003 | fix ok | Temporal Dead Zone | temporal dead zone after code is hoisted or reordered |
| r1-p004 | fix ok | Tagged Template Literal | 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. |
| r1-p005 | fix ok | Class Fields and Static Blocks | class fields, static blocks, private names, super calls |
| r1-p006 | fix ok | Trailing Comments Preservation | 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. |
| r1-p007 | fix-changes-behavior | Strict vs Sloppy Mode | strict vs sloppy mode semantics |
| r1-p008 | fix ok | Function Declarations in Blocks | function declarations inside blocks, switch cases, labeled statements |
| r2-p001 | fix ok | Trailing Comment Attached To Call | comments attached to the removed or moved code |
| r2-p002 | fix ok prediction off | Temporal Dead Zone Hoisting Conflict | temporal dead zone after code is hoisted or reordered |
| r2-p003 | fix ok | Computed Property Key Precedence Failure | 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 t |
| r2-p004 | fix ok | Newline Without Semicolon Protection ASI Hazard | 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. |
| r2-p005 | fix ok | Arguments Object And Rest Parameters Collision | arguments object, function.length, default parameters, rest parameters |
| r2-p006 | fix ok | Function Declaration In Block Scope Re-entry | function declarations inside blocks, switch cases, labeled statements |
| r2-p007 | fix ok | Regex Literal Asterisk Ambiguity In Exponentiation | 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 |
| r2-p008 | fix ok | Trailing Comment Dropped By Autofix | 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. |
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