Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full Swift 6 data race safety #59

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.5
// swift-tools-version:6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand Down
22 changes: 12 additions & 10 deletions Sources/YouTubeKit/Extensions/Concurrency.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
@available(iOS 13.0, watchOS 6.0, tvOS 13.0, macOS 10.15, *)
extension Sequence {

func asyncMap<T>(_ transform: (Element) async throws -> T) async rethrows -> [T] {
func asyncMap<T: Sendable>(_ transform: (Element) async throws -> T, isolation: isolated (any Actor)? = #isolation) async rethrows -> [T] where Element: Sendable {
var values = [T]()

for element in self {
Expand All @@ -20,16 +20,18 @@ extension Sequence {
return values
}

func concurrentMap<T: Sendable>(_ transform: @escaping @Sendable (Element) async -> T) async -> [T] where Element: Sendable {

let tasks = map { element in
Task {
await transform(element)
func concurrentMap<T: Sendable>(_ transform: @Sendable (Element) async -> T) async -> [T] where Element: Sendable {
return await withoutActuallyEscaping(transform) { escapingTransform in

let tasks = map { element in
Task {
await escapingTransform(element)
}
}

return await tasks.asyncMap { task in
await task.value
}
}

return await tasks.asyncMap { task in
await task.value
}
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/YouTubeKit/Extensions/Retry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extension Task {
// A static function that attempts to execute a block of code with each method in a provided array.
// If the block throws an error, the function will try the next method.
// If all methods have been tried and all have thrown errors, the function will throw the last error encountered.
static func retry<Method>(with methods: [Method], block: (Method) async throws -> Success) async throws -> Success where Failure == Never {
static func retry<Method: Sendable>(with methods: [Method], block: (Method) async throws -> Success, isolation: isolated (any Actor)? = #isolation) async throws -> Success where Failure == Never {

var lastError: any Error = RetryError.emptyMethods

Expand Down
6 changes: 3 additions & 3 deletions Sources/YouTubeKit/YouTube.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation
@preconcurrency import os.log

@available(iOS 13.0, watchOS 6.0, tvOS 13.0, macOS 10.15, *)
public class YouTube {
public actor YouTube {

private var _js: String?
private var _jsURL: URL?
Expand Down Expand Up @@ -81,7 +81,7 @@ public class YouTube {
}

/// - parameter methods: Methods used to extract streams from the video - ordered by priority (Default: only local)
public convenience init(url: URL, proxies: [String: URL] = [:], useOAuth: Bool = false, allowOAuthCache: Bool = false, methods: [ExtractionMethod] = [.local]) {
public init(url: URL, proxies: [String: URL] = [:], useOAuth: Bool = false, allowOAuthCache: Bool = false, methods: [ExtractionMethod] = [.local]) {
let videoID = Extraction.extractVideoID(from: url.absoluteString) ?? ""
self.init(videoID: videoID, proxies: proxies, useOAuth: useOAuth, allowOAuthCache: allowOAuthCache, methods: methods)
}
Expand Down Expand Up @@ -220,7 +220,7 @@ public class YouTube {
var streams = [Stream]()
var existingITags = Set<Int>()

func process(streamingData: InnerTube.StreamingData, videoInfo: InnerTube.VideoInfo) async throws {
func process(streamingData: InnerTube.StreamingData, videoInfo: InnerTube.VideoInfo, isolation: isolated (any Actor)? = #isolation) async throws {

var streamManifest = Extraction.applyDescrambler(streamData: streamingData)

Expand Down
Loading