8000 fix: don't crash when `fs.readFile` returns promise from another real… · eslint/eslint@37eba48 · GitHub
[go: up one dir, main page]

Skip to content

Commit 37eba48

Browse files
authored
fix: don't crash when fs.readFile returns promise from another realm (#18416)
* fix: don't crash when `fs.readFile` returns promise from another realm Fixes #18407 * update test case title
1 parent 040700a commit 37eba48

File tree

3 files changed

+65
-16
lines changed

3 files changed

+65
-16
lines changed

lib/eslint/eslint.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
// Requirements
1010
//------------------------------------------------------------------------------
1111

12-
// Note: Node.js 12 does not support fs/promises.
13-
const fs = require("fs").promises;
12+
const fs = require("fs/promises");
1413
const { existsSync } = require("fs");
1514
const path = require("path");
1615
const findUp = require("find-up");

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
"@eslint/js": "9.2.0",
7373
"@humanwhocodes/config-array": "^0.13.0",
7474
"@humanwhocodes/module-importer": "^1.0.1",
75-
"@humanwhocodes/retry": "^0.2.3",
75+
"@humanwhocodes/retry": "^0.2.4",
7676
"@nodelib/fs.walk": "^1.2.8",
7777
"ajv": "^6.12.4",
7878
"chalk": "^4.0.0",

tests/lib/eslint/eslint.js

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
const assert = require("assert");
1414
const util = require("util");
1515
const fs = require("fs");
16-
const fsp = fs.promises;
16+
const fsp = require("fs/promises");
1717
const os = require("os");
1818
const path = require("path");
1919
const timers = require("node:timers/promises");
@@ -1057,6 +1057,61 @@ describe("ESLint", () => {
10571057
await assert.rejects(async () => await eslint.lintFiles(["lib/cli.js"]), /Expected object with parse\(\) or parseForESLint\(\) method/u);
10581058
});
10591059

1060+
// https://github.com/eslint/eslint/issues/18407
1061+
it("should work in case when `fsp.readFile()` returns an object that is not an instance of Promise from this realm", async () => {
1062+
1063+
/**
1064+
* Promise wrapper
1065+
*/
1066+
class PromiseLike {
1067+
constructor(promise) {
1068+
this.promise = promise;
1069+
}
1070+
then(...args) {
1071+
return new PromiseLike(this.promise.then(...args));
1072+
}
1073+
catch(...args) {
1074+
return new PromiseLike(this.promise.catch(...args));
1075+
}
1076+
finally(...args) {
1077+
return new PromiseLike(this.promise.finally(...args));
1078+
}
1079+
}
1080+
1081+
const spy = sinon.spy(
1082+
(...args) => new PromiseLike(fsp.readFile(...args))
1083+
);
1084+
1085+
const { ESLint: LocalESLint } = proxyquire("../../../lib/eslint/eslint", {
1086+
"fs/promises": {
1087+
readFile: spy,
1088+
"@noCallThru": false // allows calling other methods of `fs/promises`
1089+
}
1090+
});
1091+
1092+
const testDir = "tests/fixtures/simple-valid-project";
1093+
const expectedLintedFiles = [
1094+
path.resolve(testDir, "foo.js"),
1095+
path.resolve(testDir, "src", "foobar.js")
1096+
];
1097+
1098+
eslint = new LocalESLint({
1099+
cwd: originalDir,
1100+
overrideConfigFile: path.resolve(testDir, "eslint.config.js")
1101+
});
1102+
1103+
const results = await eslint.lintFiles([`${testDir}/**/foo*.js`]);
1104+
1105+
assert.strictEqual(results.length, expectedLintedFiles.length);
1106+
1107+
expectedLintedFiles.forEach((file, index) => {
1108+
assert(spy.calledWith(file), `Spy was not called with ${file}`);
1109+
assert.strictEqual(results[index].filePath, file);
1110+
assert.strictEqual(results[index].messages.length, 0);
1111+
assert.strictEqual(results[index].suppressedMessages.length, 0);
1112+
});
1113+
});
1114+
10601115
describe("Invalid inputs", () => {
10611116

10621117
[
@@ -5513,13 +5568,10 @@ describe("ESLint", () => {
55135568
});
55145569

55155570
it("should call fs.writeFile() for each result with output", async () => {
5516-
const fakeFS = {
5517-
writeFile: sinon.spy(() => Promise.resolve())
5518-
};
5519-
const spy = fakeFS.writeFile;
5571+
const spy = sinon.spy(() => Promise.resolve());
55205572
const { ESLint: localESLint } = proxyquire("../../../lib/eslint/eslint", {
5521-
fs: {
5522-
promises: fakeFS
5573+
"fs/promises": {
5574+
writeFile: spy
55235575
}
55245576
});
55255577

@@ -5542,15 +5594,13 @@ describe("ESLint", () => {
55425594
});
55435595

55445596
it("should call fs.writeFile() for each result with output and not at all for a result without output", async () => {
5545-
const fakeFS = {
5546-
writeFile: sinon.spy(() => Promise.resolve())
5547-
};
5548-
const spy = fakeFS.writeFile;
5597+
const spy = sinon.spy(() => Promise.resolve());
55495598
const { ESLint: localESLint } = proxyquire("../../../lib/eslint/eslint", {
5550-
fs: {
5551-
promises: fakeFS
5599+
"fs/promises": {
5600+
writeFile: spy
55525601
}
55535602
});
5603+
55545604
const results = [
55555605
{
55565606
filePath: path.resolve("foo.js"),

0 commit comments

Comments
 (0)
0