From 37f6e09589c44b455571a1f1876cec364b5e0fab Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Wed, 25 Jun 2025 07:27:33 +0100 Subject: [PATCH] Avoid closing files multiple times in `getInterpreter`(#17665) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: fisker Cheung --- changelog_unreleased/misc/17665.md | 8 ++++++++ src/utils/get-interpreter.js | 29 +++++++++++------------------ 2 files changed, 19 insertions(+), 18 deletions(-) create mode 100644 changelog_unreleased/misc/17665.md diff --git a/changelog_unreleased/misc/17665.md b/changelog_unreleased/misc/17665.md new file mode 100644 index 000000000..dc24692c9 --- /dev/null +++ b/changelog_unreleased/misc/17665.md @@ -0,0 +1,8 @@ +#### Avoid closing files multiple times (#17665 by @43081j) + +When reading a file to infer the interpreter from a shebang, we use the +`n-readlines` library to read the first line in order to get the shebang. + +This library closes files when it reaches EOF, and we later try close the same +files again. We now close files only if `n-readlines` did not already close +them. diff --git a/src/utils/get-interpreter.js b/src/utils/get-interpreter.js index 36aac44ae..f980abd66 100644 --- a/src/utils/get-interpreter.js +++ b/src/utils/get-interpreter.js @@ -1,4 +1,3 @@ -import fs from "node:fs"; import readlines from "n-readlines"; /** @@ -6,17 +5,17 @@ import readlines from "n-readlines"; * @returns {string | undefined} */ function getInterpreter(file) { - let fd; try { - fd = fs.openSync(file, "r"); - } catch { - /* c8 ignore next */ - return; - } + const liner = new readlines(file); + const firstLineBuffer = liner.next(); - try { - const liner = new readlines(fd); - const firstLine = liner.next().toString("utf8"); + if (firstLineBuffer === false) { + return; + } + + liner.close(); + + const firstLine = firstLineBuffer.toString("utf8"); // #!/bin/env node, #!/usr/bin/env node const m1 = firstLine.match(/^#!\/(?:usr\/)?bin\/env\s+(\S+)/u); @@ -29,14 +28,8 @@ function getInterpreter(file) { if (m2) { return m2[1]; } - } finally { - try { - // There are some weird cases where paths are missing, causing Jest - // failures. It's unclear what these correspond to in the real world. - fs.closeSync(fd); - } catch { - // noop - } + } catch { + // couldn't open the file } }