@@ -184,8 +184,12 @@ const createCheckAliveURL = (ruleOptions: Options, resolvePath: (path: string, b
184184 // and see what kind of redirect is occurring
185185 redirect : "manual" as RequestRedirect
186186 } ;
187+
188+ // Declare the variable outside the try-catch block to ensure the body is always consumed in `finally`.
189+ let res : Response | null = null ;
190+
187191 try {
188- const res = await fetchWithDefaults ( uri , opts ) ;
192+ res = await fetchWithDefaults ( uri , opts ) ;
189193 const errorResult = {
190194 ok : false ,
191195 redirected : true ,
@@ -214,6 +218,7 @@ const createCheckAliveURL = (ruleOptions: Options, resolvePath: (path: string, b
214218 const finalRes = await fetchWithDefaults ( redirectedUrl , { ...opts , redirect : "follow" } ) ;
215219 const url = URL . parse ( uri ) ;
216220 const hash = url ?. hash || null ;
221+ await finalRes . body ?. cancel ( ) ;
217222 return {
218223 ok : finalRes . ok ,
219224 redirected : true ,
@@ -264,6 +269,10 @@ const createCheckAliveURL = (ruleOptions: Options, resolvePath: (path: string, b
264269 ok : false ,
265270 message : ex . message
266271 } ;
272+ } finally {
273+ if ( res && ! res . body ?. locked ) {
274+ await res . body ?. cancel ( ) ;
275+ }
267276 }
268277 } ;
269278} ;
@@ -289,6 +298,11 @@ async function isAliveLocalFile(filePath: string): Promise<AliveFunctionReturn>
289298 }
290299}
291300
301+ const memorizedIsAliveURIByOptions = new Map <
302+ string ,
303+ ReturnType < typeof pMemoize < ReturnType < typeof createCheckAliveURL > > >
304+ > ( ) ;
305+
292306const reporter : TextlintRuleReporter < Options > = ( context , options ) => {
293307 const { Syntax, getSource, report, RuleError, fixer, getFilePath, locator } = context ;
294308 const helper = new RuleHelper ( context ) ;
@@ -307,10 +321,21 @@ const reporter: TextlintRuleReporter<Options> = (context, options) => {
307321 }
308322 }
309323 } ;
310- const isAliveURI = createCheckAliveURL ( ruleOptions , resolvePath ) ;
311- const memorizedIsAliveURI = pMemoize ( isAliveURI , {
312- maxAge : ruleOptions . linkMaxAge
313- } ) ;
324+ const memorizedIsAliveURI = ( ( ) => {
325+ const memoOptionsKey = JSON . stringify ( ruleOptions ) ;
326+ const func = memorizedIsAliveURIByOptions . get ( memoOptionsKey ) ;
327+ if ( ! func ) {
328+ const isAliveURI = createCheckAliveURL ( ruleOptions , resolvePath ) ;
329+ const func = pMemoize ( isAliveURI , {
330+ maxAge : ruleOptions . linkMaxAge
331+ } ) ;
332+ memorizedIsAliveURIByOptions . set ( memoOptionsKey , func ) ;
333+ return func ;
334+ }
335+
336+ return func ;
337+ } ) ( ) ;
338+
314339 /**
315340 * Checks a given URI's availability and report if it is dead.
316341 * @param {TextLintNode } node TextLintNode the URI belongs to.
0 commit comments