Skip to content

Commit d83cc26

Browse files
authored
voice - avoid cancellation token and disposable at the same time (microsoft#205532)
* voice - avoid cancellation token and disposable at the same time * fix tests * . * .
1 parent 26fdfc6 commit d83cc26

File tree

8 files changed

+46
-39
lines changed

8 files changed

+46
-39
lines changed

src/vs/workbench/api/browser/mainThreadSpeech.ts

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { CancellationTokenSource } from 'vs/base/common/cancellation';
7-
import { Emitter } from 'vs/base/common/event';
6+
import { Emitter, Event } from 'vs/base/common/event';
87
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
98
import { ILogService } from 'vs/platform/log/common/log';
109
import { ExtHostContext, ExtHostSpeechShape, MainContext, MainThreadSpeechShape } from 'vs/workbench/api/common/extHost.protocol';
@@ -43,43 +42,53 @@ export class MainThreadSpeech implements MainThreadSpeechShape {
4342
const registration = this.speechService.registerSpeechProvider(identifier, {
4443
metadata,
4544
createSpeechToTextSession: token => {
45+
if (token.isCancellationRequested) {
46+
return {
47+
onDidChange: Event.None
48+
};
49+
}
50+
4651
const disposables = new DisposableStore();
47-
const cts = new CancellationTokenSource(token);
4852
const session = Math.random();
4953

5054
this.proxy.$createSpeechToTextSession(handle, session);
51-
disposables.add(token.onCancellationRequested(() => this.proxy.$cancelSpeechToTextSession(session)));
5255

5356
const onDidChange = disposables.add(new Emitter<ISpeechToTextEvent>());
5457
this.speechToTextSessions.set(session, { onDidChange });
5558

59+
disposables.add(token.onCancellationRequested(() => {
60+
this.proxy.$cancelSpeechToTextSession(session);
61+
this.speechToTextSessions.delete(session);
62+
disposables.dispose();
63+
}));
64+
5665
return {
57-
onDidChange: onDidChange.event,
58-
dispose: () => {
59-
cts.dispose(true);
60-
this.speechToTextSessions.delete(session);
61-
disposables.dispose();
62-
}
66+
onDidChange: onDidChange.event
6367
};
6468
},
6569
createKeywordRecognitionSession: token => {
70+
if (token.isCancellationRequested) {
71+
return {
72+
onDidChange: Event.None
73+
};
74+
}
75+
6676
const disposables = new DisposableStore();
67-
const cts = new CancellationTokenSource(token);
6877
const session = Math.random();
6978

7079
this.proxy.$createKeywordRecognitionSession(handle, session);
71-
disposables.add(token.onCancellationRequested(() => this.proxy.$cancelKeywordRecognitionSession(session)));
7280

7381
const onDidChange = disposables.add(new Emitter<IKeywordRecognitionEvent>());
7482
this.keywordRecognitionSessions.set(session, { onDidChange });
7583

84+
disposables.add(token.onCancellationRequested(() => {
85+
this.proxy.$cancelKeywordRecognitionSession(session);
86+
this.keywordRecognitionSessions.delete(session);
87+
disposables.dispose();
88+
}));
89+
7690
return {
77-
onDidChange: onDidChange.event,
78-
dispose: () => {
79-
cts.dispose(true);
80-
this.keywordRecognitionSessions.delete(session);
81-
disposables.dispose();
82-
}
91+
onDidChange: onDidChange.event
8392
};
8493
}
8594
});

src/vs/workbench/contrib/chat/common/voiceChat.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { CancellationToken } from 'vs/base/common/cancellation';
77
import { Emitter, Event } from 'vs/base/common/event';
8-
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
8+
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
99
import { rtrim } from 'vs/base/common/strings';
1010
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
1111
import { IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents';
@@ -41,7 +41,7 @@ export interface IVoiceChatTextEvent extends ISpeechToTextEvent {
4141
readonly waitingForInput?: boolean;
4242
}
4343

44-
export interface IVoiceChatSession extends IDisposable {
44+
export interface IVoiceChatSession {
4545
readonly onDidChange: Event<IVoiceChatTextEvent>;
4646
}
4747

@@ -131,12 +131,13 @@ export class VoiceChatService extends Disposable implements IVoiceChatService {
131131

132132
createVoiceChatSession(token: CancellationToken, options: IVoiceChatSessionOptions): IVoiceChatSession {
133133
const disposables = new DisposableStore();
134+
disposables.add(token.onCancellationRequested(() => disposables.dispose()));
134135

135136
let detectedAgent = false;
136137
let detectedSlashCommand = false;
137138

138139
const emitter = disposables.add(new Emitter<IVoiceChatTextEvent>());
139-
const session = disposables.add(this.speechService.createSpeechToTextSession(token, 'chat'));
140+
const session = this.speechService.createSpeechToTextSession(token, 'chat');
140141
disposables.add(session.onDidChange(e => {
141142
switch (e.status) {
142143
case SpeechToTextStatus.Recognizing:
@@ -212,8 +213,7 @@ export class VoiceChatService extends Disposable implements IVoiceChatService {
212213
}));
213214

214215
return {
215-
onDidChange: emitter.event,
216-
dispose: () => disposables.dispose()
216+
onDidChange: emitter.event
217217
};
218218
}
219219

src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ class VoiceChatSessions {
292292

293293
this.voiceChatGettingReadyKey.set(true);
294294

295-
const voiceChatSession = session.disposables.add(this.voiceChatService.createVoiceChatSession(cts.token, { usesAgents: controller.context !== 'inline' }));
295+
const voiceChatSession = this.voiceChatService.createVoiceChatSession(cts.token, { usesAgents: controller.context !== 'inline' });
296296

297297
let inputValue = controller.getInput();
298298

src/vs/workbench/contrib/chat/test/common/voiceChat.test.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as assert from 'assert';
7-
import { CancellationToken } from 'vs/base/common/cancellation';
7+
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
88
import { Emitter, Event } from 'vs/base/common/event';
99
import { IMarkdownString } from 'vs/base/common/htmlContent';
10-
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
10+
import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
1111
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
1212
import { ProviderResult } from 'vs/editor/common/languages';
1313
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
@@ -74,8 +74,7 @@ suite('VoiceChat', () => {
7474

7575
createSpeechToTextSession(token: CancellationToken): ISpeechToTextSession {
7676
return {
77-
onDidChange: emitter.event,
78-
dispose: () => { }
77+
onDidChange: emitter.event
7978
};
8079
}
8180

@@ -89,12 +88,11 @@ suite('VoiceChat', () => {
8988

9089
let service: VoiceChatService;
9190
let event: IVoiceChatTextEvent | undefined;
92-
let session: ISpeechToTextSession | undefined;
9391

9492
function createSession(options: IVoiceChatSessionOptions) {
95-
session?.dispose();
96-
97-
session = disposables.add(service.createVoiceChatSession(CancellationToken.None, options));
93+
const cts = new CancellationTokenSource();
94+
disposables.add(toDisposable(() => cts.dispose(true)));
95+
const session = service.createVoiceChatSession(cts.token, options);
9896
disposables.add(session.onDidChange(e => {
9997
event = e;
10098
}));

src/vs/workbench/contrib/codeEditor/browser/dictation/editorDictation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ export class EditorDictation extends Disposable implements IEditorContribution {
231231
const cts = new CancellationTokenSource();
232232
disposables.add(toDisposable(() => cts.dispose(true)));
233233

234-
const session = disposables.add(this.speechService.createSpeechToTextSession(cts.token));
234+
const session = this.speechService.createSpeechToTextSession(cts.token);
235235
disposables.add(session.onDidChange(e => {
236236
if (cts.token.isCancellationRequested) {
237237
return;

src/vs/workbench/contrib/inlineChat/electron-sandbox/inlineChatQuickVoice.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,6 @@ export class InlineChatQuickVoice implements IEditorContribution {
263263

264264
const done = (abort: boolean) => {
265265
cts.dispose(true);
266-
session.dispose();
267266
listener.dispose();
268267
this._widget.hide();
269268
this._ctxQuickChatInProgress.reset();

src/vs/workbench/contrib/speech/common/speechService.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export interface ISpeechToTextEvent {
3333
readonly text?: string;
3434
}
3535

36-
export interface ISpeechToTextSession extends IDisposable {
36+
export interface ISpeechToTextSession {
3737
readonly onDidChange: Event<ISpeechToTextEvent>;
3838
}
3939

@@ -48,7 +48,7 @@ export interface IKeywordRecognitionEvent {
4848
readonly text?: string;
4949
}
5050

51-
export interface IKeywordRecognitionSession extends IDisposable {
51+
export interface IKeywordRecognitionSession {
5252
readonly onDidChange: Event<IKeywordRecognitionEvent>;
5353
}
5454

src/vs/workbench/contrib/terminal/browser/terminalVoice.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { RunOnceScheduler } from 'vs/base/common/async';
77
import { CancellationTokenSource } from 'vs/base/common/cancellation';
8-
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
8+
import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
99
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
1010
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
1111
import { AccessibilityVoiceSettingId, SpeechTimeoutDefault } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
@@ -87,8 +87,9 @@ export class TerminalVoiceSession extends Disposable {
8787
this._sendText();
8888
this.stop();
8989
}, voiceTimeout));
90-
this._cancellationTokenSource = this._register(new CancellationTokenSource());
91-
const session = this._disposables.add(this._speechService.createSpeechToTextSession(this._cancellationTokenSource!.token));
90+
this._cancellationTokenSource = new CancellationTokenSource();
91+
this._register(toDisposable(() => this._cancellationTokenSource?.dispose(true)));
92+
const session = this._speechService.createSpeechToTextSession(this._cancellationTokenSource?.token);
9293

9394
this._disposables.add(session.onDidChange((e) => {
9495
if (this._cancellationTokenSource?.token.isCancellationRequested) {

0 commit comments

Comments
 (0)