Skip to content

Commit 1b66767

Browse files
Simplify stderr buffers and EOL splitting
Co-authored-by: Robert <robertbrignull@github.com>
1 parent 5ddc3c1 commit 1b66767

File tree

1 file changed

+28
-26
lines changed
  • extensions/ql-vscode/src/codeql-cli

1 file changed

+28
-26
lines changed

extensions/ql-vscode/src/codeql-cli/cli.ts

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,8 @@ export class CodeQLCliServer implements Disposable {
362362
silent?: boolean,
363363
): Promise<string> {
364364
const stderrBuffers: Buffer[] = [];
365-
// The array of fragments of stderr of this line. To be used for logging.
366-
let currentLineStderrBuffers: Buffer[] = [];
365+
// The current buffer of stderr of a single line. To be used for logging.
366+
let currentLineStderrBuffer: Buffer = Buffer.alloc(0);
367367
if (this.commandInProcess) {
368368
throw new Error("runCodeQlCliInternal called while cli was running");
369369
}
@@ -423,28 +423,34 @@ export class CodeQLCliServer implements Disposable {
423423
stderrBuffers.push(newData);
424424

425425
if (!silent) {
426-
currentLineStderrBuffers.push(newData);
426+
currentLineStderrBuffer = Buffer.concat([
427+
currentLineStderrBuffer,
428+
newData,
429+
]);
427430

428431
// Print the stderr to the logger as it comes in. We need to ensure that
429432
// we don't split messages on the same line, so we buffer the stderr and
430433
// split it on EOLs.
431-
let currentLineBuffer = Buffer.concat(currentLineStderrBuffers);
432434
const eolBuffer = Buffer.from(EOL);
433-
if (currentLineBuffer.includes(eolBuffer)) {
434-
while (currentLineBuffer.includes(eolBuffer)) {
435-
const line = currentLineBuffer.subarray(
436-
0,
437-
currentLineBuffer.indexOf(eolBuffer),
438-
);
439-
440-
void this.logger.log(line.toString("utf-8"));
441-
442-
currentLineBuffer = currentLineBuffer.subarray(
443-
currentLineBuffer.indexOf(eolBuffer) + eolBuffer.length,
444-
);
445-
}
446435

447-
currentLineStderrBuffers = [currentLineBuffer];
436+
let hasCreatedSubarray = false;
437+
438+
let eolIndex;
439+
while (
440+
(eolIndex = currentLineStderrBuffer.indexOf(eolBuffer)) !== -1
441+
) {
442+
const line = currentLineStderrBuffer.subarray(0, eolIndex);
443+
void this.logger.log(line.toString("utf-8"));
444+
currentLineStderrBuffer = currentLineStderrBuffer.subarray(
445+
eolIndex + eolBuffer.length,
446+
);
447+
hasCreatedSubarray = true;
448+
}
449+
450+
// We have created a subarray, which means that the complete original buffer is now referenced
451+
// by the subarray. We need to create a new buffer to avoid memory leaks.
452+
if (hasCreatedSubarray) {
453+
currentLineStderrBuffer = Buffer.from(currentLineStderrBuffer);
448454
}
449455
}
450456
});
@@ -461,10 +467,8 @@ export class CodeQLCliServer implements Disposable {
461467
// Make sure we remove the terminator;
462468
const data = fullBuffer.toString("utf8", 0, fullBuffer.length - 1);
463469
if (!silent) {
464-
void this.logger.log(
465-
Buffer.concat(currentLineStderrBuffers).toString("utf8"),
466-
);
467-
currentLineStderrBuffers = [];
470+
void this.logger.log(currentLineStderrBuffer.toString("utf8"));
471+
currentLineStderrBuffer = Buffer.alloc(0);
468472
void this.logger.log("CLI command succeeded.");
469473
}
470474
return data;
@@ -484,10 +488,8 @@ export class CodeQLCliServer implements Disposable {
484488
cliError.stack += getErrorStack(err);
485489
throw cliError;
486490
} finally {
487-
if (!silent && currentLineStderrBuffers.length > 0) {
488-
void this.logger.log(
489-
Buffer.concat(currentLineStderrBuffers).toString("utf8"),
490-
);
491+
if (!silent && currentLineStderrBuffer.length > 0) {
492+
void this.logger.log(currentLineStderrBuffer.toString("utf8"));
491493
}
492494
// Remove the listeners we set up.
493495
process.stdout.removeAllListeners("data");

0 commit comments

Comments
 (0)