Skip to content

Commit

Permalink
fix: include message and code on errors when logging in node.js a…
Browse files Browse the repository at this point in the history
…nd deno
  • Loading branch information
rexxars committed Jan 28, 2025
1 parent 47a195d commit f2596b3
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 8 deletions.
10 changes: 5 additions & 5 deletions src/EventSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ export class EventSource extends EventTarget {
* @param code - The HTTP status code, if available
* @internal
*/
#failConnection(error?: string, code?: number) {
#failConnection(message?: string, code?: number) {
// [spec] …if the readyState attribute is set to a value other than CLOSED,
// [spec] sets the readyState attribute to CLOSED…
if (this.#readyState !== this.CLOSED) {
Expand All @@ -530,7 +530,7 @@ export class EventSource extends EventTarget {
// [spec] > to their development consoles whenever an error event is fired, since little
// [spec] > to no information can be made available in the events themselves.
// Printing to console is not very programatically helpful, though, so we emit a custom event.
const errorEvent = new ErrorEvent('error', code, error)
const errorEvent = new ErrorEvent('error', {code, message})

this.#onError?.(errorEvent)
this.dispatchEvent(errorEvent)
Expand All @@ -539,11 +539,11 @@ export class EventSource extends EventTarget {
/**
* Schedules a reconnection attempt against the EventSource endpoint.
*
* @param error - The error causing the connection to fail
* @param message - The error causing the connection to fail
* @param code - The HTTP status code, if available
* @internal
*/
#scheduleReconnect(error?: string, code?: number) {
#scheduleReconnect(message?: string, code?: number) {
// [spec] If the readyState attribute is set to CLOSED, abort the task.
if (this.#readyState === this.CLOSED) {
return
Expand All @@ -553,7 +553,7 @@ export class EventSource extends EventTarget {
this.#readyState = this.CONNECTING

// [spec] Fire an event named `error` at the EventSource object.
const errorEvent = new ErrorEvent('error', code, error)
const errorEvent = new ErrorEvent('error', {code, message})
this.#onError?.(errorEvent)
this.dispatchEvent(errorEvent)

Expand Down
72 changes: 69 additions & 3 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,58 @@ export class ErrorEvent extends Event {
*/
public message?: string | undefined

constructor(type: string, code?: number, message?: string) {
/**
* Constructs a new `ErrorEvent` instance. This is typically not called directly,
* but rather emitted by the `EventSource` object when an error occurs.
*
* @param type - The type of the event (should be "error")
* @param errorEventInitDict - Optional properties to include in the error event
*/
constructor(
type: string,
errorEventInitDict?: {message?: string | undefined; code?: number | undefined},
) {
super(type)
this.code = code ?? undefined
this.message = message ?? undefined
this.code = errorEventInitDict?.code ?? undefined
this.message = errorEventInitDict?.message ?? undefined
}

/**
* Node.js "hides" the `message` and `code` properties of the `ErrorEvent` instance,
* when it is `console.log`'ed. This makes it harder to debug errors. To ease debugging,
* we explicitly include the properties in the `inspect` method.
*
* This is automatically called by Node.js when you `console.log` an instance of this class.
*
* @param _depth - The current depth
* @param options - The options passed to `util.inspect`
* @param inspect - The inspect function to use (prevents having to import it from `util`)
* @returns A string representation of the error
*/
[Symbol.for('nodejs.util.inspect.custom')](
_depth: number,
options: {colors: boolean},
inspect: (obj: unknown, inspectOptions: {colors: boolean}) => string,
): string {
return inspect(inspectableError(this), options)
}

/**
* Deno "hides" the `message` and `code` properties of the `ErrorEvent` instance,
* when it is `console.log`'ed. This makes it harder to debug errors. To ease debugging,
* we explicitly include the properties in the `inspect` method.
*
* This is automatically called by Deno when you `console.log` an instance of this class.
*
* @param inspect - The inspect function to use (prevents having to import it from `util`)
* @param options - The options passed to `Deno.inspect`
* @returns A string representation of the error
*/
[Symbol.for('Deno.customInspect')](
inspect: (obj: unknown, inspectOptions: {colors: boolean}) => string,
options: {colors: boolean},
): string {
return inspect(inspectableError(this), options)
}
}

Expand Down Expand Up @@ -73,3 +121,21 @@ export function flattenError(err: unknown): string {

return err.message
}

/**
* Convert an `ErrorEvent` instance into a plain object for inspection.
*
* @param err - The `ErrorEvent` instance to inspect
* @returns A plain object representation of the error
* @internal
*/
function inspectableError(err: ErrorEvent) {
return {
type: err.type,
message: err.message,
code: err.code,
defaultPrevented: err.defaultPrevented,
cancelable: err.cancelable,
timeStamp: err.timeStamp,
}
}

0 comments on commit f2596b3

Please sign in to comment.