@@ -14,7 +14,8 @@ const EMPTY_ARRAY = [];
1414const EMPTY_OPTIONS = { } ;
1515
1616function addWatchersToSet ( watchers , set ) {
17- for ( const w of watchers ) {
17+ for ( const ww of watchers ) {
18+ const w = ww . watcher ;
1819 if ( ! set . has ( w . directoryWatcher ) ) {
1920 set . add ( w . directoryWatcher ) ;
2021 }
@@ -28,24 +29,28 @@ const stringToRegexp = ignored => {
2829 return matchingStart ;
2930} ;
3031
31- const ignoredToRegexp = ignored => {
32+ const ignoredToFunction = ignored => {
3233 if ( Array . isArray ( ignored ) ) {
33- return new RegExp ( ignored . map ( i => stringToRegexp ( i ) ) . join ( "|" ) ) ;
34+ const regexp = new RegExp ( ignored . map ( i => stringToRegexp ( i ) ) . join ( "|" ) ) ;
35+ return x => regexp . test ( x . replace ( / \\ / g, "/" ) ) ;
3436 } else if ( typeof ignored === "string" ) {
35- return new RegExp ( stringToRegexp ( ignored ) ) ;
37+ const regexp = new RegExp ( stringToRegexp ( ignored ) ) ;
38+ return x => regexp . test ( x . replace ( / \\ / g, "/" ) ) ;
3639 } else if ( ignored instanceof RegExp ) {
40+ return x => ignored . test ( x . replace ( / \\ / g, "/" ) ) ;
41+ } else if ( ignored instanceof Function ) {
3742 return ignored ;
3843 } else if ( ignored ) {
3944 throw new Error ( `Invalid option for 'ignored': ${ ignored } ` ) ;
4045 } else {
41- return undefined ;
46+ return ( ) => false ;
4247 }
4348} ;
4449
4550const normalizeOptions = options => {
4651 return {
4752 followSymlinks : ! ! options . followSymlinks ,
48- ignored : ignoredToRegexp ( options . ignored ) ,
53+ ignored : ignoredToFunction ( options . ignored ) ,
4954 poll : options . poll
5055 } ;
5156} ;
@@ -59,6 +64,85 @@ const cachedNormalizeOptions = options => {
5964 return normalized ;
6065} ;
6166
67+ class WatchpackFileWatcher {
68+ constructor ( watchpack , watcher , files ) {
69+ if ( ! watcher ) throw new Error ( ) ;
70+ this . files = Array . isArray ( files ) ? files : [ files ] ;
71+ this . watcher = watcher ;
72+ watcher . on ( "initial-missing" , type => {
73+ for ( const file of this . files ) {
74+ if ( ! watchpack . _missing . has ( file ) )
75+ watchpack . _onRemove ( file , file , type ) ;
76+ }
77+ } ) ;
78+ watcher . on ( "change" , ( mtime , type ) => {
79+ for ( const file of this . files ) {
80+ watchpack . _onChange ( file , mtime , file , type ) ;
81+ }
82+ } ) ;
83+ watcher . on ( "remove" , type => {
84+ for ( const file of this . files ) {
85+ watchpack . _onRemove ( file , file , type ) ;
86+ }
87+ } ) ;
88+ }
89+
90+ update ( files ) {
91+ if ( ! Array . isArray ( files ) ) {
92+ if ( this . files . length !== 1 ) {
93+ this . files = [ files ] ;
94+ } else if ( this . files [ 0 ] !== files ) {
95+ this . files [ 0 ] = files ;
96+ }
97+ } else {
98+ this . files = files ;
99+ }
100+ }
101+
102+ close ( ) {
103+ this . watcher . close ( ) ;
104+ }
105+ }
106+
107+ class WatchpackDirectoryWatcher {
108+ constructor ( watchpack , watcher , directories ) {
109+ if ( ! watcher ) throw new Error ( ) ;
110+ this . directories = Array . isArray ( directories ) ? directories : [ directories ] ;
111+ this . watcher = watcher ;
112+ watcher . on ( "initial-missing" , type => {
113+ for ( const item of this . directories ) {
114+ watchpack . _onRemove ( item , item , type ) ;
115+ }
116+ } ) ;
117+ watcher . on ( "change" , ( file , mtime , type ) => {
118+ for ( const item of this . directories ) {
119+ watchpack . _onChange ( item , mtime , file , type ) ;
120+ }
121+ } ) ;
122+ watcher . on ( "remove" , type => {
123+ for ( const item of this . directories ) {
124+ watchpack . _onRemove ( item , item , type ) ;
125+ }
126+ } ) ;
127+ }
128+
129+ update ( directories ) {
130+ if ( ! Array . isArray ( directories ) ) {
131+ if ( this . directories . length !== 1 ) {
132+ this . directories = [ directories ] ;
133+ } else if ( this . directories [ 0 ] !== directories ) {
134+ this . directories [ 0 ] = directories ;
135+ }
136+ } else {
137+ this . directories = directories ;
138+ }
139+ }
140+
141+ close ( ) {
142+ this . watcher . close ( ) ;
143+ }
144+ }
145+
62146class Watchpack extends EventEmitter {
63147 constructor ( options ) {
64148 super ( ) ;
@@ -72,6 +156,7 @@ class Watchpack extends EventEmitter {
72156 this . watcherManager = getWatcherManager ( this . watcherOptions ) ;
73157 this . fileWatchers = new Map ( ) ;
74158 this . directoryWatchers = new Map ( ) ;
159+ this . _missing = new Set ( ) ;
75160 this . startTime = undefined ;
76161 this . paused = false ;
77162 this . aggregatedChanges = new Set ( ) ;
@@ -96,18 +181,18 @@ class Watchpack extends EventEmitter {
96181 startTime = arg3 ;
97182 }
98183 this . paused = false ;
99- const oldFileWatchers = this . fileWatchers ;
100- const oldDirectoryWatchers = this . directoryWatchers ;
184+ const fileWatchers = this . fileWatchers ;
185+ const directoryWatchers = this . directoryWatchers ;
101186 const ignored = this . watcherOptions . ignored ;
102- const filter = ignored
103- ? path => ! ignored . test ( path . replace ( / \\ / g, "/" ) )
104- : ( ) => true ;
187+ const filter = path => ! ignored ( path ) ;
105188 const addToMap = ( map , key , item ) => {
106189 const list = map . get ( key ) ;
107190 if ( list === undefined ) {
108- map . set ( key , [ item ] ) ;
109- } else {
191+ map . set ( key , item ) ;
192+ } else if ( Array . isArray ( list ) ) {
110193 list . push ( item ) ;
194+ } else {
195+ map . set ( key , [ list , item ] ) ;
111196 }
112197 } ;
113198 const fileWatchersNeeded = new Map ( ) ;
@@ -167,82 +252,47 @@ class Watchpack extends EventEmitter {
167252 }
168253 }
169254 }
170- const newFileWatchers = new Map ( ) ;
171- const newDirectoryWatchers = new Map ( ) ;
172- const setupFileWatcher = ( watcher , key , files ) => {
173- watcher . on ( "initial-missing" , type => {
174- for ( const file of files ) {
175- if ( ! missingFiles . has ( file ) ) this . _onRemove ( file , file , type ) ;
176- }
177- } ) ;
178- watcher . on ( "change" , ( mtime , type ) => {
179- for ( const file of files ) {
180- this . _onChange ( file , mtime , file , type ) ;
181- }
182- } ) ;
183- watcher . on ( "remove" , type => {
184- for ( const file of files ) {
185- this . _onRemove ( file , file , type ) ;
186- }
187- } ) ;
188- newFileWatchers . set ( key , watcher ) ;
189- } ;
190- const setupDirectoryWatcher = ( watcher , key , directories ) => {
191- watcher . on ( "initial-missing" , type => {
192- for ( const item of directories ) {
193- this . _onRemove ( item , item , type ) ;
194- }
195- } ) ;
196- watcher . on ( "change" , ( file , mtime , type ) => {
197- for ( const item of directories ) {
198- this . _onChange ( item , mtime , file , type ) ;
199- }
200- } ) ;
201- watcher . on ( "remove" , type => {
202- for ( const item of directories ) {
203- this . _onRemove ( item , item , type ) ;
204- }
205- } ) ;
206- newDirectoryWatchers . set ( key , watcher ) ;
207- } ;
208255 // Close unneeded old watchers
209- const fileWatchersToClose = [ ] ;
210- const directoryWatchersToClose = [ ] ;
211- for ( const [ key , w ] of oldFileWatchers ) {
212- if ( ! fileWatchersNeeded . has ( key ) ) {
256+ // and update existing watchers
257+ for ( const [ key , w ] of fileWatchers ) {
258+ const needed = fileWatchersNeeded . get ( key ) ;
259+ if ( needed === undefined ) {
213260 w . close ( ) ;
261+ fileWatchers . delete ( key ) ;
214262 } else {
215- fileWatchersToClose . push ( w ) ;
263+ w . update ( needed ) ;
264+ fileWatchersNeeded . delete ( key ) ;
216265 }
217266 }
218- for ( const [ key , w ] of oldDirectoryWatchers ) {
219- if ( ! directoryWatchersNeeded . has ( key ) ) {
267+ for ( const [ key , w ] of directoryWatchers ) {
268+ const needed = directoryWatchersNeeded . get ( key ) ;
269+ if ( needed === undefined ) {
220270 w . close ( ) ;
271+ directoryWatchers . delete ( key ) ;
221272 } else {
222- directoryWatchersToClose . push ( w ) ;
273+ w . update ( needed ) ;
274+ directoryWatchersNeeded . delete ( key ) ;
223275 }
224276 }
225277 // Create new watchers and install handlers on these watchers
226278 watchEventSource . batch ( ( ) => {
227279 for ( const [ key , files ] of fileWatchersNeeded ) {
228280 const watcher = this . watcherManager . watchFile ( key , startTime ) ;
229281 if ( watcher ) {
230- setupFileWatcher ( watcher , key , files ) ;
282+ fileWatchers . set ( key , new WatchpackFileWatcher ( this , watcher , files ) ) ;
231283 }
232284 }
233285 for ( const [ key , directories ] of directoryWatchersNeeded ) {
234286 const watcher = this . watcherManager . watchDirectory ( key , startTime ) ;
235287 if ( watcher ) {
236- setupDirectoryWatcher ( watcher , key , directories ) ;
288+ directoryWatchers . set (
289+ key ,
290+ new WatchpackDirectoryWatcher ( this , watcher , directories )
291+ ) ;
237292 }
238293 }
239294 } ) ;
240- // Close old watchers
241- for ( const w of fileWatchersToClose ) w . close ( ) ;
242- for ( const w of directoryWatchersToClose ) w . close ( ) ;
243- // Store watchers
244- this . fileWatchers = newFileWatchers ;
245- this . directoryWatchers = newDirectoryWatchers ;
295+ this . _missing = missingFiles ;
246296 this . startTime = startTime ;
247297 }
248298
0 commit comments