From 69d5fe6e71cfb899bcf6a762907ab1e8498c045c Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Tue, 9 Jun 2026 09:32:19 +0200 Subject: [PATCH 1/8] Add checks to indexed retrieval of qualities --- ios/THEOplayerRCTPlayerAPI.swift | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ios/THEOplayerRCTPlayerAPI.swift b/ios/THEOplayerRCTPlayerAPI.swift index 27a2f3e8c..bd0641240 100644 --- a/ios/THEOplayerRCTPlayerAPI.swift +++ b/ios/THEOplayerRCTPlayerAPI.swift @@ -341,22 +341,26 @@ class THEOplayerRCTPlayerAPI: NSObject, RCTBridgeModule { if let theView = self.bridge.uiManager.view(forReactTag: node) as? THEOplayerRCTView, let player = theView.player { let videoTracks: VideoTrackList = player.videoTracks - guard videoTracks.count > 0 else { + let videoTrackCount = videoTracks.count + guard videoTrackCount > 0 else { return } var activeVideoTrack: VideoTrack? - for i in 0...videoTracks.count-1 { + for i in 0.. Quality? in + guard index < foundTrack.qualities.count else { return nil } let quality = foundTrack.qualities.get(index) - return uids.contains { $0.intValue == quality.bandwidth } ? quality : nil + return uids.contains(where: { $0.intValue == quality.bandwidth }) ? quality : nil } - foundTrack.targetQualities = matchingQualities.count > 0 ? matchingQualities : nil + foundTrack.targetQualities = matchingQualities.isEmpty ? nil : matchingQualities if DEBUG_PLAYER_API { if matchingQualities.count > 0 { if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] targetQualities: \(uids) set on active videotrack. (matching: \(matchingQualities.map(\.bandwidth)))") } From 366824a33b6bf586db9d99169512f165d0a29c48 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Tue, 9 Jun 2026 09:34:08 +0200 Subject: [PATCH 2/8] Check index on track lookup --- ios/THEOplayerRCTPlayerAPI.swift | 18 +++++--- ...THEOplayerRCTTrackMetadataAggregator.swift | 46 +++++++++++++------ 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/ios/THEOplayerRCTPlayerAPI.swift b/ios/THEOplayerRCTPlayerAPI.swift index bd0641240..4150c79f5 100644 --- a/ios/THEOplayerRCTPlayerAPI.swift +++ b/ios/THEOplayerRCTPlayerAPI.swift @@ -281,11 +281,13 @@ class THEOplayerRCTPlayerAPI: NSObject, RCTBridgeModule { let player = theView.player { let uidValue = uid.intValue let textTracks: TextTrackList = player.textTracks - guard textTracks.count > 0 else { + let textTrackCount = textTracks.count + guard textTrackCount > 0 else { return } if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] Showing textTrack \(uidValue) on TheoPlayer") } - for i in 0...textTracks.count-1 { + for i in 0.. 0 else { + let audioTrackCount = audioTracks.count + guard audioTrackCount > 0 else { return } if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] Enabling audioTrack \(uidValue) on TheoPlayer") } - for i in 0...audioTracks.count-1 { + for i in 0.. 0 else { + let videoTrackCount = videoTracks.count + guard videoTrackCount > 0 else { return } if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] Enabling videoTrack \(uidValue) on TheoPlayer") } - for i in 0...videoTracks.count-1 { + for i in 0.. [[String:Any]] { var trackEntries:[[String:Any]] = metadataTracks - guard textTracks.count > 0 else { + let textTrackCount = textTracks.count + guard textTrackCount > 0 else { return trackEntries } - for i in 0...textTracks.count-1 { + for i in 0.. Int { - guard textTracks.count > 0 else { + let textTrackCount = textTracks.count + guard textTrackCount > 0 else { return 0 } - for i in 0...textTracks.count-1 { + for i in 0.. [[String:Any]] { var audioTrackEntries:[[String:Any]] = [] - guard audioTracks.count > 0 else { + let audioTrackCount = audioTracks.count + guard audioTrackCount > 0 else { return audioTrackEntries } - for i in 0...audioTracks.count-1 { + for i in 0.. [String:Any]? in + guard index < audioTrack.qualities.count else { return nil } return THEOplayerRCTTrackMetadataAggregator.aggregatedQualityInfo(quality: audioTrack.qualities.get(index)) } @@ -193,10 +201,12 @@ class THEOplayerRCTTrackMetadataAggregator { } private class func selectedAudioTrack(audioTracks: AudioTrackList) -> Int { - guard audioTracks.count > 0 else { + let audioTrackCount = audioTracks.count + guard audioTrackCount > 0 else { return 0 } - for i in 0...audioTracks.count-1 { + for i in 0.. [[String:Any]] { var videoTrackEntries:[[String:Any]] = [] - guard videoTracks.count > 0 else { + let videoTrackCount = videoTracks.count + guard videoTrackCount > 0 else { return videoTrackEntries } - for i in 0...videoTracks.count-1 { + for i in 0.. [String:Any]? in + guard index < videoTrack.qualities.count else { return nil } return THEOplayerRCTTrackMetadataAggregator.aggregatedQualityInfo(quality: videoTrack.qualities.get(index)) } @@ -243,12 +257,14 @@ class THEOplayerRCTTrackMetadataAggregator { } private class func selectedVideoTrack(videoTracks: VideoTrackList) -> Int { - guard videoTracks.count > 0 else { + let videoTrackCount = videoTracks.count + guard videoTrackCount > 0 else { return 0 } - for i in 0...videoTracks.count-1 { + for i in 0.. Date: Tue, 9 Jun 2026 09:37:06 +0200 Subject: [PATCH 3/8] Add changelog entry --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 931a7712b..227ffa61f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Fixed + +- Fixed an issue on iOS where setting the targetVideoQuality uids was causing a crash due to an unsafe bounds-check. + ## [11.2.0] - 26-06-04 ### Added From 3d69d70d6d47cb0d9ac386e1a9930290e75279cf Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Tue, 9 Jun 2026 11:31:07 +0200 Subject: [PATCH 4/8] Remove double debug flag check --- ios/THEOplayerRCTPlayerAPI.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/THEOplayerRCTPlayerAPI.swift b/ios/THEOplayerRCTPlayerAPI.swift index 4150c79f5..eb1fa74e7 100644 --- a/ios/THEOplayerRCTPlayerAPI.swift +++ b/ios/THEOplayerRCTPlayerAPI.swift @@ -369,9 +369,9 @@ class THEOplayerRCTPlayerAPI: NSObject, RCTBridgeModule { foundTrack.targetQualities = matchingQualities.isEmpty ? nil : matchingQualities if DEBUG_PLAYER_API { if matchingQualities.count > 0 { - if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] targetQualities: \(uids) set on active videotrack. (matching: \(matchingQualities.map(\.bandwidth)))") } + PrintUtils.printLog(logText: "[NATIVE] targetQualities: \(uids) set on active videotrack. (matching: \(matchingQualities.map(\.bandwidth)))") } else { - if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] targetQualities: \(uids) set on active videotrack. (no match or empty) => no quality restriction.") } + PrintUtils.printLog(logText: "[NATIVE] targetQualities: \(uids) set on active videotrack. (no match or empty) => no quality restriction.") } } } From 82d9b8c36a119d3def2fbd51777ba3bd8672d03a Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Tue, 9 Jun 2026 11:31:48 +0200 Subject: [PATCH 5/8] Pass quality uid as int --- ios/THEOplayerRCTTrackMetadataAggregator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/THEOplayerRCTTrackMetadataAggregator.swift b/ios/THEOplayerRCTTrackMetadataAggregator.swift index 8f0f7dbf6..2390aad30 100644 --- a/ios/THEOplayerRCTTrackMetadataAggregator.swift +++ b/ios/THEOplayerRCTTrackMetadataAggregator.swift @@ -290,7 +290,7 @@ class THEOplayerRCTTrackMetadataAggregator { "bandwidth": quality.bandwidth, "codecs": "", "id": identifier, - "uid": identifier, + "uid": quality.bandwidth, "name": label, "label": label, "available": true, From 3cf64d32b8985a1e28277ac520302301e079aaf1 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Tue, 9 Jun 2026 11:32:43 +0200 Subject: [PATCH 6/8] Don't update targetQualities if that set is already applied on the track --- ios/THEOplayerRCTPlayerAPI.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ios/THEOplayerRCTPlayerAPI.swift b/ios/THEOplayerRCTPlayerAPI.swift index eb1fa74e7..d194c1b6b 100644 --- a/ios/THEOplayerRCTPlayerAPI.swift +++ b/ios/THEOplayerRCTPlayerAPI.swift @@ -360,6 +360,12 @@ class THEOplayerRCTPlayerAPI: NSObject, RCTBridgeModule { } } if let foundTrack = activeVideoTrack { + let requestedBandwidths = Set(uids.map { $0.intValue }) + let currentBandwidths = Set(foundTrack.targetQualities?.map { $0.bandwidth } ?? []) + guard requestedBandwidths != currentBandwidths else { + if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] targetQualities: \(uids) already set on active videotrack. Skipping update.") } + return + } let qualityCount = foundTrack.qualities.count let matchingQualities = (0.. Quality? in guard index < foundTrack.qualities.count else { return nil } From 301956b89bb829f3be6294a53a66f2893852b32c Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Tue, 9 Jun 2026 13:34:54 +0200 Subject: [PATCH 7/8] Prepare changelog for release --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 227ffa61f..e5d328b86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [11.2.1] - 26-06-09 ### Fixed From 3f2d0a8546a307c8919789714e17887e80fde6d9 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Tue, 9 Jun 2026 13:43:37 +0200 Subject: [PATCH 8/8] 11.2.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d5a005e7b..469195ead 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "react-native-theoplayer", - "version": "11.2.0", + "version": "11.2.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "react-native-theoplayer", - "version": "11.2.0", + "version": "11.2.1", "license": "BSD-3-Clause-Clear", "dependencies": { "@theoplayer/cmcd-connector-web": "^1.5.0", diff --git a/package.json b/package.json index 809d1e673..9a1016fb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-theoplayer", - "version": "11.2.0", + "version": "11.2.1", "description": "A THEOplayer video component for react-native.", "main": "lib/commonjs/index", "module": "lib/module/index",