Skip to content

Commit 9f993f1

Browse files
authored
Merge pull request #1599 from matrix-org/dbkr/reemitter_dont_throw_if_no_error_handler
ReEmitter: Don't throw if no error handler is attached
2 parents 66a8634 + 975518b commit 9f993f1

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

spec/unit/ReEmitter.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ class EventSource extends EventEmitter {
2323
doTheThing() {
2424
this.emit(EVENTNAME, "foo", "bar");
2525
}
26+
27+
doAnError() {
28+
this.emit('error');
29+
}
2630
}
2731

2832
class EventTarget extends EventEmitter {
@@ -46,4 +50,23 @@ describe("ReEmitter", function() {
4650
// also the source object of the event which re-emitter adds
4751
expect(handler).toHaveBeenCalledWith("foo", "bar", src);
4852
});
53+
54+
it("Doesn't throw if no handler for 'error' event", function() {
55+
const src = new EventSource();
56+
const tgt = new EventTarget();
57+
58+
const reEmitter = new ReEmitter(tgt);
59+
reEmitter.reEmit(src, ['error']);
60+
61+
// without the workaround in ReEmitter, this would throw
62+
src.doAnError();
63+
64+
const handler = jest.fn();
65+
tgt.on('error', handler);
66+
67+
src.doAnError();
68+
69+
// Now we've attached an error handler, it should be called
70+
expect(handler).toHaveBeenCalled();
71+
});
4972
});

src/ReEmitter.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ export class ReEmitter {
3131
// such as read receipt listeners on the client class which won't have the context
3232
// of the room.
3333
const forSource = (...args) => {
34+
// EventEmitter special cases 'error' to make the emit function throw if no
35+
// handler is attached, which sort of makes sense for making sure that something
36+
// handles an error, but for re-emitting, there could be a listener on the original
37+
// source object so the test doesn't really work. We *could* try to replicate the
38+
// same logic and throw if there is no listener on either the source or the target,
39+
// but this behaviour is fairly undesireable for us anyway: the main place we throw
40+
// 'error' events is for calls, where error events are usually emitted some time
41+
// later by a different part of the code where 'emit' throwing because the app hasn't
42+
// added an error handler isn't terribly helpful. (A better fix in retrospect may
43+
// have been to just avoid using the event name 'error', but backwards compat...)
44+
if (eventName === 'error' && this.target.listenerCount('error') === 0) return;
3445
this.target.emit(eventName, ...args, source);
3546
};
3647
source.on(eventName, forSource);

0 commit comments

Comments
 (0)