forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathprepare_stack_trace.js
More file actions
87 lines (78 loc) · 2.76 KB
/
prepare_stack_trace.js
File metadata and controls
87 lines (78 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
'use strict';
const debug = require('internal/util/debuglog').debuglog('source_map');
const { findSourceMap } = require('internal/source_map/source_map_cache');
const { overrideStackTrace } = require('internal/errors');
// Create a prettified stacktrace, inserting context from source maps
// if possible.
const ErrorToString = Error.prototype.toString; // Capture original toString.
const prepareStackTrace = (globalThis, error, trace) => {
// API for node internals to override error stack formatting
// without interfering with userland code.
// TODO(bcoe): add support for source-maps to repl.
if (overrideStackTrace.has(error)) {
const f = overrideStackTrace.get(error);
overrideStackTrace.delete(error);
return f(error, trace);
}
const decoratedTrace = decorateCallSites(error, trace);
// `globalThis` is the global that contains the constructor which
// created `error`.
if (typeof globalThis.Error.prepareStackTrace === 'function') {
return globalThis.Error.prepareStackTrace(error, decoratedTrace);
}
const errorString = ErrorToString.call(error);
if (decoratedTrace.length === 0) {
return errorString;
}
const preparedTrace = decoratedTrace.map((t, i) => {
let str = i !== 0 ? '\n at ' : '';
str = `${str}${t}`;
if (t.getOriginalLineNumber) {
str += `\n -> ${
t.getOriginalFileName()
}:${
t.getOriginalLineNumber()
}:${t.getOriginalColumnNumber()}`;
}
return str;
});
return `${errorString}\n at ${preparedTrace.join('')}`;
};
function decorateCallSites(error, trace) {
const { SourceMap } = require('internal/source_map/source_map');
return trace.map((t) => {
try {
const sourceMap = findSourceMap(t.getFileName(), error);
if (sourceMap && sourceMap.data) {
const sm = new SourceMap(sourceMap.data);
// Source Map V3 lines/columns use zero-based offsets whereas, in
// stack traces, they start at 1/1.
const [, , url, line, col] =
sm.findEntry(t.getLineNumber() - 1, t.getColumnNumber() - 1);
if (url && line !== undefined && col !== undefined) {
return decorateCallSite(t, url.replace('file://', ''), line + 1,
col + 1);
}
}
} catch (err) {
debug(err.stack);
}
return decorateCallSite(t, t.getFileName(), t.getLineNumber(),
t.getColumnNumber());
});
}
function decorateCallSite(callSite, fileName, lineNumber, columnNumber) {
callSite.getOriginalFileName = () => {
return fileName;
};
callSite.getOriginalLineNumber = () => {
return lineNumber;
};
callSite.getOriginalColumnNumber = () => {
return columnNumber;
};
return callSite;
}
module.exports = {
prepareStackTrace,
};