fix(equalizer): bail out when canvas has no laid-out dimensions (#384)

drawCurve read offsetWidth/offsetHeight unconditionally. When the canvas
sits inside a collapsed <details> (SettingsSubSection) on first paint,
both are 0, innerW becomes negative, the points-loop never runs, and
points[0][0] throws. Linux WebKitGTK happens to lay out the details
expanded on first render; macOS WebKit does not, so the same code path
unmounted the entire React tree because there is no ErrorBoundary above
Settings.

Bail early when innerW or innerH is non-positive — the ResizeObserver
already triggers a redraw once the canvas gets real dimensions.

Closes #382.
This commit is contained in:
Frank Stellmacher
2026-04-30 20:19:10 +02:00
committed by GitHub
parent 316ff1d43b
commit be4e214133
+10 -4
View File
@@ -38,10 +38,6 @@ function drawCurve(canvas: HTMLCanvasElement, gains: number[], accentColor: stri
const dpr = window.devicePixelRatio || 1; const dpr = window.devicePixelRatio || 1;
const W = canvas.offsetWidth; const W = canvas.offsetWidth;
const H = canvas.offsetHeight; const H = canvas.offsetHeight;
canvas.width = W * dpr;
canvas.height = H * dpr;
const ctx = canvas.getContext('2d')!;
ctx.scale(dpr, dpr);
const fMin = 20, fMax = 20000; const fMin = 20, fMax = 20000;
const dbMin = -13, dbMax = 13; const dbMin = -13, dbMax = 13;
@@ -49,6 +45,16 @@ function drawCurve(canvas: HTMLCanvasElement, gains: number[], accentColor: stri
const innerW = W - padL - padR; const innerW = W - padL - padR;
const innerH = H - padT - padB; const innerH = H - padT - padB;
// Canvas hidden or not laid out yet (e.g. inside a collapsed <details> on macOS WebKit).
// Bail before allocating an invalid back-buffer; ResizeObserver redraws when the canvas
// gets real dimensions.
if (innerW <= 0 || innerH <= 0) return;
canvas.width = W * dpr;
canvas.height = H * dpr;
const ctx = canvas.getContext('2d')!;
ctx.scale(dpr, dpr);
const freqToX = (f: number) => const freqToX = (f: number) =>
padL + (Math.log10(f / fMin) / Math.log10(fMax / fMin)) * innerW; padL + (Math.log10(f / fMin) / Math.log10(fMax / fMin)) * innerW;
const dbToY = (db: number) => const dbToY = (db: number) =>