@@ -23,6 +23,7 @@ const HTML_DPI = 96
2323const MICRONS_INCH_RATIO = 25400
2424const MAX_EVENT_WAIT = 10000
2525const IPC_MAIN_CHANNEL_RENDER = 'READY_TO_RENDER'
26+ const eventPrefix = 'job.render.'
2627
2728const DEFAULT_OPTIONS = {
2829 closeWindow : true ,
@@ -57,7 +58,12 @@ class ExportJob extends EventEmitter {
5758 * the filesystem
5859 */
5960 constructor ( input , output , args , options ) {
60- super ( { wildcard : true } )
61+ super ( {
62+ // Allow listeners to provide wildcards
63+ wildcard : true ,
64+ // displays the event name if maxListeners is reached for an event
65+ verboseMemoryLeak : true
66+ } )
6167 this . jobId = uuid ( )
6268 this . input = _ . isArray ( input ) ? input : [ input ]
6369 this . output = output
@@ -79,7 +85,6 @@ class ExportJob extends EventEmitter {
7985 * Render markdown or html to pdf
8086 */
8187 render ( window ) {
82- const eventPrefix = 'job.render.'
8388 this . emit ( `${ eventPrefix } start` )
8489
8590 const win = this . _launchBrowserWindow ( )
@@ -396,6 +401,7 @@ class ExportJob extends EventEmitter {
396401 if ( this . args . disableCache ) {
397402 loadOpts . extraHeaders += 'pragma: no-cache\n'
398403 }
404+ this . emit ( `${ eventPrefix } loadurl` , { url : url } )
399405 window . loadURL ( wargs . urlWithArgs ( url , { } ) , loadOpts )
400406 }
401407
@@ -422,37 +428,55 @@ class ExportJob extends EventEmitter {
422428
423429 _waitForBrowserEvent ( waitForJSEvent , window , generateFunction ) {
424430 const eventName = _ . size ( waitForJSEvent ) > 0 ? waitForJSEvent : 'view-ready'
425- this . _attachIPCListener ( eventName , generateFunction )
426- this . _executeJSListener ( eventName , generateFunction , window )
431+ const ipcListener = this . _attachIPCListener ( eventName , generateFunction )
432+ this . _executeJSListener ( eventName , ipcListener , generateFunction , window )
427433 }
428434
429435 /**
430436 * responsible for executing JS in the browser that will wait for the page
431437 * to emit an event before capturing the page.
432438 *
433439 * @param eventName
440+ * @param ipcListener The listener for the ready event. This needs cancelled
441+ * if there is a timeout before it the event is received
434442 * @param generateFunction
435443 * @param window
436444 * @private
437445 */
438- _executeJSListener ( eventName , generateFunction , window ) {
446+ _executeJSListener ( eventName , ipcListener , generateFunction , window ) {
439447 // event.detail will only exist if a CustomEvent was emitted
440448 const cmd = `var ipcRenderer = require('electron').ipcRenderer
441449 document.body.addEventListener('${ eventName } ',
442450 function(event) {
443451 ipcRenderer.send('${ IPC_MAIN_CHANNEL_RENDER } ', '${ this . jobId } ', event.detail)
444452 }
445453 )`
446- // Don't let things hang forever
447- const timeout = setTimeout ( ( ) => {
448- this . emit ( 'window.event.wait.timeout' , { eventName : eventName } )
449- generateFunction ( )
450- } , this . args . outputWait > 0 ? this . args . outputWait : MAX_EVENT_WAIT )
451454
455+ // Don't let a ready event hang, set a max timeout interval
456+ const f = this . _cancelReadyEvent . bind ( this , eventName , ipcListener , generateFunction )
457+ const maxWait = this . args . outputWait > 0 ? this . args . outputWait : MAX_EVENT_WAIT
458+ const timeout = setTimeout ( f , maxWait )
459+
460+ // clear the timeout as soon as we get the ready event from the browser
452461 this . once ( 'window.event.wait.end' , ( ) => clearTimeout ( timeout ) )
462+
453463 window . webContents . executeJavaScript ( cmd )
454464 }
455465
466+ /**
467+ * Invoked when a ready event has not been received before the max timeout is reached
468+ * @param eventName The eventName provided by the client
469+ * @param ipcListener The ipcMain listener waiting for the IPC_MAIN_CHANNEL_RENDER
470+ * event from the renderer process
471+ * @param generateFunction A callback function to invoke to capture the window
472+ * @private
473+ */
474+ _cancelReadyEvent ( eventName , ipcListener , generateFunction ) {
475+ this . emit ( 'window.event.wait.timeout' , { eventName : eventName } )
476+ electron . ipcMain . removeListener ( IPC_MAIN_CHANNEL_RENDER , ipcListener )
477+ generateFunction ( )
478+ }
479+
456480 /**
457481 * Listen for the browser to emit the READY_TO_RENDER event and when it does
458482 * emit our own event so the max load timer is removed.
@@ -478,6 +502,7 @@ class ExportJob extends EventEmitter {
478502 }
479503 }
480504 electron . ipcMain . on ( IPC_MAIN_CHANNEL_RENDER , listener )
505+ return listener
481506 }
482507
483508 /**
0 commit comments