77 */
88
99import { FSWatcher } from 'chokidar' ;
10- import { normalize } from 'node:path' ;
1110
1211export class ChangedFiles {
1312 readonly added = new Set < string > ( ) ;
@@ -52,65 +51,19 @@ export function createWatcher(options?: {
5251 let currentChanges : ChangedFiles | undefined ;
5352 let nextWaitTimeout : NodeJS . Timeout | undefined ;
5453
55- /**
56- * We group the current events in a map as on Windows with certain IDE a file contents change can trigger multiple events.
57- *
58- * Example:
59- * rename | 'C:/../src/app/app.component.css'
60- * rename | 'C:/../src/app/app.component.css'
61- * change | 'C:/../src/app/app.component.css'
62- *
63- */
64- let currentEvents : Map < /* Event name */ string , /* File path */ string > | undefined ;
65-
66- /**
67- * Using `watcher.on('all')` does not capture some of events fired when using Visual studio and this does not happen all the time,
68- * but only after a file has been changed 3 or more times.
69- *
70- * Also, some IDEs such as Visual Studio (not VS Code) will fire a rename event instead of unlink when a file is renamed or changed.
71- *
72- * Example:
73- * ```
74- * watcher.on('raw')
75- * Change 1
76- * rename | 'C:/../src/app/app.component.css'
77- * rename | 'C:/../src/app/app.component.css'
78- * change | 'C:/../src/app/app.component.css'
79- *
80- * Change 2
81- * rename | 'C:/../src/app/app.component.css'
82- * rename | 'C:/../src/app/app.component.css'
83- * change | 'C:/../src/app/app.component.css'
84- *
85- * Change 3
86- * rename | 'C:/../src/app/app.component.css'
87- * rename | 'C:/../src/app/app.component.css'
88- * change | 'C:/../src/app/app.component.css'
89- *
90- * watcher.on('all')
91- * Change 1
92- * change | 'C:\\..\\src\\app\\app.component.css'
93- *
94- * Change 2
95- * unlink | 'C:\\..\\src\\app\\app.component.css'
96- *
97- * Change 3
98- * ... (Nothing)
99- * ```
100- */
101- watcher . on ( 'raw' , ( event , path , { watchedPath } ) => {
54+ watcher . on ( 'all' , ( event , path ) => {
10255 switch ( event ) {
10356 case 'add' :
57+ currentChanges ??= new ChangedFiles ( ) ;
58+ currentChanges . added . add ( path ) ;
59+ break ;
10460 case 'change' :
105- // When using Visual Studio the rename event is fired before a change event when the contents of the file changed
106- // or instead of `unlink` when the file has been renamed.
61+ currentChanges ??= new ChangedFiles ( ) ;
62+ currentChanges . modified . add ( path ) ;
63+ break ;
10764 case 'unlink' :
108- case 'rename' :
109- // When polling is enabled `watchedPath` can be undefined.
110- // `path` is always normalized unlike `watchedPath`.
111- const changedPath = watchedPath ? normalize ( watchedPath ) : path ;
112- currentEvents ??= new Map ( ) ;
113- currentEvents . set ( changedPath , event ) ;
65+ currentChanges ??= new ChangedFiles ( ) ;
66+ currentChanges . removed . add ( path ) ;
11467 break ;
11568 default :
11669 return ;
@@ -121,27 +74,10 @@ export function createWatcher(options?: {
12174 nextWaitTimeout = setTimeout ( ( ) => {
12275 nextWaitTimeout = undefined ;
12376 const next = nextQueue . shift ( ) ;
124- if ( next && currentEvents ) {
125- const events = currentEvents ;
126- currentEvents = undefined ;
127-
128- const currentChanges = new ChangedFiles ( ) ;
129- for ( const [ path , event ] of events ) {
130- switch ( event ) {
131- case 'add' :
132- currentChanges . added . add ( path ) ;
133- break ;
134- case 'change' :
135- currentChanges . modified . add ( path ) ;
136- break ;
137- case 'unlink' :
138- case 'rename' :
139- currentChanges . removed . add ( path ) ;
140- break ;
141- }
142- }
143-
144- next ( currentChanges ) ;
77+ if ( next ) {
78+ const value = currentChanges ;
79+ currentChanges = undefined ;
80+ next ( value ) ;
14581 }
14682 } , 250 ) ;
14783 nextWaitTimeout ?. unref ( ) ;
0 commit comments