Skip to content

Commit 0e0f836

Browse files
authored
Merge pull request #254 from webpack/feat-lstat-and-lstatSync
feat: `lstat` and `lstatSync`
2 parents 4a3cc76 + 823cedf commit 0e0f836

File tree

5 files changed

+145
-24
lines changed

5 files changed

+145
-24
lines changed

lib/CachedInputFileSystem.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ class CacheBackend {
141141
/** @type {number | undefined} */
142142
this._nextDecay = undefined;
143143

144-
this.provide = this.provide.bind(this);
145-
this.provideSync = this.provideSync.bind(this);
144+
this.provide = provider ? this.provide.bind(this) : null;
145+
this.provideSync = syncProvider ? this.provideSync.bind(this) : null;
146146
}
147147

148148
provide(path, options, callback) {
@@ -371,6 +371,17 @@ module.exports = class CachedInputFileSystem {
371371
constructor(fileSystem, duration) {
372372
this.fileSystem = fileSystem;
373373

374+
this._lstatBackend = createBackend(
375+
duration,
376+
this.fileSystem.lstat,
377+
this.fileSystem.lstatSync,
378+
this.fileSystem
379+
);
380+
const lstat = this._lstatBackend.provide;
381+
this.lstat = /** @type {FileSystem["lstat"]} */ (lstat);
382+
const lstatSync = this._lstatBackend.provideSync;
383+
this.lstatSync = /** @type {SyncFileSystem["lstatSync"]} */ (lstatSync);
384+
374385
this._statBackend = createBackend(
375386
duration,
376387
this.fileSystem.stat,
@@ -451,6 +462,7 @@ module.exports = class CachedInputFileSystem {
451462

452463
purge(what) {
453464
this._statBackend.purge(what);
465+
this._lstatBackend.purge(what);
454466
this._readdirBackend.purgeParent(what);
455467
this._readFileBackend.purge(what);
456468
this._readlinkBackend.purge(what);

lib/Resolver.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const {
5151
* @property {(function(string, FileSystemCallback<(Buffer | string)[] | FileSystemDirent[]>): void) & function(string, object, FileSystemCallback<(Buffer | string)[] | FileSystemDirent[]>): void} readdir
5252
* @property {((function(string, FileSystemCallback<object>): void) & function(string, object, FileSystemCallback<object>): void)=} readJson
5353
* @property {(function(string, FileSystemCallback<Buffer | string>): void) & function(string, object, FileSystemCallback<Buffer | string>): void} readlink
54+
* @property {(function(string, FileSystemCallback<FileSystemStats>): void) & function(string, object, FileSystemCallback<Buffer | string>): void=} lstat
5455
* @property {(function(string, FileSystemCallback<FileSystemStats>): void) & function(string, object, FileSystemCallback<Buffer | string>): void} stat
5556
*/
5657

@@ -60,6 +61,7 @@ const {
6061
* @property {function(string, object=): (Buffer | string)[] | FileSystemDirent[]} readdirSync
6162
* @property {(function(string, object=): object)=} readJsonSync
6263
* @property {function(string, object=): Buffer | string} readlinkSync
64+
* @property {function(string, object=): FileSystemStats=} lstatSync
6365
* @property {function(string, object=): FileSystemStats} statSync
6466
*/
6567

lib/SyncAsyncFileSystemDecorator.js

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,65 +14,82 @@
1414
*/
1515
function SyncAsyncFileSystemDecorator(fs) {
1616
this.fs = fs;
17-
this.stat = (arg, callback) => {
17+
18+
this.lstat = undefined;
19+
this.lstatSync = undefined;
20+
const lstatSync = fs.lstatSync;
21+
if (lstatSync) {
22+
this.lstat = (arg, options, callback) => {
23+
let result;
24+
try {
25+
result = lstatSync.call(fs, arg);
26+
} catch (e) {
27+
return (callback || options)(e);
28+
}
29+
(callback || options)(null, result);
30+
};
31+
this.lstatSync = (arg, options) => lstatSync.call(fs, arg, options);
32+
}
33+
34+
this.stat = (arg, options, callback) => {
1835
let result;
1936
try {
20-
result = fs.statSync(arg);
37+
result = fs.statSync(arg, options);
2138
} catch (e) {
22-
return callback(e);
39+
return (callback || options)(e);
2340
}
24-
callback(null, result);
41+
(callback || options)(null, result);
2542
};
26-
this.statSync = arg => fs.statSync(arg);
43+
this.statSync = (arg, options) => fs.statSync(arg, options);
2744

28-
this.readdir = (arg, callback) => {
45+
this.readdir = (arg, options, callback) => {
2946
let result;
3047
try {
3148
result = fs.readdirSync(arg);
3249
} catch (e) {
33-
return callback(e);
50+
return (callback || options)(e);
3451
}
35-
callback(null, result);
52+
(callback || options)(null, result);
3653
};
37-
this.readdirSync = arg => fs.readdirSync(arg);
54+
this.readdirSync = (arg, options) => fs.readdirSync(arg, options);
3855

39-
this.readFile = (arg, callback) => {
56+
this.readFile = (arg, options, callback) => {
4057
let result;
4158
try {
4259
result = fs.readFileSync(arg);
4360
} catch (e) {
44-
return callback(e);
61+
return (callback || options)(e);
4562
}
46-
callback(null, result);
63+
(callback || options)(null, result);
4764
};
48-
this.readFileSync = arg => fs.readFileSync(arg);
65+
this.readFileSync = (arg, options) => fs.readFileSync(arg, options);
4966

50-
this.readlink = (arg, callback) => {
67+
this.readlink = (arg, options, callback) => {
5168
let result;
5269
try {
5370
result = fs.readlinkSync(arg);
5471
} catch (e) {
55-
return callback(e);
72+
return (callback || options)(e);
5673
}
57-
callback(null, result);
74+
(callback || options)(null, result);
5875
};
59-
this.readlinkSync = arg => fs.readlinkSync(arg);
76+
this.readlinkSync = (arg, options) => fs.readlinkSync(arg, options);
6077

6178
this.readJson = undefined;
6279
this.readJsonSync = undefined;
6380
const readJsonSync = fs.readJsonSync;
6481
if (readJsonSync) {
65-
this.readJson = (arg, callback) => {
82+
this.readJson = (arg, options, callback) => {
6683
let result;
6784
try {
6885
result = readJsonSync.call(fs, arg);
6986
} catch (e) {
70-
return callback(e);
87+
return (callback || options)(e);
7188
}
72-
callback(null, result);
89+
(callback || options)(null, result);
7390
};
7491

75-
this.readJsonSync = arg => readJsonSync.call(fs, arg);
92+
this.readJsonSync = (arg, options) => readJsonSync.call(fs, arg, options);
7693
}
7794
}
7895
module.exports = SyncAsyncFileSystemDecorator;

test/CachedInputFileSystem.js

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ var should = require("should");
22

33
var { CachedInputFileSystem } = require("../");
44

5-
describe("CachedInputFileSystem OperationMergerBackend", function () {
5+
describe("CachedInputFileSystem OperationMergerBackend ('stat' and 'statSync')", function () {
66
this.timeout(3000);
77
var fs;
88

@@ -83,6 +83,87 @@ describe("CachedInputFileSystem OperationMergerBackend", function () {
8383
});
8484
});
8585

86+
describe("CachedInputFileSystem OperationMergerBackend ('lstat' and 'lstatSync')", function () {
87+
this.timeout(3000);
88+
var fs;
89+
90+
beforeEach(function () {
91+
fs = new CachedInputFileSystem(
92+
{
93+
lstat: function (path, options, callback) {
94+
if (!callback) {
95+
callback = options;
96+
options = undefined;
97+
}
98+
setTimeout(
99+
() =>
100+
callback(null, {
101+
path,
102+
options
103+
}),
104+
100
105+
);
106+
},
107+
lstatSync: function (path, options) {
108+
return {
109+
path,
110+
options
111+
};
112+
}
113+
},
114+
0
115+
);
116+
});
117+
afterEach(function () {
118+
fs.purge();
119+
});
120+
121+
it("should join accesses", function (done) {
122+
fs.lstat("a", function (err, result) {
123+
should.exist(result);
124+
result.a = true;
125+
});
126+
fs.lstat("a", function (err, result) {
127+
should.exist(result);
128+
should.exist(result.a);
129+
done();
130+
});
131+
});
132+
133+
it("should not join accesses with options", function (done) {
134+
fs.lstat("a", function (err, result) {
135+
should.exist(result);
136+
result.a = true;
137+
result.path.should.be.eql("a");
138+
should.not.exist(result.options);
139+
});
140+
fs.lstat("a", { options: true }, function (err, result) {
141+
should.exist(result);
142+
should.not.exist(result.a);
143+
result.path.should.be.eql("a");
144+
result.options.should.eql({ options: true });
145+
done();
146+
});
147+
});
148+
149+
it("should not cache accesses", function (done) {
150+
fs.lstat("a", function (err, result) {
151+
result.a = true;
152+
fs.lstat("a", function (err, result) {
153+
should.not.exist(result.a);
154+
done();
155+
});
156+
});
157+
});
158+
159+
it("should not cache sync accesses", function () {
160+
const result = fs.lstatSync("a");
161+
result.a = true;
162+
const result2 = fs.lstatSync("a");
163+
should.not.exist(result2.a);
164+
});
165+
});
166+
86167
describe("CachedInputFileSystem CacheBackend", function () {
87168
this.timeout(3000);
88169
var fs;

types.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ declare interface BaseResolveRequest {
1818
declare class CachedInputFileSystem {
1919
constructor(fileSystem?: any, duration?: any);
2020
fileSystem: any;
21+
lstat?: {
22+
(arg0: string, arg1: FileSystemCallback<FileSystemStats>): void;
23+
(arg0: string, arg1: any, arg2: FileSystemCallback<string | Buffer>): void;
24+
};
25+
lstatSync?: (arg0: string, arg1?: any) => FileSystemStats;
2126
stat: {
2227
(arg0: string, arg1: FileSystemCallback<FileSystemStats>): void;
2328
(arg0: string, arg1: any, arg2: FileSystemCallback<string | Buffer>): void;
@@ -85,6 +90,10 @@ declare interface FileSystem {
8590
(arg0: string, arg1: FileSystemCallback<string | Buffer>): void;
8691
(arg0: string, arg1: any, arg2: FileSystemCallback<string | Buffer>): void;
8792
};
93+
lstat?: {
94+
(arg0: string, arg1: FileSystemCallback<FileSystemStats>): void;
95+
(arg0: string, arg1: any, arg2: FileSystemCallback<string | Buffer>): void;
96+
};
8897
stat: {
8998
(arg0: string, arg1: FileSystemCallback<FileSystemStats>): void;
9099
(arg0: string, arg1: any, arg2: FileSystemCallback<string | Buffer>): void;

0 commit comments

Comments
 (0)