diff --git a/public/index.html b/public/index.html index c6f9878..1c7c4a4 100644 --- a/public/index.html +++ b/public/index.html @@ -1071,9 +1071,14 @@ } function connectSSE() { + // Clean up any prior connection attempt if (state.eventSource) { state.eventSource.close(); } + if (state.reconnectTimeout) { + clearTimeout(state.reconnectTimeout); + state.reconnectTimeout = null; + } const es = new EventSource('/events'); @@ -1091,6 +1096,7 @@ console.debug('SSE error, reconnecting...'); setStatus(false); es.close(); + state.eventSource = null; if (!state.reconnectTimeout) { state.reconnectTimeout = setTimeout(() => connectSSE(), 2000); } @@ -1419,7 +1425,18 @@ // Append only new content since last render const newChunk = session.output.slice(session.outputRenderedLength); if (newChunk) { - $output.innerHTML += newChunk; + // More efficient than innerHTML += as it avoids reparsing existing content + $output.insertAdjacentHTML('beforeend', newChunk); + session.outputRenderedLength = session.output.length; + } + + // Soft cap to prevent unbounded growth in DOM and memory + const MAX_OUTPUT_CHARS = 200000; // ~200KB of HTML per session + if (session.output.length > MAX_OUTPUT_CHARS) { + const start = session.output.length - MAX_OUTPUT_CHARS; + session.output = session.output.slice(start); + // Reset DOM to trimmed content and sync rendered length + $output.innerHTML = session.output; session.outputRenderedLength = session.output.length; }