| 490 | } |
| 491 | |
| 492 | public handleData(data: string) { |
| 493 | this.logTraffic(`<== ${data}\n`); |
| 494 | interface JsonData { |
| 495 | id: string, |
| 496 | error: { |
| 497 | code: number, |
| 498 | message: string, |
| 499 | data: any, |
| 500 | }, |
| 501 | method: any, |
| 502 | result: VMResponse, |
| 503 | params: { |
| 504 | streamId: string, |
| 505 | event: VMEvent, |
| 506 | }, |
| 507 | } |
| 508 | const json: JsonData = JSON.parse(data); |
| 509 | const id = json.id; |
| 510 | const method = json.method; |
| 511 | const error = json.error; |
| 512 | const completer: PromiseCompleter<DebuggerResult> = this.completers[id]; |
| 513 | |
| 514 | if (completer) { |
| 515 | delete this.completers[id]; |
| 516 | |
| 517 | if (error) |
| 518 | completer.reject(new RPCError(error.code, error.message, error.data)); |
| 519 | else |
| 520 | completer.resolve(new DebuggerResult(json.result)); |
| 521 | } else if (method) { |
| 522 | const params = json.params; |
| 523 | const streamId = params.streamId; |
| 524 | |
| 525 | const callback = this.eventListeners[streamId]; |
| 526 | // Responses to requests (above) are processed by completing a promise |
| 527 | // which will be processed asynchronously. If we call callback here |
| 528 | // synchronously then it may trigger before a response that was received |
| 529 | // before it. The setTimeout forces it to go into the queue to be |
| 530 | // processed in order. |
| 531 | // TODO: Try to find a better way. |
| 532 | if (callback) |
| 533 | setTimeout(callback, 0, params.event); |
| 534 | } |
| 535 | } |
| 536 | |
| 537 | public onError(cb: (err: Error) => void) { |
| 538 | this.socket.on("error", cb); |