@@ -113,6 +113,77 @@ final class JavaScriptEventLoopTests: XCTestCase {
113113 XCTAssertEqual ( context . completed , [ " t4 " , " t3 " , " t5 " ] )
114114 }
115115
116+ func testTaskPriorityOrderWithMixedPriorities ( ) async throws {
117+ final class Context : @unchecked Sendable {
118+ var completed : [ String ] = [ ]
119+ var expectedCount = 0
120+ var continuation : CheckedContinuation < Void , Never > ?
121+
122+ func record ( _ name : String ) {
123+ completed . append ( name )
124+ if completed . count == expectedCount {
125+ continuation ? . resume ( )
126+ continuation = nil
127+ }
128+ }
129+ }
130+ /// Starts tasks without awaiting them, so no await raises the priority of a queued task.
131+ func run ( expectedCount : Int , _ start : @escaping ( Context ) -> Void ) async -> [ String ] {
132+ let context = Context ( )
133+ context . expectedCount = expectedCount
134+ await withCheckedContinuation { continuation in
135+ context . continuation = continuation
136+ start ( context )
137+ }
138+ return context . completed
139+ }
140+
141+ let burst : [ ( String , TaskPriority ) ] = [
142+ ( " low1 " , . low ) , ( " medium1 " , . medium ) , ( " low2 " , . low ) , ( " high1 " , . high ) ,
143+ ( " medium2 " , . medium ) , ( " low3 " , . low ) , ( " high2 " , . high ) , ( " medium3 " , . medium ) ,
144+ ]
145+ let burstOrder = await run ( expectedCount : burst . count ) { context in
146+ for ( name , priority ) in burst {
147+ Task ( priority : priority ) { context . record ( name ) }
148+ }
149+ }
150+ XCTAssertEqual ( burstOrder , [ " high1 " , " high2 " , " medium1 " , " medium2 " , " medium3 " , " low1 " , " low2 " , " low3 " ] )
151+
152+ let nestedOrder = await run ( expectedCount : 7 ) { context in
153+ Task ( priority : . medium ) {
154+ context . record ( " outer " )
155+ let nested : [ ( String , TaskPriority ) ] = [
156+ ( " nestedLow1 " , . low ) , ( " nestedHigh " , . high ) , ( " nestedMedium " , . medium ) , ( " nestedLow2 " , . low ) ,
157+ ]
158+ for ( name , priority ) in nested {
159+ Task ( priority : priority ) { context . record ( name ) }
160+ }
161+ }
162+ Task ( priority : . medium ) { context . record ( " medium " ) }
163+ Task ( priority : . low ) { context . record ( " low " ) }
164+ }
165+ XCTAssertEqual (
166+ nestedOrder ,
167+ [ " outer " , " nestedHigh " , " medium " , " nestedMedium " , " low " , " nestedLow1 " , " nestedLow2 " ]
168+ )
169+
170+ let priorities : [ TaskPriority ] = [ . low , . high , . background , . medium , . utility , . userInitiated ]
171+ let many = ( 0 ..< 600 ) . map { index in ( " \( index ) " , priorities [ index % priorities . count ] ) }
172+ let manyOrder = await run ( expectedCount : many . count ) { context in
173+ for ( name , priority ) in many {
174+ Task ( priority : priority ) { context . record ( name ) }
175+ }
176+ }
177+ let expectedManyOrder = many . enumerated ( )
178+ . sorted { lhs , rhs in
179+ lhs . element . 1 . rawValue != rhs . element . 1 . rawValue
180+ ? lhs . element . 1 . rawValue > rhs . element . 1 . rawValue
181+ : lhs . offset < rhs . offset
182+ }
183+ . map ( \. element . 0 )
184+ XCTAssertEqual ( manyOrder , expectedManyOrder )
185+ }
186+
116187 // MARK: - Promise Tests
117188
118189 func testPromiseResolution ( ) async throws {
0 commit comments