biome suspicious/useNumberToFixedDigitsArgument
labelled safe
Analysis Nemotron 3 Super
The rule flags calls to Number.prototype.toFixed() without arguments, as they rely on the implicit default of 0 digits after the decimal point.
Fix: The autofix adds the argument `0` to the call, transforming `toFixed()` into `toFixed(0)`.
1 hazards
- If `toFixed` is a non-standard method overridden on an object, adding an argument may cause a TypeError if the custom implementation does not accept arguments. If the call is part of a larger expression, inserting the argument could alter parsing due to operator precedence, especially if the call is used in a context like `a + b.toFixed()` where semicolon insertion or binding might be affected. If the original code relied on implicit semicolon insertion and the fix introduces a syntax error by breaking ASI boundaries (e.g., if the line ends with `toFixed()` and the next line starts with a `[` or `(`, adding `(` changes the interpretation). If the call appears inside a template literal or tagged template, the added parentheses or comma could interfere with the template’s grammar. If the method is accessed via a property that has a getter with side effects, evaluating the property twice (once for the original call and once during fix application in a faulty tool) could cause unintended behavior—though the fix itself doesn’t re-evaluate, unsafe tooling might. If the code uses `toFixed` in a context where the return value is ignored but the call is made for its side effects (e.g., in a custom proxy), adding an argument might trigger different trap behavior. If the code is minified or relies on specific formatting, the fix could break formatting-dependent tools or preprocessors. If the call is in a legacy JavaScript environment where `toFixed` behaves differently with explicit arguments (e.g., older engines), the fix might not be equivalent.
Programs
| id | result | title | hazard |
|---|---|---|---|
| r1-p001 | fired, no fix | Control Flow Interference | label/break/continue control flow, finally blocks, early returns in nested blocks |
| r1-p002 | fired, no fix | Prototype Mutation Hazard | __proto__ keys, prototype access, Object.assign vs spread |
| r1-p003 | silent prediction off | Nullish vs Falsy Short-Circuit | null/undefined distinction, optional chaining short-circuit, nullish vs falsy |
| r1-p004 | fired, no fix | Temporal Dead Zone Interaction | temporal dead zone after code is hoisted or reordered |
| r1-p005 | fired, no fix | Operator Precedence and ASI Risk | If `toFixed` is a non-standard method overridden on an object, adding an argument may cause a TypeError if the custom implementation does not accept arguments. If the call is part of a larger expressi |
| r1-p006 | fired, no fix | Class Fields and Private Interaction | class fields, static blocks, private names, super calls |
| r1-p007 | fired, no fix | Getter Side Effect Hazard | getters, setters and Object.defineProperty side effects |
| r1-p008 | fired, no fix | Sparse Array and Array-Like Hazard | sparse arrays, holes, Array(n) vs [n], array-likes |
| r2-p001 | fired, no fix | Block-scoped function declaration shadowing | function declarations inside blocks, switch cases, labeled statements |
| r2-p002 | fired, no fix | Var hoisting and re-declaration in loop | var hoisting and re-declaration inside loops or after use |
| r2-p003 | fired, no fix | Non-standard toFixed override causing TypeError | If `toFixed` is a non-standard method overridden on an object, adding an argument may cause a TypeError if the custom implementation does not accept arguments. |
| r2-p004 | invalid | Numeric/string coercion with + vs template literal | numeric/string coercion: + vs template literal, objects with toString/valueOf, Symbol, BigInt |
| r2-p005 | fired, no fix | Name collision after block scope move | name collisions across scopes after a move (shadowing) |
| r2-p006 | silent prediction off | Nullish vs falsy short-circuit with optional chaining | null/undefined distinction, optional chaining short-circuit, nullish vs falsy |
| r2-p007 | fired, no fix | Order of evaluation with side effects in expression | order of evaluation when expressions are merged, duplicated or deleted (side effects run twice or never) |
| r2-p008 | fired, no fix | RegExp lastIndex interference with g flag | regular expressions: escapes, unicode flag, lastIndex with the g flag |
Sources
r1-p001 · Control Flow Interference
1outer: {
2 try {
3 let val = 123.456;
4 while (val > 0) {
5 console.log(val.toFixed());
6 if (val < 100) break outer;
7 val -= 10;
8 }
9 } finally {
10 console.log('finally');
11 }
12}
13console.log('done');
123 113 103 93 finally done
r1-p002 · Prototype Mutation Hazard
1const base = { toFixed() { return 'custom'; } };
2const obj = Object.create(base);
3obj.__proto__ = { toFixed() { return obj.value; }, value: 42.9 };
4console.log(obj.toFixed());
5Object.assign(obj, { toFixed: undefined });
6try { console.log(obj.toFixed()); } catch(e) { console.log(e.name + ': ' + e.message); }
42.9 TypeError: obj.toFixed is not a function
r1-p003 · Nullish vs Falsy Short-Circuit
1let x = null;
2console.log(x?.toFixed() ?? 'nullish');
3x = 0;
4console.log(x?.toFixed() ?? 'falsy zero');
5x = undefined;
6console.log(x?.toFixed() ?? 'undefined');
7x = false;
8console.log(x?.toFixed() ?? 'falsy false');
nullish 0 undefined
r1-p004 · Temporal Dead Zone Interaction
1function test() {
2 console.log(typeof toFixedResult);
3 let toFixedResult = (5.5).toFixed();
4 return toFixedResult;
5}
6try { test(); } catch(e) { console.log(e.name + ': ' + e.message); }
ReferenceError: Cannot access 'toFixedResult' before initialization
r1-p005 · Operator Precedence and ASI Risk
1let a = 1;
2let b = 2.5;
3console.log(a + b.toFixed());
4let arr = [1, 2];
5console.log(arr[b.toFixed()]);
6let tagged = String`value: ${b.toFixed()} end`;
7console.log(tagged);
13 undefined value: , end
r1-p006 · Class Fields and Private Interaction
1class Base {
2 #value = 3.14159;
3 getFormatted() {
4 return this.#value.toFixed();
5 }
6}
7class Derived extends Base {
8 static { console.log('static block'); }
9 getFormatted() {
10 return super.getFormatted() + ' derived';
11 }
12}
13const d = new Derived();
14console.log(d.getFormatted());
static block 3 derived
r1-p007 · Getter Side Effect Hazard
1let callCount = 0;
2const obj = {
3 get num() {
4 callCount++;
5 return 123.456;
6 }
7};
8console.log(`First: ${obj.num.toFixed()}, calls: ${callCount}`);
9console.log(`Second: ${obj.num.toFixed()}, calls: ${callCount}`);
10Object.defineProperty(obj, 'num', { value: 99.99, writable: true });
11console.log(`After: ${obj.num.toFixed()}, calls: ${callCount}`);
First: 123, calls: 1 Second: 123, calls: 2 After: 100, calls: 2
r1-p008 · Sparse Array and Array-Like Hazard
1const arr = Array(3);
2arr[1] = 2.5;
3console.log('Length:', arr.length);
4for (let i = 0; i < arr.length; i++) {
5 const val = arr[i];
6 if (val !== undefined) {
7 console.log(`idx ${i}: ${val.toFixed()}`);
8 } else {
9 console.log(`idx ${i}: hole`);
10 }
11}
12const arrLike = { '0': 1.1, '1': 2.9, length: 2 };
13console.log(Array.from(arrLike).map(x => x.toFixed()).join(','));
Length: 3 idx 0: hole idx 1: 3 idx 2: hole 1,3
r2-p001 · Block-scoped function declaration shadowing
1{
2 function f() { return { toFixed: () => 'orig' }; }
3 console.log(f().toFixed());
4 {
5 function f() { return { toFixed: n => `${n || 0}-fixed` }; }
6 console.log(f().toFixed());
7 }
8}
orig 0-fixed
r2-p002 · Var hoisting and re-declaration in loop
1for (var i = 0; i < 2; i++) {
2 var x = { toFixed: () => i };
3 console.log(x.toFixed());
4}
0 1
r2-p003 · Non-standard toFixed override causing TypeError
1const obj = {
2 toFixed: () => {
3 if (arguments.length > 0) throw new Error('no args expected');
4 return 'custom';
5 }
6};
7try {
8 console.log(obj.toFixed());
9} catch (e) {
10 console.log(e.name + ': ' + e.message);
11}
ReferenceError: arguments is not defined
r2-p004 · Numeric/string coercion with + vs template literal (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-13-0)
1const x = {
2 valueOf: () => 2.5,
3 toString: () => '2.5'
4};
5console.log(+x.toFixed());
6console.log(`${x.toFixed()`);
r2-p005 · Name collision after block scope move
1let value = 1;
2{
3 const value = { toFixed: () => 'inner' };
4 console.log(value.toFixed());
5}
6console.log(value.toFixed());
inner 1
r2-p006 · Nullish vs falsy short-circuit with optional chaining
1let x = 0;
2const obj = x ? { toFixed: () => 'truthy' } : null;
3console.log(obj?.toFixed());
4x = null;
5console.log(obj?.toFixed());
undefined undefined
r2-p007 · Order of evaluation with side effects in expression
1let i = 0;
2const getObj = () => ({
3 toFixed: () => {
4 return i++;
5 }
6});
7console.log(getObj().toFixed() + ', ' + getObj().toFixed());
0, 1
r2-p008 · RegExp lastIndex interference with g flag
1const re = /\d/g;
2let str = '5.5';
3str += '';
4console.log(str.toFixed());
5console.log(re.lastIndex);