Skip to content

Commit f2596b3

Browse files
committed
fix: include message and code on errors when logging in node.js and deno
1 parent 47a195d commit f2596b3

File tree

2 files changed

+74
-8
lines changed

2 files changed

+74
-8
lines changed

src/EventSource.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ export class EventSource extends EventTarget {
517517
* @param code - The HTTP status code, if available
518518
* @internal
519519
*/
520-
#failConnection(error?: string, code?: number) {
520+
#failConnection(message?: string, code?: number) {
521521
// [spec] …if the readyState attribute is set to a value other than CLOSED,
522522
// [spec] sets the readyState attribute to CLOSED…
523523
if (this.#readyState !== this.CLOSED) {
@@ -530,7 +530,7 @@ export class EventSource extends EventTarget {
530530
// [spec] > to their development consoles whenever an error event is fired, since little
531531
// [spec] > to no information can be made available in the events themselves.
532532
// Printing to console is not very programatically helpful, though, so we emit a custom event.
533-
const errorEvent = new ErrorEvent('error', code, error)
533+
const errorEvent = new ErrorEvent('error', {code, message})
534534

535535
this.#onError?.(errorEvent)
536536
this.dispatchEvent(errorEvent)
@@ -539,11 +539,11 @@ export class EventSource extends EventTarget {
539539
/**
540540
* Schedules a reconnection attempt against the EventSource endpoint.
541541
*
542-
* @param error - The error causing the connection to fail
542+
* @param message - The error causing the connection to fail
543543
* @param code - The HTTP status code, if available
544544
* @internal
545545
*/
546-
#scheduleReconnect(error?: string, code?: number) {
546+
#scheduleReconnect(message?: string, code?: number) {
547547
// [spec] If the readyState attribute is set to CLOSED, abort the task.
548548
if (this.#readyState === this.CLOSED) {
549549
return
@@ -553,7 +553,7 @@ export class EventSource extends EventTarget {
553553
this.#readyState = this.CONNECTING
554554

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

src/errors.ts

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,58 @@ export class ErrorEvent extends Event {
2222
*/
2323
public message?: string | undefined
2424

25-
constructor(type: string, code?: number, message?: string) {
25+
/**
26+
* Constructs a new `ErrorEvent` instance. This is typically not called directly,
27+
* but rather emitted by the `EventSource` object when an error occurs.
28+
*
29+
* @param type - The type of the event (should be "error")
30+
* @param errorEventInitDict - Optional properties to include in the error event
31+
*/
32+
constructor(
33+
type: string,
34+
errorEventInitDict?: {message?: string | undefined; code?: number | undefined},
35+
) {
2636
super(type)
27-
this.code = code ?? undefined
28-
this.message = message ?? undefined
37+
this.code = errorEventInitDict?.code ?? undefined
38+
this.message = errorEventInitDict?.message ?? undefined
39+
}
40+
41+
/**
42+
* Node.js "hides" the `message` and `code` properties of the `ErrorEvent` instance,
43+
* when it is `console.log`'ed. This makes it harder to debug errors. To ease debugging,
44+
* we explicitly include the properties in the `inspect` method.
45+
*
46+
* This is automatically called by Node.js when you `console.log` an instance of this class.
47+
*
48+
* @param _depth - The current depth
49+
* @param options - The options passed to `util.inspect`
50+
* @param inspect - The inspect function to use (prevents having to import it from `util`)
51+
* @returns A string representation of the error
52+
*/
53+
[Symbol.for('nodejs.util.inspect.custom')](
54+
_depth: number,
55+
options: {colors: boolean},
56+
inspect: (obj: unknown, inspectOptions: {colors: boolean}) => string,
57+
): string {
58+
return inspect(inspectableError(this), options)
59+
}
60+
61+
/**
62+
* Deno "hides" the `message` and `code` properties of the `ErrorEvent` instance,
63+
* when it is `console.log`'ed. This makes it harder to debug errors. To ease debugging,
64+
* we explicitly include the properties in the `inspect` method.
65+
*
66+
* This is automatically called by Deno when you `console.log` an instance of this class.
67+
*
68+
* @param inspect - The inspect function to use (prevents having to import it from `util`)
69+
* @param options - The options passed to `Deno.inspect`
70+
* @returns A string representation of the error
71+
*/
72+
[Symbol.for('Deno.customInspect')](
73+
inspect: (obj: unknown, inspectOptions: {colors: boolean}) => string,
74+
options: {colors: boolean},
75+
): string {
76+
return inspect(inspectableError(this), options)
2977
}
3078
}
3179

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

74122
return err.message
75123
}
124+
125+
/**
126+
* Convert an `ErrorEvent` instance into a plain object for inspection.
127+
*
128+
* @param err - The `ErrorEvent` instance to inspect
129+
* @returns A plain object representation of the error
130+
* @internal
131+
*/
132+
function inspectableError(err: ErrorEvent) {
133+
return {
134+
type: err.type,
135+
message: err.message,
136+
code: err.code,
137+
defaultPrevented: err.defaultPrevented,
138+
cancelable: err.cancelable,
139+
timeStamp: err.timeStamp,
140+
}
141+
}

0 commit comments

Comments
 (0)