github.com/evanw/esbuild@v0.21.4/internal/cache/cache_fs.go (about) 1 package cache 2 3 import ( 4 "sync" 5 6 "github.com/evanw/esbuild/internal/fs" 7 ) 8 9 // This cache uses information from the "stat" syscall to try to avoid re- 10 // reading files from the file system during subsequent builds if the file 11 // hasn't changed. The assumption is reading the file metadata is faster than 12 // reading the file contents. 13 14 type FSCache struct { 15 entries map[string]*fsEntry 16 mutex sync.Mutex 17 } 18 19 type fsEntry struct { 20 contents string 21 modKey fs.ModKey 22 isModKeyUsable bool 23 } 24 25 func (c *FSCache) ReadFile(fs fs.FS, path string) (contents string, canonicalError error, originalError error) { 26 entry := func() *fsEntry { 27 c.mutex.Lock() 28 defer c.mutex.Unlock() 29 return c.entries[path] 30 }() 31 32 // If the file's modification key hasn't changed since it was cached, assume 33 // the contents of the file are also the same and skip reading the file. 34 modKey, modKeyErr := fs.ModKey(path) 35 if entry != nil && entry.isModKeyUsable && modKeyErr == nil && entry.modKey == modKey { 36 return entry.contents, nil, nil 37 } 38 39 contents, err, originalError := fs.ReadFile(path) 40 if err != nil { 41 return "", err, originalError 42 } 43 44 c.mutex.Lock() 45 defer c.mutex.Unlock() 46 c.entries[path] = &fsEntry{ 47 contents: contents, 48 modKey: modKey, 49 isModKeyUsable: modKeyErr == nil, 50 } 51 return contents, nil, nil 52 }