Repository navigation
fix: keep small values and custom separators free of scientific notation - #369
Merged
avoidwork merged 1 commit intoOct 21, 2026
Merged
Conversation
The scientific notation expansion in applyNumberFormatting used Intl's default of three fraction digits, so a forced exponent with a large round (filesize(1, { exponent: 3, round: 10 })) turned 1e-9 into "0 GB". It also ran after the separator replacement, so a custom separator left "1e-9" or "1e+22" in the output.
Expand the number before replacing the separator and allow up to 20 fraction digits.
Merged
9 of 15 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The scientific-notation expansion added in #344 has two gaps:
toLocaleString("en-US", { useGrouping: false }), and Intl's defaultmaximumFractionDigitsis 3. A rounded value small enough fortoString()to give exponent form (below 1e-6) is therefore truncated to"0":filesize(1, { exponent: 3, round: 10 })returns"0 GB". The rounded value is1e-9, so the expected result is"0.000000001 GB".filesize(5, { exponent: 3, round: 9 })returns"0 GB".filesize(1, { exponent: 3, round: 10, pad: true })returns"0.0000000000 GB".separatorhas been applied, when the value is already a string, so the check never matches on that path:filesize(1, { exponent: 3, round: 10, separator: "," })returns"1e-9 GB".filesize(1e22, { exponent: 0, separator: "," })returns"1e+22 B". Without a separator it returns"10000000000000000000000 B".filesize(Number.MAX_VALUE, { separator: "," })returns"1,7976931348623158e+284 YB".This PR moves the expansion into the non-locale branch, after the pad-rounding step and before the separator replacement, and passes
maximumFractionDigits: 20. 20 is the largest value every Intl implementation accepts. The locale branches are unchanged: they already return strings, so the old check never ran on them. Theprecisionpath is also unchanged, because its value is atoPrecision()string.Type of Change
Related Issues
refs #343 (item 8, "Strip scientific notation in non-precision path"). No open issue or PR covers these two cases.
Testing
Two tests were added under "Edge case hardening (issue #343) › Sign handling", next to the existing
Number.MAX_VALUEtest:should not truncate small values when expanding scientific notationshould not leak scientific notation with a custom separatorBefore the fix, both fail on
master(actual: '0 GB'andactual: '1e-9 GB'). With the fix, both pass:npm test(oxlint + oxfmt check + node:test with coverage) passes: 271 tests, with 100% line, branch and function coverage forsrc/.npm run buildsucceeds, and the trackeddist/files were regenerated. All of this was run on Node 26.10 (macOS).A broader before/after probe of about 55 option combinations (locale, pad, separator, precision, bits, BigInt, fullform) changed only the
1e22+separatorcase.Known limit: a value that needs more than 20 fraction digits, which only happens with
round> 20, still rounds to zero.Checklist
npm testpassesnpm run buildsucceedsScreenshots (if applicable)
N/A