fixhunt

biome style/useExponentiationOperator: fix changes program behavior

fix-changes-behaviorlabelled safereal · highrelated
Findings / 2026-10-17T21-01-30-169Z-3u5f-biome-style_useExponentiationOperator / r1-p007biome 2.5.1520 → 5 lines2026-10-17 21:01 UTC

Hypothesis Nemotron 3 Super predicted to fire fired 1×

strict vs sloppy mode semantics

Program

before
1try {
2 Math.pow = 42; // Should fail in strict mode
3} catch (e) {
4}
5console.log('Math.pow still works:', Math.pow(2, 3)); // Expected: 8
after
1try {
2 Math.pow = 42; // Should fail in strict mode
3} catch (e) {
4}
5console.log('Math.pow still works:', 2 ** 3); // Expected: 8

Output

stdout beforeexit 1
(no stdout)
TypeError: Math.pow is not a function
stdout afterexit 0
Math.pow still works: 8
fired
1 before · 0 after
runs
each version twice, same file name, no network

Judge Nemotron 3 Ultra advisory real · high

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 ** 3, which bypasses the overwritten property and changes the observable behavior from a caught TypeError and no output to successful execution with output.

Explanation Nemotron 3 Super unverified

The original code attempts to overwrite `Math.pow` with a number inside a try block, which fails in strict mode because `Math.pow` is non-writable, throwing a TypeError caught silently. The rewritten version replaces the call `Math.pow(2, 3)` with the exponentiation operator `2 ** 3`, bypassing `Math.pow` entirely. Since the error occurs during the assignment, not the call, the fix avoids the error by not using `Math.pow` after it’s broken, changing behavior from error-handled failure to silent success. This alters observable output and exit status, so it is not semantics-preserving.

Reproduce

file
prog.js (the before program)
minimized program
r1-p007.js
evidence sheet
r1-p007.md
regression fixture
r1-p007.js the minimized program with a header stating the observed change, for the tool's test suite
node prog.js
bunx @biomejs/biome lint --only=style/useExponentiationOperator --write prog.js
node prog.js

Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra

useExponentiationOperator fix · style/useExponentiationOperator replace Math.pow calls · biome lint rule exponentiation operator conversion · fix behavior change from Math.pow to **

  • related biomejs/biome/issues/410 same rule style/useExponentiationOperator but different construct (test.js vs Math.pow reassignment)

Details

program
Strict vs Sloppy Mode
hazard
strict vs sloppy mode semantics
oracle
stdout before: stdout after: Math.pow still works: 8 exit 1 → 0 stderr before: TypeError: Math.pow is not a function stderr after: (none)
run
2026-10-17T21-01-30-169Z-3u5f-biome-style_useExponentiationOperator
generated program (20 lines) and the fix's diff
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
 }
rule documentation given to the models
Summary

- Name: useExponentiationOperator
- Fix: safe
- Default severity: info
- Available from version: 1.0.0
- Diagnostic category: lint/style/useExponentiationOperator
- This rule is recommended

Description

 Disallow the use of `Math.pow` in favor of the `**` operator.

 Introduced in ES2016, the infix exponentiation operator `**` is an alternative for the standard `Math.pow` function.
 Infix notation is considered to be more readable and thus more preferable than the function notation.

Examples

Invalid

 ```js,expect_diagnostic
 const foo = Math.pow(2, 8);
 ```

 ```js,expect_diagnostic
 const bar = Math.pow(a, b);
 ```

 ```js,expect_diagnostic
 let baz = Math.pow(a + b, c + d);
 ```

 ```js,expect_diagnostic
 let quux = Math.pow(-1, n);
 ```

Valid

 ```js
 const foo = 2 ** 8;

 const bar = a ** b;

 let baz = (a + b) ** (c + d);

 let quux = (-1) ** n;
 ```