diff --git a/src/RPCServer.ts b/src/RPCServer.ts index 4a75143..1b183d7 100644 --- a/src/RPCServer.ts +++ b/src/RPCServer.ts @@ -37,34 +37,36 @@ import * as events from './events'; const cleanupReason = Symbol('CleanupReason'); -function composeMessage(error: unknown): string { - if ( - typeof error === 'boolean' || - typeof error === 'number' || - typeof error === 'string' || - typeof error === 'bigint' || - typeof error === 'symbol' - ) { - return `Non-error literal ${String(error)} was thrown`; - } - if ( - typeof error === 'object' && - error != null && - 'message' in error && - error.message != null - ) { - return String(error.message); - } - if (typeof error === 'object' && error?.constructor?.name != null) { - return `Non-error object ${error.constructor.name} was thrown`; +function composeErrorMessage(error: unknown): string { + switch (typeof error) { + case 'boolean': + case 'number': + case 'string': + case 'bigint': + case 'symbol': + return `Non-error literal ${String(error)} was thrown`; + case 'object': + // Let the fallback handler catch null values. + if (error == null) break; + // If we have an error message defined, then return that. + if ('message' in error && typeof error.message === 'string') { + return error.message; + } + // If present, mention the constructor name in the message. + if (error.constructor?.name != null) { + return `Non-error object ${error.constructor.name} was thrown`; + } + // Any other values should be handled by the fallback handler. + break; } - // If an object is not serialisable (for example, Object.create(null)), then - // an error would be raised when trying to convert it to a string. In that - // case, simply avoid serialising the error. + + // Handle cases where the error is not serialisable, like objects created + // using Object.create(null). Trying to serialise this throws a TypeError. try { - return `Non-error value ${error} was thrown`; + return `Non-error value ${String(error)} was thrown`; } catch (e) { - return 'Non-error value was thrown' + if (e instanceof TypeError) return 'Non-error value was thrown'; + else throw e; } } @@ -358,7 +360,7 @@ class RPCServer { try { const rpcError: JSONRPCResponseError = { code: errors.JSONRPCResponseErrorCode.RPCRemote, - message: composeMessage(e), + message: composeErrorMessage(e), data: this.fromError(e), }; const rpcErrorMessage: JSONRPCResponseFailed = { @@ -630,7 +632,7 @@ class RPCServer { try { const rpcError: JSONRPCResponseError = { code: errors.JSONRPCResponseErrorCode.RPCRemote, - message: composeMessage(e), + message: composeErrorMessage(e), data: this.fromError(e), }; const rpcErrorMessage: JSONRPCResponseFailed = {