async _startSession(info, frontend) { const ws = new WebSocket(info.inspectorUrl); const openPromise = new Promise(resolve => ws.once('open', () => resolve(DebugState.WS_OPEN))); const errorPromise = new Promise(resolve => ws.once('error', () => resolve(DebugState.WS_ERROR))); const closePromise = new Promise(resolve => ws.once('close', () => resolve(DebugState.WS_CLOSE))); let state = await Promise.race([openPromise, errorPromise, closePromise, this._disconnectPromise]); if (state === DebugState.WS_OPEN) { this._connected.add(info.id); const channel = new Channel(ws); state = await Promise.race([frontend.detected(info, rpc.handle(channel)), this._disconnectPromise]); return async() => { if (state !== DebugState.PROCESS_DISCONNECT) state = await Promise.race([closePromise, errorPromise, this._disconnectPromise]); channel.dispose(); this._connected.delete(info.id); if (state !== DebugState.PROCESS_DISCONNECT) frontend.disconnected(info.id); else ws.send(CALL_EXIT_MESSAGE, () => ws.close()); }; } else { return async function() {}; } }
close() { return new Promise(resolve => { this.ws.close(); this.ws.once("close", resolve); }); }
/** * Closes the active connection. If there is none, rejects with a promise. * Resolves on success * * @param {number} code - passed to ws * @param {string} reason - passed to ws * @returns {Promise} p */ async close (code, reason) { if (!this._isOpen || this._ws === null) { throw new Error('not open') } debug('disconnecting...') return new Promise((resolve) => { this._ws.once('close', () => { this._isOpen = false this._ws = null debug('disconnected') resolve() }) if (!this._isClosing) { this._isClosing = true this._ws.close(code, reason) } }) }
ping() { return new Promise((resolve, reject) => { try { this.socket.ping(); let pong = false; this.socket.once('pong', () => { pong = true; resolve(); }); setTimeout(() => { if (!pong) { reject(new Error('timeout')); } }, 5000); } catch (err) { reject(err); } }); }