From 1485dc8a266399865c70cbd68404f838e0fe4d6e Mon Sep 17 00:00:00 2001 From: isaacs Date: Wed, 14 Jun 2023 16:30:02 -0700 Subject: [PATCH 1/2] module: add SourceMap.lineLengths Fix: #48460 --- doc/api/module.md | 4 ++++ lib/internal/source_map/source_map.js | 16 +++++++++++++++- lib/internal/source_map/source_map_cache.js | 2 +- test/parallel/test-source-map-api.js | 12 +++++++++++- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/doc/api/module.md b/doc/api/module.md index 1d73e88ce6149d..5b98a6a1c2b0c1 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -274,6 +274,7 @@ added: #### `new SourceMap(payload)` * `payload` {Object} +* `lineLengths` {number\[]} Creates a new `sourceMap` instance. @@ -287,6 +288,9 @@ Creates a new `sourceMap` instance. * `mappings`: {string} * `sourceRoot`: {string} +`lineLengths` is an array of the length of each line in the +generated code. + #### `sourceMap.payload` * Returns: {Object} diff --git a/lib/internal/source_map/source_map.js b/lib/internal/source_map/source_map.js index 3112a026b643e2..f09e0d45001a42 100644 --- a/lib/internal/source_map/source_map.js +++ b/lib/internal/source_map/source_map.js @@ -125,12 +125,13 @@ class SourceMap { #mappings = []; #sources = {}; #sourceContentByURL = {}; + #lineLengths = undefined; /** * @constructor * @param {SourceMapV3} payload */ - constructor(payload) { + constructor(payload, lineLengths) { if (!base64Map) { const base64Digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; @@ -140,6 +141,9 @@ class SourceMap { } this.#payload = cloneSourceMapV3(payload); this.#parseMappingPayload(); + if (ArrayIsArray(lineLengths) && lineLengths.length) { + this.#lineLengths = lineLengths; + } } /** @@ -149,6 +153,16 @@ class SourceMap { return cloneSourceMapV3(this.#payload); } + /** + * @return {number[] | undefined} line lengths of generated source code + */ + get lineLengths() { + if (this.#lineLengths) { + return ArrayPrototypeSlice(this.#lineLengths); + } + return undefined; + } + #parseMappingPayload = () => { if (this.#payload.sections) { this.#parseSections(this.#payload.sections); diff --git a/lib/internal/source_map/source_map_cache.js b/lib/internal/source_map/source_map_cache.js index ebe0288e436d90..a2a095aa24bd88 100644 --- a/lib/internal/source_map/source_map_cache.js +++ b/lib/internal/source_map/source_map_cache.js @@ -317,7 +317,7 @@ function findSourceMap(sourceURL) { } let sourceMap = entry.sourceMap; if (sourceMap === undefined) { - sourceMap = new SourceMap(entry.data); + sourceMap = new SourceMap(entry.data, entry.lineLengths); entry.sourceMap = sourceMap; } return sourceMap; diff --git a/test/parallel/test-source-map-api.js b/test/parallel/test-source-map-api.js index 2c6cf341339a53..17fc036dfe6680 100644 --- a/test/parallel/test-source-map-api.js +++ b/test/parallel/test-source-map-api.js @@ -57,6 +57,8 @@ const { readFileSync } = require('fs'); assert.strictEqual(fileName, originalSource); assert.strictEqual(lineNumber, 3); assert.strictEqual(columnNumber, 6); + assert(Array.isArray(sourceMap.lineLengths)); + assert(!sourceMap.lineLengths.some((len) => (typeof len !== 'number'))); } // findSourceMap() can be used in Error.prepareStackTrace() to lookup @@ -116,7 +118,10 @@ const { readFileSync } = require('fs'); const payload = JSON.parse(readFileSync( require.resolve('../fixtures/source-map/disk.map'), 'utf8' )); - const sourceMap = new SourceMap(payload); + const lineLengths = readFileSync( + require.resolve('../fixtures/source-map/disk.map'), 'utf8' + ).replace(/\n$/, '').split('\n').map((l) => l.length); + const sourceMap = new SourceMap(payload, lineLengths); const { originalLine, originalColumn, @@ -125,6 +130,11 @@ const { readFileSync } = require('fs'); assert.strictEqual(originalLine, 2); assert.strictEqual(originalColumn, 4); assert(originalSource.endsWith('disk.js')); + const sourceMapLineLengths = sourceMap.lineLengths; + for (let i = 0; i < sourceMapLineLengths.length; i++) { + assert.strictEqual(sourceMapLineLengths[i], lineLengths[i]); + } + assert.strictEqual(sourceMapLineLengths.length, lineLengths.length); // The stored payload should be a clone: assert.strictEqual(payload.mappings, sourceMap.payload.mappings); assert.notStrictEqual(payload, sourceMap.payload); From fed5a2fee4bcac96d362950d1fdf9733e50abfd8 Mon Sep 17 00:00:00 2001 From: isaacs Date: Mon, 10 Jul 2023 19:59:09 -0700 Subject: [PATCH 2/2] fixup! module: add SourceMap.lineLengths Document lineLengths argument Make lineLengths part of an option bag rather than a positional arg --- doc/api/module.md | 4 ++-- lib/internal/source_map/source_map.js | 2 +- lib/internal/source_map/source_map_cache.js | 2 +- test/parallel/test-source-map-api.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/api/module.md b/doc/api/module.md index 5b98a6a1c2b0c1..8dd5fd4fa59f6c 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -271,7 +271,7 @@ added: - v12.17.0 --> -#### `new SourceMap(payload)` +#### `new SourceMap(payload[, { lineLengths }])` * `payload` {Object} * `lineLengths` {number\[]} @@ -288,7 +288,7 @@ Creates a new `sourceMap` instance. * `mappings`: {string} * `sourceRoot`: {string} -`lineLengths` is an array of the length of each line in the +`lineLengths` is an optional array of the length of each line in the generated code. #### `sourceMap.payload` diff --git a/lib/internal/source_map/source_map.js b/lib/internal/source_map/source_map.js index f09e0d45001a42..9e63eabaacf665 100644 --- a/lib/internal/source_map/source_map.js +++ b/lib/internal/source_map/source_map.js @@ -131,7 +131,7 @@ class SourceMap { * @constructor * @param {SourceMapV3} payload */ - constructor(payload, lineLengths) { + constructor(payload, { lineLengths } = { __proto__: null }) { if (!base64Map) { const base64Digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; diff --git a/lib/internal/source_map/source_map_cache.js b/lib/internal/source_map/source_map_cache.js index a2a095aa24bd88..2813da21dfdc63 100644 --- a/lib/internal/source_map/source_map_cache.js +++ b/lib/internal/source_map/source_map_cache.js @@ -317,7 +317,7 @@ function findSourceMap(sourceURL) { } let sourceMap = entry.sourceMap; if (sourceMap === undefined) { - sourceMap = new SourceMap(entry.data, entry.lineLengths); + sourceMap = new SourceMap(entry.data, { lineLengths: entry.lineLengths }); entry.sourceMap = sourceMap; } return sourceMap; diff --git a/test/parallel/test-source-map-api.js b/test/parallel/test-source-map-api.js index 17fc036dfe6680..8c965891536072 100644 --- a/test/parallel/test-source-map-api.js +++ b/test/parallel/test-source-map-api.js @@ -121,7 +121,7 @@ const { readFileSync } = require('fs'); const lineLengths = readFileSync( require.resolve('../fixtures/source-map/disk.map'), 'utf8' ).replace(/\n$/, '').split('\n').map((l) => l.length); - const sourceMap = new SourceMap(payload, lineLengths); + const sourceMap = new SourceMap(payload, { lineLengths }); const { originalLine, originalColumn,