Fixes #11: Memory management enhancements
- Add clearDomCache() for jQuery object cache invalidation on panel rebuild - Track all event handlers in on()/once() for complete cleanup by unregisterAllEvents() - Migrate direct eventSource.on() calls to tracked onEvent() in index.js, injector.js, sillyTavernExpressions.js - Add clearDebugLogs() called on CHAT_CHANGED to prevent memory accumulation - Add trackJQueryHandler()/cleanupJQueryEvents() infrastructure for jQuery event cleanup - Add comprehensive memory management tests (14 new tests, all passing)
This commit is contained in:
@@ -50,10 +50,12 @@ import {
|
||||
setEquipmentContainer,
|
||||
setQuestsContainer,
|
||||
setMusicPlayerContainer,
|
||||
clearSessionAvatarPrompts
|
||||
clearSessionAvatarPrompts,
|
||||
clearDomCache,
|
||||
clearDebugLogs
|
||||
} from './src/core/state.js';
|
||||
import { loadSettings, saveSettings, saveChatData, loadChatData, updateMessageSwipeData, commitTrackerDataFromPriorMessage } from './src/core/persistence.js';
|
||||
import { registerAllEvents } from './src/core/events.js';
|
||||
import { registerAllEvents, on as onEvent } from './src/core/events.js';
|
||||
import { addExtensionSettings } from './src/core/settingsPanel.js';
|
||||
|
||||
// Generation & Parsing modules
|
||||
@@ -233,6 +235,8 @@ async function initUI() {
|
||||
}
|
||||
|
||||
// Cache UI elements using state setters
|
||||
// Clear stale DOM references first to prevent memory leaks on panel rebuild
|
||||
clearDomCache();
|
||||
setPanelContainer($('#rpg-companion-panel'));
|
||||
setUserStatsContainer($('#rpg-user-stats'));
|
||||
setInfoBoxContainer($('#rpg-info-box'));
|
||||
@@ -372,7 +376,7 @@ jQuery(async () => {
|
||||
[event_types.MESSAGE_RECEIVED]: onMessageReceived,
|
||||
[event_types.GENERATION_STOPPED]: onGenerationEnded,
|
||||
[event_types.GENERATION_ENDED]: onGenerationEnded,
|
||||
[event_types.CHAT_CHANGED]: [onCharacterChanged, updatePersonaAvatar, restoreCheckpointOnLoad, clearSessionAvatarPrompts],
|
||||
[event_types.CHAT_CHANGED]: [onCharacterChanged, updatePersonaAvatar, restoreCheckpointOnLoad, clearSessionAvatarPrompts, clearDebugLogs],
|
||||
[event_types.CHAT_LOADED]: onChatLoaded,
|
||||
[event_types.MESSAGE_DELETED]: onMessageDeleted,
|
||||
[event_types.MESSAGE_SWIPE_DELETED]: onMessageDeleted,
|
||||
@@ -381,7 +385,9 @@ jQuery(async () => {
|
||||
[event_types.SETTINGS_UPDATED]: updatePersonaAvatar
|
||||
});
|
||||
|
||||
eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, (messageId) => {
|
||||
// Use tracked event registration (onEvent) instead of direct eventSource.on()
|
||||
// This ensures all handlers are tracked for cleanup by unregisterAllEvents()
|
||||
onEvent(event_types.CHARACTER_MESSAGE_RENDERED, (messageId) => {
|
||||
if (!extensionSettings.enabled) return;
|
||||
const renderedMessage = chat[messageId];
|
||||
if (renderedMessage && !renderedMessage.is_user && !renderedMessage.is_system) {
|
||||
@@ -389,7 +395,7 @@ jQuery(async () => {
|
||||
}
|
||||
});
|
||||
|
||||
eventSource.on(event_types.MESSAGE_UPDATED, (messageId) => {
|
||||
onEvent(event_types.MESSAGE_UPDATED, (messageId) => {
|
||||
if (!extensionSettings.enabled) return;
|
||||
const updatedMessage = chat[messageId];
|
||||
if (updatedMessage && !updatedMessage.is_user && !updatedMessage.is_system) {
|
||||
@@ -397,7 +403,7 @@ jQuery(async () => {
|
||||
}
|
||||
});
|
||||
|
||||
eventSource.on(event_types.MESSAGE_SWIPED, (messageIndex) => {
|
||||
onEvent(event_types.MESSAGE_SWIPED, (messageIndex) => {
|
||||
if (!extensionSettings.enabled) return;
|
||||
const swipedMessage = chat[messageIndex];
|
||||
if (swipedMessage && !swipedMessage.is_user && !swipedMessage.is_system) {
|
||||
@@ -405,18 +411,18 @@ jQuery(async () => {
|
||||
}
|
||||
});
|
||||
|
||||
eventSource.on(event_types.CHAT_CHANGED, () => {
|
||||
onEvent(event_types.CHAT_CHANGED, () => {
|
||||
clearThoughtBasedExpressionsCache();
|
||||
setTimeout(() => onThoughtBasedExpressionsChatChanged(), 0);
|
||||
});
|
||||
|
||||
eventSource.on(event_types.MESSAGE_DELETED, () => {
|
||||
onEvent(event_types.MESSAGE_DELETED, () => {
|
||||
if (!extensionSettings.enabled) return;
|
||||
clearThoughtBasedExpressionsCache();
|
||||
setTimeout(() => onThoughtBasedExpressionsChatChanged(), 0);
|
||||
});
|
||||
|
||||
eventSource.on(event_types.MESSAGE_SWIPE_DELETED, () => {
|
||||
onEvent(event_types.MESSAGE_SWIPE_DELETED, () => {
|
||||
if (!extensionSettings.enabled) return;
|
||||
clearThoughtBasedExpressionsCache();
|
||||
setTimeout(() => onThoughtBasedExpressionsChatChanged(), 0);
|
||||
|
||||
Reference in New Issue
Block a user