Skip to content

chore(release): new release#288

Open
github-actions[bot] wants to merge 1 commit intomainfrom
changeset-release/main
Open

chore(release): new release#288
github-actions[bot] wants to merge 1 commit intomainfrom
changeset-release/main

Conversation

@github-actions
Copy link
Copy Markdown

@github-actions github-actions Bot commented Apr 17, 2026

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

watchpack@2.5.2

Patch Changes

  • fix: retry fs.lstat on transient EBUSY errors instead of flagging the (by @alexander-akait in #293)
    file as removed (fixes Webpack watch stops if one of the output files is busy #223, Watch Mode stops functioning if emitted file is busy or locked #44).

    On Windows it is common for anti-virus scanners, indexers or the editor
    itself to briefly hold an exclusive handle on a file that has just
    changed. Before this change the watcher would receive the fs.watch
    event, call lstat, get back EBUSY, and fall through to setMissing
    — causing a spurious remove event and in some cases leaving the
    watcher unable to see further changes for that file until the directory
    was re-scanned.

    DirectoryWatcher now retries lstat up to three times (100 ms apart)
    before giving up, and does not emit a remove when the only reason the
    file could not be stat'd was EBUSY.

    The retry count is controlled by the WATCHPACK_RETRIES environment
    variable (default: 3; set to 0 or "false" to disable retrying and
    restore the previous behaviour).

  • Improve perfomance for ignored and improve perfomance for reduce plan. (by @alexander-akait in #289)

  • perf: skip the path-separator replacement when the input has no backslash (by @alexander-akait in #287)
    (benchmarks measure ~35–45% less time for ignored matchers on POSIX paths),
    fast-path single-element ignored arrays, and make reducePlan's selection
    loop walk only structurally valid candidates with an early exit when the
    ideal reduction is found (measured ~20–40% faster on medium and large
    plans). Adds a tinybench suite under bench/ and a CodSpeed GitHub Actions
    workflow so future regressions are caught automatically.

  • fix: don't log "Watchpack Error (initial scan)" for unreadable entries (by @alexander-akait in #298)
    inside a watched parent directory (fixes Watchpack Error (initial scan): Error: EACCES: permission denied, lstat '/mnt/c/...' #187).

    Webpack registers every ancestor of a watched file as a watched
    directory (so /mnt/c/Users/me/proj causes watchpack to scan /mnt/c,
    /mnt, /). When such a parent contains entries the current process
    can't lstatpagefile.sys / hiberfil.sys on WSL, /efi on Linux
    when the EFI partition isn't mounted, protected paths on Node ≥22.17 on
    Windows where libuv now reports EINVAL instead of EACCES — the
    initial scan would print:

    Watchpack Error (initial scan): Error: EACCES: permission denied, lstat '/mnt/c/pagefile.sys'
    Watchpack Error (initial scan): Error: EINVAL: invalid argument, lstat 'C:\\hiberfil.sys'
    Watchpack Error (initial scan): Error: ENODEV: no such device, lstat '/efi'
    

    These entries aren't actually being watched (only their sibling, e.g.
    /mnt/c/Users, is) so the log was harmless but very noisy and sent a
    lot of users on wild goose chases.

    DirectoryWatcher#doScan now treats EACCES / ENODEV (and EINVAL
    on Windows) the same way it already treats EPERM / ENOENT /
    EBUSY: the offending entry is recorded as missing and the scan
    continues silently. The same set is applied to the readdir error path
    on the watched directory itself, so an unreadable mount point is
    treated as removed instead of logged.

    No public API change. If you were relying on the error appearing on
    stderr, set the impacted entry up as an explicit watch so a real failure
    on it surfaces through the existing error event instead.

  • fix: prevent unbounded watcher growth when a symlinked directory points (by @alexander-akait in #297)
    back to one of its own ancestors (cycle protection for the
    followSymlinks: true symlink-descent path).

    The recent fixes for Watching a directory doesn't watch nested symlinks when followSymlinks = true #190 / Add support for watching symlinks that resolve to paths outside the watch folder #231 made DirectoryWatcher follow
    symlinked directories whose realpath lives outside the watched real
    directory, registering them as nested watched directories. That logic
    short-circuits when the symlink target is a sibling in the same parent
    (dirname(realPath) === this.path), but it does not catch the case
    where the target is an ancestor of the symlink itself — for example
    a/b/loop -> ... In that case readdir followed the symlink, found
    the original tree again, and a new DirectoryWatcher was created at
    each recursion level until the path exceeded PATH_MAX (locally
    observed: ~1500 watchers within 2 s, ~2500 within 2.5 s).

    DirectoryWatcher now computes path.relative(realPath, itemPath)
    before descending; if the relative path doesn't start with .. and
    isn't absolute (i.e. the symlink target is at-or-above the symlink in
    the directory tree), the symlink is recorded as a plain entry instead
    of being descended into. Behaviour for symlinks pointing outside the
    watched tree (the case Add support for watching symlinks that resolve to paths outside the watch folder #231 fixes) is unchanged.

@github-actions github-actions Bot force-pushed the changeset-release/main branch 5 times, most recently from a7f5373 to 53210a9 Compare April 23, 2026 16:52
@github-actions github-actions Bot force-pushed the changeset-release/main branch 5 times, most recently from 06298d5 to c50c2ff Compare April 30, 2026 18:04
@github-actions github-actions Bot force-pushed the changeset-release/main branch from c50c2ff to 24ecb29 Compare April 30, 2026 18:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Webpack watch stops if one of the output files is busy Watchpack Error (initial scan): Error: EACCES: permission denied, lstat '/mnt/c/...'

0 participants