Skip to content

Commit 96d7714

Browse files
committed
Refactor XDebug command queue to check transaction IDs
1 parent dfa7629 commit 96d7714

File tree

1 file changed

+32
-25
lines changed

1 file changed

+32
-25
lines changed

src/xdebugConnection.ts

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -394,16 +394,28 @@ export class Connection extends DbgpConnection {
394394

395395
/** a counter for unique connection IDs */
396396
private static _connectionCounter = 1;
397+
397398
/** unique connection ID */
398399
public id: number;
400+
399401
/** the time this connection was established */
400402
public timeEstablished: Date;
401-
/** a counter for unique transaction IDs */
402-
private _transactionCounter = 0;
403+
404+
/** a counter for unique transaction IDs. */
405+
private _transactionCounter = 1;
406+
403407
/** the promise that gets resolved once we receive the init packet */
404408
private _initPromise: Promise<InitPacket>;
405-
/** the currently pending command that has been sent to XDebug and is awaiting a response or null */
406-
private _pendingCommand: Command;
409+
410+
/** resolves the init promise */
411+
private _initPromiseResolveFn: (initPackt: InitPacket) => any;
412+
413+
/**
414+
* a map from transaction IDs to pending commands that have been sent to XDebug and are awaiting a response.
415+
* This should in theory only contain max one element at any time.
416+
*/
417+
private _pendingCommands = new Map<number, Command>();
418+
407419
/**
408420
* XDebug does NOT support async communication.
409421
* This means before sending a new command, we have to wait until we get a response for the previous.
@@ -417,13 +429,7 @@ export class Connection extends DbgpConnection {
417429
this.id = Connection._connectionCounter++;
418430
this.timeEstablished = new Date();
419431
this._initPromise = new Promise<InitPacket>((resolve, reject) => {
420-
this._pendingCommand = {
421-
name: null,
422-
rejectFn: reject,
423-
resolveFn: (document: XMLDocument) => {
424-
resolve(new InitPacket(document, this));
425-
}
426-
};
432+
this._initPromiseResolveFn = resolve;
427433
});
428434
console.log('New XDebug Connection #' + this.id);
429435
}
@@ -438,18 +444,19 @@ export class Connection extends DbgpConnection {
438444
* After that, the next command in the queue is executed (if there is any).
439445
*/
440446
protected handleResponse(response: XMLDocument): void {
441-
// XDebug sent us a packet
442-
// Anatomy: [data length] [NULL] [xml] [NULL]
443-
const command = this._pendingCommand;
444-
if (!command) {
445-
console.error('XDebug sent a response, but there was no pending command');
446-
return;
447-
}
448-
this._pendingCommand = null;
449-
command.resolveFn(response);
450-
if (this._commandQueue.length > 0) {
451-
const command = this._commandQueue.shift();
452-
this._executeCommand(command);
447+
if (response.documentElement.nodeName === 'init') {
448+
this._initPromiseResolveFn(new InitPacket(response, this));
449+
} else {
450+
const transactionId = parseInt(response.documentElement.getAttribute('transaction_id'));
451+
if (this._pendingCommands.has(transactionId)) {
452+
const command = this._pendingCommands.get(transactionId);
453+
this._pendingCommands.delete(transactionId);
454+
command.resolveFn(response);
455+
}
456+
if (this._commandQueue.length > 0) {
457+
const command = this._commandQueue.shift();
458+
this._executeCommand(command);
459+
}
453460
}
454461
}
455462

@@ -461,7 +468,7 @@ export class Connection extends DbgpConnection {
461468
private _enqueueCommand(name: string, args?: string, data?: string): Promise<XMLDocument> {
462469
return new Promise((resolveFn, rejectFn) => {
463470
const command = {name, args, data, resolveFn, rejectFn};
464-
if (this._commandQueue.length === 0 && !this._pendingCommand) {
471+
if (this._commandQueue.length === 0 && this._pendingCommands.size === 0) {
465472
this._executeCommand(command);
466473
} else {
467474
this._commandQueue.push(command);
@@ -486,7 +493,7 @@ export class Connection extends DbgpConnection {
486493
commandString += '\0';
487494
const data = iconv.encode(commandString, ENCODING);
488495
this.write(data);
489-
this._pendingCommand = command;
496+
this._pendingCommands.set(transactionId, command);
490497
}
491498

492499
// ------------------------ status --------------------------------------------

0 commit comments

Comments
 (0)