List directory failure (#2151)

diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md
index b4727e5..30a1975 100644
--- a/pkgs/watcher/CHANGELOG.md
+++ b/pkgs/watcher/CHANGELOG.md
@@ -1,10 +1,12 @@
-## 1.1.3-wip
+## 1.1.3
 
 - Improve handling of
   `FileSystemException: Directory watcher closed unexpectedly` on Windows. The
   watcher was already attempting to restart after this error and resume sending
   events. But, the restart would sometimes silently fail. Now, it is more
   reliable.
+- Improving handling of directories that are created then immediately deleted on
+  Windows. Previously, that could cause a `PathNotfoundException` to be thrown.
 
 ## 1.1.2
 
diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart
index 6d88e65..8f21268 100644
--- a/pkgs/watcher/lib/src/directory_watcher/windows.dart
+++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart
@@ -198,7 +198,14 @@
           });
           subscription.onError((Object e, StackTrace stackTrace) {
             _listSubscriptions.remove(subscription);
-            _emitError(e, stackTrace);
+            // "Path not found" can be caused by creating then quickly removing
+            // a directory: continue without reporting an error. Nested files
+            // that get removed during the `list` are already ignored by `list`
+            // itself, so there are no other types of "path not found" that
+            // might need different handling here.
+            if (e is! PathNotFoundException) {
+              _emitError(e, stackTrace);
+            }
           });
           _listSubscriptions.add(subscription);
         } else if (event is FileSystemModifyEvent) {
diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml
index bccdfac..16af27b 100644
--- a/pkgs/watcher/pubspec.yaml
+++ b/pkgs/watcher/pubspec.yaml
@@ -1,5 +1,5 @@
 name: watcher
-version: 1.1.3-wip
+version: 1.1.3
 description: >-
   A file system watcher. It monitors changes to contents of directories and
   sends notifications when files have been added, removed, or modified.
diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart
index a6bc14d..6489771 100644
--- a/pkgs/watcher/test/directory_watcher/windows_test.dart
+++ b/pkgs/watcher/test/directory_watcher/windows_test.dart
@@ -66,6 +66,52 @@
     },
   );
 
+  // Regression test for https://github.com/dart-lang/tools/issues/2152:
+  // watcher can throws if a directory is created then quickly deleted.
+  group('Transient directory', () {
+    late StreamSubscription<Object> subscription;
+    late Directory temp;
+    late Watcher watcher;
+    late int errorsSeen;
+
+    setUp(() async {
+      temp = Directory.systemTemp.createTempSync();
+      watcher = DirectoryWatcher(temp.path);
+      errorsSeen = 0;
+      subscription = watcher.events.listen(
+        (e) {},
+        onError: (Object e, _) {
+          print('Event stream error: $e');
+          ++errorsSeen;
+        },
+      );
+      await watcher.ready;
+    });
+
+    tearDown(() {
+      subscription.cancel();
+    });
+
+    test('does not break watching', () async {
+      // Iterate creating 10 directories and deleting 1-10 of them. This means
+      // the directories will exist for different lengths of times, exploring
+      // possible race conditions in directory handling.
+      for (var i = 0; i != 50; ++i) {
+        for (var j = 0; j != 10; ++j) {
+          File('${temp.path}\\$j\\file').createSync(recursive: true);
+        }
+        await Future<void>.delayed(const Duration(milliseconds: 1));
+        for (var j = 0; j != i % 10 + 1; ++j) {
+          final d = Directory('${temp.path}\\$j');
+          d.deleteSync(recursive: true);
+        }
+        await Future<void>.delayed(const Duration(milliseconds: 1));
+      }
+
+      expect(errorsSeen, 0);
+    });
+  });
+
   // The Windows native watcher has a buffer that gets exhausted if events are
   // not handled quickly enough. Then, it throws an error and stops watching.
   // The exhaustion is reliably triggered if enough events arrive during a sync