From 312e8f92f6d682a4c4fcc9e326d5fdc0ebe3f94d Mon Sep 17 00:00:00 2001 From: Christopher Pruijsen Date: Sun, 13 Sep 2026 10:44:57 +0000 Subject: [PATCH] fix infinite loop in numAxisSplits for big-magnitude flat ranges numIntDigits() wrapped to int32 for |x| >= 2^31, so findIncr's significant-digits guard under-counted the magnitude and could pick a sub-ULP foundIncr (e.g. 1e-8 at 1e14) that can never advance val in the numAxisSplits loop, hanging the browser. - numIntDigits: use log10(abs(x)) outside the int32 fast range - numAxisSplits: require val to strictly increase each iteration --- src/opts.js | 2 +- src/utils.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/opts.js b/src/opts.js index 528d3b18..2ae7fd22 100644 --- a/src/opts.js +++ b/src/opts.js @@ -599,7 +599,7 @@ export function numAxisSplits(self, axisIdx, scaleMin, scaleMax, foundIncr, foun scaleMin = forceMin ? scaleMin : roundDec(incrRoundUp(scaleMin, foundIncr), numDec); - for (let val = scaleMin; val <= scaleMax; val = roundDec(val + foundIncr, numDec)) + for (let val = scaleMin, prevVal = -inf; val <= scaleMax && val > prevVal; prevVal = val, val = roundDec(val + foundIncr, numDec)) splits.push(Object.is(val, -0) ? 0 : val); // coalesces -0 return splits; diff --git a/src/utils.js b/src/utils.js index 454a7e6b..24448245 100644 --- a/src/utils.js +++ b/src/utils.js @@ -307,7 +307,8 @@ export const asinh = (v, linthresh = 1) => M.asinh(v / linthresh); export const inf = Infinity; export function numIntDigits(x) { - return (log10((x ^ (x >> 31)) - (x >> 31)) | 0) + 1; + x = abs(x); + return (log10(x < 2147483648 ? x | 0 : x) | 0) + 1; } export function clamp(num, _min, _max) {