@@ -15,6 +15,16 @@ let EXISTANCE_ONLY_TIME_ENTRY; // lazy required
1515const EMPTY_ARRAY = [ ] ;
1616const EMPTY_OPTIONS = { } ;
1717
18+ function addWatchpackWatchersToSet ( watchers , set ) {
19+ for ( const ww of watchers ) {
20+ const w = ww . watcher ;
21+ if ( ! set . has ( w . directoryWatcher ) ) {
22+ set . add ( w . directoryWatcher ) ;
23+ addWatchersToSet ( w . directoryWatcher . directories . values ( ) , set ) ;
24+ }
25+ }
26+ }
27+
1828function addWatchersToSet ( watchers , set ) {
1929 for ( const w of watchers ) {
2030 if ( w !== true && ! set . has ( w . directoryWatcher ) ) {
@@ -62,6 +72,85 @@ const cachedNormalizeOptions = options => {
6272 return normalized ;
6373} ;
6474
75+ class WatchpackFileWatcher {
76+ constructor ( watchpack , watcher , files ) {
77+ if ( ! watcher ) throw new Error ( ) ;
78+ this . files = Array . isArray ( files ) ? files : [ files ] ;
79+ this . watcher = watcher ;
80+ watcher . on ( "initial-missing" , type => {
81+ for ( const file of this . files ) {
82+ if ( ! watchpack . _missing . has ( file ) )
83+ watchpack . _onRemove ( file , file , type ) ;
84+ }
85+ } ) ;
86+ watcher . on ( "change" , ( mtime , type ) => {
87+ for ( const file of this . files ) {
88+ watchpack . _onChange ( file , mtime , file , type ) ;
89+ }
90+ } ) ;
91+ watcher . on ( "remove" , type => {
92+ for ( const file of this . files ) {
93+ watchpack . _onRemove ( file , file , type ) ;
94+ }
95+ } ) ;
96+ }
97+
98+ update ( files ) {
99+ if ( ! Array . isArray ( files ) ) {
100+ if ( this . files . length !== 1 ) {
101+ this . files = [ files ] ;
102+ } else if ( this . files [ 0 ] !== files ) {
103+ this . files [ 0 ] = files ;
104+ }
105+ } else {
106+ this . files = files ;
107+ }
108+ }
109+
110+ close ( ) {
111+ this . watcher . close ( ) ;
112+ }
113+ }
114+
115+ class WatchpackDirectoryWatcher {
116+ constructor ( watchpack , watcher , directories ) {
117+ if ( ! watcher ) throw new Error ( ) ;
118+ this . directories = Array . isArray ( directories ) ? directories : [ directories ] ;
119+ this . watcher = watcher ;
120+ watcher . on ( "initial-missing" , type => {
121+ for ( const item of this . directories ) {
122+ watchpack . _onRemove ( item , item , type ) ;
123+ }
124+ } ) ;
125+ watcher . on ( "change" , ( file , mtime , type ) => {
126+ for ( const item of this . directories ) {
127+ watchpack . _onChange ( item , mtime , file , type ) ;
128+ }
129+ } ) ;
130+ watcher . on ( "remove" , type => {
131+ for ( const item of this . directories ) {
132+ watchpack . _onRemove ( item , item , type ) ;
133+ }
134+ } ) ;
135+ }
136+
137+ update ( directories ) {
138+ if ( ! Array . isArray ( directories ) ) {
139+ if ( this . directories . length !== 1 ) {
140+ this . directories = [ directories ] ;
141+ } else if ( this . directories [ 0 ] !== directories ) {
142+ this . directories [ 0 ] = directories ;
143+ }
144+ } else {
145+ this . directories = directories ;
146+ }
147+ }
148+
149+ close ( ) {
150+ this . watcher . close ( ) ;
151+ }
152+ }
153+
65154class Watchpack extends EventEmitter {
66155 constructor ( options ) {
67156 super ( ) ;
@@ -75,6 +164,7 @@ class Watchpack extends EventEmitter {
75164 this . watcherManager = getWatcherManager ( this . watcherOptions ) ;
76165 this . fileWatchers = new Map ( ) ;
77166 this . directoryWatchers = new Map ( ) ;
167+ this . _missing = new Set ( ) ;
78168 this . startTime = undefined ;
79169 this . paused = false ;
80170 this . aggregatedChanges = new Set ( ) ;
@@ -99,18 +189,20 @@ class Watchpack extends EventEmitter {
99189 startTime = arg3 ;
100190 }
101191 this . paused = false ;
102- const oldFileWatchers = this . fileWatchers ;
103- const oldDirectoryWatchers = this . directoryWatchers ;
192+ const fileWatchers = this . fileWatchers ;
193+ const directoryWatchers = this . directoryWatchers ;
104194 const ignored = this . watcherOptions . ignored ;
105195 const filter = ignored
106196 ? path => ! ignored . test ( path . replace ( / \\ / g, "/" ) )
107197 : ( ) => true ;
108198 const addToMap = ( map , key , item ) => {
109199 const list = map . get ( key ) ;
110200 if ( list === undefined ) {
111- map . set ( key , [ item ] ) ;
112- } else {
201+ map . set ( key , item ) ;
202+ } else if ( Array . isArray ( list ) ) {
113203 list . push ( item ) ;
204+ } else {
205+ map . set ( key , [ list , item ] ) ;
114206 }
115207 } ;
116208 const fileWatchersNeeded = new Map ( ) ;
@@ -170,82 +262,47 @@ class Watchpack extends EventEmitter {
170262 }
171263 }
172264 }
173- const newFileWatchers = new Map ( ) ;
174- const newDirectoryWatchers = new Map ( ) ;
175- const setupFileWatcher = ( watcher , key , files ) => {
176- watcher . on ( "initial-missing" , type => {
177- for ( const file of files ) {
178- if ( ! missingFiles . has ( file ) ) this . _onRemove ( file , file , type ) ;
179- }
180- } ) ;
181- watcher . on ( "change" , ( mtime , type ) => {
182- for ( const file of files ) {
183- this . _onChange ( file , mtime , file , type ) ;
184- }
185- } ) ;
186- watcher . on ( "remove" , type => {
187- for ( const file of files ) {
188- this . _onRemove ( file , file , type ) ;
189- }
190- } ) ;
191- newFileWatchers . set ( key , watcher ) ;
192- } ;
193- const setupDirectoryWatcher = ( watcher , key , directories ) => {
194- watcher . on ( "initial-missing" , type => {
195- for ( const item of directories ) {
196- this . _onRemove ( item , item , type ) ;
197- }
198- } ) ;
199- watcher . on ( "change" , ( file , mtime , type ) => {
200- for ( const item of directories ) {
201- this . _onChange ( item , mtime , file , type ) ;
202- }
203- } ) ;
204- watcher . on ( "remove" , type => {
205- for ( const item of directories ) {
206- this . _onRemove ( item , item , type ) ;
207- }
208- } ) ;
209- newDirectoryWatchers . set ( key , watcher ) ;
210- } ;
211265 // Close unneeded old watchers
212- const fileWatchersToClose = [ ] ;
213- const directoryWatchersToClose = [ ] ;
214- for ( const [ key , w ] of oldFileWatchers ) {
215- if ( ! fileWatchersNeeded . has ( key ) ) {
266+ // and update existing watchers
267+ for ( const [ key , w ] of fileWatchers ) {
268+ const needed = fileWatchersNeeded . get ( key ) ;
269+ if ( needed === undefined ) {
216270 w . close ( ) ;
271+ fileWatchers . delete ( key ) ;
217272 } else {
218- fileWatchersToClose . push ( w ) ;
273+ w . update ( needed ) ;
274+ fileWatchersNeeded . delete ( key ) ;
219275 }
220276 }
221- for ( const [ key , w ] of oldDirectoryWatchers ) {
222- if ( ! directoryWatchersNeeded . has ( key ) ) {
277+ for ( const [ key , w ] of directoryWatchers ) {
278+ const needed = directoryWatchersNeeded . get ( key ) ;
279+ if ( needed === undefined ) {
223280 w . close ( ) ;
281+ directoryWatchers . delete ( key ) ;
224282 } else {
225- directoryWatchersToClose . push ( w ) ;
283+ w . update ( needed ) ;
284+ directoryWatchersNeeded . delete ( key ) ;
226285 }
227286 }
228287 // Create new watchers and install handlers on these watchers
229288 watchEventSource . batch ( ( ) => {
230289 for ( const [ key , files ] of fileWatchersNeeded ) {
231290 const watcher = this . watcherManager . watchFile ( key , startTime ) ;
232291 if ( watcher ) {
233- setupFileWatcher ( watcher , key , files ) ;
292+ fileWatchers . set ( key , new WatchpackFileWatcher ( this , watcher , files ) ) ;
234293 }
235294 }
236295 for ( const [ key , directories ] of directoryWatchersNeeded ) {
237296 const watcher = this . watcherManager . watchDirectory ( key , startTime ) ;
238297 if ( watcher ) {
239- setupDirectoryWatcher ( watcher , key , directories ) ;
298+ directoryWatchers . set (
299+ key ,
300+ new WatchpackDirectoryWatcher ( this , watcher , directories )
301+ ) ;
240302 }
241303 }
242304 } ) ;
243- // Close old watchers
244- for ( const w of fileWatchersToClose ) w . close ( ) ;
245- for ( const w of directoryWatchersToClose ) w . close ( ) ;
246- // Store watchers
247- this . fileWatchers = newFileWatchers ;
248- this . directoryWatchers = newDirectoryWatchers ;
305+ this . _missing = missingFiles ;
249306 this . startTime = startTime ;
250307 }
251308
@@ -265,8 +322,11 @@ class Watchpack extends EventEmitter {
265322
266323 getTimes ( ) {
267324 const directoryWatchers = new Set ( ) ;
268- addWatchersToSet ( this . fileWatchers . values ( ) , directoryWatchers ) ;
269- addWatchersToSet ( this . directoryWatchers . values ( ) , directoryWatchers ) ;
325+ addWatchpackWatchersToSet ( this . fileWatchers . values ( ) , directoryWatchers ) ;
326+ addWatchpackWatchersToSet (
327+ this . directoryWatchers . values ( ) ,
328+ directoryWatchers
329+ ) ;
270330 const obj = Object . create ( null ) ;
271331 for ( const w of directoryWatchers ) {
272332 const times = w . getTimes ( ) ;
@@ -281,8 +341,11 @@ class Watchpack extends EventEmitter {
281341 . EXISTANCE_ONLY_TIME_ENTRY ;
282342 }
283343 const directoryWatchers = new Set ( ) ;
284- addWatchersToSet ( this . fileWatchers . values ( ) , directoryWatchers ) ;
285- addWatchersToSet ( this . directoryWatchers . values ( ) , directoryWatchers ) ;
344+ addWatchpackWatchersToSet ( this . fileWatchers . values ( ) , directoryWatchers ) ;
345+ addWatchpackWatchersToSet (
346+ this . directoryWatchers . values ( ) ,
347+ directoryWatchers
348+ ) ;
286349 const map = new Map ( ) ;
287350 for ( const w of directoryWatchers ) {
288351 const times = w . getTimeInfoEntries ( ) ;
0 commit comments