fix(pi-tui): patch 5 resource leak bugs in TUI components
- Loader: clear existing interval in start() to prevent orphaned timers on double-call; add dispose() to stop and null TUI ref - CancellableLoader: abort the AbortController and clear onAbort in dispose() so external signal holders release the controller - Editor: add public dispose() that clears the autocomplete debounce timer to prevent post-removal callbacks - Input: convert focused to getter/setter that resets isInPaste and pasteBuffer on focus loss, preventing paste state corruption - TUI.stop(): iterate overlayStack calling dispose() on each component before clearing, stopping overlay timers (e.g. dashboard refresh)
This commit is contained in:
parent
2fdcc08eb0
commit
ea2efe804f
5 changed files with 34 additions and 1 deletions
|
|
@ -35,6 +35,8 @@ export class CancellableLoader extends Loader {
|
|||
}
|
||||
|
||||
dispose(): void {
|
||||
this.abortController.abort();
|
||||
this.onAbort = undefined;
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2055,6 +2055,10 @@ https://github.com/EsotericSoftware/spine-runtimes/actions/runs/19536643416/job/
|
|||
this.lastAutocompleteLookupPrefix = null;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.clearAutocompleteDebounce();
|
||||
}
|
||||
|
||||
public isShowingAutocomplete(): boolean {
|
||||
return this.autocompleteState !== null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,17 @@ export class Input implements Component, Focusable {
|
|||
public onEscape?: () => void;
|
||||
|
||||
/** Focusable interface - set by TUI when focus changes */
|
||||
focused: boolean = false;
|
||||
private _focused: boolean = false;
|
||||
get focused(): boolean {
|
||||
return this._focused;
|
||||
}
|
||||
set focused(value: boolean) {
|
||||
this._focused = value;
|
||||
if (!value) {
|
||||
this.isInPaste = false;
|
||||
this.pasteBuffer = "";
|
||||
}
|
||||
}
|
||||
|
||||
// Bracketed paste mode buffering
|
||||
private pasteBuffer: string = "";
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ export class Loader extends Text {
|
|||
}
|
||||
|
||||
start() {
|
||||
if (this.intervalId) {
|
||||
clearInterval(this.intervalId);
|
||||
}
|
||||
this.updateDisplay();
|
||||
this.intervalId = setInterval(() => {
|
||||
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
|
||||
|
|
@ -40,6 +43,11 @@ export class Loader extends Text {
|
|||
}
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.stop();
|
||||
this.ui = null;
|
||||
}
|
||||
|
||||
setMessage(message: string) {
|
||||
this.message = message;
|
||||
this.updateDisplay();
|
||||
|
|
|
|||
|
|
@ -441,6 +441,15 @@ export class TUI extends Container {
|
|||
|
||||
stop(): void {
|
||||
this.stopped = true;
|
||||
|
||||
// Dispose all overlays to stop any running timers
|
||||
for (const entry of this.overlayStack) {
|
||||
if ("dispose" in entry.component && typeof (entry.component as any).dispose === "function") {
|
||||
(entry.component as any).dispose();
|
||||
}
|
||||
}
|
||||
this.overlayStack = [];
|
||||
|
||||
// Move cursor to the end of the content to prevent overwriting/artifacts on exit
|
||||
if (this.previousLines.length > 0) {
|
||||
const targetRow = this.previousLines.length; // Line after the last content
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue