* @param {VirtualProvider} provider The VFS provider * @param {string} path The path to watch (provider-relative) * @param {object} [options] Options
(provider, path, options = kEmptyObject)
| 588 | * @param {object} [options] Options |
| 589 | */ |
| 590 | constructor(provider, path, options = kEmptyObject) { |
| 591 | // Strip signal from options passed to VFSWatcher - we handle abort |
| 592 | // at the iterable level to reject pending next() with AbortError |
| 593 | // instead of resolving with done:true via the 'close' event. |
| 594 | const signal = options.signal; |
| 595 | const watcherOptions = ObjectAssign({ __proto__: null }, options); |
| 596 | delete watcherOptions.signal; |
| 597 | this.#watcher = new VFSWatcher(provider, path, watcherOptions); |
| 598 | |
| 599 | this.#watcher.on('change', (eventType, filename) => { |
| 600 | const event = { eventType, filename }; |
| 601 | if (this.#pendingResolvers.length > 0) { |
| 602 | const { resolve } = this.#pendingResolvers.shift(); |
| 603 | resolve({ done: false, value: event }); |
| 604 | } else if (this.#pendingEvents.length < kMaxPendingEvents) { |
| 605 | ArrayPrototypePush(this.#pendingEvents, event); |
| 606 | } |
| 607 | // Drop events when queue is full to prevent unbounded memory growth |
| 608 | }); |
| 609 | |
| 610 | this.#watcher.on('close', () => { |
| 611 | this.#closed = true; |
| 612 | // Resolve any pending iterators |
| 613 | while (this.#pendingResolvers.length > 0) { |
| 614 | const { resolve } = this.#pendingResolvers.shift(); |
| 615 | resolve({ done: true, value: undefined }); |
| 616 | } |
| 617 | }); |
| 618 | |
| 619 | // Handle abort signal - reject pending next() with AbortError |
| 620 | if (signal) { |
| 621 | const onAbort = () => { |
| 622 | this.#closed = true; |
| 623 | const err = new AbortError(undefined, { cause: signal.reason }); |
| 624 | while (this.#pendingResolvers.length > 0) { |
| 625 | const { reject } = this.#pendingResolvers.shift(); |
| 626 | reject(err); |
| 627 | } |
| 628 | this.#watcher.close(); |
| 629 | }; |
| 630 | if (signal.aborted) { |
| 631 | onAbort(); |
| 632 | } else { |
| 633 | signal.addEventListener('abort', onAbort, { once: true }); |
| 634 | } |
| 635 | } |
| 636 | } |
| 637 | |
| 638 | /** |
| 639 | * Returns the async iterator. |
nothing calls this directly
no test coverage detected