Skip to content

Commit

Permalink
fix: Proper data validation in findNearestContainer (#754)
Browse files Browse the repository at this point in the history
This prevents a thrown when the statement map needs to be processed for
container hits, because the statement map entries do not contain a "loc"
field, they just have this inforation at the top level.

Fix: #753
  • Loading branch information
isaacs committed Nov 7, 2023
1 parent c9f6e64 commit c4895bb
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 2 deletions.
12 changes: 10 additions & 2 deletions packages/istanbul-lib-coverage/lib/file-coverage.js
Expand Up @@ -45,13 +45,21 @@ function assertValidObject(obj) {
const keyFromLoc = ({ start, end }) =>
`${start.line}|${start.column}|${end.line}|${end.column}`;

const isObj = o => !!o && typeof o === 'object';
const isLineCol = o =>
isObj(o) && typeof o.line === 'number' && typeof o.column === 'number';
const isLoc = o => isObj(o) && isLineCol(o.start) && isLineCol(o.end);
const getLoc = o => (isLoc(o) ? o : isLoc(o.loc) ? o.loc : null);

// When merging, we can have a case where two ranges cover
// the same block of code with `hits=1`, and each carve out a
// different range with `hits=0` to indicate it's uncovered.
// Find the nearest container so that we can properly indicate
// that both sections are hit.
// Returns null if no containing item is found.
const findNearestContainer = (item, map) => {
const itemLoc = getLoc(item);
if (!itemLoc) return null;
// the B item is not an identified range in the A set, BUT
// it may be contained by an identified A range. If so, then
// any hit of that containing A range counts as a hit of this
Expand All @@ -62,8 +70,8 @@ const findNearestContainer = (item, map) => {
let containerDistance = null;
let containerKey = null;
for (const [i, mapItem] of Object.entries(map)) {
const mapLoc = mapItem.loc;
const itemLoc = item.loc;
const mapLoc = getLoc(mapItem);
if (!mapLoc) continue;
// contained if all of line distances are > 0
// or line distance is 0 and col dist is >= 0
const distance = [
Expand Down
17 changes: 17 additions & 0 deletions packages/istanbul-lib-coverage/test/file.test.js
Expand Up @@ -1123,3 +1123,20 @@ describe('addNearestContainerHits unit coverage', () => {
);
});
});

describe('findNearestContainer missing loc defense', () => {
it('does not throw if loc is missing', () => {
const loc = (sl, sc, el, ec) => ({
start: { line: sl, column: sc },
end: { line: el, column: ec }
});
const map = {
0: { loc: loc(1, 1, 100, 100) },
1: {},
2: loc(10, 10, 50, 50),
3: { loc: loc(20, 20, 40, 40) }
};
assert.equal(findNearestContainer({ no: 'loc' }, map), null);
assert.equal(findNearestContainer(loc(30, 30, 35, 35), '3'));
});
});

0 comments on commit c4895bb

Please sign in to comment.