@@ -40,9 +40,8 @@ class Dir {
40
40
#options;
41
41
#readPromisified;
42
42
#closePromisified;
43
- // Either `null` or an Array of pending operations (= functions to be called
44
- // once the current operation is done).
45
43
#operationQueue = null ;
44
+ #handlerQueue = [ ] ;
46
45
47
46
constructor ( handle , path , options ) {
48
47
if ( handle == null ) throw new ERR_MISSING_ARGS ( 'handle' ) ;
@@ -67,6 +66,33 @@ class Dir {
67
66
return this . #path;
68
67
}
69
68
69
+ #processHandlerQueue( ) {
70
+ while ( this . #handlerQueue. length > 0 ) {
71
+ const handler = ArrayPrototypeShift ( this . #handlerQueue) ;
72
+ const { handle, path } = handler ;
73
+
74
+ const result = handle . read (
75
+ this . #options. encoding ,
76
+ this . #options. bufferSize ,
77
+ ) ;
78
+
79
+ if ( result !== null ) {
80
+ this . processReadResult ( path , result ) ;
81
+ if ( result . length > 0 ) {
82
+ ArrayPrototypePush ( this . #handlerQueue, handler ) ;
83
+ }
84
+ } else {
85
+ handle . close ( ) ;
86
+ }
87
+
88
+ if ( this . #bufferedEntries. length > 0 ) {
89
+ break ;
90
+ }
91
+ }
92
+
93
+ return this . #bufferedEntries. length > 0 ;
94
+ }
95
+
70
96
read ( callback ) {
71
97
return this . #readImpl( true , callback ) ;
72
98
}
@@ -89,7 +115,7 @@ class Dir {
89
115
return ;
90
116
}
91
117
92
- if ( this . #bufferedEntries . length > 0 ) {
118
+ if ( this . #processHandlerQueue ( ) ) {
93
119
try {
94
120
const dirent = ArrayPrototypeShift ( this . #bufferedEntries) ;
95
121
@@ -159,25 +185,11 @@ class Dir {
159
185
this . #options. encoding ,
160
186
) ;
161
187
162
- // Terminate early, since it's already thrown.
163
188
if ( handle === undefined ) {
164
189
return ;
165
190
}
166
191
167
- // Fully read the directory and buffer the entries.
168
- // This is a naive solution and for very large sub-directories
169
- // it can even block the event loop. Essentially, `bufferSize` is
170
- // not respected for recursive mode. This is a known limitation.
171
- // Issue to fix: https://github.com/nodejs/node/issues/55764
172
- let result ;
173
- while ( ( result = handle . read (
174
- this . #options. encoding ,
175
- this . #options. bufferSize ,
176
- ) ) ) {
177
- this . processReadResult ( path , result ) ;
178
- }
179
-
180
- handle . close ( ) ;
192
+ ArrayPrototypePush ( this . #handlerQueue, { handle, path } ) ;
181
193
}
182
194
183
195
readSync ( ) {
@@ -189,7 +201,7 @@ class Dir {
189
201
throw new ERR_DIR_CONCURRENT_OPERATION ( ) ;
190
202
}
191
203
192
- if ( this . #bufferedEntries . length > 0 ) {
204
+ if ( this . #processHandlerQueue ( ) ) {
193
205
const dirent = ArrayPrototypeShift ( this . #bufferedEntries) ;
194
206
if ( this . #options. recursive && dirent . isDirectory ( ) ) {
195
207
this . readSyncRecursive ( dirent ) ;
@@ -216,15 +228,13 @@ class Dir {
216
228
}
217
229
218
230
close ( callback ) {
219
- // Promise
220
231
if ( callback === undefined ) {
221
232
if ( this . #closed === true ) {
222
233
return PromiseReject ( new ERR_DIR_CLOSED ( ) ) ;
223
234
}
224
235
return this . #closePromisified( ) ;
225
236
}
226
237
227
- // callback
228
238
validateFunction ( callback , 'callback' ) ;
229
239
230
240
if ( this . #closed === true ) {
@@ -239,6 +249,11 @@ class Dir {
239
249
return ;
240
250
}
241
251
252
+ while ( this . #handlerQueue. length > 0 ) {
253
+ const handler = ArrayPrototypeShift ( this . #handlerQueue) ;
254
+ handler . handle . close ( ) ;
255
+ }
256
+
242
257
this . #closed = true ;
243
258
const req = new FSReqCallback ( ) ;
244
259
req . oncomplete = callback ;
@@ -254,6 +269,11 @@ class Dir {
254
269
throw new ERR_DIR_CONCURRENT_OPERATION ( ) ;
255
270
}
256
271
272
+ while ( this . #handlerQueue. length > 0 ) {
273
+ const handler = ArrayPrototypeShift ( this . #handlerQueue) ;
274
+ handler . handle . close ( ) ;
275
+ }
276
+
257
277
this . #closed = true ;
258
278
this . #handle. close ( ) ;
259
279
}
0 commit comments