@@ -20,19 +20,19 @@ const Rejected = 2;
2020type PendingRecord = { |
2121 status : 0 ,
2222 value : Wakeable ,
23- cache : Array < mixed > ,
23+ cache : null ,
2424| } ;
2525
2626type ResolvedRecord < T > = { |
2727 status : 1 ,
2828 value : T ,
29- cache : Array < mixed > ,
29+ cache : null | Array < mixed > ,
3030| } ;
3131
3232type RejectedRecord = { |
3333 status : 2 ,
3434 value : mixed ,
35- cache : Array < mixed > ,
35+ cache : null ,
3636| } ;
3737
3838type Record < T > = PendingRecord | ResolvedRecord < T > | RejectedRecord ;
@@ -41,7 +41,7 @@ function createRecordFromThenable<T>(thenable: Thenable<T>): Record<T> {
4141 const record : Record < T > = {
4242 status : Pending ,
4343 value : thenable ,
44- cache : [ ] ,
44+ cache : null ,
4545 } ;
4646 thenable . then (
4747 value => {
@@ -62,9 +62,10 @@ function createRecordFromThenable<T>(thenable: Thenable<T>): Record<T> {
6262 return record ;
6363}
6464
65- function readRecordValue < T > (record: Record< T > ): T {
65+ function readRecord < T > (record: Record< T > ): ResolvedRecord < T > {
6666 if ( record . status === Resolved ) {
67- return record . value ;
67+ // This is just a type refinement.
68+ return record ;
6869 } else {
6970 throw record . value ;
7071 }
@@ -91,7 +92,122 @@ function checkPathInDev(path: string) {
9192 }
9293}
9394
94- function createReadFileCache ( ) : Map < string , Record < Buffer > > {
95+ function createAccessMap ( ) : Map < string , Array < number | Record < void > >> {
96+ return new Map ( ) ;
97+ }
98+
99+ export function access(path: string, mode?: number): void {
100+ checkPathInDev ( path ) ;
101+ if ( mode == null ) {
102+ mode = 0 ; // fs.constants.F_OK
103+ }
104+ const map = unstable_getCacheForType(createAccessMap);
105+ let accessCache = map.get(path);
106+ if (!accessCache) {
107+ accessCache = [ ] ;
108+ map . set ( path , accessCache ) ;
109+ }
110+ let record;
111+ for (let i = 0; i < accessCache . length ; i += 2 ) {
112+ const cachedMode : number = ( accessCache [ i ] : any ) ;
113+ if ( mode = = = cachedMode ) {
114+ const cachedRecord : Record < void > = (accessCache[i + 1]: any);
115+ record = cachedRecord;
116+ break;
117+ }
118+ }
119+ if ( ! record ) {
120+ const thenable = fs . access ( path , mode ) ;
121+ record = createRecordFromThenable ( thenable ) ;
122+ accessCache . push ( mode , record ) ;
123+ }
124+ readRecord(record); // No return value.
125+ }
126+
127+ function createLstatMap ( ) : Map < string , Array < boolean | Record < mixed > >> {
128+ return new Map ( ) ;
129+ }
130+
131+ export function lstat(path: string, options?: { bigint ? : boolean } ): mixed {
132+ checkPathInDev ( path ) ;
133+ let bigint = false ;
134+ if ( options && options . bigint ) {
135+ bigint = true ;
136+ }
137+ const map = unstable_getCacheForType ( createLstatMap ) ;
138+ let lstatCache = map . get ( path ) ;
139+ if ( ! lstatCache ) {
140+ lstatCache = [ ] ;
141+ map . set ( path , lstatCache ) ;
142+ }
143+ let record ;
144+ for ( let i = 0 ; i < lstatCache . length ; i += 2 ) {
145+ const cachedBigint : boolean = ( lstatCache [ i ] : any ) ;
146+ if ( bigint === cachedBigint ) {
147+ const cachedRecord : Record < void > = ( lstatCache [ i + 1 ] : any ) ;
148+ record = cachedRecord ;
149+ break ;
150+ }
151+ }
152+ if ( ! record ) {
153+ const thenable = fs . lstat ( path , { bigint} ) ;
154+ record = createRecordFromThenable ( thenable ) ;
155+ lstatCache . push ( bigint , record ) ;
156+ }
157+ const stats = readRecord ( record ) . value ;
158+ return stats ;
159+ }
160+
161+ function createReaddirMap(): Map<
162+ string ,
163+ Array < string | boolean | Record < mixed > > ,
164+ > {
165+ return new Map ( ) ;
166+ }
167+
168+ export function readdir(
169+ path: string,
170+ options?: string | { encoding ? : string , withFileTypes ? : boolean } ,
171+ ): mixed {
172+ checkPathInDev ( path ) ;
173+ let encoding = 'utf8' ;
174+ let withFileTypes = false ;
175+ if ( typeof options === 'string' ) {
176+ encoding = options ;
177+ } else if ( options != null ) {
178+ if ( options . encoding ) {
179+ encoding = options . encoding ;
180+ }
181+ if ( options . withFileTypes ) {
182+ withFileTypes = true ;
183+ }
184+ }
185+ const map = unstable_getCacheForType(createReaddirMap);
186+ let readdirCache = map.get(path);
187+ if (!readdirCache) {
188+ readdirCache = [ ] ;
189+ map . set ( path , readdirCache ) ;
190+ }
191+ let record;
192+ for (let i = 0; i < readdirCache . length ; i += 3 ) {
193+ const cachedEncoding : string = ( readdirCache [ i ] : any ) ;
194+ const cachedWithFileTypes : boolean = ( readdirCache [ i + 1 ] : any ) ;
195+ if ( encoding = = = cachedEncoding && withFileTypes = = = cachedWithFileTypes ) {
196+ const cachedRecord : Record < void > = (readdirCache[i + 2]: any);
197+ record = cachedRecord;
198+ break;
199+ }
200+ }
201+ if ( ! record ) {
202+ const thenable = fs . readdir ( path , { encoding, withFileTypes} ) ;
203+ record = createRecordFromThenable ( thenable ) ;
204+ readdirCache . push ( encoding , withFileTypes , record ) ;
205+ }
206+ const files = readRecord(record).value;
207+ return files;
208+ }
209+
210+ function createReadFileMap ( ) : Map < string , Record < Buffer > > {
95211 return new Map ( ) ;
96212}
97213
@@ -106,15 +222,16 @@ export function readFile(
106222 signal ? : mixed , // We'll have our own signal
107223 } ,
108224): string | Buffer {
109- const map = unstable_getCacheForType ( createReadFileCache ) ;
110225 checkPathInDev ( path ) ;
226+ const map = unstable_getCacheForType ( createReadFileMap ) ;
111227 let record = map . get ( path ) ;
112228 if ( ! record ) {
113229 const thenable = fs . readFile ( path ) ;
114230 record = createRecordFromThenable ( thenable ) ;
115231 map . set ( path , record ) ;
116232 }
117- const buffer : Buffer = readRecordValue ( record ) ;
233+ const resolvedRecord = readRecord ( record ) ;
234+ const buffer : Buffer = resolvedRecord . value ;
118235 if ( ! options ) {
119236 return buffer ;
120237 }
@@ -136,7 +253,7 @@ export function readFile(
136253 if ( typeof encoding !== 'string' ) {
137254 return buffer ;
138255 }
139- const textCache = record . cache ;
256+ const textCache = resolvedRecord . cache || ( resolvedRecord . cache = [ ] ) ;
140257 for ( let i = 0 ; i < textCache . length ; i += 2 ) {
141258 if ( textCache [ i ] === encoding ) {
142259 return ( textCache [ i + 1 ] : any ) ;
@@ -146,3 +263,119 @@ export function readFile(
146263 textCache . push ( encoding , text ) ;
147264 return text ;
148265}
266+
267+ function createReadlinkMap(): Map< string , Array < string | Record < mixed > >> {
268+ return new Map ( ) ;
269+ }
270+
271+ export function readlink(
272+ path: string,
273+ options?: string | { encoding ? : string } ,
274+ ): mixed {
275+ checkPathInDev ( path ) ;
276+ let encoding = 'utf8' ;
277+ if ( typeof options === 'string' ) {
278+ encoding = options ;
279+ } else if ( options != null ) {
280+ if ( options . encoding ) {
281+ encoding = options . encoding ;
282+ }
283+ }
284+ const map = unstable_getCacheForType ( createReadlinkMap ) ;
285+ let readlinkCache = map . get ( path ) ;
286+ if ( ! readlinkCache ) {
287+ readlinkCache = [ ] ;
288+ map . set ( path , readlinkCache ) ;
289+ }
290+ let record ;
291+ for ( let i = 0 ; i < readlinkCache . length ; i += 2 ) {
292+ const cachedEncoding : string = ( readlinkCache [ i ] : any ) ;
293+ if ( encoding === cachedEncoding ) {
294+ const cachedRecord : Record < void > = ( readlinkCache [ i + 1 ] : any ) ;
295+ record = cachedRecord ;
296+ break ;
297+ }
298+ }
299+ if ( ! record ) {
300+ const thenable = fs . readlink ( path , { encoding} ) ;
301+ record = createRecordFromThenable ( thenable ) ;
302+ readlinkCache . push ( encoding , record ) ;
303+ }
304+ const linkString = readRecord ( record ) . value ;
305+ return linkString ;
306+ }
307+
308+ function createRealpathMap(): Map< string , Array < string | Record < mixed > >> {
309+ return new Map ( ) ;
310+ }
311+
312+ export function realpath(
313+ path: string,
314+ options?: string | { encoding ? : string } ,
315+ ): mixed {
316+ checkPathInDev ( path ) ;
317+ let encoding = 'utf8' ;
318+ if ( typeof options === 'string' ) {
319+ encoding = options ;
320+ } else if ( options != null ) {
321+ if ( options . encoding ) {
322+ encoding = options . encoding ;
323+ }
324+ }
325+ const map = unstable_getCacheForType ( createRealpathMap ) ;
326+ let realpathCache = map . get ( path ) ;
327+ if ( ! realpathCache ) {
328+ realpathCache = [ ] ;
329+ map . set ( path , realpathCache ) ;
330+ }
331+ let record ;
332+ for ( let i = 0 ; i < realpathCache . length ; i += 2 ) {
333+ const cachedEncoding : string = ( realpathCache [ i ] : any ) ;
334+ if ( encoding === cachedEncoding ) {
335+ const cachedRecord : Record < void > = ( realpathCache [ i + 1 ] : any ) ;
336+ record = cachedRecord ;
337+ break ;
338+ }
339+ }
340+ if ( ! record ) {
341+ const thenable = fs . realpath ( path , { encoding} ) ;
342+ record = createRecordFromThenable ( thenable ) ;
343+ realpathCache . push ( encoding , record ) ;
344+ }
345+ const resolvedPath = readRecord ( record ) . value ;
346+ return resolvedPath ;
347+ }
348+
349+ function createStatMap(): Map< string , Array < boolean | Record < mixed > >> {
350+ return new Map ( ) ;
351+ }
352+
353+ export function stat(path: string, options?: { bigint ? : boolean } ): mixed {
354+ checkPathInDev ( path ) ;
355+ let bigint = false ;
356+ if ( options && options . bigint ) {
357+ bigint = true ;
358+ }
359+ const map = unstable_getCacheForType ( createStatMap ) ;
360+ let statCache = map . get ( path ) ;
361+ if ( ! statCache ) {
362+ statCache = [ ] ;
363+ map . set ( path , statCache ) ;
364+ }
365+ let record ;
366+ for ( let i = 0 ; i < statCache . length ; i += 2 ) {
367+ const cachedBigint : boolean = ( statCache [ i ] : any ) ;
368+ if ( bigint === cachedBigint ) {
369+ const cachedRecord : Record < void > = ( statCache [ i + 1 ] : any ) ;
370+ record = cachedRecord ;
371+ break ;
372+ }
373+ }
374+ if ( ! record ) {
375+ const thenable = fs . stat ( path , { bigint} ) ;
376+ record = createRecordFromThenable ( thenable ) ;
377+ statCache . push ( bigint , record ) ;
378+ }
379+ const stats = readRecord ( record ) . value ;
380+ return stats ;
381+ }
0 commit comments