v8-to-istanbul: Cannot read properties of undefined (reading 'endCol')

I am getting Cannot read properties of undefined (reading 'endCol') when trying to generate coverage after a jest test run when using @swc/jest as a transformer.

Error

TypeError: Cannot read properties of undefined (reading 'endCol')
    at module.exports.sliceRange (/workspace/node_modules/.pnpm/v8-to-istanbul@9.0.1/node_modules/v8-to-istanbul/lib/range.js:30:54)
    at /workspace/node_modules/.pnpm/v8-to-istanbul@9.0.1/node_modules/v8-to-istanbul/lib/v8-to-istanbul.js:139:19
    at Array.forEach (<anonymous>)
    at /workspace/node_modules/.pnpm/v8-to-istanbul@9.0.1/node_modules/v8-to-istanbul/lib/v8-to-istanbul.js:125:20
    at Array.forEach (<anonymous>)
    at V8ToIstanbul.applyCoverage (/workspace/node_modules/.pnpm/v8-to-istanbul@9.0.1/node_modules/v8-to-istanbul/lib/v8-to-istanbul.js:124:12)

Details

During this call: https://github.com/istanbuljs/v8-to-istanbul/blob/b5ecd8242cf64389c9a656d78530bd0428edf195/lib/v8-to-istanbul.js#L205

_maybeRemapStartColEndCol({
  count: 0,
  startOffset: 340,
  endOffset: 348
})

It receives object with all properties null from originalPositionFor here: https://github.com/istanbuljs/v8-to-istanbul/blob/b5ecd8242cf64389c9a656d78530bd0428edf195/lib/source.js#L105

Which causes it to fail somewhere down the line.

Source File

export const noop = () => Promise.resolve();
export const noopSync = () => {
  /* noop */
};

Transformed File

If I transform it with @swc with source maps enabled, I get this:

"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: all[name]
    });
}
_export(exports, {
    noop: ()=>noop,
    noopSync: ()=>noopSync
});
const noop = ()=>Promise.resolve();
const noopSync = ()=>{
/* noop */ };

//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi93b3Jrc3BhY2Uvc3JjL3V0aWxzL2Z1bmN0aW9uLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCBub29wID0gKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCk7XG5leHBvcnQgY29uc3Qgbm9vcFN5bmMgPSAoKSA9PiB7XG4gIC8qIG5vb3AgKi9cbn07XG4iXSwibmFtZXMiOlsibm9vcCIsIm5vb3BTeW5jIiwiUHJvbWlzZSIsInJlc29sdmUiXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7OztJQUFhQSxJQUFJLE1BQUpBO0lBQ0FDLFFBQVEsTUFBUkE7O0FBRE4sTUFBTUQsT0FBTyxJQUFNRSxRQUFRQyxPQUFPO0FBQ2xDLE1BQU1GLFdBQVcsSUFBTTtBQUM1QixRQUFRLEdBQ1YifQ==

Source map

{
    "version": 3,
    "sources": [
        "/workspace/src/utils/function.ts"
    ],
    "sourcesContent": [
        "export const noop = () => Promise.resolve();\nexport const noopSync = () => {\n  /* noop */\n};\n"
    ],
    "names": [
        "noop",
        "noopSync",
        "Promise",
        "resolve"
    ],
    "mappings": "AAAA;;;;;;;;;;;IAAaA,IAAI,MAAJA;IACAC,QAAQ,MAARA;;AADN,MAAMD,OAAO,IAAME,QAAQC,OAAO;AAClC,MAAMF,WAAW,IAAM;AAC5B,QAAQ,GACV"
}

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 17
  • Comments: 24 (5 by maintainers)

Commits related to this issue

Most upvoted comments

Not sure if this will help anyone, but I encountered the same issue, the file was exporting constants only:

export const XXXXXXX = 'something'
export const YYYYYYY = 'something'

After tracking down the issue, I figured out the solution, I just added one space above the very first export, so my file became:

// Constants

export const XXXXXXX = 'something'
export const YYYYYYY = 'something'

I guessed it because in the file range.js, I found that the end variable was -1, so by adding that comment line on top of the file, the issue went away.

Having an export const in the first line of the file was the problem for me. Adding a comment in line 1 and a return in line 2 as @aladinflux did worked for me.

1   // leave this line here so the test coverage won't break
2
3   export const func = () => {...}

🤷‍♂️

i’ve run into this too, i’ve pinned @swc/core at 1.3.3, every patch release after that seems to cause this error

    "@swc/core": "1.3.36",
    "@swc/jest": "0.2.24",

today’s latest, doesn’t work.

I ran into this today as well and really appreciate all the suggestions here but have to many tests to go one by one. In order to find the file that had export const at the top I modified ./node_modules/v8-to-istanbul/lib/v8-to-istanbul.js:146. Wrapping the call site in a try/catch and logging the path shows you which file is the issue. Hope it helps until a fix can be merged 👍

} else {
  try {
    lines = sliceRange(covSource.lines, startCol, endCol)
  } catch (e) {
    console.log(path);
    console.log(e);
  }
}

Ran into this same issue, and pinning the @swc/jest version didn’t work. @aladinflux, thank you for the idea to check for top-line exports; that ended up being the problem.

For other folks’ reference, I had to:

  1. isolate the one test in our suite that was throwing this error, and run it alone
  2. comment out every import in the file, and run again. Test fails, but coverage bug does not appear.
  3. one by one, uncomment an import and run the test again. If the coverage bug still does not appear, uncomment the next import and run again. If you uncomment an import and the coverage bug reappears, you’ll know the issue is somewhere in the import tree of that file. Open it.
  4. Repeat steps 2 and 3 until you reach the leaf node(s) of your problem. Pay particular attention to any files whose first line is an export–add a comment and newline to the top of the file. Keep going til it’s fixed.
  5. If your import tree was as large as mine, indulge in your vice of choice

As @aladinflux and @mitestainer, adding a comment in line 1 of a file that was only exporting constants solved the issue (which was previously encountered in another project, and back then strangely resolved by lowering axios from 1.2.3 to 1.1.3). Quite curious as to why it happens.

I lowered @swc/jest to version 2.20 and it worked!

Hi, same issue experienced here. Independently to a proper and source based fix we have an easy patch applied at @jest/reporters/v8-to-istanbul@^9.0.1

diff --git a/lib/range.js b/lib/range.js
index 4abdfe78be6c8fab30225d65970cf66cb055f941..901722bcee414924eafe8b4585d2f0522ba8681e 100644
--- a/lib/range.js
+++ b/lib/range.js
@@ -16,7 +16,7 @@ module.exports.sliceRange = (lines, startCol, endCol, inclusive = false) => {
     if (startCol >= lines[mid].endCol) {
       start = mid + 1
     } else if (endCol < lines[mid].startCol) {
-      end = mid - 1
+      end = Math.max(mid - 1, start);
     } else {
       end = mid
       while (mid >= 0 && startCol < lines[mid].endCol && endCol >= lines[mid].startCol) {

That makes end not go beneath start position. I would suggest to add that to a PR but knowing that is not a fix of the problem creator but a problem stopper.