Skip to content

Commit 50f912c

Browse files
authored
fix: rename event emitter class (#2173)
We add types to a `EventEmitter` class which extends the plain js `EventTarget`. The name is chosen to give familiarity to node developers but it's not generally a good idea. This refactor: 1. Exports a new `TypedEventTarget` interface which adds types to `EventTarget` 2. Renames `EventEmitter` to `TypedEventEmitter` to draw a distinction between them 3. Re-exports `TypedEventEmitter` as `EventEmitter` to preserve backwards compatibility In the future all consuming code should rely on the `TypedEventTarget` interface while implementing code uses `TypedEventEmitter` as an implementation of a `TypedEventEmitter`. By depending on the interface and not the implementation consuming code is isolated from problems that arise when two versions of `@libp2p/interface` is in the dependency tree and the event subsystems would otherwise be compatible due to type overlap. This manifests as an error message about incompatible implementations of the private `#listeners` field in EventEmitter. Backwards compatibility is achieved by exporting the `TypedEventEmitter` class as the older `EventEmitter` name. This should be removed in a future PR to the v1.0 branch once external modules (e.g. Gossipsub) have been updated to use the new `TypedEventEmitter` symbol. ## Change checklist - [x] I have performed a self-review of my own code - [ ] I have made corresponding changes to the documentation if necessary (this includes comments as well) - [ ] I have added tests that prove my fix is effective or that my feature works
1 parent 0ef5f7f commit 50f912c

File tree

81 files changed

+212
-195
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+212
-195
lines changed

packages/interface-compliance-tests/src/mocks/connection-manager.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { isMultiaddr, type Multiaddr } from '@multiformats/multiaddr'
66
import { connectionPair } from './connection.js'
77
import type { Libp2pEvents, PendingDial } from '@libp2p/interface'
88
import type { Connection } from '@libp2p/interface/connection'
9-
import type { EventEmitter } from '@libp2p/interface/events'
9+
import type { TypedEventTarget } from '@libp2p/interface/events'
1010
import type { PubSub } from '@libp2p/interface/pubsub'
1111
import type { Startable } from '@libp2p/interface/startable'
1212
import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager'
@@ -16,7 +16,7 @@ export interface MockNetworkComponents {
1616
peerId: PeerId
1717
registrar: Registrar
1818
connectionManager: ConnectionManager
19-
events: EventEmitter<Libp2pEvents>
19+
events: TypedEventTarget<Libp2pEvents>
2020
pubsub?: PubSub
2121
}
2222

@@ -51,7 +51,7 @@ export const mockNetwork = new MockNetwork()
5151
export interface MockConnectionManagerComponents {
5252
peerId: PeerId
5353
registrar: Registrar
54-
events: EventEmitter<Libp2pEvents>
54+
events: TypedEventTarget<Libp2pEvents>
5555
}
5656

5757
class MockConnectionManager implements ConnectionManager, Startable {

packages/interface-compliance-tests/src/mocks/peer-discovery.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { EventEmitter } from '@libp2p/interface/events'
1+
import { TypedEventEmitter } from '@libp2p/interface/events'
22
import { peerDiscovery } from '@libp2p/interface/peer-discovery'
33
import * as PeerIdFactory from '@libp2p/peer-id-factory'
44
import { multiaddr } from '@multiformats/multiaddr'
@@ -12,7 +12,7 @@ interface MockDiscoveryInit {
1212
/**
1313
* Emits 'peer' events on discovery.
1414
*/
15-
export class MockDiscovery extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery {
15+
export class MockDiscovery extends TypedEventEmitter<PeerDiscoveryEvents> implements PeerDiscovery {
1616
public readonly options: MockDiscoveryInit
1717
private _isRunning: boolean
1818
private _timer: any

packages/interface-compliance-tests/src/mocks/upgrader.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { mockConnection } from './connection.js'
22
import type { Libp2pEvents } from '@libp2p/interface'
33
import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection'
4-
import type { EventEmitter } from '@libp2p/interface/events'
4+
import type { TypedEventTarget } from '@libp2p/interface/events'
55
import type { Upgrader, UpgraderOptions } from '@libp2p/interface/transport'
66
import type { Registrar } from '@libp2p/interface-internal/registrar'
77

88
export interface MockUpgraderInit {
99
registrar?: Registrar
10-
events?: EventEmitter<Libp2pEvents>
10+
events?: TypedEventTarget<Libp2pEvents>
1111
}
1212

1313
class MockUpgrader implements Upgrader {
1414
private readonly registrar?: Registrar
15-
private readonly events?: EventEmitter<Libp2pEvents>
15+
private readonly events?: TypedEventTarget<Libp2pEvents>
1616

1717
constructor (init: MockUpgraderInit) {
1818
this.registrar = init.registrar

packages/interface-compliance-tests/src/pubsub/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { EventEmitter } from '@libp2p/interface/events'
1+
import { TypedEventEmitter } from '@libp2p/interface/events'
22
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
33
import { pEvent } from 'p-event'
44
import pWaitFor from 'p-wait-for'
@@ -19,7 +19,7 @@ export async function createComponents (): Promise<MockNetworkComponents> {
1919
const components: any = {
2020
peerId: await createEd25519PeerId(),
2121
registrar: mockRegistrar(),
22-
events: new EventEmitter()
22+
events: new TypedEventEmitter()
2323
}
2424
components.connectionManager = mockConnectionManager(components)
2525

packages/interface-compliance-tests/src/transport/dial-test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AbortError } from '@libp2p/interface/errors'
2-
import { EventEmitter } from '@libp2p/interface/events'
2+
import { TypedEventEmitter } from '@libp2p/interface/events'
33
import { expect } from 'aegir/chai'
44
import all from 'it-all'
55
import drain from 'it-drain'
@@ -27,7 +27,7 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
2727
registrar = mockRegistrar()
2828
upgrader = mockUpgrader({
2929
registrar,
30-
events: new EventEmitter()
30+
events: new TypedEventEmitter()
3131
});
3232

3333
({ addrs, transport, connector } = await common.setup())

packages/interface-compliance-tests/src/transport/listen-test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint max-nested-callbacks: ["error", 8] */
2-
import { CustomEvent, EventEmitter } from '@libp2p/interface/events'
2+
import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events'
33
import { expect } from 'aegir/chai'
44
import drain from 'it-drain'
55
import { pipe } from 'it-pipe'
@@ -27,7 +27,7 @@ export default (common: TestSetup<TransportTestFixtures>): void => {
2727
registrar = mockRegistrar()
2828
upgrader = mockUpgrader({
2929
registrar,
30-
events: new EventEmitter()
30+
events: new TypedEventEmitter()
3131
});
3232

3333
({ transport, addrs } = await common.setup())

packages/interface/src/events.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,23 @@ interface Listener {
1515
* https://github.com/microsoft/TypeScript/issues/299
1616
* etc
1717
*/
18-
export class EventEmitter<EventMap extends Record<string, any>> extends EventTarget {
18+
export interface TypedEventTarget <EventMap extends Record<string, any>> extends EventTarget {
19+
addEventListener<K extends keyof EventMap>(type: K, listener: EventHandler<EventMap[K]> | null, options?: boolean | AddEventListenerOptions): void
20+
21+
listenerCount (type: string): number
22+
23+
removeEventListener<K extends keyof EventMap>(type: K, listener?: EventHandler<EventMap[K]> | null, options?: boolean | EventListenerOptions): void
24+
25+
removeEventListener (type: string, listener?: EventHandler<Event>, options?: boolean | EventListenerOptions): void
26+
27+
safeDispatchEvent<Detail>(type: keyof EventMap, detail: CustomEventInit<Detail>): boolean
28+
}
29+
30+
/**
31+
* An implementation of a typed event target
32+
* etc
33+
*/
34+
export class TypedEventEmitter<EventMap extends Record<string, any>> extends EventTarget implements TypedEventTarget<EventMap> {
1935
#listeners = new Map<any, Listener[]>()
2036

2137
listenerCount (type: string): number {
@@ -98,3 +114,6 @@ class CustomEventPolyfill<T = any> extends Event {
98114
}
99115

100116
export const CustomEvent = globalThis.CustomEvent ?? CustomEventPolyfill
117+
118+
// TODO: remove this in v1
119+
export { TypedEventEmitter as EventEmitter }

packages/interface/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import type { Connection, NewStreamOptions, Stream } from './connection/index.js'
1818
import type { ContentRouting } from './content-routing/index.js'
19-
import type { EventEmitter } from './events.js'
19+
import type { TypedEventTarget } from './events.js'
2020
import type { KeyChain } from './keychain/index.js'
2121
import type { Metrics } from './metrics/index.js'
2222
import type { PeerId } from './peer-id/index.js'
@@ -303,7 +303,7 @@ export interface PendingDial {
303303
/**
304304
* Libp2p nodes implement this interface.
305305
*/
306-
export interface Libp2p<T extends ServiceMap = ServiceMap> extends Startable, EventEmitter<Libp2pEvents<T>> {
306+
export interface Libp2p<T extends ServiceMap = ServiceMap> extends Startable, TypedEventTarget<Libp2pEvents<T>> {
307307
/**
308308
* The PeerId is a unique identifier for a node on the network.
309309
*

packages/interface/src/peer-discovery/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { EventEmitter } from '../events.js'
1+
import type { TypedEventTarget } from '../events.js'
22
import type { PeerInfo } from '../peer-info/index.js'
33

44
/**
@@ -26,4 +26,4 @@ export interface PeerDiscoveryEvents {
2626
'peer': CustomEvent<PeerInfo>
2727
}
2828

29-
export interface PeerDiscovery extends EventEmitter<PeerDiscoveryEvents> {}
29+
export interface PeerDiscovery extends TypedEventTarget<PeerDiscoveryEvents> {}

packages/interface/src/pubsub/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Stream } from '../connection/index.js'
2-
import type { EventEmitter } from '../events.js'
2+
import type { TypedEventTarget } from '../events.js'
33
import type { PeerId } from '../peer-id/index.js'
44
import type { Pushable } from 'it-pushable'
55
import type { Uint8ArrayList } from 'uint8arraylist'
@@ -65,7 +65,7 @@ export interface PubSubRPC {
6565
messages: PubSubRPCMessage[]
6666
}
6767

68-
export interface PeerStreams extends EventEmitter<PeerStreamEvents> {
68+
export interface PeerStreams extends TypedEventTarget<PeerStreamEvents> {
6969
id: PeerId
7070
protocol: string
7171
outboundStream?: Pushable<Uint8ArrayList>
@@ -152,7 +152,7 @@ export interface TopicValidatorFn {
152152
(peer: PeerId, message: Message): TopicValidatorResult | Promise<TopicValidatorResult>
153153
}
154154

155-
export interface PubSub<Events extends Record<string, any> = PubSubEvents> extends EventEmitter<Events> {
155+
export interface PubSub<Events extends Record<string, any> = PubSubEvents> extends TypedEventTarget<Events> {
156156
/**
157157
* The global signature policy controls whether or not we sill send and receive
158158
* signed or unsigned messages.

0 commit comments

Comments
 (0)