lib: suppress source map lookup exceptions

When the source map data are invalid json strings, skip construct
`SourceMap` on it. Additionally, suppress exceptions on source map
lookups and fix test runners crash on invalid source maps.

PR-URL: https://github.com/nodejs/node/pull/56299
Refs: https://github.com/nodejs/node/issues/56296
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Pietro Marchini <pietro.marchini94@gmail.com>
pull/56299/head
Chengzhong Wu 2024-12-17 23:12:00 +00:00 committed by Antoine du Hamel
parent 990497c514
commit a33ec1248b
No known key found for this signature in database
GPG Key ID: 21D900FFDB233756
2 changed files with 42 additions and 11 deletions

View File

@ -155,6 +155,9 @@ function maybeCacheSourceMap(filename, content, moduleInstance, isGeneratedSourc
}
const data = dataFromUrl(filename, sourceMapURL);
// `data` could be null if the source map is invalid.
// In this case, create a cache entry with null data with source url for test coverage.
const entry = {
__proto__: null,
lineLengths: lineLengths(content),
@ -277,6 +280,8 @@ function sourceMapFromDataUrl(sourceURL, url) {
const parsedData = JSONParse(decodedData);
return sourcesToAbsolute(sourceURL, parsedData);
} catch (err) {
// TODO(legendecas): warn about invalid source map JSON string.
// But it could be verbose.
debug(err);
return null;
}
@ -331,24 +336,38 @@ function sourceMapCacheToObject() {
/**
* Find a source map for a given actual source URL or path.
*
* This function may be invoked from user code or test runner, this must not throw
* any exceptions.
* @param {string} sourceURL - actual source URL or path
* @returns {import('internal/source_map/source_map').SourceMap | undefined} a source map or undefined if not found
*/
function findSourceMap(sourceURL) {
if (RegExpPrototypeExec(kLeadingProtocol, sourceURL) === null) {
sourceURL = pathToFileURL(sourceURL).href;
}
SourceMap ??= require('internal/source_map/source_map').SourceMap;
const entry = getModuleSourceMapCache().get(sourceURL) ?? generatedSourceMapCache.get(sourceURL);
if (entry === undefined) {
if (typeof sourceURL !== 'string') {
return undefined;
}
let sourceMap = entry.sourceMap;
if (sourceMap === undefined) {
sourceMap = new SourceMap(entry.data, { lineLengths: entry.lineLengths });
entry.sourceMap = sourceMap;
SourceMap ??= require('internal/source_map/source_map').SourceMap;
try {
if (RegExpPrototypeExec(kLeadingProtocol, sourceURL) === null) {
// If the sourceURL is an invalid path, this will throw an error.
sourceURL = pathToFileURL(sourceURL).href;
}
const entry = getModuleSourceMapCache().get(sourceURL) ?? generatedSourceMapCache.get(sourceURL);
if (entry?.data == null) {
return undefined;
}
let sourceMap = entry.sourceMap;
if (sourceMap === undefined) {
sourceMap = new SourceMap(entry.data, { lineLengths: entry.lineLengths });
entry.sourceMap = sourceMap;
}
return sourceMap;
} catch (err) {
debug(err);
return undefined;
}
return sourceMap;
}
module.exports = {

View File

@ -0,0 +1,12 @@
// Flags: --enable-source-maps
'use strict';
require('../common');
const test = require('node:test');
// Verify that test runner can handle invalid source maps.
test('ok', () => {});
// eslint-disable-next-line @stylistic/js/spaced-comment
//# sourceMappingURL=data:application/json;base64,-1