Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debugger,errors: add ERR_DEBUGGER errors and use them in the former node-inspect code #39024

Merged
merged 5 commits into from
Jun 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 17 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,22 @@ added: v15.0.0

An attempt to invoke an unsupported crypto operation was made.

<a id="ERR_DEBUGGER_ERROR"></a>
### `ERR_DEBUGGER_ERROR`
<!-- YAML
added: REPLACEME
-->

An error occurred with the [debugger][].

<a id="ERR_DEBUGGER_STARTUP_ERROR"></a>
### `ERR_DEBUGGER_STARTUP_ERROR`
<!-- YAML
added: REPLACEME
-->

The [debugger][] timed out waiting for the required host/port to be free.

<a id="ERR_DLOPEN_FAILED"></a>
### `ERR_DLOPEN_FAILED`
<!-- YAML
Expand Down Expand Up @@ -2832,6 +2848,7 @@ The native call from `process.cpuUsage` could not be processed.
[`util.getSystemErrorName(error.errno)`]: util.md#util_util_getsystemerrorname_err
[`zlib`]: zlib.md
[crypto digest algorithm]: crypto.md#crypto_crypto_gethashes
[debugger]: debugger.md
[define a custom subpath]: packages.md#packages_subpath_exports
[domains]: domain.md
[event emitter-based]: events.md#events_class_eventemitter
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,8 @@ E('ERR_CRYPTO_SCRYPT_INVALID_PARAMETER', 'Invalid scrypt parameter', Error);
E('ERR_CRYPTO_SCRYPT_NOT_SUPPORTED', 'Scrypt algorithm not supported', Error);
// Switch to TypeError. The current implementation does not seem right.
E('ERR_CRYPTO_SIGN_KEY_REQUIRED', 'No key provided to sign', Error);
E('ERR_DEBUGGER_ERROR', '%s', Error);
E('ERR_DEBUGGER_STARTUP_ERROR', '%s', Error);
E('ERR_DIR_CLOSED', 'Directory handle was closed', Error);
E('ERR_DIR_CONCURRENT_OPERATION',
'Cannot do synchronous work on directory handle with concurrent ' +
Expand Down
12 changes: 3 additions & 9 deletions lib/internal/inspector/_inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const {
ArrayPrototypePop,
ArrayPrototypeShift,
ArrayPrototypeSlice,
Error,
FunctionPrototypeBind,
Number,
Promise,
Expand Down Expand Up @@ -46,12 +45,7 @@ const { 0: InspectClient, 1: createRepl } =

const debuglog = util.debuglog('inspect');

class StartupError extends Error {
constructor(message) {
super(message);
this.name = 'StartupError';
}
}
const { ERR_DEBUGGER_STARTUP_ERROR } = require('internal/errors').codes;

async function portIsFree(host, port, timeout = 9999) {
if (port === 0) return; // Binding to a random port.
Expand All @@ -66,7 +60,7 @@ async function portIsFree(host, port, timeout = 9999) {
while (true) {
await asyncIterator.next();
if (signal.aborted) {
throw new StartupError( // eslint-disable-line no-restricted-syntax
throw new ERR_DEBUGGER_STARTUP_ERROR(
`Timeout (${timeout}) waiting for ${host}:${port} to be free`);
}
const error = await new Promise((resolve) => {
Expand Down Expand Up @@ -342,7 +336,7 @@ function startInspect(argv = ArrayPrototypeSlice(process.argv, 2),
stdin.resume();

function handleUnexpectedError(e) {
if (!(e instanceof StartupError)) {
if (e.code !== 'ERR_DEBUGGER_STARTUP_ERROR') {
console.error('There was an internal error in Node.js. ' +
'Please report this bug.');
console.error(e.message);
Expand Down
25 changes: 11 additions & 14 deletions lib/internal/inspector/inspect_client.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
// TODO(aduh95): use errors exported by the internal/errors module
/* eslint-disable no-restricted-syntax */

'use strict';

const {
ArrayPrototypePush,
Error,
ErrorCaptureStackTrace,
FunctionPrototypeBind,
JSONParse,
Expand All @@ -15,6 +11,7 @@ const {
} = primordials;

const Buffer = require('buffer').Buffer;
const { ERR_DEBUGGER_ERROR } = require('internal/errors').codes;
const { EventEmitter } = require('events');
const http = require('http');
const URL = require('url');
Expand All @@ -39,7 +36,7 @@ const kEightBytePayloadLengthField = 127;
const kMaskingKeyWidthInBytes = 4;

function unpackError({ code, message, data }) {
const err = new Error(`${message} - ${data}`);
const err = new ERR_DEBUGGER_ERROR(`${message} - ${data}`);
err.code = code;
ErrorCaptureStackTrace(err, unpackError);
return err;
Expand Down Expand Up @@ -101,14 +98,14 @@ function decodeFrameHybi17(data) {
const masked = (secondByte & kMaskBit) !== 0;
const compressed = reserved1;
if (compressed) {
throw new Error('Compressed frames not supported');
throw new ERR_DEBUGGER_ERROR('Compressed frames not supported');
}
if (!final || reserved2 || reserved3) {
throw new Error('Only compression extension is supported');
throw new ERR_DEBUGGER_ERROR('Only compression extension is supported');
}

if (masked) {
throw new Error('Masked server frame - not supported');
throw new ERR_DEBUGGER_ERROR('Masked server frame - not supported');
}

let closed = false;
Expand All @@ -119,7 +116,7 @@ function decodeFrameHybi17(data) {
case kOpCodeText:
break;
default:
throw new Error(`Unsupported op code ${opCode}`);
throw new ERR_DEBUGGER_ERROR(`Unsupported op code ${opCode}`);
}

let payloadLength = secondByte & kPayloadLengthMask;
Expand Down Expand Up @@ -183,7 +180,7 @@ class Client extends EventEmitter {
debuglog('< %s', payloadStr);
const lastChar = payloadStr[payloadStr.length - 1];
if (payloadStr[0] !== '{' || lastChar !== '}') {
throw new Error(`Payload does not look like JSON: ${payloadStr}`);
throw new ERR_DEBUGGER_ERROR(`Payload does not look like JSON: ${payloadStr}`);
}
let payload;
try {
Expand All @@ -204,7 +201,7 @@ class Client extends EventEmitter {
this.emit('debugEvent', method, params);
this.emit(method, params);
} else {
throw new Error(`Unsupported response: ${payloadStr}`);
throw new ERR_DEBUGGER_ERROR(`Unsupported response: ${payloadStr}`);
}
}
}
Expand All @@ -226,7 +223,7 @@ class Client extends EventEmitter {
callMethod(method, params) {
return new Promise((resolve, reject) => {
if (!this._socket) {
reject(new Error('Use `run` to start the app again.'));
reject(new ERR_DEBUGGER_ERROR('Use `run` to start the app again.'));
return;
}
const data = { id: ++this._lastId, method, params };
Expand Down Expand Up @@ -254,13 +251,13 @@ class Client extends EventEmitter {
function parseChunks() {
const resBody = Buffer.concat(chunks).toString();
if (httpRes.statusCode !== 200) {
reject(new Error(`Unexpected ${httpRes.statusCode}: ${resBody}`));
reject(new ERR_DEBUGGER_ERROR(`Unexpected ${httpRes.statusCode}: ${resBody}`));
return;
}
try {
resolve(JSONParse(resBody));
} catch {
reject(new Error(`Response didn't contain JSON: ${resBody}`));
reject(new ERR_DEBUGGER_ERROR(`Response didn't contain JSON: ${resBody}`));

}
}
Expand Down
18 changes: 9 additions & 9 deletions lib/internal/inspector/inspect_repl.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// TODO(trott): enable ESLint
/* eslint-disable getter-return, no-restricted-syntax */
/* eslint-disable getter-return */

'use strict';

Expand All @@ -18,7 +18,6 @@ const {
ArrayPrototypeSome,
ArrayPrototypeSplice,
Date,
Error,
FunctionPrototypeCall,
JSONStringify,
MathMax,
Expand Down Expand Up @@ -47,9 +46,12 @@ const {
StringPrototypeStartsWith,
StringPrototypeToUpperCase,
StringPrototypeTrim,
TypeError,
} = primordials;

const { ERR_DEBUGGER_ERROR } = require('internal/errors').codes;

const { validateString } = require('internal/validators');

const FS = require('fs');
const Path = require('path');
const Repl = require('repl');
Expand Down Expand Up @@ -176,7 +178,7 @@ function extractErrorMessage(stack) {

function convertResultToError(result) {
const { className, description } = result;
const err = new Error(extractErrorMessage(description));
const err = new ERR_DEBUGGER_ERROR(extractErrorMessage(description));
err.stack = description;
ObjectDefineProperty(err, 'name', { value: className });
return err;
Expand Down Expand Up @@ -357,7 +359,7 @@ function createRepl(inspector) {

function getCurrentLocation() {
if (!selectedFrame) {
throw new Error('Requires execution to be paused');
throw new ERR_DEBUGGER_ERROR('Requires execution to be paused');
}
return selectedFrame.location;
}
Expand Down Expand Up @@ -543,7 +545,7 @@ function createRepl(inspector) {
// Repl asked for scope variables
if (code === '.scope') {
if (!selectedFrame) {
throw new Error('Requires execution to be paused');
throw new ERR_DEBUGGER_ERROR('Requires execution to be paused');
}
const scopes = await selectedFrame.loadScopes();
return ArrayPrototypeMap(scopes, (scope) => scope.completionGroup);
Expand Down Expand Up @@ -706,9 +708,7 @@ function createRepl(inspector) {
registerBreakpoint);
}

if (typeof script !== 'string') {
throw new TypeError(`setBreakpoint() expects a string, got ${script}`);
}
validateString(script, 'script');

// setBreakpoint('fn()'): Break when a function is called
if (StringPrototypeEndsWith(script, '()')) {
Expand Down