From 3fa56e782561675b456b2bac6ea991403fb72c0b Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 16 Jul 2021 17:27:27 +0300 Subject: [PATCH] Fixed a bug when onUndeliveredElement was invoked for normally-receive elements on JS Fixes #2826 --- .../channels/ChannelUndeliveredElementTest.kt | 15 +++++++++++++++ .../js/src/internal/LinkedList.kt | 15 +++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementTest.kt b/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementTest.kt index 9915d38fe6..f26361f2f8 100644 --- a/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementTest.kt +++ b/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementTest.kt @@ -123,4 +123,19 @@ class ChannelUndeliveredElementTest : TestBase() { check(!_cancelled.getAndSet(true)) { "Already cancelled" } } } + + @Test + fun testHandlerIsNotInvoked() = runTest { // #2826 + val channel = Channel { + expectUnreached() + } + + expect(1) + launch { + expect(2) + channel.receive() + } + channel.send(Unit) + finish(3) + } } diff --git a/kotlinx-coroutines-core/js/src/internal/LinkedList.kt b/kotlinx-coroutines-core/js/src/internal/LinkedList.kt index f2711f50af..147b31dc3e 100644 --- a/kotlinx-coroutines-core/js/src/internal/LinkedList.kt +++ b/kotlinx-coroutines-core/js/src/internal/LinkedList.kt @@ -32,7 +32,18 @@ public open class LinkedListNode { this._prev = node } + /* + * Remove that is invoked as a virtual function with a + * potentially augmented behaviour. + * I.g. `LockFreeLinkedListHead` throws, while `SendElementWithUndeliveredHandler` + * invokes handler on remove + */ public open fun remove(): Boolean { + return removeImpl() + } + + @PublishedApi + internal fun removeImpl(): Boolean { if (_removed) return false val prev = this._prev val next = this._next @@ -76,7 +87,7 @@ public open class LinkedListNode { public fun removeFirstOrNull(): Node? { val next = _next if (next === this) return null - check(next.remove()) { "Should remove" } + check(next.removeImpl()) { "Should remove" } return next } @@ -85,7 +96,7 @@ public open class LinkedListNode { if (next === this) return null if (next !is T) return null if (predicate(next)) return next - check(next.remove()) { "Should remove" } + check(next.removeImpl()) { "Should remove" } return next } }