@@ -164,8 +164,13 @@ export function createSvelteModuleLoader(
164164 > ( ) ;
165165
166166 const impliedNodeFormatResolver = new ImpliedNodeFormatResolver ( tsSystem ) ;
167- const failedPathToContainingFile = new FileMap < FileSet > ( ) ;
168- const failedLocationInvalidated = new FileSet ( ) ;
167+ const resolutionWithFailedLookup = new Set <
168+ ts . ResolvedModuleWithFailedLookupLocations & {
169+ files ?: Set < string > ;
170+ }
171+ > ( ) ;
172+ const failedLocationInvalidated = new FileSet ( tsSystem . useCaseSensitiveFileNames ) ;
173+ const pendingFailedLocationCheck = new FileSet ( tsSystem . useCaseSensitiveFileNames ) ;
169174
170175 return {
171176 svelteFileExists : svelteSys . svelteFileExists ,
@@ -179,16 +184,7 @@ export function createSvelteModuleLoader(
179184 deleteUnresolvedResolutionsFromCache : ( path : string ) => {
180185 svelteSys . deleteFromCache ( path ) ;
181186 moduleCache . deleteUnresolvedResolutionsFromCache ( path ) ;
182-
183- const previousTriedButFailed = failedPathToContainingFile . get ( path ) ;
184-
185- if ( ! previousTriedButFailed ) {
186- return ;
187- }
188-
189- for ( const containingFile of previousTriedButFailed ) {
190- failedLocationInvalidated . add ( containingFile ) ;
191- }
187+ pendingFailedLocationCheck . add ( path ) ;
192188
193189 tsModuleCache . clear ( ) ;
194190 typeReferenceCache . clear ( ) ;
@@ -197,7 +193,8 @@ export function createSvelteModuleLoader(
197193 resolveTypeReferenceDirectiveReferences,
198194 mightHaveInvalidatedResolutions,
199195 clearPendingInvalidations,
200- getModuleResolutionCache : ( ) => tsModuleCache
196+ getModuleResolutionCache : ( ) => tsModuleCache ,
197+ invalidateFailedLocationResolution
201198 } ;
202199
203200 function resolveModuleNames (
@@ -222,11 +219,7 @@ export function createSvelteModuleLoader(
222219 options
223220 ) ;
224221
225- resolvedModule ?. failedLookupLocations ?. forEach ( ( failedLocation ) => {
226- const failedPaths = failedPathToContainingFile . get ( failedLocation ) ?? new FileSet ( ) ;
227- failedPaths . add ( containingFile ) ;
228- failedPathToContainingFile . set ( failedLocation , failedPaths ) ;
229- } ) ;
222+ cacheResolutionWithFailedLookup ( resolvedModule , containingFile ) ;
230223
231224 moduleCache . set ( moduleName , containingFile , resolvedModule ?. resolvedModule ) ;
232225 return resolvedModule ?. resolvedModule ;
@@ -333,5 +326,46 @@ export function createSvelteModuleLoader(
333326 function clearPendingInvalidations ( ) {
334327 moduleCache . clearPendingInvalidations ( ) ;
335328 failedLocationInvalidated . clear ( ) ;
329+ pendingFailedLocationCheck . clear ( ) ;
330+ }
331+
332+ function cacheResolutionWithFailedLookup (
333+ resolvedModule : ts . ResolvedModuleWithFailedLookupLocations & {
334+ files ?: Set < string > ;
335+ } ,
336+ containingFile : string
337+ ) {
338+ if ( ! resolvedModule . failedLookupLocations ?. length ) {
339+ return ;
340+ }
341+
342+ // The resolvedModule object will be reused in different files. A bit hacky, but TypeScript also does this.
343+ // https://github.com/microsoft/TypeScript/blob/11e79327598db412a161616849041487673fadab/src/compiler/resolutionCache.ts#L1103
344+ resolvedModule . files ??= new Set ( ) ;
345+ resolvedModule . files . add ( containingFile ) ;
346+ resolutionWithFailedLookup . add ( resolvedModule ) ;
347+ }
348+
349+ function invalidateFailedLocationResolution ( ) {
350+ resolutionWithFailedLookup . forEach ( ( resolvedModule ) => {
351+ if (
352+ ! resolvedModule . resolvedModule ||
353+ ! resolvedModule . files ||
354+ ! resolvedModule . failedLookupLocations
355+ ) {
356+ return ;
357+ }
358+ for ( const location of resolvedModule . failedLookupLocations ) {
359+ if ( pendingFailedLocationCheck . has ( location ) ) {
360+ moduleCache . delete ( resolvedModule . resolvedModule . resolvedFileName ) ;
361+ resolvedModule . files ?. forEach ( ( file ) => {
362+ failedLocationInvalidated . add ( file ) ;
363+ } ) ;
364+ break ;
365+ }
366+ }
367+ } ) ;
368+
369+ pendingFailedLocationCheck . clear ( ) ;
336370 }
337371}
0 commit comments