fix(toasts): cap items array at 50 to bound runaway error toasts
Error toasts are sticky (duration: 0) so a misbehaving command that fires errors in a loop — a backend that flaps, a polling effect over a broken endpoint — accumulates toast items in the in-memory store indefinitely. The audit found no other unbounded $state arrays in the frontend stores (history caps at 500, recentNudges prunes by time, tasks/taskLists replace-on-load), but `items.push(toast)` had no upper bound. Add MAX_TOASTS = 50 with FIFO eviction. Doesn't change behaviour for realistic toast volumes; only kicks in if something is genuinely wrong. https://claude.ai/code/session_0189xUb6ie6t9qHkzatGZ9Rb
This commit is contained in:
@@ -18,6 +18,12 @@ import { errorMessage } from "$lib/utils/errors.js";
|
||||
|
||||
let nextId = 1;
|
||||
|
||||
// Soft cap on how many toasts can be queued at once. Error toasts are sticky
|
||||
// (duration: 0) so a misbehaving command that fires errors in a loop can pile
|
||||
// up indefinitely without this cap. When exceeded, the oldest toast is
|
||||
// evicted to make room.
|
||||
const MAX_TOASTS = 50;
|
||||
|
||||
function defaultDuration(severity: ToastSeverity): number {
|
||||
switch (severity) {
|
||||
case "success": return 3000;
|
||||
@@ -38,6 +44,9 @@ function createToastsStore() {
|
||||
const duration = defaultDuration(severity);
|
||||
const toast = { id, severity, title, body: body ?? '', duration };
|
||||
items.push(toast);
|
||||
if (items.length > MAX_TOASTS) {
|
||||
items.splice(0, items.length - MAX_TOASTS);
|
||||
}
|
||||
if (duration > 0) {
|
||||
setTimeout(() => dismiss(id), duration);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user