99import {
1010 assertSpyCalls ,
1111 resolvesNext ,
12+ spy ,
1213 stub ,
1314} from "jsr:@std/[email protected] /mock" ; 1415import { delay } from "jsr:@std/[email protected] /delay" ; @@ -17,6 +18,7 @@ import * as nvimCodec from "jsr:@lambdalisue/messagepack@^1.0.1";
1718import { createFakeMeta } from "./testutil/mock.ts" ;
1819import { Neovim } from "./host/nvim.ts" ;
1920import { Vim } from "./host/vim.ts" ;
21+ import { Service } from "./service.ts" ;
2022import { main } from "./worker.ts" ;
2123
2224const CONSOLE_PATCH_METHODS = [
@@ -125,6 +127,14 @@ for (const { host, mode } of matrix) {
125127 using _addEventListenerSpy = spyAddEventListener ( ) ;
126128 using _denoCommandStub = stubDenoCommand ( ) ;
127129 using deno_addSignalListener = stub ( Deno , "addSignalListener" ) ;
130+ using host_asyncDispose = spy (
131+ ( host === "vim" ? Vim : Neovim ) . prototype ,
132+ Symbol . asyncDispose ,
133+ ) ;
134+ using service_asyncDispose = spy (
135+ Service . prototype ,
136+ Symbol . asyncDispose ,
137+ ) ;
128138 using self_close = stub ( globalThis , "close" ) ;
129139 const usePostMessageHistory = ( ) => ( {
130140 [ Symbol . dispose ] : ( ) => messageStub . postMessage . resetHistory ( ) ,
@@ -353,15 +363,37 @@ for (const { host, mode } of matrix) {
353363 assertInstanceOf ( signalHandler , Function ) ;
354364 } ) ;
355365
356- await t . step ( "closes worker when stream is closed" , async ( ) => {
357- assertSpyCalls ( self_close , 0 ) ;
366+ await t . step ( "before stream is closed" , async ( t ) => {
367+ await t . step ( "does not dispose service" , ( ) => {
368+ assertSpyCalls ( service_asyncDispose , 0 ) ;
369+ } ) ;
358370
359- // NOTE: Send `null` to close workerio stream.
360- messageStub . fakeHostMessage ( null ) ;
371+ await t . step ( "does not dispose host" , ( ) => {
372+ assertSpyCalls ( host_asyncDispose , 0 ) ;
373+ } ) ;
361374
362- await delay ( 0 ) ;
363- assertSpyCalls ( self_close , 1 ) ;
364- await mainPromise ;
375+ await t . step ( "does not close worker" , ( ) => {
376+ assertSpyCalls ( self_close , 0 ) ;
377+ } ) ;
378+ } ) ;
379+
380+ // NOTE: Send `null` to close workerio stream.
381+ messageStub . fakeHostMessage ( null ) ;
382+ await delay ( 0 ) ;
383+
384+ await t . step ( "after stream is closed" , async ( t ) => {
385+ await t . step ( "disposes service" , ( ) => {
386+ assertSpyCalls ( service_asyncDispose , 1 ) ;
387+ } ) ;
388+
389+ await t . step ( "disposes host" , ( ) => {
390+ assertSpyCalls ( host_asyncDispose , 1 ) ;
391+ } ) ;
392+
393+ await t . step ( "closes worker" , async ( ) => {
394+ assertSpyCalls ( self_close , 1 ) ;
395+ await mainPromise ;
396+ } ) ;
365397 } ) ;
366398 } ) ;
367399
@@ -397,6 +429,14 @@ for (const { host, mode } of matrix) {
397429 using _addEventListenerSpy = spyAddEventListener ( ) ;
398430 using _denoCommandStub = stubDenoCommand ( ) ;
399431 using deno_addSignalListener = stub ( Deno , "addSignalListener" ) ;
432+ using host_asyncDispose = spy (
433+ ( host === "vim" ? Vim : Neovim ) . prototype ,
434+ Symbol . asyncDispose ,
435+ ) ;
436+ using service_asyncDispose = spy (
437+ Service . prototype ,
438+ Symbol . asyncDispose ,
439+ ) ;
400440 using self_close = stub ( globalThis , "close" ) ;
401441 const fakeMeta = { ...createFakeMeta ( ) , host, mode } ;
402442
@@ -441,6 +481,82 @@ for (const { host, mode } of matrix) {
441481 ) ;
442482 } ) ;
443483
484+ await t . step ( "disposes service" , ( ) => {
485+ assertSpyCalls ( service_asyncDispose , 1 ) ;
486+ } ) ;
487+
488+ await t . step ( "disposes host" , ( ) => {
489+ assertSpyCalls ( host_asyncDispose , 1 ) ;
490+ } ) ;
491+
492+ await t . step ( "closes worker" , async ( ) => {
493+ assertSpyCalls ( self_close , 1 ) ;
494+ await mainPromise ;
495+ } ) ;
496+ } ) ;
497+
498+ await t . step ( "main() if service is closed" , async ( t ) => {
499+ using messageStub = stubMessage ( ) ;
500+ using _consoleStub = stubConsole ( ) ;
501+ using _addEventListenerSpy = spyAddEventListener ( ) ;
502+ using _denoCommandStub = stubDenoCommand ( ) ;
503+ using _deno_addSignalListener = stub ( Deno , "addSignalListener" ) ;
504+ using host_asyncDispose = spy (
505+ ( host === "vim" ? Vim : Neovim ) . prototype ,
506+ Symbol . asyncDispose ,
507+ ) ;
508+ using service_asyncDispose = spy (
509+ Service . prototype ,
510+ Symbol . asyncDispose ,
511+ ) ;
512+ const service_waitClosed_waiter = Promise . withResolvers < void > ( ) ;
513+ using service_waitClosed = stub (
514+ Service . prototype ,
515+ "waitClosed" ,
516+ ( ) => service_waitClosed_waiter . promise ,
517+ ) ;
518+ using self_close = stub ( globalThis , "close" ) ;
519+ const fakeMeta = { ...createFakeMeta ( ) , host, mode } ;
520+
521+ const mainPromise = main ( ) ;
522+
523+ if ( host === "vim" ) {
524+ // Initial message from the host.
525+ messageStub . fakeHostMessage ( vimCodec . encode ( [ 0 , [ "void" ] ] ) ) ;
526+ await delay ( 0 ) ;
527+ // requests Meta data
528+ messageStub . fakeHostMessage ( vimCodec . encode ( [ - 1 , [ fakeMeta , "" ] ] ) ) ;
529+ await delay ( 0 ) ;
530+ // doautocmd `User DenopsReady`
531+ messageStub . fakeHostMessage ( vimCodec . encode ( [ - 2 , [ "" , "" ] ] ) ) ;
532+ await delay ( 0 ) ;
533+ } else {
534+ // Initial message from the host.
535+ messageStub . fakeHostMessage ( nvimCodec . encode ( [ 2 , "void" , [ ] ] ) ) ;
536+ await delay ( 0 ) ;
537+ // requests Meta data
538+ messageStub . fakeHostMessage ( nvimCodec . encode ( [ 1 , 0 , null , fakeMeta ] ) ) ;
539+ await delay ( 0 ) ;
540+ // sets client info
541+ messageStub . fakeHostMessage ( nvimCodec . encode ( [ 1 , 1 , null , 0 ] ) ) ;
542+ await delay ( 0 ) ;
543+ // doautocmd `User DenopsReady`
544+ messageStub . fakeHostMessage ( nvimCodec . encode ( [ 1 , 2 , null , "" ] ) ) ;
545+ await delay ( 0 ) ;
546+ }
547+
548+ assertSpyCalls ( service_waitClosed , 1 ) ;
549+ service_waitClosed_waiter . resolve ( ) ;
550+ await delay ( 0 ) ;
551+
552+ await t . step ( "disposes service" , ( ) => {
553+ assertSpyCalls ( service_asyncDispose , 1 ) ;
554+ } ) ;
555+
556+ await t . step ( "disposes host" , ( ) => {
557+ assertSpyCalls ( host_asyncDispose , 1 ) ;
558+ } ) ;
559+
444560 await t . step ( "closes worker" , async ( ) => {
445561 assertSpyCalls ( self_close , 1 ) ;
446562 await mainPromise ;
0 commit comments