Skip to content

Commit c02e01e

Browse files
authored
ClineProvider Instance cleanup (#4266)
disposable cleanup
1 parent 467c52f commit c02e01e

File tree

1 file changed

+38
-33
lines changed

1 file changed

+38
-33
lines changed

src/core/webview/ClineProvider.ts

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export class ClineProvider
9292
public static readonly tabPanelId = `${Package.name}.TabPanelProvider`
9393
private static activeInstances: Set<ClineProvider> = new Set()
9494
private disposables: vscode.Disposable[] = []
95+
private webviewDisposables: vscode.Disposable[] = []
9596
private view?: vscode.WebviewView | vscode.WebviewPanel
9697
private clineStack: Task[] = []
9798
private codeIndexStatusSubscription?: vscode.Disposable
@@ -228,6 +229,15 @@ export class ClineProvider
228229
- https://vscode-docs.readthedocs.io/en/stable/extensions/patterns-and-principles/
229230
- https://github.com/microsoft/vscode-extension-samples/blob/main/webview-sample/src/extension.ts
230231
*/
232+
private clearWebviewResources() {
233+
while (this.webviewDisposables.length) {
234+
const x = this.webviewDisposables.pop()
235+
if (x) {
236+
x.dispose()
237+
}
238+
}
239+
}
240+
231241
async dispose() {
232242
this.log("Disposing ClineProvider...")
233243
await this.removeClineFromStack()
@@ -238,6 +248,8 @@ export class ClineProvider
238248
this.log("Disposed webview")
239249
}
240250

251+
this.clearWebviewResources()
252+
241253
while (this.disposables.length) {
242254
const x = this.disposables.pop()
243255

@@ -254,7 +266,6 @@ export class ClineProvider
254266
this.log("Disposed all disposables")
255267
ClineProvider.activeInstances.delete(this)
256268

257-
// Unregister from McpServerManager
258269
McpServerManager.unregisterProvider(this)
259270
}
260271

@@ -425,8 +436,7 @@ export class ClineProvider
425436
values: update,
426437
})
427438
})
428-
// Add the subscription to the main disposables array
429-
this.disposables.push(this.codeIndexStatusSubscription)
439+
this.webviewDisposables.push(this.codeIndexStatusSubscription)
430440
}
431441

432442
// Logs show up in bottom panel > Debug Console
@@ -437,26 +447,20 @@ export class ClineProvider
437447
if ("onDidChangeViewState" in webviewView) {
438448
// WebviewView and WebviewPanel have all the same properties except for this visibility listener
439449
// panel
440-
webviewView.onDidChangeViewState(
441-
() => {
442-
if (this.view?.visible) {
443-
this.postMessageToWebview({ type: "action", action: "didBecomeVisible" })
444-
}
445-
},
446-
null,
447-
this.disposables,
448-
)
450+
const viewStateDisposable = webviewView.onDidChangeViewState(() => {
451+
if (this.view?.visible) {
452+
this.postMessageToWebview({ type: "action", action: "didBecomeVisible" })
453+
}
454+
})
455+
this.webviewDisposables.push(viewStateDisposable)
449456
} else if ("onDidChangeVisibility" in webviewView) {
450457
// sidebar
451-
webviewView.onDidChangeVisibility(
452-
() => {
453-
if (this.view?.visible) {
454-
this.postMessageToWebview({ type: "action", action: "didBecomeVisible" })
455-
}
456-
},
457-
null,
458-
this.disposables,
459-
)
458+
const visibilityDisposable = webviewView.onDidChangeVisibility(() => {
459+
if (this.view?.visible) {
460+
this.postMessageToWebview({ type: "action", action: "didBecomeVisible" })
461+
}
462+
})
463+
this.webviewDisposables.push(visibilityDisposable)
460464
}
461465

462466
// Listen for when the view is disposed
@@ -467,24 +471,24 @@ export class ClineProvider
467471
this.log("Disposing ClineProvider instance for tab view")
468472
await this.dispose()
469473
} else {
470-
this.log("Preserving ClineProvider instance for sidebar view reuse")
474+
this.log("Clearing webview resources for sidebar view")
475+
this.clearWebviewResources()
476+
this.codeIndexStatusSubscription?.dispose()
477+
this.codeIndexStatusSubscription = undefined
471478
}
472479
},
473480
null,
474481
this.disposables,
475482
)
476483

477484
// Listen for when color changes
478-
vscode.workspace.onDidChangeConfiguration(
479-
async (e) => {
480-
if (e && e.affectsConfiguration("workbench.colorTheme")) {
481-
// Sends latest theme name to webview
482-
await this.postMessageToWebview({ type: "theme", text: JSON.stringify(await getTheme()) })
483-
}
484-
},
485-
null,
486-
this.disposables,
487-
)
485+
const configDisposable = vscode.workspace.onDidChangeConfiguration(async (e) => {
486+
if (e && e.affectsConfiguration("workbench.colorTheme")) {
487+
// Sends latest theme name to webview
488+
await this.postMessageToWebview({ type: "theme", text: JSON.stringify(await getTheme()) })
489+
}
490+
})
491+
this.webviewDisposables.push(configDisposable)
488492

489493
// If the extension is starting a new session, clear previous task state.
490494
await this.removeClineFromStack()
@@ -767,7 +771,8 @@ export class ClineProvider
767771
private setWebviewMessageListener(webview: vscode.Webview) {
768772
const onReceiveMessage = async (message: WebviewMessage) => webviewMessageHandler(this, message)
769773

770-
webview.onDidReceiveMessage(onReceiveMessage, null, this.disposables)
774+
const messageDisposable = webview.onDidReceiveMessage(onReceiveMessage)
775+
this.webviewDisposables.push(messageDisposable)
771776
}
772777

773778
/**

0 commit comments

Comments
 (0)