diff --git a/Foundation/NSString.swift b/Foundation/NSString.swift index 57f651c4f2..b1f7f78162 100644 --- a/Foundation/NSString.swift +++ b/Foundation/NSString.swift @@ -27,7 +27,11 @@ func NSLocalizedString(_ key: String, bundle: Bundle = Bundle.main, value: String = "", comment: String) -> String { - return bundle.localizedString(forKey: key, value: value, table: tableName) + #if os(Android) + return key + #else + return bundle.localizedString(forKey: key, value: value, table: tableName) + #endif } #if os(OSX) || os(iOS) diff --git a/Foundation/URLSession/TaskRegistry.swift b/Foundation/URLSession/TaskRegistry.swift index b817bcec0a..0e8cb8f676 100644 --- a/Foundation/URLSession/TaskRegistry.swift +++ b/Foundation/URLSession/TaskRegistry.swift @@ -72,14 +72,19 @@ extension URLSession._TaskRegistry { func remove(_ task: URLSessionTask) { let identifier = task.taskIdentifier guard identifier != 0 else { fatalError("Invalid task identifier") } - guard let tasksIdx = tasks.index(forKey: identifier) else { - fatalError("Trying to remove task, but it's not in the registry.") + + if let tasksIdx = tasks.index(forKey: identifier) { + tasks.remove(at: tasksIdx) + } else { + NSLog("Trying to remove task, but it's not in the registry.") } - tasks.remove(at: tasksIdx) - guard let behaviourIdx = behaviours.index(forKey: identifier) else { - fatalError("Trying to remove task's behaviour, but it's not in the registry.") + + if let behaviourIdx = behaviours.index(forKey: identifier) { + behaviours.remove(at: behaviourIdx) + } else { + NSLog("Trying to remove task's behaviour, but it's not in the registry.") } - behaviours.remove(at: behaviourIdx) + guard let allTasksFinished = tasksFinishedCallback else { return } if self.isEmpty { @@ -115,4 +120,8 @@ extension URLSession._TaskRegistry { } return b } + + func containsBehaviour(for task: URLSessionTask) -> Bool { + return behaviours[task.taskIdentifier] != nil + } } diff --git a/Foundation/URLSession/URLSession.swift b/Foundation/URLSession/URLSession.swift index 3d503d43c0..f974626043 100644 --- a/Foundation/URLSession/URLSession.swift +++ b/Foundation/URLSession/URLSession.swift @@ -546,6 +546,10 @@ internal extension URLSession { } func behaviour(for task: URLSessionTask) -> _TaskBehaviour { + guard taskRegistry.containsBehaviour(for: task) else { + return .noDelegate + } + switch taskRegistry.behaviour(for: task) { case .dataCompletionHandler(let c): return .dataCompletionHandler(c) case .downloadCompletionHandler(let c): return .downloadCompletionHandler(c) diff --git a/Foundation/URLSession/URLSessionTask.swift b/Foundation/URLSession/URLSessionTask.swift index 82028da0b6..adccfe97cc 100644 --- a/Foundation/URLSession/URLSessionTask.swift +++ b/Foundation/URLSession/URLSessionTask.swift @@ -702,24 +702,30 @@ extension _ProtocolClient: URLProtocolClient { session.delegateQueue.addOperation { delegate.urlSession(session, task: task, didCompleteWithError: nil) task.state = .completed - task.workQueue.async { + session.workQueue.async { session.taskRegistry.remove(task) } } case .noDelegate: task.state = .completed - session.taskRegistry.remove(task) + session.workQueue.async { + session.taskRegistry.remove(task) + } case .dataCompletionHandler(let completion): session.delegateQueue.addOperation { completion(`protocol`.properties[URLProtocol._PropertyKey.responseData] as? Data ?? Data(), task.response, nil) task.state = .completed - session.taskRegistry.remove(task) + session.workQueue.async { + session.taskRegistry.remove(task) + } } case .downloadCompletionHandler(let completion): session.delegateQueue.addOperation { completion(`protocol`.properties[URLProtocol._PropertyKey.temporaryFileURL] as? URL, task.response, nil) task.state = .completed - session.taskRegistry.remove(task) + session.workQueue.async { + session.taskRegistry.remove(task) + } } } task._protocol = nil @@ -786,18 +792,20 @@ extension _ProtocolClient: URLProtocolClient { session.delegateQueue.addOperation { delegate.urlSession(session, task: task, didCompleteWithError: error as Error) task.state = .completed - task.workQueue.async { + session.workQueue.async { session.taskRegistry.remove(task) } } case .noDelegate: task.state = .completed - session.taskRegistry.remove(task) + session.workQueue.async { + session.taskRegistry.remove(task) + } case .dataCompletionHandler(let completion): session.delegateQueue.addOperation { completion(nil, nil, error) task.state = .completed - task.workQueue.async { + session.workQueue.async { session.taskRegistry.remove(task) } } @@ -805,7 +813,9 @@ extension _ProtocolClient: URLProtocolClient { session.delegateQueue.addOperation { completion(nil, nil, error) task.state = .completed - session.taskRegistry.remove(task) + session.workQueue.async { + session.taskRegistry.remove(task) + } } } task._protocol = nil diff --git a/Foundation/URLSession/http/HTTPURLProtocol.swift b/Foundation/URLSession/http/HTTPURLProtocol.swift index 8f4dc69bf5..4c218ca400 100644 --- a/Foundation/URLSession/http/HTTPURLProtocol.swift +++ b/Foundation/URLSession/http/HTTPURLProtocol.swift @@ -56,7 +56,7 @@ internal class _HTTPURLProtocol: URLProtocol { suspend() } else { self.internalState = .transferFailed - guard let error = self.task?.error else { fatalError() } + let error = self.task?.error ?? NSError(domain: NSURLErrorDomain, code: URLError.Code.unknown.rawValue) completeTask(withError: error) } }