@@ -20,6 +20,7 @@ const {
2020} = primordials ;
2121const {
2222 copyFileSync,
23+ globSync,
2324 mkdirSync,
2425 mkdtempSync,
2526 opendirSync,
@@ -29,7 +30,7 @@ const {
2930const { setupCoverageHooks } = require ( 'internal/util' ) ;
3031const { tmpdir } = require ( 'os' ) ;
3132const { join, resolve, relative } = require ( 'path' ) ;
32- const { fileURLToPath, URL } = require ( 'internal/url' ) ;
33+ const { fileURLToPath, pathToFileURL , URL } = require ( 'internal/url' ) ;
3334const { kMappings, SourceMap } = require ( 'internal/source_map/source_map' ) ;
3435const {
3536 codes : {
@@ -51,6 +52,7 @@ const kStatusRegex = /\/\* node:coverage (?<status>enable|disable) \*\//;
5152const kMatchGlobPatternOptions = { __proto__ : null , dot : true } ;
5253const kTypeOnlyImportRegex = / ^ \s * i m p o r t \s + t y p e \b / u;
5354const kTypeScriptSourceRegex = / \. (?: c t s | m t s | t s ) $ / u;
55+ const kSourceFileGlob = '**/*.{cjs,cts,js,mjs,mts,ts}' ;
5456
5557let stripTypeScriptTypesForCoverage ;
5658
@@ -418,6 +420,10 @@ class TestCoverage {
418420 this . mergeCoverage ( result , this . mapCoverageWithSourceMap ( coverage ) ) ;
419421 }
420422
423+ if ( this . options . coverageIncludeAll ) {
424+ this . #addUntestedFileCoverage( result ) ;
425+ }
426+
421427 return ArrayFrom ( result . values ( ) ) ;
422428 } finally {
423429 if ( dir ) {
@@ -426,6 +432,48 @@ class TestCoverage {
426432 }
427433 }
428434
435+ #addUntestedFileCoverage( merged ) {
436+ const files = globSync ( kSourceFileGlob , {
437+ __proto__ : null ,
438+ cwd : this . options . cwd ,
439+ // Skip node_modules/, since `shouldSkipFileCoverage` would skip it anyway
440+ exclude : ( name ) => name === 'node_modules' ,
441+ } ) ;
442+
443+ for ( let i = 0 ; i < files . length ; ++ i ) {
444+ const url = pathToFileURL ( resolve ( this . options . cwd , files [ i ] ) ) . href ;
445+
446+ if ( merged . has ( url ) || this . shouldSkipFileCoverage ( url ) ) {
447+ continue ;
448+ }
449+
450+ this . markTypeScriptOnlyLines ( url ) ;
451+ const lines = this . getLines ( url ) ;
452+
453+ if ( ! lines || lines . length === 0 ) {
454+ continue ;
455+ }
456+
457+ const lastLine = lines [ lines . length - 1 ] ;
458+
459+ merged . set ( url , {
460+ __proto__ : null ,
461+ url,
462+ functions : [ {
463+ __proto__ : null ,
464+ functionName : '' ,
465+ isBlockCoverage : false ,
466+ ranges : [ {
467+ __proto__ : null ,
468+ startOffset : 0 ,
469+ endOffset : lastLine . startOffset + lastLine . src . length ,
470+ count : 0 ,
471+ } ] ,
472+ } ] ,
473+ } ) ;
474+ }
475+ }
476+
429477
430478 mapCoverageWithSourceMap ( coverage ) {
431479 const { result } = coverage ;
0 commit comments