Open-Source Wikis

/

TypeScript

/

Apps

/

watchGuard

microsoft/TypeScript

watchGuard

A 17-line helper executable that exists for a single reason: deciding whether it is safe for tsserver to enable recursive directory watching on a given path. Used only on Windows.

Purpose

Node's fs.watch(dir, { recursive: true }) is convenient but throws on certain Windows paths — network drives, mapped UNC paths, junctioned filesystems, paths exceeding internal handle limits. A throw inside tsserver itself would crash the whole language server. So tsserver first asks a separate child process to attempt the recursive watch; if the child crashes, tsserver falls back to non-recursive watching for that directory.

Source

src/watchGuard/watchGuard.ts:

import * as fs from 'fs';

if (process.argv.length < 3) {
  process.exit(1);
}
const directoryName = process.argv[2];
// main reason why we need separate process to check if it is safe to watch some path
// is to guard against crashes that cannot be intercepted with protected blocks and
// code in tsserver already can handle normal cases, like non-existing folders.
// This means that here we treat any result (success or exception) from fs.watch as success since it does not tear down the process.
// The only case that should be considered as failure - when watchGuard process crashes.
try {
  const watcher = fs.watch(directoryName, { recursive: true }, () => ({}));
  watcher.close();
} catch {
  /*ignore*/
}
process.exit(0);

That's the entire program. Exit-zero means "safe to watch"; the process crashing (segfault, native abort) is interpreted as "not safe".

Directory layout

src/watchGuard/
├── tsconfig.json
└── watchGuard.ts    # the entire program

How it works

sequenceDiagram
    participant tsserver
    participant watchGuard
    participant fs as Node fs

    tsserver->>watchGuard: spawn (path)
    watchGuard->>fs: fs.watch(path, { recursive: true })
    alt Native crash
        fs--xwatchGuard: process aborts
        watchGuard-->>tsserver: exit code != 0
        tsserver->>tsserver: fall back to per-file watch
    else Normal exception
        fs->>watchGuard: throw
        watchGuard-->>tsserver: exit 0 (caught)
        tsserver->>tsserver: try recursive watch (will throw and be handled)
    else Success
        fs->>watchGuard: returns watcher
        watchGuard-->>tsserver: exit 0
        tsserver->>tsserver: enable recursive watch
    end

Integration points

  • Spawned by src/server/editorServices.ts (and the host setup in src/tsserver/nodeServer.ts) when tsserver first considers recursive-watching a directory it hasn't seen before.
  • Output is consumed only via the child-process exit code.
  • Has no dependencies beyond Node's built-in fs.

Entry points for modification

In practice nobody modifies watchGuard.ts. The interesting code is on the caller side — when and how tsserver decides to invoke it, what fallback it uses on a non-zero exit, and how it caches the per-directory verdict.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

watchGuard – TypeScript wiki | Factory