diff --git a/lib/internal/debugger/inspect_probe.js b/lib/internal/debugger/inspect_probe.js index e7abc2e48cd365..6e3cf25cacef2b 100644 --- a/lib/internal/debugger/inspect_probe.js +++ b/lib/internal/debugger/inspect_probe.js @@ -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); @@ -730,6 +731,7 @@ class ProbeInspectorSession { this.recordInspectorFailure({ reason: 'Target process exited during probe evaluation', advice: kReviewProbeExprAdvice, + inFlight, }); } throw kInspectorFailedSentinel; @@ -741,41 +743,47 @@ 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) { @@ -783,7 +791,7 @@ class ProbeInspectorSession { 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') {