biome complexity/useNumericLiterals
labelled safe
Analysis Nemotron 3 Super
The rule flags calls to parseInt() or Number.parseInt() where the first argument is a string literal representing a number in base 2, 8, or 16, suggesting replacement with numeric literals.
Fix: Replace parseInt(str, radix) or Number.parseInt(str, radix) with the equivalent numeric literal: 0b... for radix 2, 0o... for radix 8, 0x... for radix 16, preserving the string content and applying the minus sign if present.
11 hazards
- Rewriting parseInt("01", 2) to 0b01 changes behavior because "01" in base 2 is invalid and parseInt returns 0, while 0b01 is 1, altering the value.
- If the string contains whitespace like " 101 ", parseInt trims it and returns 5, but 0b 101 is a syntax error, breaking compilation.
- When the string has invalid digits for the radix (e.g., "2" in base 2), parseInt returns the value parsed up to the first invalid digit (or 0), but the literal form would be a syntax error, causing a crash.
- For strings like "0x12" passed to parseInt with radix 16, parseInt ignores the "0x" prefix and parses "0x12" as 0x12 = 18, but rewriting to 0x0x12 is invalid syntax.
- If the string is empty "", parseInt returns NaN, but there is no numeric literal equivalent for NaN, so the rewrite would be incorrect or absent, changing behavior.
- In non-strict mode, if a variable named parseInt is in scope (e.g., var parseInt = 5;), the call parseInt("10",2) becomes 5("10",2), which throws, but the fix would incorrectly replace it with 0b10, altering behavior and possibly hiding the error.
- When Number.parseInt is used and Number has been reassigned (e.g., Number = {};), the call is already broken, but the fix would still apply and produce a literal, masking the original error and changing program flow.
- Comments attached to the call expression (e.g., parseInt/*comment*/("101",2)) would be lost during rewriting, as the fix replaces the entire expression.
- If the string is a string object (e.g., new String("101")), the rule does not fire, but if it did by mistake, the fix would ignore the object nature and produce a primitive literal, potentially altering behavior in edge cases involving [[PrimitiveValue]].
- In eval contexts or with dynamic imports, replacing a function call with a literal could change timing or side effects if the call was part of a larger expression relying on its evaluation point.
- Automatic semicolon insertion may be affected if the fix removes a trailing semicolon or alters token boundaries in a way that conflicts with ASI rules, though unlikely, it remains a theoretical hazard.
Programs
| id | result | title | hazard |
|---|---|---|---|
| r2-p001 | fix ok | ASI interaction with missing semicolon | Automatic semicolon insertion may be affected if the fix removes a trailing semicolon or alters token boundaries. |
| r2-p002 | fix ok | Sparse array element access | sparse arrays, holes, Array(n) vs [n], array-likes |
| r2-p003 | invalid | String with 0x prefix misinterpreted | For strings like "0x12" passed to parseInt with radix 16, parseInt ignores the "0x" prefix and parses "0x12" as 0x12 = 18, but rewriting to 0x0x12 is invalid syntax. |
| r2-p004 | silent prediction off | This binding in extracted method | this binding: arrow vs function, methods extracted from objects, call/apply/bind |
| r2-p005 | silent prediction off | Null vs undefined with optional chaining | null/undefined distinction, optional chaining short-circuit, nullish vs falsy |
| r2-p006 | silent prediction off | Exception inside rewritten expression | exceptions thrown inside the code the fix removes or rewrites |
| r2-p007 | silent prediction off | Proto key interaction via assignment | __proto__ keys, prototype access, Object.assign vs spread |
| r2-p008 | silent prediction off | Getter side effect dependency | getters, setters and Object.defineProperty side effects |
Sources
r2-p001 · ASI interaction with missing semicolon
1let x
2parseInt('11', 2)
3['a','b'].forEach(v => console.log(v + x))
--- orig.js 2026-10-17 16:13:13.532340913 -0400 +++ fixed.js 2026-10-17 16:13:13.792335653 -0400 @@ -1,3 +1,3 @@ let x -parseInt('11', 2) +0b11 ['a','b'].forEach(v => console.log(v + x))
r2-p002 · Sparse array element access
1const arr = Array(3)
2advanced: {
3 arr[0] = parseInt('10', 2)
4 arr[2] = parseInt('10', 8)
5 console.log(arr.map((v, i) => v !== undefined ? v : 'hole'))
6}
--- orig.js 2026-10-17 16:13:13.952332416 -0400 +++ fixed.js 2026-10-17 16:13:14.224326924 -0400 @@ -1,6 +1,6 @@ const arr = Array(3) advanced: { - arr[0] = parseInt('10', 2) - arr[2] = parseInt('10', 8) + arr[0] = 0b10 + arr[2] = 0o10 console.log(arr.map((v, i) => v !== undefined ? v : 'hole')) }
[ 2, <1 empty item>, 8 ]
r2-p003 · String with 0x prefix misinterpreted (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-12-5)
1try {
2 const val = parseInt('0x12', 16)
3 console.log(val === 0x0x12 ? 'rewritten' : val)
4} catch (e) {
5 console.log(e.name + ': ' + e.message)
6}
r2-p004 · This binding in extracted method
1const obj = {
2 base: 2,
3 convert(s) { return parseInt(s, this.base) }
4}
5const fn = obj.convert
6console.log(fn.call(obj, '11'))
3
r2-p005 · Null vs undefined with optional chaining
1let input = null
2let radix = undefined
3try {
4 console.log(parseInt(input?.trim(), radix ?? 10))
5} catch (e) {
6 console.log(e.name + ': ' + e.message)
7}
8input = '11'
9radix = 2
10console.log(parseInt(input?.trim(), radix ?? 10))
NaN 3
r2-p006 · Exception inside rewritten expression
1function badString() { throw new TypeError('invalid') }
2try {
3 console.log(parseInt(badString(), 2))
4} catch (e) {
5 console.log(e.name + ': ' + e.message)
6}
TypeError: invalid
r2-p007 · Proto key interaction via assignment
1const map = {}
2Object.defineProperty(map, '__proto__', {
3 set(v) { console.log('proto set to:', v) }
4})
5map.__proto__ = { parseInt: (s, r) => parseInt(s, r) + 100 }
6console.log(map.parseInt('10', 2))
proto set to: { parseInt: [Function: parseInt] }r2-p008 · Getter side effect dependency
1let callCount = 0
2const obj = {
3 get value() {
4 callCount++
5 return '101'
6 }
7}
8console.log(parseInt(obj.value, 2), callCount)
9console.log(parseInt(obj.value, 2), callCount)
5 1 5 2