Skip to content

Expose lineLengths from source map cache #48460

@isaacs

Description

@isaacs

What is the problem this feature will solve?

Currently, if a test framework (or any other kind of program) wants to do anything interesting with source maps or V8's built-in coverage APIs, they need to be able to get at the lineLengths in order to map the byte offsets to line and column numbers in ergonomic coverage reports. (For example, c8 report.)

When the generated and origin source filenames are different, this easy enough, by reading the actual generated file on disk.

However, when a module is compiled in-place (as with ts-node or other transpiliers) the generated source code is never exposed anywhere. It's generated, passed to node, and then never exposed again.

The information is available when getting a SourceMap object (since that's where it gets the SourceMap.payload from), but it's not exposed, and there's no reliable way to get it.

What is the feature you are proposing to solve the problem?

Add SourceMap.lineLengths property, and set it in the constructor when the object is created from the cached source map data.

What alternatives have you considered?

  • Using NODE_V8_COVERAGE env.
  • Reading the file directly to get lineLengths
  • Inspect in require.extensions and/or --loader load() method

using NODE_V8_COVERAGE env

When using NODE_V8_COVERAGE, there is no option to limit what gets dumped into the coverage directory. As a result, in a typical node program, 99% or more of the test coverage data is irrelevant. Several projects of mine generate up to a GB of coverage data using this approach, only 100k or less of which is actually used in generating coverage reports, making these reports unnecessarily slow to generate and since I have hundreds of projects and am continually converting them to use built-in coverage instead of nyc, this data consumes a significant and growing amount of disk space for no benefit. Using the V8 coverage API directly, I'm able to produce the same reports using only around 5MB at most, even in fairly large projects.

Reading the file directly to get lineLengths

This doesn't work when the file is transpiled, because what you end up with is the origin line lengths, not the generated line lengths, which are what's actually required.

Inferring lineLengths from source map payload data

This is what I'm exploring currently. It's a lot of math, and Node already has the answer right there in memory, so it seems rather inelegant to be having to do this.

Nope. Not possible. Happy to share the proof if anyone's curious why this isn't an option.

Some kind of hack in require.extensions or --loader load() method

It seems like it would b possible to get the generated source by means of hooking into require.extensions['.js'] for cjs, or inspecting the return value of nextLoad in an esm loader hook. However, this is extremely brittle, and works if the loader is defined after any transpilers that might return generated code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssues that request new features to be added to Node.js.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions