From 397abb145fa2558b2ad23230905795a88643261f Mon Sep 17 00:00:00 2001 From: James Beattie Date: Mon, 29 Mar 2021 07:56:07 +0100 Subject: [PATCH 1/2] Add failing test for memory leak issue --- Tests/ShareReplayTests.swift | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Tests/ShareReplayTests.swift b/Tests/ShareReplayTests.swift index 14c68c2..76121d9 100644 --- a/Tests/ShareReplayTests.swift +++ b/Tests/ShareReplayTests.swift @@ -213,5 +213,33 @@ final class ShareReplayTests: XCTestCase { XCTAssertTrue(results.isEmpty) XCTAssertEqual(completions, [.failure(.someError)]) } + + func testSharingDoesNotRetainClassBasedPublisher() { + var results = [Int]() + var completions = [Subscribers.Completion]() + + var source: PassthroughSubject? = PassthroughSubject() + weak var weakSource = source + + var stream = source?.share(replay: 1) + + stream? + .sink( + receiveCompletion: { completions.append($0) }, + receiveValue: { results.append($0) } + ) + .store(in: &subscriptions) + + source?.send(1) + source?.send(completion: .finished) + + subscriptions.forEach({ $0.cancel() }) + stream = nil + source = nil + + XCTAssertEqual(results, [1]) + XCTAssertEqual(completions, [.finished]) + XCTAssertNil(weakSource) + } } #endif From 11cedcd339fdbb221743a86b8ec8339c217e9ec2 Mon Sep 17 00:00:00 2001 From: James Beattie Date: Mon, 29 Mar 2021 07:56:27 +0100 Subject: [PATCH 2/2] Ensure the cancellationHandler is called if present when completion received --- Sources/Subjects/ReplaySubject.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/Subjects/ReplaySubject.swift b/Sources/Subjects/ReplaySubject.swift index 46ed794..9466459 100644 --- a/Sources/Subjects/ReplaySubject.swift +++ b/Sources/Subjects/ReplaySubject.swift @@ -137,6 +137,7 @@ extension ReplaySubject { func forwardCompletionToBuffer(_ completion: Subscribers.Completion) { demandBuffer?.complete(completion: completion) + cancel() } func request(_ demand: Subscribers.Demand) {