@@ -32,6 +32,7 @@ registerContextMenu({
3232
3333import { reportStartupEvents } from './report-install-event' ;
3434import { menu } from './menu' ;
35+ import { getDeferred } from './util' ;
3536
3637const rmRF = promisify ( rimraf ) ;
3738
@@ -141,18 +142,6 @@ if (!amMainInstance) {
141142 process . exit ( 1 ) ; // Safe to hard exit - we haven't opened/started anything yet.
142143 }
143144
144- app . on ( 'ready' , ( ) => {
145- Menu . setApplicationMenu ( menu ) ;
146- } ) ;
147-
148- app . on ( 'window-all-closed' , ( ) => {
149- // On OS X it is common for applications and their menu bar
150- // to stay active until the user quits explicitly with Cmd + Q
151- if ( process . platform !== 'darwin' ) {
152- app . quit ( ) ;
153- }
154- } ) ;
155-
156145 let serverKilled = false ;
157146 app . on ( 'will-quit' , ( event ) => {
158147 if ( server && ! serverKilled ) {
@@ -186,14 +175,6 @@ if (!amMainInstance) {
186175 }
187176 } ) ;
188177
189- app . on ( 'activate' , ( ) => {
190- // On OS X it's common to re-create a window in the app when the
191- // dock icon is clicked and there are no other windows open.
192- if ( windows . length === 0 ) {
193- createWindow ( ) ;
194- }
195- } ) ;
196-
197178 app . on ( 'web-contents-created' , ( _event , contents ) => {
198179 function injectValue ( name : string , value : string ) {
199180 // Set a variable globally, and self-postmessage it too (to ping
@@ -400,17 +381,47 @@ if (!amMainInstance) {
400381 reportStartupEvents ( ) ;
401382
402383 cleanupOldServers ( ) . catch ( console . log )
403- . then ( ( ) => startServer ( ) )
404- . catch ( ( err ) => {
384+ . then ( ( ) =>
385+ startServer ( )
386+ ) . catch ( ( err ) => {
405387 console . error ( 'Failed to start server, exiting.' , err ) ;
406388
407389 // Hide immediately, shutdown entirely after a brief pause for Sentry
408390 windows . forEach ( window => window . hide ( ) ) ;
409391 setTimeout ( ( ) => process . exit ( 1 ) , 500 ) ;
410392 } ) ;
411393
412- app . on ( 'ready' , ( ) => createWindow ( ) ) ;
394+ // Use a promise to organize events around 'ready', and ensure they never
395+ // fire before, as Electron will refuse to do various things if they do.
396+ const appReady = getDeferred ( ) ;
397+ app . on ( 'ready' , ( ) => appReady . resolve ( ) ) ;
398+
399+ appReady . promise . then ( ( ) => {
400+ Menu . setApplicationMenu ( menu ) ;
401+ createWindow ( ) ;
402+ } ) ;
403+
413404 // We use a single process instance to manage the server, but we
414405 // do allow multiple windows.
415- app . on ( 'second-instance' , ( ) => createWindow ( ) ) ;
406+ app . on ( 'second-instance' , ( ) =>
407+ appReady . promise . then ( ( ) => createWindow ( ) )
408+ ) ;
409+
410+ app . on ( 'activate' , ( ) => {
411+ // On OS X it's common to re-create a window in the app when the
412+ // dock icon is clicked and there are no other windows open.
413+ if ( windows . length === 0 ) {
414+ // Wait until the ready event - it's possible that this can fire
415+ // before the app is ready (not sure how) in which case things break!
416+ appReady . promise . then ( ( ) => createWindow ( ) ) ;
417+ }
418+ } ) ;
419+
420+ app . on ( 'window-all-closed' , ( ) => {
421+ // On OS X it is common for applications and their menu bar
422+ // to stay active until the user quits explicitly with Cmd + Q
423+ if ( process . platform !== 'darwin' ) {
424+ app . quit ( ) ;
425+ }
426+ } ) ;
416427}
0 commit comments