From 766c3b86ca2052b23c53a36f04109bb30f2c3cdd Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Tue, 25 Jun 2024 09:33:27 +0200 Subject: [PATCH 1/4] fix: forward dispatch return value --- lib/dispatcher/dispatcher.js | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/dispatcher/dispatcher.js b/lib/dispatcher/dispatcher.js index b1e0098ec4b..9ce5c20b780 100644 --- a/lib/dispatcher/dispatcher.js +++ b/lib/dispatcher/dispatcher.js @@ -39,18 +39,35 @@ class Dispatcher extends EventEmitter { } } +const kOnDrain = Symbol('onDrain') +const kOnConnect = Symbol('onConnect') +const kOnDisconnect = Symbol('onDisconnect') +const kOnConnectionError = Symbol('onConnectionError') + class ComposedDispatcher extends Dispatcher { - #dispatcher = null - #dispatch = null + #dispatcher + #dispatch constructor (dispatcher, dispatch) { super() + this.#dispatcher = dispatcher this.#dispatch = dispatch + + this[kOnDrain] = (...args) => this.emit('drain', ...args) + this[kOnConnect] = (...args) => this.emit('connect', ...args) + this[kOnDisconnect] = (...args) => this.emit('disconnect', ...args) + this[kOnConnectionError] = (...args) => this.emit('connectionError', ...args) + + this.#dispatcher + .on('drain', this[kOnDrain]) + .on('connect', this[kOnConnect]) + .on('disconnect', this[kOnDisconnect]) + .on('connectionError', this[kOnConnectionError]) } dispatch (...args) { - this.#dispatch(...args) + return this.#dispatch(...args) } close (...args) { From 8844ee6cb81da2ea2e7f1d99e314c84fd2aaf65a Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Tue, 25 Jun 2024 20:28:57 +0200 Subject: [PATCH 2/4] fixup --- lib/dispatcher/dispatcher.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/dispatcher/dispatcher.js b/lib/dispatcher/dispatcher.js index 9ce5c20b780..4f23e6e3485 100644 --- a/lib/dispatcher/dispatcher.js +++ b/lib/dispatcher/dispatcher.js @@ -59,6 +59,7 @@ class ComposedDispatcher extends Dispatcher { this[kOnDisconnect] = (...args) => this.emit('disconnect', ...args) this[kOnConnectionError] = (...args) => this.emit('connectionError', ...args) + // TODO (fix): These must be weak references... this.#dispatcher .on('drain', this[kOnDrain]) .on('connect', this[kOnConnect]) From 67de8922e628f7611b1dc2361528d6a0142e2356 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Tue, 25 Jun 2024 20:40:55 +0200 Subject: [PATCH 3/4] fixuP --- lib/dispatcher/dispatcher.js | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/lib/dispatcher/dispatcher.js b/lib/dispatcher/dispatcher.js index 4f23e6e3485..d7e2956ccfc 100644 --- a/lib/dispatcher/dispatcher.js +++ b/lib/dispatcher/dispatcher.js @@ -39,10 +39,11 @@ class Dispatcher extends EventEmitter { } } -const kOnDrain = Symbol('onDrain') -const kOnConnect = Symbol('onConnect') -const kOnDisconnect = Symbol('onDisconnect') -const kOnConnectionError = Symbol('onConnectionError') +const registry = new FinalizationRegistry(({ dispatcher, handlers }) => { + for (const [event, listener] of handlers) { + dispatcher.off(event, listener) + } +}) class ComposedDispatcher extends Dispatcher { #dispatcher @@ -54,17 +55,18 @@ class ComposedDispatcher extends Dispatcher { this.#dispatcher = dispatcher this.#dispatch = dispatch - this[kOnDrain] = (...args) => this.emit('drain', ...args) - this[kOnConnect] = (...args) => this.emit('connect', ...args) - this[kOnDisconnect] = (...args) => this.emit('disconnect', ...args) - this[kOnConnectionError] = (...args) => this.emit('connectionError', ...args) - - // TODO (fix): These must be weak references... - this.#dispatcher - .on('drain', this[kOnDrain]) - .on('connect', this[kOnConnect]) - .on('disconnect', this[kOnDisconnect]) - .on('connectionError', this[kOnConnectionError]) + const weakThis = new WeakRef(this) + const handlers = [] + + for (const event of ['drain', 'connect', 'disconnect', 'connectionError']) { + const listener = function (...args) { + weakThis.deref()?.emit(event, ...args) + } + handlers.push([event, listener]) + dispatcher.on(event, listener) + } + + registry.register(this, { dispatcher, handlers }) } dispatch (...args) { From 194c37a598f597c622ce55cce73583d51b316a46 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Wed, 26 Jun 2024 07:33:37 +0200 Subject: [PATCH 4/4] fixup: use Proxy --- lib/dispatcher/dispatcher.js | 47 +++--------------------------------- test/dispatcher.js | 5 +--- 2 files changed, 4 insertions(+), 48 deletions(-) diff --git a/lib/dispatcher/dispatcher.js b/lib/dispatcher/dispatcher.js index d7e2956ccfc..ecff2a9b168 100644 --- a/lib/dispatcher/dispatcher.js +++ b/lib/dispatcher/dispatcher.js @@ -35,50 +35,9 @@ class Dispatcher extends EventEmitter { } } - return new ComposedDispatcher(this, dispatch) - } -} - -const registry = new FinalizationRegistry(({ dispatcher, handlers }) => { - for (const [event, listener] of handlers) { - dispatcher.off(event, listener) - } -}) - -class ComposedDispatcher extends Dispatcher { - #dispatcher - #dispatch - - constructor (dispatcher, dispatch) { - super() - - this.#dispatcher = dispatcher - this.#dispatch = dispatch - - const weakThis = new WeakRef(this) - const handlers = [] - - for (const event of ['drain', 'connect', 'disconnect', 'connectionError']) { - const listener = function (...args) { - weakThis.deref()?.emit(event, ...args) - } - handlers.push([event, listener]) - dispatcher.on(event, listener) - } - - registry.register(this, { dispatcher, handlers }) - } - - dispatch (...args) { - return this.#dispatch(...args) - } - - close (...args) { - return this.#dispatcher.close(...args) - } - - destroy (...args) { - return this.#dispatcher.destroy(...args) + return new Proxy(this, { + get: (target, key) => key === 'dispatch' ? dispatch : target[key] + }) } } diff --git a/test/dispatcher.js b/test/dispatcher.js index 1febdf53b4b..fbb56e94bc1 100644 --- a/test/dispatcher.js +++ b/test/dispatcher.js @@ -22,14 +22,11 @@ test('dispatcher implementation', (t) => { }) test('dispatcher.compose', (t) => { - t = tspl(t, { plan: 10 }) + t = tspl(t, { plan: 7 }) const dispatcher = new Dispatcher() const interceptor = () => (opts, handler) => {} // Should return a new dispatcher - t.ok(Object.getPrototypeOf(dispatcher.compose(interceptor)) instanceof Dispatcher) - t.ok(Object.getPrototypeOf(dispatcher.compose(interceptor, interceptor)) instanceof Dispatcher) - t.ok(Object.getPrototypeOf(dispatcher.compose([interceptor, interceptor])) instanceof Dispatcher) t.ok(dispatcher.compose(interceptor) !== dispatcher) t.throws(() => dispatcher.dispatch({}), Error, 'invalid interceptor') t.throws(() => dispatcher.dispatch(() => null), Error, 'invalid interceptor')