biome style/useNumberNamespace
labelled safe
Analysis Nemotron 3 Super
The rule flags usage of global numeric functions and constants (`parseInt`, `parseFloat`, `NaN`, `Infinity`, `-Infinity`) without the `Number.` namespace prefix.
Fix: Replace the global identifier with its equivalent property on the `Number` object (e.g., `parseInt` → `Number.parseInt`, `NaN` → `Number.NaN`, `Infinity` → `Number.POSITIVE_INFINITY`, `-Infinity` → `Number.NEGATIVE_INFINITY`).
11 hazards
- Rewriting `parseInt` as `Number.parseInt` changes behavior if a local variable named `Number` exists in scope, causing a ReferenceError or accessing the wrong object.
- If `Number` is reassigned (e.g., `let Number = 42;`), the fix will reference the reassigned value instead of the built-in Number constructor, altering semantics.
- In strict mode, if `Number` is not declared, the fix assumes it refers to the global Number constructor, but if a with-block shadows Number, the lookup may resolve incorrectly.
- The fix removes any comments attached to the original token (e.g., `parseInt/*foo*/("1");` becomes `Number.parseInt("1");` with the comment lost).
- When used in new expressions like `new parseInt()`, rewriting to `new Number.parseInt()` is invalid syntax because `Number.parseInt` is not a constructor, causing a TypeError at runtime.
- If the code relies on the global `parseInt` being accessed via the global object (e.g., in a sandbox where `globalThis.parseInt` is mocked), replacing it with `Number.parseInt` bypasses the mock and uses the real built-in.
- In environments where `Number` is not defined (e.g., some old or minimal JS environments), the fix would throw a ReferenceError where the original code worked.
- If `Infinity` is used as a property name (e.g., `obj.Infinity`), the fix would incorrectly rewrite it to `obj.Number.POSITIVE_INFINITY`, which is a different property and likely undefined.
- When `-Infinity` appears in a template literal (e.g., "-Infinity"), the fix does not apply because it’s a string, but if mistakenly applied, it would corrupt the string literal.
- If the code depends on the global `NaN` being identical to `window.NaN` in a browser context, and `Number.NaN` is used instead, it remains equivalent in value but may break identity checks in realms with multiple global contexts (e.g., iframes).
- In eval() or Function constructor contexts, the rewritten code may be parsed in a different lexical scope, causing `Number` to resolve differently than the original global lookup.
Findings
| program | oracle | label | judge | status | summary |
|---|---|---|---|---|---|
| r1-p002 | fix-changes-behavior | labelled safe | real · medium | related | The rule rewrites the global `parseInt` call to `Number.parseInt`, but the program declares a local variable named `Number` that shadows the global namespace. … |
| r1-p006 | fix-changes-behavior | labelled safe | real · medium | related | The rule rewrites global parseInt to Number.parseInt assuming the global Number object, but the program explicitly defines Number as undefined on the global ob… |
| r2-p003 | fix-changes-behavior | labelled safe | real · medium | related | The rule rewrites global parseInt to Number.parseInt, but the program declares a local variable named Number that shadows the global Number object. After the f… |
| r2-p004 | fix-changes-behavior | labelled safe | real · medium | related | The rule rewrites `parseInt` to `Number.parseInt` assuming `Number` refers to the global namespace, but the program declares a local variable `Number` that sha… |
| r2-p008 | fix-changes-behavior | labelled safe | real · medium | duplicate | The rule rewrites global parseInt to Number.parseInt assuming the global Number object, but the program declares a local const Number that shadows it. The docu… |
Programs
| id | result | title | hazard |
|---|---|---|---|
| r1-p001 | invalid | Shadowed Number via with statement | If `Number` is shadowed by a with-block, the fix resolves to the wrong object. |
| r1-p002 | fix-changes-behavior | Reassigned Number variable | If `Number` is reassigned, the fix uses the reassigned value instead of the built-in constructor. |
| r1-p003 | fix ok | Function declaration inside block scope | The rule fires inside a block-scoped function; the fix may capture a different Number due to hoisting or TDZ-like effects. |
| r1-p004 | fix ok prediction off | Temporal Dead Zone after hoisting simulation | Simulates TDZ by declaring Number after use in a closure that captures the uninitialized binding. |
| r1-p005 | fix ok | Order of evaluation with side effects | The fix duplicates the argument expression due to macro-like expansion, causing side effects to run twice. |
| r1-p006 | fix-changes-behavior | Environment where Number is undefined | In an environment without global Number, the fix throws ReferenceError while original works (if global parseInt exists). |
| r1-p007 | fix ok | Async/await interaction with rewritten expression | The fix occurs inside an async function; await ordering may be affected if the expression has side effects. |
| r1-p008 | fix ok | Label/break/continue with finally and early return | The fix is inside a loop with labeled break and finally; altered control flow changes how many times the body runs. |
| r2-p001 | fix ok | __proto__ assignment affects Number resolution | __proto__ keys, prototype access, Object.assign vs spread |
| r2-p002 | fix ok | Comment preservation during replacement | comments attached to the removed or moved code |
| r2-p003 | fix-changes-behavior | Reassigned Number variable breaks fix | If `Number` is reassigned (e.g., `let Number = 42;`), the fix will reference the reassigned value instead of the built-in Number constructor, altering semantics. |
| r2-p004 | fix-changes-behavior | Var hoisting and redeclaration in loop | var hoisting and re-declaration inside loops or after use |
| r2-p005 | fix ok | Label/break/continue with finally and early return | label/break/continue control flow, finally blocks, early returns in nested blocks |
| r2-p006 | fix ok | Global NaN identity vs Number.NaN in realm-like check | If the code depends on the global `NaN` being identical to `window.NaN` in a browser context, and `Number.NaN` is used instead, it remains equivalent in value but may break identity checks in realms w |
| r2-p007 | silent prediction off | Eval context changes Number resolution | In eval() or Function constructor contexts, the rewritten code may be parsed in a different lexical scope, causing `Number` to resolve differently than the original global lookup. |
| r2-p008 | fix-changes-behavior | Name collision after move due to shadowing | name collisions across scopes after a move (shadowing) |
Sources
r1-p001 · Shadowed Number via with statement (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-04-1)
1"use strict";
2const obj = { parseInt: s => s + 'shadow' };
3with (obj) {
4 console.log(parseInt('1'));
5}
r1-p002 · Reassigned Number variable
1"use strict";
2let Number = { parseInt: s => s + 'reassigned' };
3console.log(parseInt('1'));
--- orig.js 2026-10-17 17:04:25.492627017 -0400 +++ fixed.js 2026-10-17 17:04:25.766630125 -0400 @@ -1,3 +1,3 @@ "use strict"; let Number = { parseInt: s => s + 'reassigned' }; -console.log(parseInt('1')); +console.log(Number.parseInt('1'));
1
r1-p003 · Function declaration inside block scope
1"use strict";
2{
3 function f() {
4 return parseInt('1');
5 }
6 console.log(f());
7}
--- orig.js 2026-10-17 17:04:25.937632064 -0400 +++ fixed.js 2026-10-17 17:04:26.222635296 -0400 @@ -1,7 +1,7 @@ "use strict"; { function f() { - return parseInt('1'); + return Number.parseInt('1'); } console.log(f()); }
1
r1-p004 · Temporal Dead Zone after hoisting simulation
1"use strict";
2(() => {
3 try {
4 return parseInt('1');
5 } catch (e) {
6 return e instanceof ReferenceError ? 'TDZ' : 'other';
7 }
8})();
9let Number = 42;
--- orig.js 2026-10-17 17:04:26.392637224 -0400 +++ fixed.js 2026-10-17 17:04:26.638640013 -0400 @@ -1,7 +1,7 @@ "use strict"; (() => { try { - return parseInt('1'); + return Number.parseInt('1'); } catch (e) { return e instanceof ReferenceError ? 'TDZ' : 'other'; }
r1-p005 · Order of evaluation with side effects
1"use strict";
2let i = 0;
3function next() { return ++i; }
4console.log(parseInt(String(next())));
--- orig.js 2026-10-17 17:04:26.787641703 -0400 +++ fixed.js 2026-10-17 17:04:27.061644809 -0400 @@ -1,4 +1,4 @@ "use strict"; let i = 0; function next() { return ++i; } -console.log(parseInt(String(next()))); +console.log(Number.parseInt(String(next())));
1
r1-p006 · Environment where Number is undefined
1"use strict";
2const g = Function('return this')();
3defineProperty(g, 'Number', { value: undefined });
4try {
5 console.log(parseInt('1'));
6} catch (e) {
7 console.log(e.name + ': ' + e.message);
8}
9function defineProperty(obj, name, desc) { Object.defineProperty(obj, name, desc); }
--- orig.js 2026-10-17 17:04:27.232646748 -0400 +++ fixed.js 2026-10-17 17:04:27.500649785 -0400 @@ -2,7 +2,7 @@ const g = Function('return this')(); defineProperty(g, 'Number', { value: undefined }); try { - console.log(parseInt('1')); + console.log(Number.parseInt('1')); } catch (e) { console.log(e.name + ': ' + e.message); }
1
r1-p007 · Async/await interaction with rewritten expression
1"use strict";
2async function f() {
3 let x = 0;
4 const inc = () => ++x;
5 const v = await Promise.resolve(parseInt(String(inc())));
6 return v + x;
7}
8f().then(console.log);
--- orig.js 2026-10-17 17:04:27.673651746 -0400 +++ fixed.js 2026-10-17 17:04:27.938654750 -0400 @@ -2,7 +2,7 @@ async function f() { let x = 0; const inc = () => ++x; - const v = await Promise.resolve(parseInt(String(inc()))); + const v = await Promise.resolve(Number.parseInt(String(inc()))); return v + x; } f().then(console.log);
2
r1-p008 · Label/break/continue with finally and early return
1"use strict";
2outer: {
3 for (let i = 0; i < 3; i++) {
4 if (i === 1) break outer;
5 try {
6 console.log(parseInt(String(i)));
7 } finally {
8 console.log('finally');
9 }
10 }
11}
--- orig.js 2026-10-17 17:04:28.105656643 -0400 +++ fixed.js 2026-10-17 17:04:28.373659679 -0400 @@ -3,7 +3,7 @@ for (let i = 0; i < 3; i++) { if (i === 1) break outer; try { - console.log(parseInt(String(i))); + console.log(Number.parseInt(String(i))); } finally { console.log('finally'); }
0 finally
r2-p001 · __proto__ assignment affects Number resolution
1const obj = {};
2obj.__proto__ = { Number: { parseInt: (s) => 'shadow' } };
3console.log(parseInt('123')); // Should be 'shadow', fixed becomes 123
--- orig.js 2026-10-17 17:04:33.572718544 -0400 +++ fixed.js 2026-10-17 17:04:33.853721723 -0400 @@ -1,3 +1,3 @@ const obj = {}; obj.__proto__ = { Number: { parseInt: (s) => 'shadow' } }; -console.log(parseInt('123')); // Should be 'shadow', fixed becomes 123 +console.log(Number.parseInt('123')); // Should be 'shadow', fixed becomes 123
123
r2-p002 · Comment preservation during replacement
1/* comment before */
2let x = parseInt(/* arg comment */ '42'); /* comment after */
3console.log(x);
--- orig.js 2026-10-17 17:04:34.023723646 -0400 +++ fixed.js 2026-10-17 17:04:34.290726665 -0400 @@ -1,3 +1,3 @@ /* comment before */ -let x = parseInt(/* arg comment */ '42'); /* comment after */ +let x = Number.parseInt(/* arg comment */ '42'); /* comment after */ console.log(x);
42
r2-p003 · Reassigned Number variable breaks fix
1let Number = 42;
2try {
3 console.log(typeof parseInt('1'));
4} catch (e) {
5 console.log(e.name + ': ' + e.message);
6}
--- orig.js 2026-10-17 17:04:34.452728497 -0400 +++ fixed.js 2026-10-17 17:04:34.725731585 -0400 @@ -1,6 +1,6 @@ let Number = 42; try { - console.log(typeof parseInt('1')); + console.log(typeof Number.parseInt('1')); } catch (e) { console.log(e.name + ': ' + e.message); }
number
r2-p004 · Var hoisting and redeclaration in loop
1for (var i = 0; i < 2; i++) {
2 var Number = i;
3 console.log(typeof parseInt('1'));
4}
--- orig.js 2026-10-17 17:04:34.895733507 -0400 +++ fixed.js 2026-10-17 17:04:35.164736549 -0400 @@ -1,4 +1,4 @@ for (var i = 0; i < 2; i++) { var Number = i; - console.log(typeof parseInt('1')); + console.log(typeof Number.parseInt('1')); }
number number
r2-p005 · Label/break/continue with finally and early return
1outer: {
2 try {
3 if (true) break outer;
4 console.log(parseInt('1'));
5 } finally {
6 console.log('finally');
7 }
8}
9console.log('after');
--- orig.js 2026-10-17 17:04:35.339738528 -0400 +++ fixed.js 2026-10-17 17:04:35.614741637 -0400 @@ -1,7 +1,7 @@ outer: { try { if (true) break outer; - console.log(parseInt('1')); + console.log(Number.parseInt('1')); } finally { console.log('finally'); }
finally after
r2-p006 · Global NaN identity vs Number.NaN in realm-like check
1console.log(NaN === Number.NaN);
2console.log(Object.is(NaN, Number.NaN));
--- orig.js 2026-10-17 17:04:35.778743491 -0400 +++ fixed.js 2026-10-17 17:04:36.055746622 -0400 @@ -1,2 +1,2 @@ -console.log(NaN === Number.NaN); -console.log(Object.is(NaN, Number.NaN)); +console.log(Number.NaN === Number.NaN); +console.log(Object.is(Number.NaN, Number.NaN));
false true
r2-p007 · Eval context changes Number resolution
1eval("console.log(typeof parseInt('1'))");
number
r2-p008 · Name collision after move due to shadowing
1{
2 const Number = { parseInt: () => 999 };
3 console.log(parseInt('1'));
4}
--- orig.js 2026-10-17 17:04:36.450751086 -0400 +++ fixed.js 2026-10-17 17:04:36.715754081 -0400 @@ -1,4 +1,4 @@ { const Number = { parseInt: () => 999 }; - console.log(parseInt('1')); + console.log(Number.parseInt('1')); }
1