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;
}