@@ -206,7 +206,7 @@ public final class PlaybackURLProtocol: URLProtocol, @unchecked Sendable {
206206 // URLProtocol predates Swift concurrency; wrap self to cross isolation boundary
207207 let sendableSelf = UnsafeSendable ( value: self )
208208 streamTask = Task {
209- let `self` = sendableSelf. value
209+ let urlProtocol = sendableSelf. value
210210 do {
211211 var matchingRequest = markedRequest
212212
@@ -228,10 +228,10 @@ public final class PlaybackURLProtocol: URLProtocol, @unchecked Sendable {
228228
229229 switch disposition {
230230 case . recorded( let response, let data) :
231- self . client? . urlProtocol (
232- self , didReceive: response, cacheStoragePolicy: . notAllowed)
233- self . client? . urlProtocol ( self , didLoad: data)
234- self . client? . urlProtocolDidFinishLoading ( self )
231+ urlProtocol . client? . urlProtocol (
232+ urlProtocol , didReceive: response, cacheStoragePolicy: . notAllowed)
233+ urlProtocol . client? . urlProtocol ( urlProtocol , didLoad: data)
234+ urlProtocol . client? . urlProtocolDidFinishLoading ( urlProtocol )
235235
236236 case . error( let error) :
237237 throw error
@@ -247,19 +247,20 @@ public final class PlaybackURLProtocol: URLProtocol, @unchecked Sendable {
247247 config. timeoutIntervalForResource = . infinity
248248 let session = URLSession ( configuration: config, delegate: delegate, delegateQueue: nil )
249249 let dataTask = session. dataTask ( with: matchingRequest)
250+ let sendableDataTask = UnsafeSendable ( value: dataTask)
250251
251252 // Initialize dataStream BEFORE starting the request
252253 let dataStream = delegate. dataStream
253254
254255 // Store task reference for cancellation
255- self . urlSessionTask = dataTask
256+ urlProtocol . urlSessionTask = dataTask
256257 dataTask. resume ( )
257258
258259 // Wait for response
259260 let httpResponse = try await delegate. waitForResponse ( )
260261
261- self . client? . urlProtocol (
262- self , didReceive: httpResponse, cacheStoragePolicy: . notAllowed)
262+ urlProtocol . client? . urlProtocol (
263+ urlProtocol , didReceive: httpResponse, cacheStoragePolicy: . notAllowed)
263264
264265 // Stream data incrementally, collecting for potential recording
265266 // Use a class to allow capturing in the finish handler
@@ -268,13 +269,13 @@ public final class PlaybackURLProtocol: URLProtocol, @unchecked Sendable {
268269 var finished = false
269270 }
270271 let state = StreamState ( )
271- let protocol Id = ObjectIdentifier ( self )
272+ let protocol Id = ObjectIdentifier ( urlProtocol )
272273 let capturedRequest = matchingRequest
273274 let capturedResponse = httpResponse
274275
275276 // Register finish handler for flush()
276277 if shouldRecord {
277- await store. registerStreamingProtocol ( id: protocolId) { [ state] in
278+ await store. registerStreamingProtocol ( id: protocolId) { [ state, sendableDataTask ] in
278279 guard !state. finished, !state. collectedData. isEmpty else { return }
279280 state. finished = true
280281 let duration = Date ( ) . timeIntervalSince ( startTime)
@@ -291,16 +292,19 @@ public final class PlaybackURLProtocol: URLProtocol, @unchecked Sendable {
291292 " Replay: Failed to record response for \( requestDescription ( capturedRequest) ) : \( error) "
292293 )
293294 }
295+
296+ // Stop the underlying stream so it doesn't keep accumulating data after `flush()` is called
297+ sendableDataTask. value. cancel ( )
294298 }
295299 }
296300
297301 let urlTask = dataTask
298302 do {
299303 try await withTaskCancellationHandler {
300304 for try await chunk in dataStream {
301- if Task . isCancelled { break }
305+ if Task . isCancelled || state . finished { break }
302306 state. collectedData. append ( chunk)
303- self . client? . urlProtocol ( self , didLoad: chunk)
307+ urlProtocol . client? . urlProtocol ( urlProtocol , didLoad: chunk)
304308 }
305309 } onCancel: {
306310 urlTask. cancel ( )
@@ -330,11 +334,11 @@ public final class PlaybackURLProtocol: URLProtocol, @unchecked Sendable {
330334 }
331335
332336 session. invalidateAndCancel ( )
333- self . client? . urlProtocolDidFinishLoading ( self )
337+ urlProtocol . client? . urlProtocolDidFinishLoading ( urlProtocol )
334338 }
335339 } catch {
336340 if !Task. isCancelled {
337- self . client? . urlProtocol ( self , didFailWithError: error)
341+ urlProtocol . client? . urlProtocol ( urlProtocol , didFailWithError: error)
338342 }
339343 }
340344 }
0 commit comments