33 ArrayFrom,
44 ArrayPrototypeMap,
55 ArrayPrototypePush,
6+ ArrayPrototypeSort,
67 JSONParse,
78 MathFloor,
89 MathMax,
@@ -30,10 +31,8 @@ const { tmpdir } = require('os');
3031const { join, resolve, relative } = require ( 'path' ) ;
3132const { fileURLToPath, URL } = require ( 'internal/url' ) ;
3233const { kMappings, SourceMap } = require ( 'internal/source_map/source_map' ) ;
33- const { Parser : AcornParser } =
34- require ( 'internal/deps/acorn/acorn/dist/acorn' ) ;
35- const { simple : acornWalkSimple } =
36- require ( 'internal/deps/acorn/acorn-walk/dist/walk' ) ;
34+ let AcornParser ; // Lazy loaded -- only needed when statement coverage is enabled.
35+ let acornWalkSimple ;
3736const {
3837 codes : {
3938 ERR_SOURCE_MAP_CORRUPT ,
@@ -94,6 +93,11 @@ class TestCoverage {
9493 return null ;
9594 }
9695
96+ AcornParser ??=
97+ require ( 'internal/deps/acorn/acorn/dist/acorn' ) . Parser ;
98+ acornWalkSimple ??=
99+ require ( 'internal/deps/acorn/acorn-walk/dist/walk' ) . simple ;
100+
97101 const statements = [ ] ;
98102
99103 // Parse as script with permissive flags -- script mode is non-strict,
@@ -333,8 +337,6 @@ class TestCoverage {
333337 const statementReports = [ ] ;
334338
335339 if ( statements ) {
336- // Flatten all V8 coverage ranges into a single array so
337- // the statement loop only needs two levels of iteration.
338340 const allRanges = [ ] ;
339341 for ( let fi = 0 ; fi < functions . length ; ++ fi ) {
340342 const { ranges } = functions [ fi ] ;
@@ -343,13 +345,17 @@ class TestCoverage {
343345 }
344346 }
345347
348+ // Sort by startOffset so the inner loop can break early.
349+ ArrayPrototypeSort ( allRanges , ( a , b ) => a . startOffset - b . startOffset ) ;
350+
346351 for ( let j = 0 ; j < statements . length ; ++ j ) {
347352 const stmt = statements [ j ] ;
348353 let bestCount = 0 ;
349354 let bestSize = Infinity ;
350355
351356 for ( let ri = 0 ; ri < allRanges . length ; ++ ri ) {
352357 const range = allRanges [ ri ] ;
358+ if ( range . startOffset > stmt . startOffset ) break ;
353359 if ( doesRangeContainOtherRange ( range , stmt ) ) {
354360 const size = range . endOffset - range . startOffset ;
355361 if ( size < bestSize ) {
@@ -378,6 +384,11 @@ class TestCoverage {
378384 }
379385 }
380386
387+ // When the file could not be parsed (statements === null),
388+ // report 0% rather than the misleading 100% from toPercentage(0, 0).
389+ const coveredStmtPercent = statements != null ?
390+ toPercentage ( statementsCovered , totalStatements ) : 0 ;
391+
381392 ArrayPrototypePush ( coverageSummary . files , {
382393 __proto__ : null ,
383394 path : fileURLToPath ( url ) ,
@@ -392,7 +403,7 @@ class TestCoverage {
392403 coveredLinePercent : toPercentage ( coveredCnt , lines . length ) ,
393404 coveredBranchPercent : toPercentage ( branchesCovered , totalBranches ) ,
394405 coveredFunctionPercent : toPercentage ( functionsCovered , totalFunctions ) ,
395- coveredStatementPercent : toPercentage ( statementsCovered , totalStatements ) ,
406+ coveredStatementPercent : coveredStmtPercent ,
396407 functions : functionReports ,
397408 branches : branchReports ,
398409 lines : lineReports ,
0 commit comments