Repository: apple/swift-nio
File: Sources/NIOCore/EventLoopFuture.swift (Swift)

Code before:
    /// - Returns: The value of the `EventLoopFuture` when it completes.
    /// - Throws: The error value of the `EventLoopFuture` if it errors.
    @available(*, noasync, message: "wait() can block indefinitely, prefer get()", renamed: "get()")
    @preconcurrency
    @inlinable
    public func wait(file: StaticString = #file, line: UInt = #line) throws -> Value where Value: Sendable {
        #if os(WASI)
        // NOTE: As of July 22, 2025 `wait()` calling wait() is not supported on WASI platforms.
        //
        // This may change down the road if and when true multi-threading evolves. But right now
        // calling wait here results in the following runtime crash:
        //
        // ```
        // SomeExecutable.wasm:0x123456 Uncaught (in promise) RuntimeError: Atomics.wait cannot be called in this context
        // ```
        //
        // Using the following fatal error here gives wasm runtime users a much more clear error message
        // to identify the issue.
        //
        // If you're running into this error on WASI, refactoring to `get()` instead of `wait()` will
        // likely solve the issue.
        fatalError(
            "NIO's wait() function should not be called on WASI platforms. It will freeze or crash. Use get() instead."
        )
        #endif  // os(WASI)

        try self._blockingWaitForFutureCompletion(file: file, line: line)
    }

    @inlinable
    @inline(never)
    func _blockingWaitForFutureCompletion(file: StaticString, line: UInt) throws -> Value where Value: Sendable {
        self.eventLoop._preconditionSafeToWait(file: file, line: line)

        let v: UnsafeMutableTransferBox<Result<Value, Error>?> = .init(nil)
        let lock = ConditionLock(value: 0)
        self._whenComplete { () -> CallbackList in
            lock.lock()
            v.wrappedValue = self._value
            lock.unlock(withValue: 1)
            return CallbackList()
        }
        lock.lock(whenValue: 1)
        lock.unlock()

        switch v.wrappedValue! {
        case .success(let result):
            return result
        case .failure(let error):
            throw error
        }

Review comment (suggestion):
This should fix CI breakage.

```suggestion
        return try self._blockingWaitForFutureCompletion(file: file, line: line)
```

Code after:
    /// - Returns: The value of the `EventLoopFuture` when it completes.
    /// - Throws: The error value of the `EventLoopFuture` if it errors.
    @available(*, noasync, message: "wait() can block indefinitely, prefer get()", renamed: "get()")
    @preconcurrency
    @inlinable
    public func wait(file: StaticString = #file, line: UInt = #line) throws -> Value where Value: Sendable {
        #if os(WASI)
        // NOTE: As of July 22, 2025 `wait()` calling wait() is not supported on WASI platforms.
        //
        // This may change down the road if and when true multi-threading evolves. But right now
        // calling wait here results in the following runtime crash:
        //
        // ```
        // SomeExecutable.wasm:0x123456 Uncaught (in promise) RuntimeError: Atomics.wait cannot be called in this context
        // ```
        //
        // Using the following fatal error here gives wasm runtime users a much more clear error message
        // to identify the issue.
        //
        // If you're running into this error on WASI, refactoring to `get()` instead of `wait()` will
        // likely solve the issue.
        fatalError(
            "NIO's wait() function should not be called on WASI platforms. It will freeze or crash. Use get() instead."
        )
        #else
        try self._blockingWaitForFutureCompletion(file: file, line: line)
        #endif
    }

    @inlinable
    @inline(never)
    func _blockingWaitForFutureCompletion(file: StaticString, line: UInt) throws -> Value where Value: Sendable {
        self.eventLoop._preconditionSafeToWait(file: file, line: line)

        let v: UnsafeMutableTransferBox<Result<Value, Error>?> = .init(nil)
        let lock = ConditionLock(value: 0)
        self._whenComplete { () -> CallbackList in
            lock.lock()
            v.wrappedValue = self._value
            lock.unlock(withValue: 1)
            return CallbackList()
        }
        lock.lock(whenValue: 1)
        lock.unlock()

        switch v.wrappedValue! {
        case .success(let result):
            return result
        case .failure(let error):
            throw error
        }