You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
toString(radix) above 2^53 emits exact digits, not V8's shortest round-trip ((1e21).toString(36) → 5v1j4f4ds7c4ks vs 5v1j4f4ds7c000) #9725
Number.prototype.toString(radix) for a non-power-of-two radix emits the double's exact digits above 2^53, where V8 emits the shortest round-trip form. Static and dynamic call sites are both affected, so this is the radix formatter itself, not a dispatch divergence.
Everything at or below 2^53 agrees. Above it the two disagree in the trailing digits: node stops at the last digit the shortest round-trip decimal justifies and pads with zeros, while perry keeps emitting the exact binary value's digits.
Power-of-two radices are unaffected — (1e21).toString(16) is 3635c9adc5dea00000 on both — which is what you would expect if the culprit is the general-radix digit loop rather than the value.
The mechanism is the same one INT_EXACT_FASTPATH_LIMIT documents for base 10 (crates/perry-runtime/src/builtins/formatting.rs): at and above 2^53 several integers map to one double, and the exact integer carries more significant digits than the shortest decimal that round-trips. Base 10 already routes through the shortest-round-trip formatter above that bound; the general-radix path (double_to_radix_string / js_jsvalue_to_string_radix) appears not to apply the equivalent cut.
Low severity on its own, same as #9713 — it matters where the text is compared, hashed, or parsed. Found while building the regression fixture for #9713; the two are independent (this one reproduces with a plain static n.toString(36) and #9713's fix does not touch it), so the #9713 fixture deliberately keeps its radix checks at or below 2^53.
Fixed by #9746, which landed on main via merge train #9798. The train was merged as its own branch, so the Fixes #9725 keyword in #9746 never fired — closing manually. Verified the fix is on main by patch-id (git cherry), not just by the PR being closed.
Activity
proggeramlug commentedon Sep 5, 2026
Fixed by #9746, which landed on
mainvia merge train #9798. The train was merged as its own branch, so theFixes #9725keyword in #9746 never fired — closing manually. Verified the fix is onmainby patch-id (git cherry), not just by the PR being closed.