From 40a2c7bf6dd338f0444a1ff814e0a23d4895fde6 Mon Sep 17 00:00:00 2001 From: Barrie Treloar Date: Fri, 6 Sep 2019 09:24:30 +0930 Subject: [PATCH] Fix: use async reading of stdin in bin/eslint.js closes eslint/eslint#12212 --- bin/eslint.js | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/bin/eslint.js b/bin/eslint.js index 061e94767f0..80931451f45 100755 --- a/bin/eslint.js +++ b/bin/eslint.js @@ -60,13 +60,41 @@ process.once("uncaughtException", err => { if (useStdIn) { /* - * Note: `process.stdin.fd` is not used here due to https://github.com/nodejs/node/issues/7439. - * Accessing the `process.stdin` property seems to modify the behavior of file descriptor 0, resulting - * in an error when stdin is piped in asynchronously. + * Note: See + * - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin + * - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io + * - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html + * - https://github.com/nodejs/node/issues/7439 (historical) + * + * On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems + * to read 4096 bytes before blocking and never drains to read further data. + * + * The investigation on the Emacs thread indicates: + * + * > Emacs on MS-Windows uses pipes to communicate with subprocesses; a + * > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than + * > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for + * > the subprocess to read its end of the pipe, at which time Emacs will + * > write the rest of the stuff. + * + * Using the nodejs code example for reading from stdin. */ - const STDIN_FILE_DESCRIPTOR = 0; + const input = []; - process.exitCode = cli.execute(process.argv, fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")); + process.stdin.on("readable", () => { + let chunk; + + // Use a loop to make sure we read all available data. + while ((chunk = process.stdin.read()) !== null) { + input.push(chunk); + } + }); + + process.stdin.on("end", () => { + const contents = input.join(""); + + process.exitCode = cli.execute(process.argv, contents, "utf8"); + }); } else if (init) { const configInit = require("../lib/init/config-initializer");