@@ -22,6 +22,7 @@ import http from 'http';
2222import { HttpServer } from '@utils/httpServer' ;
2323import { makeSocketPath } from '@utils/fileUtils' ;
2424import { gracefullyProcessExitDoNotHang } from '@utils/processLauncher' ;
25+ import { ManualPromise } from '@isomorphic/manualPromise' ;
2526import { libPath } from '../../package' ;
2627import { playwright } from '../../inprocess' ;
2728import { findChromiumChannelBestEffort , registryDirectory } from '../../server/registry/index' ;
@@ -41,9 +42,8 @@ declare const __PW_HMR__: boolean;
4142
4243type DashboardServer = {
4344 url : string ;
44- reveal : ( options : DashboardOptions ) => void ;
45- triggerAnnotate : ( ) => void ;
46- registerAnnotateWaiter : ( socket : net . Socket ) => void ;
45+ reveal : ( options : DashboardOptions ) => Promise < void > ;
46+ triggerAnnotate : ( socket : net . Socket ) => Promise < void > ;
4747 close : ( ) => Promise < void > ;
4848} ;
4949
@@ -52,8 +52,7 @@ async function startDashboardServer(provider: SessionProvider, options: Dashboar
5252 const httpServer = new HttpServer ( dashboardDir ) ;
5353
5454 const connections = new Set < DashboardConnection > ( ) ;
55- let currentReveal : DashboardOptions = options ;
56- let pendingAnnotate = false ;
55+ let connectionLanded = new ManualPromise < void > ( ) ;
5756 const waitingSockets = new Set < net . Socket > ( ) ;
5857
5958 const submitAnnotation = ( frames : SubmittedAnnotationFrame [ ] , feedback : string ) => {
@@ -70,15 +69,12 @@ async function startDashboardServer(provider: SessionProvider, options: Dashboar
7069 httpServer . createWebSocket ( ( ) => {
7170 let connection : DashboardConnection ;
7271 // eslint-disable-next-line prefer-const
73- connection = new DashboardConnection ( provider , ( ) => connections . delete ( connection ) , ( ) => {
74- if ( currentReveal . pageId )
75- connection . revealPage ( currentReveal . pageId ) ;
76- else if ( currentReveal . sessionName )
77- connection . revealSession ( currentReveal . sessionName , currentReveal . workspaceDir ) ;
78- if ( pendingAnnotate ) {
79- pendingAnnotate = false ;
80- connection . emitAnnotate ( ) ;
81- }
72+ connection = new DashboardConnection ( provider , ( ) => {
73+ connections . delete ( connection ) ;
74+ if ( connections . size === 0 )
75+ connectionLanded = new ManualPromise < void > ( ) ;
76+ } , ( ) => {
77+ connectionLanded . resolve ( ) ;
8278 } , submitAnnotation ) ;
8379 connections . add ( connection ) ;
8480 return connection ;
@@ -102,48 +98,38 @@ async function startDashboardServer(provider: SessionProvider, options: Dashboar
10298 attachDashboardStaticServer ( httpServer , dashboardDir ) ;
10399 await httpServer . start ( { port : options . port , host : options . host } ) ;
104100
105- const reveal = ( next : DashboardOptions ) => {
106- currentReveal = next ;
107- if ( next . pageId ) {
108- for ( const connection of connections )
109- connection . revealPage ( next . pageId ) ;
110- return ;
111- }
112- if ( ! next . sessionName )
113- return ;
114- for ( const connection of connections )
115- connection . revealSession ( next . sessionName , next . workspaceDir ) ;
101+ const reveal = async ( next : DashboardOptions ) : Promise < void > => {
102+ await connectionLanded ;
103+ await Promise . all ( [ ...connections ] . map ( async c => {
104+ if ( next . pageId )
105+ await c . revealPage ( next . pageId ) ;
106+ else if ( next . sessionName )
107+ await c . revealSession ( next . sessionName , next . workspaceDir ) ;
108+ } ) ) ;
116109 } ;
117110
118- const triggerAnnotate = ( ) => {
119- if ( connections . size === 0 ) {
120- pendingAnnotate = true ;
121- return ;
122- }
123- for ( const connection of connections )
124- connection . emitAnnotate ( ) ;
125- } ;
126-
127- const notifyAnnotateEnded = ( ) => {
128- pendingAnnotate = false ;
129- for ( const connection of connections )
130- connection . emitCancelAnnotate ( ) ;
131- } ;
132-
133- const registerAnnotateWaiter = ( socket : net . Socket ) => {
111+ const triggerAnnotate = async ( socket : net . Socket ) => {
134112 waitingSockets . add ( socket ) ;
135113 const cleanup = ( ) => {
136114 if ( ! waitingSockets . delete ( socket ) )
137115 return ;
138- if ( waitingSockets . size === 0 )
139- notifyAnnotateEnded ( ) ;
116+ if ( waitingSockets . size === 0 ) {
117+ for ( const connection of connections )
118+ connection . emitCancelAnnotate ( ) ;
119+ }
140120 } ;
141121 socket . on ( 'close' , cleanup ) ;
142122 socket . on ( 'error' , cleanup ) ;
123+
124+ await connectionLanded ;
125+ if ( waitingSockets . size === 0 )
126+ return ;
127+ for ( const connection of connections )
128+ connection . emitAnnotate ( ) ;
143129 } ;
144130
145131 const close = ( ) => httpServer . stop ( ) ;
146- return { url : httpServer . urlPrefix ( 'human-readable' ) , reveal, triggerAnnotate, registerAnnotateWaiter , close } ;
132+ return { url : httpServer . urlPrefix ( 'human-readable' ) , reveal, triggerAnnotate, close } ;
147133}
148134
149135function attachDashboardStaticServer ( httpServer : HttpServer , dashboardDir : string ) {
@@ -168,6 +154,7 @@ async function attachDashboardDevServer(httpServer: HttpServer) {
168154
169155async function innerOpenDashboardApp ( options : DashboardOptions ) : Promise < { page : api . Page ; server : DashboardServer } > {
170156 const server = await startDashboardServer ( new RegistrySessionProvider ( ) , options ) ;
157+ void server . reveal ( options ) . catch ( ( ) => { } ) ;
171158 const { page } = await launchApp ( 'dashboard' , { onClose : ( ) => gracefullyProcessExitDoNotHang ( 0 ) } ) ;
172159 await page . goto ( server . url ) ;
173160 return { page, server } ;
@@ -279,8 +266,8 @@ async function acquireSingleton(options: DashboardOptions): Promise<net.Server>
279266 return reject ( err ) ;
280267 const client = net . connect ( socketPath , ( ) => {
281268 client . write ( JSON . stringify ( options ) + '\n' ) ;
282- reject ( new Error ( 'already running' ) ) ;
283269 } ) ;
270+ client . on ( 'end' , ( ) => reject ( new Error ( 'already running' ) ) ) ;
284271 client . on ( 'error' , ( ) => {
285272 if ( process . platform !== 'win32' )
286273 fs . unlinkSync ( socketPath ) ;
@@ -305,9 +292,10 @@ export async function openDashboardApp() {
305292 console . error ( 'Unhandled promise rejection:' , error ) ;
306293 } ) ;
307294 if ( options . port !== undefined ) {
308- const { url } = await startDashboardServer ( new RegistrySessionProvider ( ) , options ) ;
295+ const server = await startDashboardServer ( new RegistrySessionProvider ( ) , options ) ;
296+ void server . reveal ( options ) . catch ( ( ) => { } ) ;
309297 // eslint-disable-next-line no-console
310- console . log ( `Listening on ${ url } ` ) ;
298+ console . log ( `Listening on ${ server . url } ` ) ;
311299 // eslint-disable-next-line no-restricted-properties
312300 await new Promise ( f => process . stdout . write ( '' , f ) ) ; // Make sure stdout is flushed.
313301 selfDestructOnParentGone ( ) ;
@@ -345,7 +333,7 @@ async function startApp(server: net.Server, options: DashboardOptions) {
345333 const statePromise = innerOpenDashboardApp ( options ) ;
346334 server . on ( 'connection' , socket => {
347335 let buffer = '' ;
348- socket . on ( 'data' , data => {
336+ socket . on ( 'data' , async data => {
349337 buffer += data . toString ( ) ;
350338 const newlineIndex = buffer . indexOf ( '\n' ) ;
351339 if ( newlineIndex === - 1 )
@@ -362,21 +350,27 @@ async function startApp(server: net.Server, options: DashboardOptions) {
362350 socket . end ( ) ;
363351 return ;
364352 }
365- void statePromise . then ( ( { page, server : dashboard } ) => {
366- if ( parsed . annotate ) {
367- page ?. bringToFront ( ) . catch ( ( ) => { } ) ;
368- dashboard . reveal ( parsed ) ;
369- dashboard . triggerAnnotate ( ) ;
370- dashboard . registerAnnotateWaiter ( socket ) ;
371- } else if ( parsed . kill ) {
372- socket . end ( ) ;
373- gracefullyProcessExitDoNotHang ( 0 ) ;
374- } else {
375- page ?. bringToFront ( ) . catch ( ( ) => { } ) ;
376- dashboard . reveal ( parsed ) ;
353+ const { page, server : dashboard } = await statePromise ;
354+ if ( parsed . annotate ) {
355+ try {
356+ await page ?. bringToFront ( ) ;
357+ await dashboard . reveal ( parsed ) ;
358+ await dashboard . triggerAnnotate ( socket ) ;
359+ } catch ( e ) {
360+ socket . end ( e ) ;
361+ }
362+ } else if ( parsed . kill ) {
363+ socket . end ( ) ;
364+ gracefullyProcessExitDoNotHang ( 0 ) ;
365+ } else {
366+ try {
367+ await page ?. bringToFront ( ) ;
368+ await dashboard . reveal ( parsed ) ;
377369 socket . end ( ) ;
370+ } catch ( e ) {
371+ socket . end ( e ) ;
378372 }
379- } ) ;
373+ }
380374 } ) ;
381375 } ) ;
382376 await statePromise ;
0 commit comments