Skip to content

Commit

Permalink
loader: speed up line length calc used by moduleProvider
Browse files Browse the repository at this point in the history
When using a loader, for say TypeScript, the esm loader invokes the
`lineLengths` function via `maybeCacheSourceMap` when sourcemaps are
enabled. Therefore, `lineLengths` ends up getting called quite often
when running large servers written in TypeScript for example. Making
`lineLengths` faster should therefore speed up server startup times
for anyone using a loader with node with sourcemaps enabled.

The change itself is fairly simple and is all about removing creation
of unnecessary memory and iterating the whole source content only once
with the hope of making the function cache friendly.

PR-URL: #50969
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Geoffrey Booth <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Vinícius Lourenço Claro Cardoso <[email protected]>
Reviewed-By: Jacob Smith <[email protected]>
  • Loading branch information
zeusdeux authored and targos committed Dec 4, 2023
1 parent f79b54e commit 9bc7917
Showing 1 changed file with 20 additions and 8 deletions.
28 changes: 20 additions & 8 deletions lib/internal/source_map/source_map_cache.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use strict';

const {
ArrayPrototypeMap,
ArrayPrototypePush,
JSONParse,
ObjectKeys,
RegExpPrototypeExec,
RegExpPrototypeSymbolSplit,
SafeMap,
StringPrototypeCodePointAt,
StringPrototypeSplit,
} = primordials;

Expand Down Expand Up @@ -205,14 +205,26 @@ function dataFromUrl(sourceURL, sourceMappingURL) {
// from. This allows translation from byte offset V8 coverage reports,
// to line/column offset Source Map V3.
function lineLengths(content) {
// We purposefully keep \r as part of the line-length calculation, in
// cases where there is a \r\n separator, so that this can be taken into
// account in coverage calculations.
return ArrayPrototypeMap(RegExpPrototypeSymbolSplit(/\n|\u2028|\u2029/, content), (line) => {
return line.length;
});
const contentLength = content.length;
const output = [];
let lineLength = 0;
for (let i = 0; i < contentLength; i++, lineLength++) {
const codePoint = StringPrototypeCodePointAt(content, i);

// We purposefully keep \r as part of the line-length calculation, in
// cases where there is a \r\n separator, so that this can be taken into
// account in coverage calculations.
// codepoints for \n (new line), \u2028 (line separator) and \u2029 (paragraph separator)
if (codePoint === 10 || codePoint === 0x2028 || codePoint === 0x2029) {
ArrayPrototypePush(output, lineLength);
lineLength = -1; // To not count the matched codePoint such as \n character
}
}
ArrayPrototypePush(output, lineLength);
return output;
}


function sourceMapFromFile(mapURL) {
try {
const fs = require('fs');
Expand Down

0 comments on commit 9bc7917

Please sign in to comment.