From 3e0e546d5a89bca60452703def7ede8c0c8d85ef Mon Sep 17 00:00:00 2001 From: Shuhei Takahashi Date: Sat, 16 Apr 2022 10:17:40 +0900 Subject: [PATCH 1/2] Fix line-oriented callbacks stdoutcb/stderrcb assume that an input string is a single line, but in fact it can contain multiple lines, or even be a part of a line. One of the consequence is that cocopa fails to parse compiler output when it contains long lines (#1275). This patch fixes the issue by introducing a buffer to accumulate received data before passing them to callbacks. Fixes #1275. --- src/arduino/arduino.ts | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/arduino/arduino.ts b/src/arduino/arduino.ts index 3de74779..391f6a51 100644 --- a/src/arduino/arduino.ts +++ b/src/arduino/arduino.ts @@ -746,7 +746,25 @@ export class ArduinoApp { } return ret; } - const stdoutcb = (line: string) => { + + // Wrap line-oriented callbacks to accept arbitrary chunks of data. + const wrapLineCallback = (callback: (line: string) => void) => { + let buffer = ""; + return (data: string) => { + buffer += data; + for (;;) { + const pos = buffer.indexOf(os.EOL); + if (pos < 0) { + break; + } + const line = buffer.substring(0, pos + os.EOL.length); + buffer = buffer.substring(pos + os.EOL.length); + callback(line); + } + }; + } + + const stdoutcb = wrapLineCallback((line: string) => { if (cocopa.callback) { cocopa.callback(line); } @@ -758,8 +776,8 @@ export class ArduinoApp { arduinoChannel.channel.append(line); } } - } - const stderrcb = (line: string) => { + }); + const stderrcb = wrapLineCallback((line: string) => { if (os.platform() === "win32") { line = line.trim(); if (line.length <= 0) { @@ -784,7 +802,7 @@ export class ArduinoApp { } } arduinoChannel.channel.append(line); - } + }); return await util.spawn( this._settings.commandPath, From 81ba0abe09704ec0b75ea913fe3b9bf5182331ef Mon Sep 17 00:00:00 2001 From: Ben McMorran Date: Fri, 29 Apr 2022 14:18:48 -0700 Subject: [PATCH 2/2] Avoid n^2 runtime on long lines --- src/arduino/arduino.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/arduino/arduino.ts b/src/arduino/arduino.ts index 30f8ee7c..a6135133 100644 --- a/src/arduino/arduino.ts +++ b/src/arduino/arduino.ts @@ -756,15 +756,18 @@ export class ArduinoApp { // Wrap line-oriented callbacks to accept arbitrary chunks of data. const wrapLineCallback = (callback: (line: string) => void) => { let buffer = ""; + let startIndex = 0; return (data: string) => { buffer += data; - for (;;) { - const pos = buffer.indexOf(os.EOL); + while (true) { + const pos = buffer.indexOf(os.EOL, startIndex); if (pos < 0) { + startIndex = buffer.length; break; } const line = buffer.substring(0, pos + os.EOL.length); buffer = buffer.substring(pos + os.EOL.length); + startIndex = 0; callback(line); } };