@@ -33,7 +33,7 @@ namespace ts {
33
33
Deleted
34
34
}
35
35
36
- export type FileWatcherCallback = ( fileName : string , eventKind : FileWatcherEventKind ) => void ;
36
+ export type FileWatcherCallback = ( fileName : string , eventKind : FileWatcherEventKind , modifiedTime ?: Date ) => void ;
37
37
export type DirectoryWatcherCallback = ( fileName : string ) => void ;
38
38
/*@internal */
39
39
export interface WatchedFile {
@@ -364,15 +364,15 @@ namespace ts {
364
364
const watcher = fsWatch (
365
365
dirName ,
366
366
FileSystemEntryKind . Directory ,
367
- ( _eventName : string , relativeFileName ) => {
367
+ ( _eventName : string , relativeFileName , modifiedTime ) => {
368
368
// When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined"
369
369
if ( ! isString ( relativeFileName ) ) return ;
370
370
const fileName = getNormalizedAbsolutePath ( relativeFileName , dirName ) ;
371
371
// Some applications save a working file via rename operations
372
372
const callbacks = fileName && fileWatcherCallbacks . get ( toCanonicalName ( fileName ) ) ;
373
373
if ( callbacks ) {
374
374
for ( const fileCallback of callbacks ) {
375
- fileCallback ( fileName , FileWatcherEventKind . Changed ) ;
375
+ fileCallback ( fileName , FileWatcherEventKind . Changed , modifiedTime ) ;
376
376
}
377
377
}
378
378
} ,
@@ -446,9 +446,9 @@ namespace ts {
446
446
cache . set ( path , {
447
447
watcher : watchFile (
448
448
fileName ,
449
- ( fileName , eventKind ) => forEach (
449
+ ( fileName , eventKind , modifiedTime ) => forEach (
450
450
callbacksCache . get ( path ) ,
451
- cb => cb ( fileName , eventKind )
451
+ cb => cb ( fileName , eventKind , modifiedTime )
452
452
) ,
453
453
pollingInterval ,
454
454
options
@@ -480,7 +480,7 @@ namespace ts {
480
480
const newTime = modifiedTime . getTime ( ) ;
481
481
if ( oldTime !== newTime ) {
482
482
watchedFile . mtime = modifiedTime ;
483
- watchedFile . callback ( watchedFile . fileName , getFileWatcherEventKind ( oldTime , newTime ) ) ;
483
+ watchedFile . callback ( watchedFile . fileName , getFileWatcherEventKind ( oldTime , newTime ) , modifiedTime ) ;
484
484
return true ;
485
485
}
486
486
@@ -776,7 +776,7 @@ namespace ts {
776
776
}
777
777
778
778
/*@internal */
779
- export type FsWatchCallback = ( eventName : "rename" | "change" , relativeFileName : string | undefined ) => void ;
779
+ export type FsWatchCallback = ( eventName : "rename" | "change" , relativeFileName : string | undefined , modifiedTime ?: Date ) => void ;
780
780
/*@internal */
781
781
export type FsWatch = ( fileOrDirectory : string , entryKind : FileSystemEntryKind , callback : FsWatchCallback , recursive : boolean , fallbackPollingInterval : PollingInterval , fallbackOptions : WatchOptions | undefined ) => FileWatcher ;
782
782
@@ -788,21 +788,22 @@ namespace ts {
788
788
789
789
/*@internal */
790
790
export function createFileWatcherCallback ( callback : FsWatchCallback ) : FileWatcherCallback {
791
- return ( _fileName , eventKind ) => callback ( eventKind === FileWatcherEventKind . Changed ? "change" : "rename" , "" ) ;
791
+ return ( _fileName , eventKind , modifiedTime ) => callback ( eventKind === FileWatcherEventKind . Changed ? "change" : "rename" , "" , modifiedTime ) ;
792
792
}
793
793
794
794
function createFsWatchCallbackForFileWatcherCallback (
795
795
fileName : string ,
796
796
callback : FileWatcherCallback ,
797
- fileExists : System [ "fileExists" ]
797
+ getModifiedTime : NonNullable < System [ "getModifiedTime" ] >
798
798
) : FsWatchCallback {
799
- return eventName => {
799
+ return ( eventName , _relativeFileName , modifiedTime ) => {
800
800
if ( eventName === "rename" ) {
801
- callback ( fileName , fileExists ( fileName ) ? FileWatcherEventKind . Created : FileWatcherEventKind . Deleted ) ;
801
+ modifiedTime ||= getModifiedTime ( fileName ) || missingFileModifiedTime ;
802
+ callback ( fileName , modifiedTime !== missingFileModifiedTime ? FileWatcherEventKind . Created : FileWatcherEventKind . Deleted , modifiedTime ) ;
802
803
}
803
804
else {
804
805
// Change
805
- callback ( fileName , FileWatcherEventKind . Changed ) ;
806
+ callback ( fileName , FileWatcherEventKind . Changed , modifiedTime ) ;
806
807
}
807
808
} ;
808
809
}
@@ -850,7 +851,6 @@ namespace ts {
850
851
clearTimeout : NonNullable < System [ "clearTimeout" ] > ;
851
852
// For fs events :
852
853
fsWatch : FsWatch ;
853
- fileExists : System [ "fileExists" ] ;
854
854
useCaseSensitiveFileNames : boolean ;
855
855
getCurrentDirectory : System [ "getCurrentDirectory" ] ;
856
856
fsSupportsRecursiveFsWatch : boolean ;
@@ -871,7 +871,6 @@ namespace ts {
871
871
setTimeout,
872
872
clearTimeout,
873
873
fsWatch,
874
- fileExists,
875
874
useCaseSensitiveFileNames,
876
875
getCurrentDirectory,
877
876
fsSupportsRecursiveFsWatch,
@@ -908,7 +907,7 @@ namespace ts {
908
907
return fsWatch (
909
908
fileName ,
910
909
FileSystemEntryKind . File ,
911
- createFsWatchCallbackForFileWatcherCallback ( fileName , callback , fileExists ) ,
910
+ createFsWatchCallbackForFileWatcherCallback ( fileName , callback , getModifiedTime ) ,
912
911
/*recursive*/ false ,
913
912
pollingInterval ,
914
913
getFallbackOptions ( options )
@@ -1297,7 +1296,6 @@ namespace ts {
1297
1296
fsWatch,
1298
1297
useCaseSensitiveFileNames,
1299
1298
getCurrentDirectory,
1300
- fileExists,
1301
1299
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
1302
1300
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
1303
1301
fsSupportsRecursiveFsWatch,
@@ -1542,7 +1540,7 @@ namespace ts {
1542
1540
close : ( ) => _fs . unwatchFile ( fileName , fileChanged )
1543
1541
} ;
1544
1542
1545
- function fileChanged ( curr : any , prev : any ) {
1543
+ function fileChanged ( curr : import ( "fs" ) . Stats , prev : import ( "fs" ) . Stats ) {
1546
1544
// previous event kind check is to ensure we recongnize the file as previously also missing when it is restored or renamed twice (that is it disappears and reappears)
1547
1545
// In such case, prevTime returned is same as prev time of event when file was deleted as per node documentation
1548
1546
const isPreviouslyDeleted = + prev . mtime === 0 || eventKind === FileWatcherEventKind . Deleted ;
@@ -1564,7 +1562,7 @@ namespace ts {
1564
1562
// File changed
1565
1563
eventKind = FileWatcherEventKind . Changed ;
1566
1564
}
1567
- callback ( fileName , eventKind ) ;
1565
+ callback ( fileName , eventKind , curr . mtime ) ;
1568
1566
}
1569
1567
}
1570
1568
@@ -1599,10 +1597,10 @@ namespace ts {
1599
1597
* Invoke the callback with rename and update the watcher if not closed
1600
1598
* @param createWatcher
1601
1599
*/
1602
- function invokeCallbackAndUpdateWatcher ( createWatcher : ( ) => FileWatcher ) {
1600
+ function invokeCallbackAndUpdateWatcher ( createWatcher : ( ) => FileWatcher , modifiedTime ?: Date ) {
1603
1601
sysLog ( `sysLog:: ${ fileOrDirectory } :: Changing watcher to ${ createWatcher === watchPresentFileSystemEntry ? "Present" : "Missing" } FileSystemEntryWatcher` ) ;
1604
1602
// Call the callback for current directory
1605
- callback ( "rename" , "" ) ;
1603
+ callback ( "rename" , "" , modifiedTime ) ;
1606
1604
1607
1605
// If watcher is not closed, update it
1608
1606
if ( watcher ) {
@@ -1656,13 +1654,14 @@ namespace ts {
1656
1654
function callbackChangingToMissingFileSystemEntry ( event : "rename" | "change" , relativeName : string | undefined ) {
1657
1655
// because relativeName is not guaranteed to be correct we need to check on each rename with few combinations
1658
1656
// Eg on ubuntu while watching app/node_modules the relativeName is "node_modules" which is neither relative nor full path
1657
+ const modifiedTime = getModifiedTime ( fileOrDirectory ) || missingFileModifiedTime ;
1659
1658
return event === "rename" &&
1660
1659
( ! relativeName ||
1661
1660
relativeName === lastDirectoryPart ||
1662
1661
( relativeName . lastIndexOf ( lastDirectoryPartWithDirectorySeparator ! ) !== - 1 && relativeName . lastIndexOf ( lastDirectoryPartWithDirectorySeparator ! ) === relativeName . length - lastDirectoryPartWithDirectorySeparator ! . length ) ) &&
1663
- ! fileSystemEntryExists ( fileOrDirectory , entryKind ) ?
1664
- invokeCallbackAndUpdateWatcher ( watchMissingFileSystemEntry ) :
1665
- callback ( event , relativeName ) ;
1662
+ modifiedTime === missingFileModifiedTime ?
1663
+ invokeCallbackAndUpdateWatcher ( watchMissingFileSystemEntry , modifiedTime ) :
1664
+ callback ( event , relativeName , modifiedTime ) ;
1666
1665
}
1667
1666
1668
1667
/**
@@ -1685,12 +1684,15 @@ namespace ts {
1685
1684
function watchMissingFileSystemEntry ( ) : FileWatcher {
1686
1685
return watchFile (
1687
1686
fileOrDirectory ,
1688
- ( _fileName , eventKind ) => {
1689
- if ( eventKind === FileWatcherEventKind . Created && fileSystemEntryExists ( fileOrDirectory , entryKind ) ) {
1690
- // Call the callback for current file or directory
1691
- // For now it could be callback for the inner directory creation,
1692
- // but just return current directory, better than current no-op
1693
- invokeCallbackAndUpdateWatcher ( watchPresentFileSystemEntry ) ;
1687
+ ( _fileName , eventKind , modifiedTime ) => {
1688
+ if ( eventKind === FileWatcherEventKind . Created ) {
1689
+ modifiedTime ||= getModifiedTime ( fileOrDirectory ) || missingFileModifiedTime ;
1690
+ if ( modifiedTime !== missingFileModifiedTime ) {
1691
+ // Call the callback for current file or directory
1692
+ // For now it could be callback for the inner directory creation,
1693
+ // but just return current directory, better than current no-op
1694
+ invokeCallbackAndUpdateWatcher ( watchPresentFileSystemEntry , modifiedTime ) ;
1695
+ }
1694
1696
}
1695
1697
} ,
1696
1698
fallbackPollingInterval ,
0 commit comments