1
1
'use strict' ;
2
2
3
3
const {
4
+ ArrayPrototypePush,
5
+ ArrayPrototypeShift,
4
6
FunctionPrototypeCall,
5
7
ObjectDefineProperty,
8
+ ObjectPrototypeHasOwnProperty,
6
9
ObjectSetPrototypeOf,
7
10
PromiseWithResolvers,
8
11
Symbol,
@@ -14,13 +17,13 @@ const {
14
17
codes : {
15
18
ERR_INVALID_ARG_VALUE ,
16
19
} ,
20
+ genericNodeError,
17
21
} = require ( 'internal/errors' ) ;
22
+
18
23
const {
19
24
kEmptyObject,
20
25
} = require ( 'internal/util' ) ;
21
26
22
- const FixedQueue = require ( 'internal/fixed_queue' ) ;
23
-
24
27
const {
25
28
kFsStatsFieldsNumber,
26
29
StatWatcher : _StatWatcher ,
@@ -47,6 +50,8 @@ const {
47
50
validateBoolean,
48
51
validateObject,
49
52
validateUint32,
53
+ validateInteger,
54
+ validateOneOf,
50
55
} = require ( 'internal/validators' ) ;
51
56
52
57
const {
@@ -311,11 +316,15 @@ async function* watch(filename, options = kEmptyObject) {
311
316
persistent = true ,
312
317
recursive = false ,
313
318
encoding = 'utf8' ,
319
+ maxQueue = 2048 ,
320
+ overflow = 'swallow' ,
314
321
signal,
315
322
} = options ;
316
323
317
324
validateBoolean ( persistent , 'options.persistent' ) ;
318
325
validateBoolean ( recursive , 'options.recursive' ) ;
326
+ validateInteger ( maxQueue , 'options.maxQueue' ) ;
327
+ validateOneOf ( overflow , 'options.overflow' , [ 'swallow' , 'throw' ] ) ;
319
328
validateAbortSignal ( signal , 'options.signal' ) ;
320
329
321
330
if ( encoding && ! isEncoding ( encoding ) ) {
@@ -328,7 +337,7 @@ async function* watch(filename, options = kEmptyObject) {
328
337
329
338
const handle = new FSEvent ( ) ;
330
339
let { promise, resolve } = PromiseWithResolvers ( ) ;
331
- const queue = new FixedQueue ( ) ;
340
+ const queue = [ ] ;
332
341
const oncancel = ( ) => {
333
342
handle . close ( ) ;
334
343
resolve ( ) ;
@@ -348,12 +357,21 @@ async function* watch(filename, options = kEmptyObject) {
348
357
} ) ;
349
358
error . filename = filename ;
350
359
handle . close ( ) ;
351
- queue . push ( error ) ;
360
+ ArrayPrototypePush ( queue , error ) ;
352
361
resolve ( ) ;
353
362
return ;
354
363
}
355
- queue . push ( { eventType, filename } ) ;
356
- resolve ( ) ;
364
+ if ( queue . length < maxQueue ) {
365
+ ArrayPrototypePush ( queue , { eventType, filename } ) ;
366
+ resolve ( ) ;
367
+ } else if ( overflow === 'throw' ) {
368
+ const overflowError = genericNodeError ( 'fs.watch maxQueue exceeded' ) ;
369
+ queue . length = 0 ;
370
+ ArrayPrototypePush ( queue , overflowError ) ;
371
+ resolve ( ) ;
372
+ } else {
373
+ process . emitWarning ( 'fs.watch maxQueue exceeded' ) ;
374
+ }
357
375
} ;
358
376
359
377
const err = handle . start ( path , persistent , recursive , encoding ) ;
@@ -372,13 +390,18 @@ async function* watch(filename, options = kEmptyObject) {
372
390
373
391
while ( ! signal ?. aborted ) {
374
392
await promise ;
375
- while ( ! queue . isEmpty ( ) ) {
376
- const item = queue . shift ( ) ;
377
- if ( item instanceof UVException ) throw item ;
378
- yield item ;
393
+ while ( queue . length ) {
394
+ const item = ArrayPrototypeShift ( queue ) ;
395
+ if (
396
+ ObjectPrototypeHasOwnProperty ( item , 'eventType' ) &&
397
+ ObjectPrototypeHasOwnProperty ( item , 'filename' )
398
+ ) {
399
+ yield item ;
400
+ } else {
401
+ throw item ;
402
+ }
379
403
}
380
404
( { promise, resolve } = PromiseWithResolvers ( ) ) ;
381
-
382
405
}
383
406
if ( signal ?. aborted ) {
384
407
throw new AbortError ( undefined , { cause : signal ?. reason } ) ;
0 commit comments