From 746d81b1518e000d568006212abd8f6c055fe5b6 Mon Sep 17 00:00:00 2001 From: Kevin Riehl Date: Sun, 9 Aug 2026 00:27:30 -0700 Subject: [PATCH] =?UTF-8?q?fix:=20audit=20phase=202=20=E2=80=94=20teardown?= =?UTF-8?q?,=20failure=20paths,=20service=20worker,=20tooltip,=20resize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correctness phase of the frontend audit. Nothing here is visible on a happy path; it is what the app does when something goes wrong, when the window changes, or when the component goes away. Teardown (new src/lib/pixi/lifecycle.ts): - Nothing was ever released: no app.destroy(), no ticker.remove(), no killTweensOf, no onDestroy. ~480 GSAP tweens (most repeat:-1), a ticker callback, and a dozen DOM listeners lived forever. - 112 of those tweens are created inside an onComplete, so they don't exist when a call-site sweep would run. gsap.context() handles exactly this: GSAP records each animation's context on creation and restores it while invoking that animation's callbacks (see _callback in gsap-core), so late-created pulses land in the same context. One ctx.kill() gets all of them. kill(), not revert(), so GSAP doesn't write properties back onto objects about to be destroyed. - All DOM listeners now go through life.listen(), which registers removal at the same time. Previously 6 canvas listeners were never removed, each closing over the whole ~713-object scene graph. - The unmount race: cleanup used to be registered on the LAST line of an async onMount, after the asset waterfall, so unmounting mid-load cleaned up nothing. The lifecycle is now created before any await, with life.disposed guards after each one. - Hover tweens re-enter the context per event and use overwrite:'auto' so rapid sweeps don't stack conflicting tweens. Failure paths: - onMount had no try/catch and no WebGL detection. Any init or asset failure left the spinner up forever, the stats toggle at opacity:0, and Escape dead (attachKeyboard never ran). Now caught, and it hands off to +page.svelte to reveal the text version. - There was no