@@ -318,34 +318,73 @@ class CppReferenceExtension {
318318 const isDevelopOnly = this . config . version === 'develop'
319319
320320 // Sort the releases by the date of their latest asset
321- releasesInfo . sort ( ( a , b ) => {
322- // check if at least one asset exists
323- if ( ! a . assets ) {
324- return 1
325- }
326- if ( ! b . assets ) {
327- return - 1
321+ const releasesArray = Array . isArray ( releasesInfo ) ? releasesInfo : [ ]
322+ if ( ! Array . isArray ( releasesInfo ) ) {
323+ this . logger . warn ( 'GitHub releases response is not an array. Skipping malformed response.' )
324+ return
325+ }
326+
327+ const sanitizedReleases = [ ]
328+ releasesArray . forEach ( ( release , releaseIndex ) => {
329+ if ( ! release || typeof release !== 'object' ) {
330+ this . logger . debug ( `Skipping release at index ${ releaseIndex } because it is not an object.` )
331+ return
328332 }
329- // check if at least one asset has an updated_at field
330- if ( ! a . assets . some ( asset => asset . updated_at ) ) {
331- return 1
333+
334+ const releaseTag = typeof release . tag_name === 'string' && release . tag_name . trim ( )
335+ ? release . tag_name . trim ( )
336+ : null
337+ if ( ! releaseTag ) {
338+ this . logger . debug ( `Skipping release at index ${ releaseIndex } because tag_name is missing or invalid.` )
339+ return
332340 }
333- if ( ! b . assets . some ( asset => asset . updated_at ) ) {
334- return - 1
341+
342+ const rawAssets = Array . isArray ( release . assets ) ? release . assets : [ ]
343+ if ( ! Array . isArray ( release . assets ) ) {
344+ this . logger . debug ( `Skipping release ${ releaseTag } because assets is not an array.` )
345+ return
335346 }
336347
337- // Find the latest asset in each release
338- const latestAssetA = a . assets . reduce ( ( latest , asset ) => {
339- return new Date ( asset . updated_at ) > new Date ( latest . updated_at ) ? asset : latest ;
340- } , a . assets [ 0 ] ) ;
348+ const validAssets = [ ]
349+ rawAssets . forEach ( ( asset , assetIndex ) => {
350+ if ( ! asset || typeof asset !== 'object' ) {
351+ this . logger . debug ( `Skipping asset ${ releaseTag } #${ assetIndex } because it is not an object.` )
352+ return
353+ }
354+
355+ const downloadUrl = typeof asset . browser_download_url === 'string' && asset . browser_download_url . trim ( )
356+ ? asset . browser_download_url . trim ( )
357+ : null
358+ if ( ! downloadUrl ) {
359+ this . logger . debug ( `Skipping asset ${ releaseTag } #${ assetIndex } because browser_download_url is missing or invalid.` )
360+ return
361+ }
362+
363+ const updatedAtRaw = asset . updated_at
364+ if ( ! updatedAtRaw ) {
365+ this . logger . debug ( `Skipping asset ${ downloadUrl } because updated_at is missing.` )
366+ return
367+ }
368+
369+ const updatedAt = new Date ( updatedAtRaw )
370+ if ( Number . isNaN ( updatedAt . getTime ( ) ) ) {
371+ this . logger . debug ( `Skipping asset ${ downloadUrl } because updated_at "${ updatedAtRaw } " is not a valid date.` )
372+ return
373+ }
374+
375+ validAssets . push ( { asset, updatedAt, downloadUrl} )
376+ } )
341377
342- const latestAssetB = b . assets . reduce ( ( latest , asset ) => {
343- return new Date ( asset . updated_at ) > new Date ( latest . updated_at ) ? asset : latest ;
344- } , b . assets [ 0 ] ) ;
378+ if ( ! validAssets . length ) {
379+ this . logger . debug ( `Skipping release ${ releaseTag } because it has no valid assets.` )
380+ return
381+ }
345382
346- // Sort the releases by the date of their latest asset
347- return new Date ( latestAssetB . updated_at ) - new Date ( latestAssetA . updated_at ) ;
348- } ) ;
383+ validAssets . sort ( ( a , b ) => b . updatedAt - a . updatedAt )
384+ sanitizedReleases . push ( { tag : releaseTag , assets : validAssets } )
385+ } )
386+
387+ sanitizedReleases . sort ( ( a , b ) => b . assets [ 0 ] . updatedAt - a . assets [ 0 ] . updatedAt )
349388
350389 // Determine the appropriate suffix for the current platform
351390 let platformSuffix ;
@@ -363,7 +402,7 @@ class CppReferenceExtension {
363402 throw new Error ( `Unsupported platform: ${ process . platform } . Supported platforms are win32, linux, and darwin.` ) ;
364403 }
365404
366- function isReleaseMatch ( releaseTag , logger ) {
405+ const isReleaseMatch = ( releaseTag , logger ) => {
367406 if ( isMatchAny ) {
368407 logger . debug ( `Matching any version. Found a release that satisfies the version requirement: ${ releaseTag } ` )
369408 return true ;
@@ -405,34 +444,21 @@ class CppReferenceExtension {
405444 }
406445
407446 // Iterate over the releases
408- for ( const release of releasesInfo ) {
409- if ( ! isReleaseMatch ( release . tag_name , this . logger ) ) {
447+ for ( const release of sanitizedReleases ) {
448+ if ( ! isReleaseMatch ( release . tag , this . logger ) ) {
410449 continue
411450 }
412451
413- if ( ! release . assets ) {
414- this . logger . debug ( `Skipping release ${ release . tag_name } as it has no assets` )
415- continue
416- }
417-
418- if ( ! release . assets . every ( asset => asset . updated_at ) ) {
419- this . logger . debug ( `Skipping release ${ release . tag_name } as it has assets without an updated_at field` )
420- continue
421- }
422-
423- // Sort release assets descending by updated_at
424- release . assets . sort ( ( a , b ) => new Date ( b . updated_at ) - new Date ( a . updated_at ) ) ;
425-
426452 // Iterate over the assets of the release
427- for ( const asset of release . assets ) {
453+ for ( const { asset, downloadUrl } of release . assets ) {
428454 // Check if the asset URL ends with the appropriate suffix for the platform
429- if ( asset . browser_download_url . endsWith ( platformSuffix ) ) {
455+ if ( downloadUrl . endsWith ( platformSuffix ) ) {
430456 // Return the URL of the asset and the tag name of the release
431- this . MrDocsVersion = release . tag_name
432- this . logger . debug ( `Found asset ${ asset . browser_download_url } for platform ${ process . platform } ` )
433- return { downloadUrl : asset . browser_download_url , downloadTag : release . tag_name } ;
457+ this . MrDocsVersion = release . tag
458+ this . logger . debug ( `Found asset ${ downloadUrl } for platform ${ process . platform } ` )
459+ return { downloadUrl, downloadTag : release . tag } ;
434460 }
435- this . logger . debug ( `Skipping asset ${ asset . browser_download_url } as it doesn't match the platform suffix ${ platformSuffix } ` )
461+ this . logger . debug ( `Skipping asset ${ downloadUrl } as it doesn't match the platform suffix ${ platformSuffix } ` )
436462 }
437463 }
438464
@@ -630,11 +656,16 @@ class CppReferenceExtension {
630656 'User-Agent' : 'request'
631657 }
632658 const releasesResponse = await axios . get ( 'https://api.github.com/repos/cppalliance/mrdocs/releases' , { headers : apiHeaders } )
633- const releasesInfo = releasesResponse . data
659+ const releasesInfo = Array . isArray ( releasesResponse && releasesResponse . data )
660+ ? releasesResponse . data
661+ : [ ]
662+ if ( ! Array . isArray ( releasesResponse && releasesResponse . data ) ) {
663+ this . logger . warn ( 'GitHub releases API did not return an array. Continuing with an empty list.' )
664+ }
634665 this . logger . debug ( `Found ${ releasesInfo . length } MrDocs releases` )
635666 const { downloadUrl, downloadTag } = this . findDownloadUrl ( releasesInfo )
636- if ( ! downloadUrl ) {
637- this . logger . error ( `Could not find MrDocs binaries for ${ process . platform } ` )
667+ if ( ! downloadUrl || ! downloadTag ) {
668+ this . logger . error ( `Could not find MrDocs binaries for ${ process . platform } . ` )
638669 process . exit ( 1 )
639670 }
640671 const mrdocsDownloadDir = path . join ( mrDocsTreeDir , process . platform )
@@ -1861,4 +1892,4 @@ class CppReferenceExtension {
18611892 }
18621893}
18631894
1864- module . exports = CppReferenceExtension
1895+ module . exports = CppReferenceExtension
0 commit comments