@@ -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 : {
@@ -48,6 +49,7 @@ const kLineSplitRegex = /(?<=\r?\n)/u;
4849const kStatusRegex = / \/ \* n o d e : c o v e r a g e (?< status > e n a b l e | d i s a b l e ) \* \/ / ;
4950const kTypeOnlyImportRegex = / ^ \s * i m p o r t \s + t y p e \b / u;
5051const kTypeScriptSourceRegex = / \. (?: c t s | m t s | t s ) $ / u;
52+ const kSourceFileGlob = '**/*.{cjs,cts,js,mjs,mts,ts}' ;
5153
5254let stripTypeScriptTypesForCoverage ;
5355
@@ -407,6 +409,10 @@ class TestCoverage {
407409 this . mergeCoverage ( result , this . mapCoverageWithSourceMap ( coverage ) ) ;
408410 }
409411
412+ if ( this . options . coverageIncludeAll ) {
413+ this . #addUntestedFileCoverage( result ) ;
414+ }
415+
410416 return ArrayFrom ( result . values ( ) ) ;
411417 } finally {
412418 if ( dir ) {
@@ -415,6 +421,48 @@ class TestCoverage {
415421 }
416422 }
417423
424+ #addUntestedFileCoverage( merged ) {
425+ const files = globSync ( kSourceFileGlob , {
426+ __proto__ : null ,
427+ cwd : this . options . cwd ,
428+ // Skip node_modules/, since `shouldSkipFileCoverage` would skip it anyway
429+ exclude : ( name ) => name === 'node_modules' ,
430+ } ) ;
431+
432+ for ( let i = 0 ; i < files . length ; ++ i ) {
433+ const url = pathToFileURL ( resolve ( this . options . cwd , files [ i ] ) ) . href ;
434+
435+ if ( merged . has ( url ) || this . shouldSkipFileCoverage ( url ) ) {
436+ continue ;
437+ }
438+
439+ this . markTypeScriptOnlyLines ( url ) ;
440+ const lines = this . getLines ( url ) ;
441+
442+ if ( ! lines || lines . length === 0 ) {
443+ continue ;
444+ }
445+
446+ const lastLine = lines [ lines . length - 1 ] ;
447+
448+ merged . set ( url , {
449+ __proto__ : null ,
450+ url,
451+ functions : [ {
452+ __proto__ : null ,
453+ functionName : '' ,
454+ isBlockCoverage : false ,
455+ ranges : [ {
456+ __proto__ : null ,
457+ startOffset : 0 ,
458+ endOffset : lastLine . startOffset + lastLine . src . length ,
459+ count : 0 ,
460+ } ] ,
461+ } ] ,
462+ } ) ;
463+ }
464+ }
465+
418466
419467 mapCoverageWithSourceMap ( coverage ) {
420468 const { result } = coverage ;
0 commit comments