@@ -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,8 +56,9 @@ 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 ;
61+ this . process = options . process ;
6062 // locals
6163 this . _notifier = notifier ;
6264 this . _callbacks = { } ;
@@ -101,26 +103,12 @@ class Chrome extends EventEmitter {
101103 }
102104
103105 close ( callback ) {
104- const closeWebSocket = ( callback ) => {
105- // don't close if it's already closed
106- if ( this . _ws . readyState === 3 ) {
107- callback ( ) ;
108- } else {
109- // don't notify on user-initiated shutdown ('disconnect' event)
110- this . _ws . removeAllListeners ( 'close' ) ;
111- this . _ws . once ( 'close' , ( ) => {
112- this . _ws . removeAllListeners ( ) ;
113- callback ( ) ;
114- } ) ;
115- this . _ws . close ( ) ;
116- }
117- } ;
118106 if ( typeof callback === 'function' ) {
119- closeWebSocket ( callback ) ;
107+ this . _close ( callback ) ;
120108 return undefined ;
121109 } else {
122110 return new Promise ( ( fulfill , reject ) => {
123- closeWebSocket ( fulfill ) ;
111+ this . _close ( fulfill ) ;
124112 } ) ;
125113 }
126114 }
@@ -135,20 +123,22 @@ class Chrome extends EventEmitter {
135123 alterPath : this . alterPath
136124 } ;
137125 try {
138- // fetch the WebSocket debugger URL
139- const url = await this . _fetchDebuggerURL ( options ) ;
140- // allow the user to alter the URL
141- const urlObject = parseUrl ( url ) ;
142- urlObject . pathname = options . alterPath ( urlObject . pathname ) ;
143- this . webSocketUrl = formatUrl ( urlObject ) ;
144- // update the connection parameters using the debugging URL
145- options . host = urlObject . hostname ;
146- options . port = urlObject . port || options . port ;
126+ if ( ! this . process ) {
127+ // fetch the WebSocket debugger URL
128+ const url = await this . _fetchDebuggerURL ( options ) ;
129+ // allow the user to alter the URL
130+ const urlObject = parseUrl ( url ) ;
131+ urlObject . pathname = options . alterPath ( urlObject . pathname ) ;
132+ this . webSocketUrl = formatUrl ( urlObject ) ;
133+ // update the connection parameters using the debugging URL
134+ options . host = urlObject . hostname ;
135+ options . port = urlObject . port || options . port ;
136+ }
147137 // fetch the protocol and prepare the API
148138 const protocol = await this . _fetchProtocol ( options ) ;
149139 api . prepare ( this , protocol ) ;
150- // finally connect to the WebSocket
151- await this . _connectToWebSocket ( ) ;
140+ // finally connect to the WebSocket or stdio
141+ await this . _connect ( ) ;
152142 // since the handler is executed synchronously, the emit() must be
153143 // performed in the next tick so that uncaught errors in the client code
154144 // are not intercepted by the Promise mechanism and therefore reported
@@ -211,32 +201,59 @@ class Chrome extends EventEmitter {
211201 }
212202 }
213203
214- // establish the WebSocket connection and start processing user commands
215- _connectToWebSocket ( ) {
204+ _createStdioWrapper ( ) {
205+ const stdio = new StdioWrapper ( this . process . stdio [ 3 ] , this . process . stdio [ 4 ] ) ;
206+ this . _close = stdio . close . bind ( stdio ) ;
207+ this . _send = stdio . send . bind ( stdio ) ;
208+ return stdio ;
209+ }
210+
211+ _createWebSocketWrapper ( ) {
212+ if ( this . secure ) {
213+ this . webSocketUrl = this . webSocketUrl . replace ( / ^ w s : / i, 'wss:' ) ;
214+ }
215+ const ws = new WebSocket ( this . webSocketUrl ) ;
216+ this . _close = ( callback ) => {
217+ // don't close if it's already closed
218+ if ( ws . readyState === 3 ) {
219+ callback ( ) ;
220+ } else {
221+ // don't notify on user-initiated shutdown ('disconnect' event)
222+ ws . removeAllListeners ( 'close' ) ;
223+ ws . once ( 'close' , ( ) => {
224+ ws . removeAllListeners ( ) ;
225+ callback ( ) ;
226+ } ) ;
227+ ws . close ( ) ;
228+ }
229+ } ;
230+ this . _send = ws . send . bind ( ws ) ;
231+ return ws ;
232+ }
233+
234+ // establish the connection wrapper and start processing user commands
235+ _connect ( ) {
216236 return new Promise ( ( fulfill , reject ) => {
217- // create the WebSocket
237+ let wrapper ;
218238 try {
219- if ( this . secure ) {
220- this . webSocketUrl = this . webSocketUrl . replace ( / ^ w s : / i, 'wss:' ) ;
221- }
222- this . _ws = new WebSocket ( this . webSocketUrl ) ;
239+ wrapper = this . process ? this . _createStdioWrapper ( ) : this . _createWebSocketWrapper ( ) ;
223240 } catch ( err ) {
224- // handles bad URLs
241+ // handle missing stdio streams, bad URLs...
225242 reject ( err ) ;
226243 return ;
227244 }
228245 // set up event handlers
229- this . _ws . on ( 'open' , ( ) => {
246+ wrapper . on ( 'open' , ( ) => {
230247 fulfill ( ) ;
231248 } ) ;
232- this . _ws . on ( 'message' , ( data ) => {
249+ wrapper . on ( 'message' , ( data ) => {
233250 const message = JSON . parse ( data ) ;
234251 this . _handleMessage ( message ) ;
235252 } ) ;
236- this . _ws . on ( 'close' , ( code ) => {
253+ wrapper . on ( 'close' , ( code ) => {
237254 this . emit ( 'disconnect' ) ;
238255 } ) ;
239- this . _ws . on ( 'error' , ( err ) => {
256+ wrapper . on ( 'error' , ( err ) => {
240257 reject ( err ) ;
241258 } ) ;
242259 } ) ;
@@ -278,7 +295,7 @@ class Chrome extends EventEmitter {
278295 id, method,
279296 params : params || { }
280297 } ;
281- this . _ws . send ( JSON . stringify ( message ) , ( err ) => {
298+ this . _send ( JSON . stringify ( message ) , ( err ) => {
282299 if ( err ) {
283300 // handle low-level WebSocket errors
284301 if ( typeof callback === 'function' ) {
0 commit comments