-
-
Notifications
You must be signed in to change notification settings - Fork 35.7k
Expand file tree
/
Copy pathdebugger-probe.js
More file actions
85 lines (75 loc) Β· 3.01 KB
/
debugger-probe.js
File metadata and controls
85 lines (75 loc) Β· 3.01 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
'use strict';
const assert = require('assert');
// Work around a pre-existing inspector issue: if the debuggee exits too quickly
// the inspector can segfault while tearing down. For now normalize the segfault
// back to the expected terminal event (e.g. "completed" or "miss")
// until the upstream bug is fixed.
// See https://github.com/nodejs/node/issues/62765
// https://github.com/nodejs/node/issues/58245
const probeTargetExitSignal = 'SIGSEGV';
function isProbeSegvTeardown(result) {
if (result?.event !== 'error') { return false; }
const error = result.error;
if (error?.signal !== probeTargetExitSignal) { return false; }
return error.code === 'probe_target_exit' || error.code === 'probe_failure';
}
function findProbeSegvTeardownLine(output) {
const signalPrefix = `Target exited with signal ${probeTargetExitSignal}`;
if (output.startsWith(signalPrefix)) { return 0; }
const idx = output.indexOf(`\n${signalPrefix}`);
return idx === -1 ? -1 : idx + 1;
}
// Replace volatile fields in a probe report (stack frames, Node.js version,
// scriptId, callFrames) with stable placeholders for deepStrictEqual.
function normalizeProbeReport(value) {
if (typeof value === 'string') {
return value
.replace(/(?:\n[ \t]+at\s[^\n]*)+/g, '\n<stack>')
.replace(/\nNode\.js v[^\n]+/g, '\nNode.js <version>');
}
if (Array.isArray(value)) {
return value.map(normalizeProbeReport);
}
if (value !== null && typeof value === 'object') {
const result = {};
for (const key of Object.keys(value)) {
if (key === 'scriptId') {
result[key] = '<scriptId>';
} else if (key === 'callFrames') {
result[key] = '<callFrames>';
} else {
result[key] = normalizeProbeReport(value[key]);
}
}
return result;
}
return value;
}
function assertProbeJson(output, expected) {
const normalized = typeof output === 'string' ? JSON.parse(output) : output;
const lastResult = normalized.results?.[normalized.results.length - 1];
if (isProbeSegvTeardown(lastResult)) {
// Log to facilitate debugging if this normalization is occurring.
console.log('Normalizing trailing SIGSEGV in JSON probe output');
normalized.results[normalized.results.length - 1] = expected.results.at(-1);
}
assert.deepStrictEqual(normalizeProbeReport(normalized), normalizeProbeReport(expected));
}
function assertProbeText(output, expected) {
const lineStart = findProbeSegvTeardownLine(output);
let normalized;
if (lineStart !== -1) {
// Log to facilitate debugging if this normalization is occurring.
console.log('Normalizing trailing SIGSEGV in text probe output');
const expectedLineStart = expected.lastIndexOf('\n');
const terminalLine = expectedLineStart === -1 ? expected : expected.slice(expectedLineStart + 1);
normalized = lineStart === 0 ? terminalLine : `${output.slice(0, lineStart - 1)}\n${terminalLine}`;
} else {
normalized = output;
}
assert.strictEqual(normalized, expected);
}
module.exports = {
assertProbeJson,
assertProbeText,
};