@@ -10,6 +10,7 @@ const WebSocket = require('ws');
1010const api = require ( './api.js' ) ;
1111const defaults = require ( './defaults.js' ) ;
1212const devtools = require ( './devtools.js' ) ;
13+ const StdioWrapper = require ( './stdio-wrapper.js' ) ;
1314
1415class ProtocolError extends Error {
1516 constructor ( request , response ) {
@@ -55,9 +56,10 @@ class Chrome extends EventEmitter {
5556 this . useHostName = ! ! ( options . useHostName ) ;
5657 this . alterPath = options . alterPath || ( ( path ) => path ) ;
5758 this . protocol = options . protocol ;
58- this . local = ! ! ( options . local ) ;
59+ this . local = ! ! ( options . local || options . process ) ;
5960 this . target = options . target || defaultTarget ;
6061 this . connectOptions = options . connectOptions ;
62+ this . process = options . process ;
6163 // locals
6264 this . _notifier = notifier ;
6365 this . _callbacks = { } ;
@@ -104,27 +106,12 @@ class Chrome extends EventEmitter {
104106 }
105107
106108 close ( callback ) {
107- const closeWebSocket = ( callback ) => {
108- // don't close if it's already closed
109- if ( this . _ws . readyState === 3 ) {
110- callback ( ) ;
111- } else {
112- // don't notify on user-initiated shutdown ('disconnect' event)
113- this . _ws . removeAllListeners ( 'close' ) ;
114- this . _ws . once ( 'close' , ( ) => {
115- this . _ws . removeAllListeners ( ) ;
116- this . _handleConnectionClose ( ) ;
117- callback ( ) ;
118- } ) ;
119- this . _ws . close ( ) ;
120- }
121- } ;
122109 if ( typeof callback === 'function' ) {
123- closeWebSocket ( callback ) ;
110+ this . _close ( callback ) ;
124111 return undefined ;
125112 } else {
126113 return new Promise ( ( fulfill , reject ) => {
127- closeWebSocket ( fulfill ) ;
114+ this . _close ( fulfill ) ;
128115 } ) ;
129116 }
130117 }
@@ -140,20 +127,22 @@ class Chrome extends EventEmitter {
140127 ...this . connectOptions ,
141128 } ;
142129 try {
143- // fetch the WebSocket debugger URL
144- const url = await this . _fetchDebuggerURL ( options ) ;
145- // allow the user to alter the URL
146- const urlObject = parseUrl ( url ) ;
147- urlObject . pathname = options . alterPath ( urlObject . pathname ) ;
148- this . webSocketUrl = formatUrl ( urlObject ) ;
149- // update the connection parameters using the debugging URL
150- options . host = urlObject . hostname ;
151- options . port = urlObject . port || options . port ;
130+ if ( ! this . process ) {
131+ // fetch the WebSocket debugger URL
132+ const url = await this . _fetchDebuggerURL ( options ) ;
133+ // allow the user to alter the URL
134+ const urlObject = parseUrl ( url ) ;
135+ urlObject . pathname = options . alterPath ( urlObject . pathname ) ;
136+ this . webSocketUrl = formatUrl ( urlObject ) ;
137+ // update the connection parameters using the debugging URL
138+ options . host = urlObject . hostname ;
139+ options . port = urlObject . port || options . port ;
140+ }
152141 // fetch the protocol and prepare the API
153142 const protocol = await this . _fetchProtocol ( options ) ;
154143 api . prepare ( this , protocol ) ;
155- // finally connect to the WebSocket
156- await this . _connectToWebSocket ( ) ;
144+ // finally connect to the WebSocket or stdio
145+ await this . _connect ( ) ;
157146 // since the handler is executed synchronously, the emit() must be
158147 // performed in the next tick so that uncaught errors in the client code
159148 // are not intercepted by the Promise mechanism and therefore reported
@@ -216,36 +205,64 @@ class Chrome extends EventEmitter {
216205 }
217206 }
218207
219- // establish the WebSocket connection and start processing user commands
220- _connectToWebSocket ( ) {
208+ _createStdioWrapper ( ) {
209+ const stdio = new StdioWrapper ( this . process . stdio [ 3 ] , this . process . stdio [ 4 ] ) ;
210+ this . _close = stdio . close . bind ( stdio ) ;
211+ this . _send = stdio . send . bind ( stdio ) ;
212+ return stdio ;
213+ }
214+
215+ _createWebSocketWrapper ( ) {
216+ if ( this . secure ) {
217+ this . webSocketUrl = this . webSocketUrl . replace ( / ^ w s : / i, 'wss:' ) ;
218+ }
219+ const ws = new WebSocket ( this . webSocketUrl , [ ] , {
220+ followRedirects : true ,
221+ ...this . connectOptions ,
222+ } ) ;
223+ this . _close = ( callback ) => {
224+ // don't close if it's already closed
225+ if ( ws . readyState === 3 ) {
226+ callback ( ) ;
227+ } else {
228+ // don't notify on user-initiated shutdown ('disconnect' event)
229+ ws . removeAllListeners ( 'close' ) ;
230+ ws . once ( 'close' , ( ) => {
231+ ws . removeAllListeners ( ) ;
232+ this . _handleConnectionClose ( ) ;
233+ callback ( ) ;
234+ } ) ;
235+ ws . close ( ) ;
236+ }
237+ } ;
238+ this . _send = ws . send . bind ( ws ) ;
239+ return ws ;
240+ }
241+
242+ // establish the connection wrapper and start processing user commands
243+ _connect ( ) {
221244 return new Promise ( ( fulfill , reject ) => {
222- // create the WebSocket
245+ let wrapper ;
223246 try {
224- if ( this . secure ) {
225- this . webSocketUrl = this . webSocketUrl . replace ( / ^ w s : / i, 'wss:' ) ;
226- }
227- this . _ws = new WebSocket ( this . webSocketUrl , [ ] , {
228- followRedirects : true ,
229- ...this . connectOptions
230- } ) ;
247+ wrapper = this . process ? this . _createStdioWrapper ( ) : this . _createWebSocketWrapper ( ) ;
231248 } catch ( err ) {
232- // handles bad URLs
249+ // handle missing stdio streams, bad URLs...
233250 reject ( err ) ;
234251 return ;
235252 }
236253 // set up event handlers
237- this . _ws . on ( 'open' , ( ) => {
254+ wrapper . on ( 'open' , ( ) => {
238255 fulfill ( ) ;
239256 } ) ;
240- this . _ws . on ( 'message' , ( data ) => {
257+ wrapper . on ( 'message' , ( data ) => {
241258 const message = JSON . parse ( data ) ;
242259 this . _handleMessage ( message ) ;
243260 } ) ;
244- this . _ws . on ( 'close' , ( code ) => {
261+ wrapper . on ( 'close' , ( code ) => {
245262 this . _handleConnectionClose ( ) ;
246263 this . emit ( 'disconnect' ) ;
247264 } ) ;
248- this . _ws . on ( 'error' , ( err ) => {
265+ wrapper . on ( 'error' , ( err ) => {
249266 reject ( err ) ;
250267 } ) ;
251268 } ) ;
@@ -305,7 +322,7 @@ class Chrome extends EventEmitter {
305322 sessionId,
306323 params : params || { }
307324 } ;
308- this . _ws . send ( JSON . stringify ( message ) , ( err ) => {
325+ this . _send ( JSON . stringify ( message ) , ( err ) => {
309326 if ( err ) {
310327 // handle low-level WebSocket errors
311328 if ( typeof callback === 'function' ) {
0 commit comments