realWatchDirectories(directories: string[],realpath?: (directory: string) => Promise<string>): Promise<string[]>
Expands each directory to its real path before anything watches it.
Windows 8.3 short names are why. A script under C:\Users\RUNNER~1\… registers the watch on
the short spelling, while ReadDirectoryChangesW reports its events under the expanded long one.
libuv prefix-compares the two and, when they disagree, ABORTS the process outright
(uv_fs_event, src/win/fs-event.c) — so the CLI dies mid-watch having printed nothing, which
is indistinguishable from a hang. Nothing else in the chain normalises the path: esbuild's
metafile echoes back whatever entryPlugin was handed, which is the spelling the user
typed. Same reason the test runner's own watcher realpaths what it walks.
A directory that will not resolve is kept as given — watching the path as typed beats not watching it at all.
import { realWatchDirectories } from './run.ts'; await realWatchDirectories(['/a', '/b'], (directory) => Promise.resolve(`${directory}-real`)); // ['/a-real', '/b-real']