Skip to content

Commit

Permalink
Remove ability to pass array of event names to EventEmitter.prototype…
Browse files Browse the repository at this point in the history
….once

This functionality is implemented by wrapping the listener argument in
another listener.  This means that the event emitter does not hold a
reference to the listener argument (other than that held indirectly
through the wrapper) and so it is not possible to remove this listener
using `off(..., listener)`.

The client library specification does not specify a version of `once`
which accepts an array of event names, and we do not advertise it as
part of the public API. So, I think the simplest thing is to remove this
functionality.

Resolves #1452.
  • Loading branch information
lawrence-forooghian committed Sep 28, 2023
1 parent 76cc74f commit cd4f7b3
Show file tree
Hide file tree
Showing 3 changed files with 6 additions and 57 deletions.
6 changes: 4 additions & 2 deletions src/common/lib/client/realtimechannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,11 @@ class RealtimeChannel extends Channel {
// Ignore 'attaching' -- could be just due to to a resume & reattach, should not
// call back setOptions until we're definitely attached with the new options (or
// else in a terminal state)
this._allChannelChanges.once(
const self = this;
this._allChannelChanges.on(
['attached', 'update', 'detached', 'failed'],
function (this: { event: string }, stateChange: ConnectionStateChange) {
function listener(this: { event: string }, stateChange: ConnectionStateChange) {
self._allChannelChanges.off(listener);
switch (this.event) {
case 'update':
case 'attached':
Expand Down
19 changes: 2 additions & 17 deletions src/common/lib/util/eventemitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,14 +237,14 @@ class EventEmitter {
* @param event the name of the event to listen to
* @param listener the listener to be called
*/
once(event?: string | string[] | null, listener?: Function): void;
once(event?: string | null, listener?: Function): void;

once(...args: unknown[]): void | Promise<void> {
const argCount = args.length;
if ((argCount === 0 || (argCount === 1 && typeof args[0] !== 'function')) && Platform.Config.Promise) {
const event = args[0];
return new Platform.Config.Promise((resolve) => {
this.once(event as string | string[] | null, resolve);
this.once(event as string | null, resolve);
});
}

Expand All @@ -256,21 +256,6 @@ class EventEmitter {
throw new Error('EventEmitter.once(): Invalid arguments:' + Platform.Config.inspect(args));
}
this.anyOnce.push(secondArg);
} else if (Utils.isArray(firstArg)) {
const self = this;
const listenerWrapper = function (this: any) {
const innerArgs = Array.prototype.slice.call(arguments);
Utils.arrForEach(firstArg, function (eventName) {
self.off(eventName, listenerWrapper);
});
if (typeof secondArg !== 'function') {
throw new Error('EventEmitter.once(): Invalid arguments:' + Platform.Config.inspect(args));
}
secondArg.apply(this, innerArgs);
};
Utils.arrForEach(firstArg, function (eventName) {
self.on(eventName, listenerWrapper);
});
} else {
if (typeof firstArg !== 'string') {
throw new Error('EventEmitter.once(): Invalid arguments:' + Platform.Config.inspect(args));
Expand Down
38 changes: 0 additions & 38 deletions test/realtime/event_emitter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,31 +342,6 @@ define(['shared_helper', 'chai'], function (helper, chai) {
closeAndFinish(done, realtime);
});

it('arrayOfEventsWithOnce', function (done) {
var realtime = helper.AblyRealtime({ autoConnect: false }),
callbackCalled = 0,
eventEmitter = realtime.connection;

var callback = function (arg) {
callbackCalled += 1;
expect(arg).to.equal('expected');
};

try {
callbackCalled = 0;
eventEmitter.once(['a', 'b', 'c'], callback);
eventEmitter.emit('a', 'expected');
eventEmitter.emit('b', 'wrong');
eventEmitter.emit('c', 'wrong');
expect(callbackCalled).to.equal(1, 'listener called back only once, for the first event emitted');
} catch (err) {
closeAndFinish(done, realtime, err);
return;
}

closeAndFinish(done, realtime);
});

/* check that listeners added in a listener cb are not called during that
* emit instance */
it('listenerAddedInListenerCb', function (done) {
Expand Down Expand Up @@ -481,19 +456,6 @@ define(['shared_helper', 'chai'], function (helper, chai) {
closeAndFinish(done, realtime, err);
});
});

it('arrayOfEventsWithOnce', function (done) {
var realtime = helper.AblyRealtime({ autoConnect: false }),
eventEmitter = realtime.connection;

const p = eventEmitter.once(['a', 'b', 'c']);
eventEmitter.emit('b');
p.then(function () {
closeAndFinish(done, realtime);
}).catch(function (err) {
closeAndFinish(done, realtime, err);
});
});
});
}
});
Expand Down

0 comments on commit cd4f7b3

Please sign in to comment.