Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions lib/internal/debugger/inspect_probe.js
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,8 @@ class ProbeInspectorSession {

async callCdp(method, params, probe = null) {
if (this.finished) { throw kInspectorFailedSentinel; }
this.inFlight = { __proto__: null, method, probe };
const inFlight = { __proto__: null, method, probe };
this.inFlight = inFlight;
debug('CDP -> %s%s', method, probe !== null ? `, probe=${probe.index}` : '');
try {
const result = await this.client.callMethod(method, params);
Expand All @@ -730,6 +731,7 @@ class ProbeInspectorSession {
this.recordInspectorFailure({
reason: 'Target process exited during probe evaluation',
advice: kReviewProbeExprAdvice,
inFlight,
});
}
throw kInspectorFailedSentinel;
Expand All @@ -741,49 +743,55 @@ class ProbeInspectorSession {
reason: 'Probe mode failed before user code ran',
advice: kStartupTeardownAdvice,
cdpError: err,
inFlight,
});
} else if (method === 'Debugger.evaluateOnCallFrame') {
this.recordInspectorFailure({
reason: 'The inspector could not evaluate a probe expression',
advice: `The rejection details are recorded on the probe hit. ${kReviewProbeExprAdvice}`,
cdpError: err,
inFlight,
});
} else if (this.lastProbeIndex !== null) {
this.recordInspectorFailure({
reason: 'Probe session failed after a probe evaluation',
advice: 'If the failure repeats, review the most-recently-evaluated probe expression.',
cdpError: err,
inFlight,
});
} else {
this.recordInspectorFailure({
reason: 'Probe session failed during inspector activity',
advice: 'This is likely a Node.js bug. Please file an issue.',
cdpError: err,
inFlight,
});
}
throw kInspectorFailedSentinel;
} finally {
this.inFlight = null;
if (this.inFlight === inFlight) {
this.inFlight = null;
}
}
}

// Records the first inspector-side terminal for the session, later callers are ignored.
recordInspectorFailure({ reason, advice, cdpError, internalError }) {
recordInspectorFailure({ reason, advice, cdpError, internalError, inFlight = this.inFlight }) {
if (this.finished) { return; }
debug('recordInspectorFailure "%s": inFlight=%j, lastProbeIndex=%s, cdpError=%j',
reason, this.inFlight, this.lastProbeIndex, cdpError);
reason, inFlight, this.lastProbeIndex, cdpError);
const child = this.child;
const exitedAbnormally = child !== null &&
(child.signalCode !== null || (child.exitCode !== null && child.exitCode !== 0));
const inFlightProbe = this.inFlight === null ? null : this.inFlight.probe;
const inFlightProbe = inFlight === null ? null : inFlight.probe;
// This normally emits `probe_failure`, but yields to `probe_target_exit` when the child
// has already exited abnormally and there is no in-flight probe to attribute to.
if (exitedAbnormally && inFlightProbe === null) {
this.finishWithTrustedResult(this.getProbeTargetExitEvent(child.exitCode, child.signalCode));
return;
}

const failedCdpMethod = this.inFlight === null ? null : this.inFlight.method;
const failedCdpMethod = inFlight === null ? null : inFlight.method;
let protocolError = null;
// // `ERR_DEBUGGER_ERROR` is a Node-internal code, not a CDP-level protocol code
if (cdpError !== undefined && cdpError.code !== 'ERR_DEBUGGER_ERROR') {
Expand Down
Loading