11
22import * as net from 'net' ;
33import { EventEmitter } from 'events' ;
4- import { parseString } from 'xml2js' ;
54import { Thread } from 'vscode-debugadapter' ;
65import * as iconv from 'iconv-lite' ;
6+ import { DOMParser } from 'xmldom' ;
77
8- export class InvalidMessageError extends Error {
9- public data : Buffer ;
10- constructor ( data : Buffer ) {
11- super ( 'Invalid message from XDebug: ' + data . toString ( 'ascii' ) ) ;
12- this . data = data ;
13- }
14- }
8+ const ENCODING = 'iso-8859-1' ;
159
16- export interface XMLNode {
17- /** The attributes of the XML Node */
18- attributes : {
19- [ attributeName : string ] : string ;
20- } ;
21- /** An array of child nodes */
22- childNodes ?: {
23- [ childNodeName : string ] : XMLNode [ ] ;
24- } ;
25- /** Text inside the XML tag */
26- content ?: string ;
10+ export interface InitResponse {
11+ fileUri : string ;
12+ protocolVersion : string ;
13+ language : string ;
14+ ideKey : string ;
2715}
2816
2917interface Command {
3018 name : string ;
3119 args ?: string ;
3220 data ?: string ;
33- resolveFn : ( response : XMLNode ) => any ;
21+ resolveFn : ( response : Document ) => any ;
3422 rejectFn : ( error ?: Error ) => any ;
3523}
3624
@@ -51,7 +39,7 @@ export class XDebugConnection extends EventEmitter {
5139 }
5240 private _socket : net . Socket ;
5341 private _transactionCounter = 0 ;
54- private _initPromise : Promise < XMLNode > ;
42+ private _initPromise : Promise < InitResponse > ;
5543
5644 /**
5745 * The currently pending command that has been sent to XDebug and is awaiting a response
@@ -71,13 +59,25 @@ export class XDebugConnection extends EventEmitter {
7159 this . _socket = socket ;
7260 this . _timeEstablished = new Date ( ) ;
7361 socket . on ( 'data' , ( data : Buffer ) => this . _handleResponse ( data ) ) ;
74- this . _initPromise = new Promise ( ( resolveFn , rejectFn ) => {
75- this . _pendingCommand = { name : null , rejectFn, resolveFn} ;
62+ this . _initPromise = new Promise < InitResponse > ( ( resolve , reject ) => {
63+ this . _pendingCommand = {
64+ name : null ,
65+ rejectFn : reject ,
66+ resolveFn : ( document : Document ) => {
67+ const documentElement = document . documentElement ;
68+ resolve ( {
69+ fileUri : documentElement . getAttribute ( 'fileuri' ) ,
70+ language : documentElement . getAttribute ( 'language' ) ,
71+ protocolVersion : documentElement . getAttribute ( 'protocolversion' ) ,
72+ ideKey : documentElement . getAttribute ( 'idekey' )
73+ } ) ;
74+ }
75+ } ;
7676 } ) ;
7777 console . log ( 'New XDebug Connection #' + this . _id ) ;
7878 }
7979
80- public waitForInitPacket ( ) : Promise < XMLNode > {
80+ public waitForInitPacket ( ) : Promise < Document > {
8181 return this . _initPromise ;
8282 }
8383
@@ -101,24 +101,20 @@ export class XDebugConnection extends EventEmitter {
101101 if ( firstNullByte === - 1 || secondNullByte === - 1 ) {
102102 throw new InvalidMessageError ( data ) ;
103103 }
104- const dataLength = parseInt ( data . toString ( 'ascii' , 0 , firstNullByte ) ) ;
105- const xmlData = data . slice ( firstNullByte + 1 , secondNullByte ) ;
106- const xml = iconv . decode ( xmlData , 'iso-8859-1' ) ;
107- parseString ( xml , { attrkey : 'attributes' , childkey : 'childNodes' , charkey : 'content' , explicitCharkey : true , explicitArray : true , explicitChildren : true , explicitRoot : false } , ( err ?: Error , result ?: XMLNode ) => {
108- //console.log('#' + this._connectionId + ' received packet from XDebug, packet length ' + dataLength, result);
109- //const transactionId = parseInt(result.attributes['transaction_id']);
110- if ( err ) {
111- command . rejectFn ( err ) ;
112- } else {
113- command . resolveFn ( result ) ;
114- }
115- if ( this . _queue . length > 0 ) {
116- const command = this . _queue . shift ( ) ;
117- this . _executeCommand ( command ) ;
118- }
119- } ) ;
104+ const dataLength = parseInt ( iconv . decode ( data . slice ( 0 , firstNullByte ) , ENCODING ) ) ;
105+ const xml = iconv . decode ( data . slice ( firstNullByte + 1 , secondNullByte ) , ENCODING ) ;
106+ const parser = new DOMParser ( ) ;
107+ const document = parser . parseFromString ( xml , 'application/xml' ) ;
108+ command . resolveFn ( document ) ;
109+ //console.log('#' + this._connectionId + ' received packet from XDebug, packet length ' + dataLength, result);
110+ //const transactionId = parseInt(result.attributes['transaction_id']);
120111 } catch ( err ) {
121112 command . rejectFn ( err ) ;
113+ } finally {
114+ if ( this . _queue . length > 0 ) {
115+ const command = this . _queue . shift ( ) ;
116+ this . _executeCommand ( command ) ;
117+ }
122118 }
123119 }
124120
@@ -153,7 +149,7 @@ export class XDebugConnection extends EventEmitter {
153149 commandString += ' -- ' + ( new Buffer ( command . data , 'utf8' ) ) . toString ( 'base64' ) ;
154150 }
155151 commandString += '\0' ;
156- const data = iconv . encode ( commandString , 'iso-8859-1' ) ;
152+ const data = iconv . encode ( commandString , ENCODING ) ;
157153 this . _socket . write ( data ) ;
158154 this . _pendingCommand = command ;
159155 }
0 commit comments