From 80b56bbab0f3962b1ee21d8fdd6b8f94ca0adf0f Mon Sep 17 00:00:00 2001 From: simon-id Date: Mon, 14 Oct 2024 12:55:39 +0200 Subject: [PATCH] diagnostics_channel: fix unsubscribe during publish PR-URL: https://github.com/nodejs/node/pull/55116 Reviewed-By: Stephen Belanger Reviewed-By: Claudio Wunder --- lib/diagnostics_channel.js | 13 ++++++++++--- .../test-diagnostics-channel-sync-unsubscribe.js | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/diagnostics_channel.js b/lib/diagnostics_channel.js index 59a95b08226..312bd258f58 100644 --- a/lib/diagnostics_channel.js +++ b/lib/diagnostics_channel.js @@ -4,6 +4,8 @@ const { ArrayPrototypeAt, ArrayPrototypeIndexOf, ArrayPrototypePush, + ArrayPrototypePushApply, + ArrayPrototypeSlice, ArrayPrototypeSplice, ObjectDefineProperty, ObjectGetPrototypeOf, @@ -97,6 +99,7 @@ function wrapStoreRun(store, data, next, transform = defaultTransform) { class ActiveChannel { subscribe(subscription) { validateFunction(subscription, 'subscription'); + this._subscribers = ArrayPrototypeSlice(this._subscribers); ArrayPrototypePush(this._subscribers, subscription); channels.incRef(this.name); } @@ -105,7 +108,10 @@ class ActiveChannel { const index = ArrayPrototypeIndexOf(this._subscribers, subscription); if (index === -1) return false; - ArrayPrototypeSplice(this._subscribers, index, 1); + const before = ArrayPrototypeSlice(this._subscribers, 0, index); + const after = ArrayPrototypeSlice(this._subscribers, index + 1); + this._subscribers = before; + ArrayPrototypePushApply(this._subscribers, after); channels.decRef(this.name); maybeMarkInactive(this); @@ -137,9 +143,10 @@ class ActiveChannel { } publish(data) { - for (let i = 0; i < (this._subscribers?.length || 0); i++) { + const subscribers = this._subscribers; + for (let i = 0; i < (subscribers?.length || 0); i++) { try { - const onMessage = this._subscribers[i]; + const onMessage = subscribers[i]; onMessage(data, this.name); } catch (err) { process.nextTick(() => { diff --git a/test/parallel/test-diagnostics-channel-sync-unsubscribe.js b/test/parallel/test-diagnostics-channel-sync-unsubscribe.js index 87bf44249f5..51db6a56c23 100644 --- a/test/parallel/test-diagnostics-channel-sync-unsubscribe.js +++ b/test/parallel/test-diagnostics-channel-sync-unsubscribe.js @@ -9,6 +9,7 @@ const published_data = 'some message'; const onMessageHandler = common.mustCall(() => dc.unsubscribe(channel_name, onMessageHandler)); dc.subscribe(channel_name, onMessageHandler); +dc.subscribe(channel_name, common.mustCall()); // This must not throw. dc.channel(channel_name).publish(published_data);