@@ -32,6 +32,7 @@ import { IConfigurationService, InteractiveWindowMode, IsWebExtension, Resource
32
32
import { noop } from '../platform/common/utils/misc' ;
33
33
import {
34
34
IKernel ,
35
+ IKernelProvider ,
35
36
isLocalConnection ,
36
37
KernelAction ,
37
38
KernelConnectionMetadata ,
@@ -41,7 +42,6 @@ import { chainable } from '../platform/common/utils/decorators';
41
42
import { InteractiveCellResultError } from '../platform/errors/interactiveCellResultError' ;
42
43
import { DataScience } from '../platform/common/utils/localize' ;
43
44
import { createDeferred , Deferred } from '../platform/common/utils/async' ;
44
- import { IServiceContainer } from '../platform/ioc/types' ;
45
45
import { SysInfoReason } from '../messageTypes' ;
46
46
import { createOutputWithErrorMessageForDisplay } from '../platform/errors/errorUtils' ;
47
47
import { INotebookExporter } from '../kernels/jupyter/types' ;
@@ -54,11 +54,9 @@ import {
54
54
IInteractiveWindowDebuggingManager ,
55
55
InteractiveTab
56
56
} from './types' ;
57
- import { generateInteractiveCode , isInteractiveInputTab } from './helpers' ;
57
+ import { generateInteractiveCode , getInteractiveCellMetadata , isInteractiveInputTab } from './helpers' ;
58
58
import { IControllerSelection , IVSCodeNotebookController } from '../notebooks/controllers/types' ;
59
59
import { DisplayOptions } from '../kernels/displayOptions' ;
60
- import { getInteractiveCellMetadata } from './helpers' ;
61
- import { KernelConnector } from '../notebooks/controllers/kernelConnector' ;
62
60
import { getFilePath } from '../platform/common/platform/fs-paths' ;
63
61
import {
64
62
ICodeGeneratorFactory ,
@@ -71,6 +69,8 @@ import { updateNotebookMetadata } from '../kernels/execution/helpers';
71
69
import { chainWithPendingUpdates } from '../kernels/execution/notebookUpdater' ;
72
70
import { initializeInteractiveOrNotebookTelemetryBasedOnUserAction } from '../kernels/telemetry/helper' ;
73
71
import { generateMarkdownFromCodeLines , parseForComments } from '../platform/common/utils' ;
72
+ import { IServiceContainer } from '../platform/ioc/types' ;
73
+ import { KernelConnector } from '../notebooks/controllers/kernelConnector' ;
74
74
75
75
/**
76
76
* ViewModel for an interactive window from the Jupyter extension's point of view.
@@ -105,7 +105,8 @@ export class InteractiveWindow implements IInteractiveWindowLoadable {
105
105
private kernelDisposables : Disposable [ ] = [ ] ;
106
106
private _insertSysInfoPromise : Promise < NotebookCell > | undefined ;
107
107
private currentKernelInfo : {
108
- kernel ?: Deferred < IKernel > ;
108
+ kernelStarted ?: Deferred < void > ;
109
+ kernel ?: IKernel ;
109
110
controller ?: NotebookController ;
110
111
metadata ?: KernelConnectionMetadata ;
111
112
} = { } ;
@@ -135,6 +136,7 @@ export class InteractiveWindow implements IInteractiveWindowLoadable {
135
136
private readonly debuggingManager : IInteractiveWindowDebuggingManager ;
136
137
private readonly isWebExtension : boolean ;
137
138
private readonly commandManager : ICommandManager ;
139
+ private readonly kernelProvider : IKernelProvider ;
138
140
constructor (
139
141
private readonly serviceContainer : IServiceContainer ,
140
142
private _owner : Resource ,
@@ -156,6 +158,7 @@ export class InteractiveWindow implements IInteractiveWindowLoadable {
156
158
this . errorHandler = this . serviceContainer . get < IDataScienceErrorHandler > ( IDataScienceErrorHandler ) ;
157
159
this . codeGeneratorFactory = this . serviceContainer . get < ICodeGeneratorFactory > ( ICodeGeneratorFactory ) ;
158
160
this . storageFactory = this . serviceContainer . get < IGeneratedCodeStorageFactory > ( IGeneratedCodeStorageFactory ) ;
161
+ this . kernelProvider = this . serviceContainer . get < IKernelProvider > ( IKernelProvider ) ;
159
162
this . debuggingManager = this . serviceContainer . get < IInteractiveWindowDebuggingManager > (
160
163
IInteractiveWindowDebuggingManager
161
164
) ;
@@ -229,31 +232,39 @@ export class InteractiveWindow implements IInteractiveWindowLoadable {
229
232
// This cannot happen, but we need to make typescript happy.
230
233
throw new Error ( 'Controller not selected' ) ;
231
234
}
232
- if ( this . currentKernelInfo . kernel ) {
233
- return this . currentKernelInfo . kernel . promise ;
235
+ if ( this . currentKernelInfo . kernelStarted ) {
236
+ await this . currentKernelInfo . kernelStarted . promise ;
237
+ return this . currentKernelInfo . kernel ! ;
234
238
}
235
- const kernelPromise = createDeferred < IKernel > ( ) ;
236
- kernelPromise . promise . catch ( noop ) ;
237
- this . currentKernelInfo = { controller, metadata, kernel : kernelPromise } ;
239
+ const kernelStarted = createDeferred < void > ( ) ;
240
+ kernelStarted . promise . catch ( noop ) ;
241
+ this . currentKernelInfo = { controller, metadata, kernelStarted } ;
238
242
239
243
const sysInfoCell = this . insertSysInfoMessage ( metadata , SysInfoReason . Start ) ;
240
244
try {
241
245
// Try creating a kernel
242
246
initializeInteractiveOrNotebookTelemetryBasedOnUserAction ( this . owner , metadata ) ;
243
247
244
- const onStartKernel = ( action : KernelAction , k : IKernel ) => {
248
+ const onKernelStarted = async ( action : KernelAction , k : IKernel ) => {
245
249
if ( action !== 'start' && action !== 'restart' ) {
246
250
return ;
247
251
}
248
252
// Id may be different if the user switched controllers
249
- this . currentKernelInfo . controller = k . controller ;
250
- this . currentKernelInfo . metadata = k . kernelConnectionMetadata ;
253
+ this . currentKernelInfo . kernel = k ;
251
254
this . updateSysInfoMessage (
252
255
this . getSysInfoMessage ( k . kernelConnectionMetadata , SysInfoReason . Start ) ,
253
256
false ,
254
257
sysInfoCell
255
258
) ;
256
259
} ;
260
+ const onKernelStartCompleted = async ( action : KernelAction , _ : unknown , k : IKernel ) => {
261
+ if ( action !== 'start' && action !== 'restart' ) {
262
+ return ;
263
+ }
264
+ // Id may be different if the user switched controllers
265
+ this . currentKernelInfo . controller = k . controller ;
266
+ this . currentKernelInfo . metadata = k . kernelConnectionMetadata ;
267
+ } ;
257
268
// When connecting, we need to update the sys info message
258
269
this . updateSysInfoMessage ( this . getSysInfoMessage ( metadata , SysInfoReason . Start ) , false , sysInfoCell ) ;
259
270
const kernel = await KernelConnector . connectToNotebookKernel (
@@ -264,7 +275,8 @@ export class InteractiveWindow implements IInteractiveWindowLoadable {
264
275
new DisplayOptions ( false ) ,
265
276
this . internalDisposables ,
266
277
'jupyterExtension' ,
267
- onStartKernel
278
+ onKernelStarted ,
279
+ onKernelStartCompleted
268
280
) ;
269
281
this . currentKernelInfo . controller = kernel . controller ;
270
282
this . currentKernelInfo . metadata = kernel . kernelConnectionMetadata ;
@@ -304,10 +316,11 @@ export class InteractiveWindow implements IInteractiveWindowLoadable {
304
316
this . fileInKernel = undefined ;
305
317
await this . runInitialization ( kernel , this . owner ) ;
306
318
this . finishSysInfoMessage ( kernel , sysInfoCell , SysInfoReason . Start ) ;
307
- kernelPromise . resolve ( kernel ) ;
319
+ kernelStarted . resolve ( ) ;
308
320
return kernel ;
309
321
} catch ( ex ) {
310
- kernelPromise . reject ( ex ) ;
322
+ kernelStarted . reject ( ex ) ;
323
+ this . currentKernelInfo . kernelStarted = undefined ;
311
324
this . currentKernelInfo . kernel = undefined ;
312
325
this . disconnectKernel ( ) ;
313
326
if ( this . owner ) {
@@ -423,26 +436,8 @@ export class InteractiveWindow implements IInteractiveWindowLoadable {
423
436
message = message . split ( '\n' ) . join ( ' \n' ) ;
424
437
this . updateSysInfoMessage ( message , true , cellPromise ) ;
425
438
}
426
- private registerControllerChangeListener ( controller : IVSCodeNotebookController ) {
427
- const controllerChangeListener = controller . controller . onDidChangeSelectedNotebooks (
428
- ( selectedEvent : { notebook : NotebookDocument ; selected : boolean } ) => {
429
- // Controller was deselected for this InteractiveWindow's NotebookDocument
430
- if ( selectedEvent . selected === false && selectedEvent . notebook === this . notebookEditor . notebook ) {
431
- controllerChangeListener . dispose ( ) ;
432
- this . disconnectKernel ( ) ;
433
- }
434
- } ,
435
- this ,
436
- this . internalDisposables
437
- ) ;
438
- }
439
439
440
440
private listenForControllerSelection ( ) {
441
- const controller = this . notebookControllerSelection . getSelected ( this . notebookEditor . notebook ) ;
442
- if ( controller !== undefined ) {
443
- this . registerControllerChangeListener ( controller ) ;
444
- }
445
-
446
441
// Ensure we hear about any controller changes so we can update our cached promises
447
442
this . notebookControllerSelection . onControllerSelected (
448
443
( e : { notebook : NotebookDocument ; controller : IVSCodeNotebookController } ) => {
@@ -451,8 +446,13 @@ export class InteractiveWindow implements IInteractiveWindowLoadable {
451
446
}
452
447
453
448
// Clear cached kernel when the selected controller for this document changes
454
- this . registerControllerChangeListener ( e . controller ) ;
455
- if ( e . controller . id !== this . currentKernelInfo . controller ?. id ) {
449
+ const kernel = this . kernelProvider . get ( this . notebookDocument . uri ) ;
450
+ const isControllerAttachedToTheSameKernel =
451
+ kernel && this . currentKernelInfo . kernel && kernel === this . currentKernelInfo . kernel ;
452
+ if (
453
+ e . controller . connection . id !== this . currentKernelInfo . kernel ?. kernelConnectionMetadata . id &&
454
+ ! isControllerAttachedToTheSameKernel
455
+ ) {
456
456
this . disconnectKernel ( ) ;
457
457
this . startKernel ( e . controller . controller , e . controller . connection ) . ignoreErrors ( ) ;
458
458
}
@@ -615,6 +615,7 @@ export class InteractiveWindow implements IInteractiveWindowLoadable {
615
615
private disconnectKernel ( ) {
616
616
this . kernelDisposables . forEach ( ( d ) => d . dispose ( ) ) ;
617
617
this . kernelDisposables = [ ] ;
618
+ this . currentKernelInfo . kernelStarted = undefined ;
618
619
this . currentKernelInfo . kernel = undefined ;
619
620
}
620
621
0 commit comments