diff --git a/packages/@jsii/dotnet-runtime/src/Amazon.JSII.Runtime/Services/INodeProcess.cs b/packages/@jsii/dotnet-runtime/src/Amazon.JSII.Runtime/Services/INodeProcess.cs index 49baed7bfc..344cab0303 100644 --- a/packages/@jsii/dotnet-runtime/src/Amazon.JSII.Runtime/Services/INodeProcess.cs +++ b/packages/@jsii/dotnet-runtime/src/Amazon.JSII.Runtime/Services/INodeProcess.cs @@ -11,4 +11,4 @@ internal interface INodeProcess : IDisposable TextReader StandardError { get; } } -} \ No newline at end of file +} diff --git a/packages/@jsii/dotnet-runtime/src/Amazon.JSII.Runtime/Services/NodeProcess.cs b/packages/@jsii/dotnet-runtime/src/Amazon.JSII.Runtime/Services/NodeProcess.cs index ee60e92b91..71f4367992 100644 --- a/packages/@jsii/dotnet-runtime/src/Amazon.JSII.Runtime/Services/NodeProcess.cs +++ b/packages/@jsii/dotnet-runtime/src/Amazon.JSII.Runtime/Services/NodeProcess.cs @@ -4,6 +4,7 @@ using System.IO; using System.Reflection; using System.Runtime.Versioning; +using System.Text; using Microsoft.Extensions.Logging; namespace Amazon.JSII.Runtime.Services @@ -26,15 +27,19 @@ public NodeProcess(IJsiiRuntimeProvider jsiiRuntimeProvider, ILoggerFactory logg if (string.IsNullOrWhiteSpace(runtimePath)) runtimePath = jsiiRuntimeProvider.JsiiRuntimePath; + var utf8 = new UTF8Encoding(false /* no BOM */); _process = new Process { StartInfo = new ProcessStartInfo { FileName = "node", - Arguments = "--max-old-space-size=4096 " + runtimePath, + Arguments = $"--max-old-space-size=4096 {runtimePath}", RedirectStandardInput = true, + StandardInputEncoding = utf8, RedirectStandardOutput = true, - RedirectStandardError = true + StandardOutputEncoding = utf8, + RedirectStandardError = true, + StandardErrorEncoding = utf8 } }; diff --git a/packages/@jsii/runtime/lib/sync-stdio.ts b/packages/@jsii/runtime/lib/sync-stdio.ts index 422eb5958e..0bfd15c5a7 100644 --- a/packages/@jsii/runtime/lib/sync-stdio.ts +++ b/packages/@jsii/runtime/lib/sync-stdio.ts @@ -5,9 +5,10 @@ const STDOUT_FD = 1; const STDERR_FD = 2; const INPUT_BUFFER_SIZE = 1024 * 1024; // not related to max line length +const EMPTY_BUFFER = Buffer.alloc(0); + export class SyncStdio { - private readonly inputQueue = new Array(); - private currentLine = ''; + private bufferedData = EMPTY_BUFFER; public writeErrorLine(line: string) { this.writeBuffer(Buffer.from(`${line}\n`), STDERR_FD); @@ -19,7 +20,7 @@ export class SyncStdio { public readLine(): string | undefined { const buff = Buffer.alloc(INPUT_BUFFER_SIZE); - while (this.inputQueue.length === 0) { + while (!this.bufferedData.includes('\n', 0, 'utf-8')) { try { const read = fs.readSync(STDIN_FD, buff, 0, buff.length, null); @@ -27,16 +28,8 @@ export class SyncStdio { return undefined; } - const str = buff.slice(0, read).toString(); - - for (const ch of str) { - if (ch === '\n') { - this.inputQueue.push(this.currentLine); - this.currentLine = ''; - } else { - this.currentLine += ch; - } - } + const newData = buff.slice(0, read); + this.bufferedData = Buffer.concat([this.bufferedData, newData]); } catch (e) { // HACK: node may set O_NONBLOCK on it's STDIN depending on what kind of input it is made // of (see https://github.com/nodejs/help/issues/2663). When STDIN has O_NONBLOCK, calls may @@ -52,7 +45,10 @@ export class SyncStdio { } } - const next = this.inputQueue.shift(); + const newLinePos = this.bufferedData.indexOf('\n', 0, 'utf-8'); + const next = this.bufferedData.slice(0, newLinePos).toString('utf-8'); + this.bufferedData = this.bufferedData.slice(newLinePos + 1); + return next; }