mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00
util: add sourcemap support to getCallSites
PR-URL: https://github.com/nodejs/node/pull/55589 Fixes: https://github.com/nodejs/node/issues/55109 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
This commit is contained in:
parent
bdc266269c
commit
d35cde624f
6 changed files with 194 additions and 6 deletions
84
lib/util.js
84
lib/util.js
|
@ -24,6 +24,7 @@
|
|||
const {
|
||||
ArrayIsArray,
|
||||
ArrayPrototypePop,
|
||||
ArrayPrototypePush,
|
||||
Error,
|
||||
ErrorCaptureStackTrace,
|
||||
FunctionPrototypeBind,
|
||||
|
@ -61,6 +62,7 @@ const {
|
|||
validateNumber,
|
||||
validateString,
|
||||
validateOneOf,
|
||||
validateObject,
|
||||
} = require('internal/validators');
|
||||
const {
|
||||
isReadableStream,
|
||||
|
@ -74,11 +76,13 @@ function lazyUtilColors() {
|
|||
utilColors ??= require('internal/util/colors');
|
||||
return utilColors;
|
||||
}
|
||||
const { getOptionValue } = require('internal/options');
|
||||
|
||||
const binding = internalBinding('util');
|
||||
|
||||
const {
|
||||
deprecate,
|
||||
getLazy,
|
||||
getSystemErrorMap,
|
||||
getSystemErrorName: internalErrorName,
|
||||
getSystemErrorMessage: internalErrorMessage,
|
||||
|
@ -328,14 +332,90 @@ function parseEnv(content) {
|
|||
return binding.parseEnv(content);
|
||||
}
|
||||
|
||||
const lazySourceMap = getLazy(() => require('internal/source_map/source_map_cache'));
|
||||
|
||||
/**
|
||||
* @typedef {object} CallSite // The call site
|
||||
* @property {string} scriptName // The name of the resource that contains the
|
||||
* script for the function for this StackFrame
|
||||
* @property {string} functionName // The name of the function associated with this stack frame
|
||||
* @property {number} lineNumber // The number, 1-based, of the line for the associate function call
|
||||
* @property {number} columnNumber // The 1-based column offset on the line for the associated function call
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {CallSite} callSite // The call site object to reconstruct from source map
|
||||
* @returns {CallSite | undefined} // The reconstructed call site object
|
||||
*/
|
||||
function reconstructCallSite(callSite) {
|
||||
const { scriptName, lineNumber, column } = callSite;
|
||||
const sourceMap = lazySourceMap().findSourceMap(scriptName);
|
||||
if (!sourceMap) return;
|
||||
const entry = sourceMap.findEntry(lineNumber - 1, column - 1);
|
||||
if (!entry?.originalSource) return;
|
||||
return {
|
||||
__proto__: null,
|
||||
// If the name is not found, it is an empty string to match the behavior of `util.getCallSite()`
|
||||
functionName: entry.name ?? '',
|
||||
scriptName: entry.originalSource,
|
||||
lineNumber: entry.originalLine + 1,
|
||||
column: entry.originalColumn + 1,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The call site array to map
|
||||
* @param {CallSite[]} callSites
|
||||
* Array of objects with the reconstructed call site
|
||||
* @returns {CallSite[]}
|
||||
*/
|
||||
function mapCallSite(callSites) {
|
||||
const result = [];
|
||||
for (let i = 0; i < callSites.length; ++i) {
|
||||
const callSite = callSites[i];
|
||||
const found = reconstructCallSite(callSite);
|
||||
ArrayPrototypePush(result, found ?? callSite);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {object} CallSiteOptions // The call site options
|
||||
* @property {boolean} sourceMap // Enable source map support
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the callSite
|
||||
* @param {number} frameCount
|
||||
* @returns {object}
|
||||
* @param {CallSiteOptions} options
|
||||
* @returns {CallSite[]}
|
||||
*/
|
||||
function getCallSites(frameCount = 10) {
|
||||
function getCallSites(frameCount = 10, options) {
|
||||
// If options is not provided check if frameCount is an object
|
||||
if (options === undefined) {
|
||||
if (typeof frameCount === 'object') {
|
||||
// If frameCount is an object, it is the options object
|
||||
options = frameCount;
|
||||
validateObject(options, 'options');
|
||||
validateBoolean(options.sourceMap, 'options.sourceMap');
|
||||
frameCount = 10;
|
||||
} else {
|
||||
// If options is not provided, set it to an empty object
|
||||
options = {};
|
||||
};
|
||||
} else {
|
||||
// If options is provided, validate it
|
||||
validateObject(options, 'options');
|
||||
validateBoolean(options.sourceMap, 'options.sourceMap');
|
||||
}
|
||||
|
||||
// Using kDefaultMaxCallStackSizeToCapture as reference
|
||||
validateNumber(frameCount, 'frameCount', 1, 200);
|
||||
// If options.sourceMaps is true or if sourceMaps are enabled but the option.sourceMaps is not set explictly to false
|
||||
if (options.sourceMap === true || (getOptionValue('--enable-source-maps') && options.sourceMap !== false)) {
|
||||
return mapCallSite(binding.getCallSites(frameCount));
|
||||
}
|
||||
return binding.getCallSites(frameCount);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue