/// BridgeJS Intrinsics
///
/// This file contains low-level intrinsic functions that are used by code generated
/// by the BridgeJS system.

import _CJavaScriptKit
import _Concurrency

#if !arch(wasm32)
@usableFromInline func _onlyAvailableOnWasm() -> Never {
    fatalError("Only available on WebAssembly")
}
#endif

// MARK: Exception Handling

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_throw")
private func _swift_js_throw_extern(_ id: Int32)
#else
private func _swift_js_throw_extern(_ id: Int32) {
    _onlyAvailableOnWasm()
}
#endif

/// Throws a JavaScript exception from Swift code.
///
/// This function is called by the BridgeJS code generator when a Swift function throws
/// an error. The exception object is retained and stored for later retrieval by the
/// JavaScript-side runtime code.
///
/// - Parameter id: The ID of the JavaScript exception object to throw
@_spi(BridgeJS) @inline(never) public func _swift_js_throw(_ id: Int32) {
    _swift_js_throw_extern(id)
}

/// Retrieves and clears any pending JavaScript exception.
///
/// This function checks for any JavaScript exceptions that were thrown during
/// the execution of imported JavaScript functions. If an exception exists, it
/// is retrieved, cleared from the global storage, and returned as a `JSException`.
///
/// - Returns: A `JSException` if an exception was pending, `nil` otherwise
@_spi(BridgeJS) @_transparent public func _swift_js_take_exception() -> JSException? {
    #if arch(wasm32)
    let value = _swift_js_exception_get()
    if _fastPath(value == 0) {
        return nil
    }
    _swift_js_exception_set(0)
    return JSException(JSObject(id: UInt32(bitPattern: value)).jsValue)
    #else
    _onlyAvailableOnWasm()
    #endif
}

/// Releases a Swift closure from the FinalizationRegistry
///
/// This function is called by the BridgeJS code generator when a Swift closure is released.
/// The closure is released from the FinalizationRegistry so it can be garbage collected to
/// balance the
///
/// - Parameter pointer: The pointer to `_BridgeJSTypedClosureBox` instance
@_expose(wasm, "bjs_release_swift_closure")
public func _bjs_release_swift_closure(_ pointer: UnsafeMutableRawPointer) {
    Unmanaged<AnyObject>.fromOpaque(pointer).release()
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_closure_unregister")
private func _swift_js_closure_unregister_extern(_ id: Int32)
#else
private func _swift_js_closure_unregister_extern(_ id: Int32) {
    _onlyAvailableOnWasm()
}
#endif
/// Unregisters a Swift closure from the FinalizationRegistry
///
/// - Parameter id: The JavaScriptObjectRef of the JS closure object created by
///                 the BridgeJS's `make_swift_closure_{signature}` function.
///
/// - Note: This is a best-effort operation.
///         According to the ECMAScript specification, calling
///         `FinalizationRegistry.prototype.unregister` does not guarantee that
///         a finalization callback will be suppressed if the target object has
///         already been garbage-collected and cleanup has been scheduled.
///         This means that the finalization callback should be tolerant of the
///         object being already collected.
///         See: https://tc39.es/ecma262/multipage/managing-memory.html#sec-finalization-registry.prototype.unregister
@inline(never) internal func _swift_js_closure_unregister(_ id: Int32) {
    _swift_js_closure_unregister_extern(id)
}

// MARK: Type lowering/lifting
//
// The following part defines the parameter and return value lowering/lifting
// for a given type. They follow the following pattern:
//
// ```swift
// extension <#TargetType#> {
//     // MARK: ImportTS
//     @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> <#WasmCoreType#> {
//     }
//     @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ ...) -> <#Self#> {
//     }
//     // MARK: ExportSwift
//     @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ ...) -> <#Self#> {
//     }
//     @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> <#WasmCoreType#> {
//     }
//     // MARK: Stack ABI
//     @_spi(BridgeJS) public static func bridgeJSStackPop() -> <#Self#> {
//     }
//     @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
//     }
// }
// ```
//
// where:
// - <#TargetType#>: the higher-level type to be lowered/lifted
// - <#WasmCoreType#>: the corresponding WebAssembly core type or Void
// - `func bridgeJSLowerParameter()`: lower the given higher-level parameter to a WebAssembly core type
// - `func bridgeJSLiftReturn(_ ...) -> <#TargetType#>`: lift the given Wasm core type return value to a higher-level type
// - `func bridgeJSLiftParameter(_ ...) -> <#TargetType#>`: lift the given Wasm core type parameters to a higher-level type
// - `func bridgeJSLowerReturn() -> <#WasmCoreType#>`: lower the given higher-level return value to a Wasm core type
// - `func bridgeJSStackPop() -> <#TargetType#>`: no-arg overload that pops parameters from the param stack internally.
//   Note: Pop order must match Swift's left-to-right argument evaluation order.
// - `func bridgeJSStackPush()`: push the value onto the return stack (used by _BridgedSwiftStackType for array elements)
//
// Optional types (ExportSwift only) additionally define:
// - `func bridgeJSLiftReturnFromSideChannel()`: lift optional from side-channel storage for protocol property getters
//
// See JSGlueGen.swift in BridgeJSLink for JS-side lowering/lifting implementation.

/// A protocol that Swift types that can appear as parameters or return values on
public protocol _BridgedSwiftTypeLoweredIntoSingleWasmCoreType {
    associatedtype WasmCoreType
    // MARK: ImportTS
    consuming func bridgeJSLowerParameter() -> WasmCoreType
    static func bridgeJSLiftReturn(_ value: WasmCoreType) -> Self
    // MARK: ExportSwift
    static func bridgeJSLiftParameter(_ value: WasmCoreType) -> Self
    consuming func bridgeJSLowerReturn() -> WasmCoreType
}

public protocol _BridgedSwiftStackType {
    associatedtype StackLiftResult = Self
    static func bridgeJSStackPop() -> StackLiftResult
    consuming func bridgeJSStackPush()

    // MARK: Specialization points

    /// Specialization point for popping an `Optional<Self>`
    static func bridgeJSStackPopAsOptional() -> StackLiftResult?
    /// Specialization point for pushing an `Optional<Self>`
    static func bridgeJSStackPushAsOptional(_ value: consuming Self?)
}

extension _BridgedSwiftStackType {
    /// Default implementation for popping an `Optional<Self>` using
    /// a leading discriminator on the stack (0 for nil, 1 for some).
    public static func bridgeJSStackPopAsOptional() -> StackLiftResult? {
        let isSome = _swift_js_pop_i32()
        if isSome == 0 {
            return nil
        }
        return Self.bridgeJSStackPop()
    }

    /// Default implementation for pushing an `Optional<Self>` using
    /// a leading discriminator on the stack (0 for nil, 1 for some).
    public static func bridgeJSStackPushAsOptional(_ value: consuming Self?) {
        switch consume value {
        case .none:
            _swift_js_push_i32(0)
        case .some(let value):
            value.bridgeJSStackPush()
            _swift_js_push_i32(1)
        }
    }
}

/// Types that bridge with the same (isSome, value) ABI as Optional.
/// Used by JSUndefinedOr so all bridge methods delegate to Optional<Wrapped>.
@_spi(BridgeJS) public protocol _BridgedAsOptional {
    associatedtype Wrapped
    var asOptional: Wrapped? { get }
    init(optional: Wrapped?)
}

@_spi(BridgeJS) extension Optional: _BridgedAsOptional {
    public var asOptional: Wrapped? { self }
    public init(optional: Wrapped?) { self = optional }
}

extension Bool: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    // MARK: ImportTS
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 {
        self ? 1 : 0
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Bool {
        value == 1
    }
    // MARK: ExportSwift
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Bool {
        value == 1
    }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Bool {
        bridgeJSLiftParameter(_swift_js_pop_i32())
    }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 {
        self ? 1 : 0
    }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_i32(self ? 1 : 0)
    }
}

extension Int: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    // MARK: ImportTS
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 {
        Int32(self)
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Int {
        Int(value)
    }
    // MARK: ExportSwift
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Int {
        Int(value)
    }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Int {
        bridgeJSLiftParameter(_swift_js_pop_i32())
    }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 {
        Int32(self)
    }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_i32(Int32(self))
    }
}

extension UInt: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    // MARK: ImportTS
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 {
        Int32(bitPattern: UInt32(self))
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> UInt {
        UInt(UInt32(bitPattern: value))
    }
    // MARK: ExportSwift
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> UInt {
        UInt(UInt32(bitPattern: value))
    }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> UInt {
        bridgeJSLiftParameter(_swift_js_pop_i32())
    }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 {
        Int32(bitPattern: UInt32(self))
    }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_i32(Int32(bitPattern: UInt32(self)))
    }
}

extension Int8: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { Int32(self) }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Int8 {
        Int8(truncatingIfNeeded: value)
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Int8 {
        Int8(truncatingIfNeeded: value)
    }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Int8 { bridgeJSLiftParameter(_swift_js_pop_i32()) }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { Int32(self) }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() { _swift_js_push_i32(Int32(self)) }
}

extension UInt8: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { Int32(self) }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> UInt8 {
        UInt8(truncatingIfNeeded: value)
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> UInt8 {
        UInt8(truncatingIfNeeded: value)
    }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> UInt8 { bridgeJSLiftParameter(_swift_js_pop_i32()) }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { Int32(self) }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() { _swift_js_push_i32(Int32(self)) }
}

extension Int16: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { Int32(self) }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Int16 {
        Int16(truncatingIfNeeded: value)
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Int16 {
        Int16(truncatingIfNeeded: value)
    }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Int16 { bridgeJSLiftParameter(_swift_js_pop_i32()) }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { Int32(self) }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() { _swift_js_push_i32(Int32(self)) }
}

extension UInt16: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { Int32(self) }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> UInt16 {
        UInt16(truncatingIfNeeded: value)
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> UInt16 {
        UInt16(truncatingIfNeeded: value)
    }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> UInt16 { bridgeJSLiftParameter(_swift_js_pop_i32()) }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { Int32(self) }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() { _swift_js_push_i32(Int32(self)) }
}

extension Int32: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { self }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Int32 { value }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Int32 { value }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Int32 {
        _swift_js_pop_i32()
    }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { self }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_i32(self)
    }
}

extension UInt32: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { Int32(bitPattern: self) }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> UInt32 {
        UInt32(bitPattern: value)
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> UInt32 {
        UInt32(bitPattern: value)
    }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> UInt32 {
        UInt32(bitPattern: _swift_js_pop_i32())
    }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { Int32(bitPattern: self) }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_i32(Int32(bitPattern: self))
    }
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_push_i64")
private func _swift_js_push_i64_extern(_ v: Int64)
#else
private func _swift_js_push_i64_extern(_ v: Int64) {
    _onlyAvailableOnWasm()
}
#endif
@_spi(BridgeJS) @inline(never) public func _swift_js_push_i64(_ v: Int64) {
    _swift_js_push_i64_extern(v)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_pop_i64")
private func _swift_js_pop_i64_extern() -> Int64
#else
private func _swift_js_pop_i64_extern() -> Int64 {
    _onlyAvailableOnWasm()
}
#endif
@_spi(BridgeJS) @inline(never) public func _swift_js_pop_i64() -> Int64 {
    return _swift_js_pop_i64_extern()
}

extension Int64: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int64 { self }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int64) -> Int64 { value }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int64) -> Int64 { value }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Int64 {
        Int64(bitPattern: UInt64(bitPattern: _swift_js_pop_i64()))
    }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int64 { self }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_i64(self)
    }
}

extension UInt64: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int64 { Int64(bitPattern: self) }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int64) -> UInt64 {
        UInt64(bitPattern: value)
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int64) -> UInt64 {
        UInt64(bitPattern: value)
    }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> UInt64 {
        UInt64(bitPattern: _swift_js_pop_i64())
    }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int64 { Int64(bitPattern: self) }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_i64(Int64(bitPattern: self))
    }
}

extension Float: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    // MARK: ImportTS
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Float32 {
        Float32(self)
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Float32) -> Float {
        Float(value)
    }
    // MARK: ExportSwift
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Float32) -> Float {
        Float(value)
    }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Float {
        bridgeJSLiftParameter(_swift_js_pop_f32())
    }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Float32 {
        Float32(self)
    }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_f32(Float32(self))
    }
}

extension Double: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftStackType {
    // MARK: ImportTS
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Float64 {
        Float64(self)
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Float64) -> Double {
        Double(value)
    }
    // MARK: ExportSwift
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Float64) -> Double {
        Double(value)
    }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Double {
        bridgeJSLiftParameter(_swift_js_pop_f64())
    }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Float64 {
        Float64(self)
    }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_f64(Float64(self))
    }
}

extension String: _BridgedSwiftStackType {
    public typealias StackLiftResult = String

    // MARK: ImportTS

    @_spi(BridgeJS) public consuming func bridgeJSWithLoweredParameter<T>(_ body: (Int32, Int32) -> T) -> T {
        return self.withUTF8 { b in
            body(Int32(bitPattern: UInt32(UInt(bitPattern: b.baseAddress))), Int32(b.count))
        }
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ bytesCount: Int32) -> String {
        #if !arch(wasm32)
        guard #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) else { _onlyAvailableOnWasm() }
        #endif
        return String(unsafeUninitializedCapacity: Int(bytesCount)) { b in
            _swift_js_init_memory_with_result(b.baseAddress.unsafelyUnwrapped, Int32(bytesCount))
            return Int(bytesCount)
        }
    }

    // MARK: ExportSwift

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ bytes: Int32, _ count: Int32) -> String {
        #if !arch(wasm32)
        guard #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) else { _onlyAvailableOnWasm() }
        #endif
        return String(unsafeUninitializedCapacity: Int(count)) { b in
            _swift_js_init_memory(bytes, b.baseAddress.unsafelyUnwrapped)
            return Int(count)
        }
    }

    @_spi(BridgeJS) public static func bridgeJSStackPop() -> String {
        let bytes = _swift_js_pop_i32()
        let count = _swift_js_pop_i32()
        return bridgeJSLiftParameter(bytes, count)
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void {
        return self.withUTF8 { ptr in
            _swift_js_return_string(ptr.baseAddress, Int32(ptr.count))
        }
    }

    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        self.withUTF8 { ptr in
            _swift_js_push_string(ptr.baseAddress, Int32(ptr.count))
        }
    }
}

extension JSObject: _BridgedSwiftStackType {
    // JSObject is a non-final class, so we must explicitly specify the associated type
    // rather than relying on the default `Self` (which Swift requires for covariant returns).
    public typealias StackLiftResult = JSObject

    // MARK: ImportTS

    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 {
        Int32(bitPattern: self.id)
    }
    @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ id: Int32) -> JSObject {
        JSObject(id: JavaScriptObjectRef(bitPattern: id))
    }

    // MARK: ExportSwift

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ id: Int32) -> JSObject {
        JSObject(id: JavaScriptObjectRef(bitPattern: id))
    }

    @_spi(BridgeJS) public static func bridgeJSStackPop() -> JSObject {
        bridgeJSLiftParameter(_swift_js_pop_i32())
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Int32 {
        // withExtendedLifetime is required here to prevent a use-after-free.
        // In a `consuming func`, Swift ARC may release `self` (and thus release
        // the underlying JS reference) as soon as it extracts `self.id`, which
        // happens *before* `_swift_js_retain` is called. `withExtendedLifetime` forces
        // `self` to stay alive until after `_swift_js_retain` returns.
        return withExtendedLifetime(self) { _swift_js_retain(Int32(bitPattern: self.id)) }
    }

    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_i32(bridgeJSLowerReturn())
    }
}

extension JSValue: _BridgedSwiftStackType {
    public typealias StackLiftResult = JSValue

    @_transparent
    private static func bridgeJSRetainPayloadIfNeeded(kind: Int32, payload1: Int32) -> Int32 {
        guard let kindEnum = JavaScriptValueKind(rawValue: UInt32(kind)) else {
            return payload1
        }
        switch kindEnum {
        case .string, .object, .symbol, .bigInt:
            return _swift_js_retain(payload1)
        default:
            return payload1
        }
    }

    @_spi(BridgeJS) public static func bridgeJSStackPop() -> JSValue {
        let payload2 = _swift_js_pop_f64()
        let payload1 = _swift_js_pop_i32()
        let kind = _swift_js_pop_i32()
        return bridgeJSLiftParameter(kind, payload1, payload2)
    }

    @_spi(BridgeJS) public consuming func bridgeJSStackPush() -> Void {
        let lowered = bridgeJSLowerParameter()
        let retainedPayload1 = Self.bridgeJSRetainPayloadIfNeeded(kind: lowered.kind, payload1: lowered.payload1)
        _swift_js_push_i32(lowered.kind)
        _swift_js_push_i32(retainedPayload1)
        _swift_js_push_f64(lowered.payload2)
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (kind: Int32, payload1: Int32, payload2: Double) {
        return withRawJSValue { raw in
            (
                kind: Int32(raw.kind.rawValue),
                payload1: Int32(bitPattern: raw.payload1),
                payload2: raw.payload2
            )
        }
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(
        _ kind: Int32,
        _ payload1: Int32,
        _ payload2: Double
    ) -> JSValue {
        let retainedPayload1 = bridgeJSRetainPayloadIfNeeded(kind: kind, payload1: payload1)

        guard let kindEnum = JavaScriptValueKind(rawValue: UInt32(kind)) else {
            fatalError("Invalid JSValue kind: \(kind)")
        }
        let rawValue = RawJSValue(
            kind: kindEnum,
            payload1: JavaScriptPayload1(UInt32(bitPattern: retainedPayload1)),
            payload2: payload2
        )
        return rawValue.jsValue
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> JSValue {
        bridgeJSStackPop()
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() {
        bridgeJSStackPush()
    }
}

/// A protocol that Swift heap objects exposed to JavaScript via `@JS class` must conform to.
///
/// The conformance is automatically synthesized by the BridgeJS code generator.
public protocol _BridgedSwiftHeapObject: AnyObject, _BridgedSwiftStackType {}

/// Define the lowering/lifting for `_BridgedSwiftHeapObject`
extension _BridgedSwiftHeapObject {

    // MARK: ImportTS
    @_spi(BridgeJS) @_transparent public func bridgeJSLowerParameter() -> UnsafeMutableRawPointer {
        // Transfer ownership to JS for imported SwiftHeapObject parameters.
        // JS side must eventually release (via release() or FinalizationRegistry).
        return Unmanaged.passRetained(self).toOpaque()
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ pointer: UnsafeMutableRawPointer) -> Self {
        // For protocol returns, take an unretained value since JS manages the lifetime
        return Unmanaged<Self>.fromOpaque(pointer).takeUnretainedValue()
    }

    // MARK: ExportSwift
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ pointer: UnsafeMutableRawPointer) -> Self {
        Unmanaged<Self>.fromOpaque(pointer).takeUnretainedValue()
    }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer {
        // Perform a manual retain on the object, which will be balanced by a release called via FinalizationRegistry
        return Unmanaged.passRetained(self).toOpaque()
    }

    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self {
        bridgeJSLiftParameter(_swift_js_pop_pointer())
    }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_pointer(Unmanaged.passRetained(self).toOpaque())
    }
}
// MARK: Closure Box Protocol

/// A protocol that Swift closure box types must conform to.
///
/// The conformance is automatically synthesized by the BridgeJS code generator.
@_spi(BridgeJS) public protocol _BridgedSwiftClosureBox: AnyObject {}

extension _JSBridgedClass {
    // MARK: ImportTS
    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { jsObject.bridgeJSLowerParameter() }
    @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ id: Int32) -> Self {
        Self(unsafelyWrapping: JSObject.bridgeJSLiftReturn(id))
    }

    // MARK: ExportSwift
    @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ id: Int32) -> Self {
        Self(unsafelyWrapping: JSObject.bridgeJSLiftParameter(id))
    }
    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Int32 { jsObject.bridgeJSLowerReturn() }

    public static func bridgeJSStackPop() -> Self {
        Self(unsafelyWrapping: JSObject.bridgeJSStackPop())
    }
    public consuming func bridgeJSStackPush() {
        jsObject.bridgeJSStackPush()
    }
}

/// A protocol that Swift protocol wrappers exposed from JavaScript must conform to.
///
/// The conformance is automatically synthesized by the BridgeJS code generator.
public protocol _BridgedSwiftProtocolWrapper: _BridgedSwiftStackType, _BridgedSwiftProtocolExportable {
    var jsObject: JSObject { get }
    static func bridgeJSLiftParameter(_ value: Int32) -> Self
}

extension _BridgedSwiftProtocolWrapper {
    // MARK: ExportSwift
    @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self {
        bridgeJSStackPop()
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: Int32) -> Self {
        bridgeJSLiftParameter(value)
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Int32 {
        jsObject.bridgeJSLowerReturn()
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 {
        jsObject.bridgeJSLowerParameter()
    }

    // MARK: Stack ABI
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self {
        bridgeJSLiftParameter(_swift_js_pop_i32())
    }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_i32(jsObject.bridgeJSLowerReturn())
    }
}

/// A protocol that allows any BridgeJS-exported type to be lowered to a JSObject ID
/// for protocol existential bridging in the Swift-to-JS direction.
///
/// Both `_BridgedSwiftProtocolWrapper` (JS-originated protocol objects) and `@JS class`
/// types conform to this, enabling runtime dispatch when a protocol existential is returned.
public protocol _BridgedSwiftProtocolExportable {
    consuming func bridgeJSLowerAsProtocolReturn() -> Int32
}

extension _BridgedSwiftProtocolExportable where Self: _BridgedSwiftProtocolWrapper {
    @_spi(BridgeJS) public consuming func bridgeJSLowerAsProtocolReturn() -> Int32 {
        jsObject.bridgeJSLowerReturn()
    }
}

/// A protocol that Swift enum types that do not have a payload can conform to.
///
/// The conformance is automatically synthesized by the BridgeJS code generator.
public protocol _BridgedSwiftEnumNoPayload {}

/// A protocol for raw value enums that enables automatic stack operations.
///
/// Conforming to this protocol provides default implementations of `_BridgedSwiftStackType`
/// methods by delegating to the raw value's stack operations. The raw value type must itself
/// conform to `_BridgedSwiftStackType`.
///
/// The conformance is automatically synthesized by the BridgeJS code generator.
public protocol _BridgedSwiftRawValueEnum: _BridgedSwiftStackType, RawRepresentable
where RawValue: _BridgedSwiftStackType, RawValue.StackLiftResult == RawValue {}

extension _BridgedSwiftRawValueEnum {
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self {
        Self(rawValue: RawValue.bridgeJSStackPop())!
    }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        rawValue.bridgeJSStackPush()
    }
}

/// A protocol that Swift case enum types (enums without raw values or associated values) conform to.
///
/// The conformance is automatically synthesized by the BridgeJS code generator.
public protocol _BridgedSwiftCaseEnum: _BridgedSwiftStackType {
    // MARK: ImportTS
    @_spi(BridgeJS) consuming func bridgeJSLowerParameter() -> Int32
    @_spi(BridgeJS) static func bridgeJSLiftReturn(_ value: Int32) -> Self

    // MARK: ExportSwift
    @_spi(BridgeJS) static func bridgeJSLiftParameter(_ value: Int32) -> Self
    @_spi(BridgeJS) consuming func bridgeJSLowerReturn() -> Int32
}

extension _BridgedSwiftCaseEnum {
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self {
        bridgeJSLiftParameter(_swift_js_pop_i32())
    }

    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_i32(bridgeJSLowerReturn())
    }
}

/// A protocol that Swift associated value enum types conform to.
///
/// The conformance is automatically synthesized by the BridgeJS code generator.
public protocol _BridgedSwiftAssociatedValueEnum: _BridgedSwiftTypeLoweredIntoVoidType, _BridgedSwiftStackType
where StackLiftResult == Self {
    /// Pops the payload of the associated value enum from the stack.
    ///
    /// - Parameter caseId: The enum case ID.
    /// - Returns: The associated value enum with its payload popped from the stack.
    @_spi(BridgeJS) static func bridgeJSStackPopPayload(_ caseId: Int32) -> Self

    /// Pushes the payload of the associated value enum onto the stack.
    ///
    /// - Returns: The enum case ID.
    @_spi(BridgeJS) consuming func bridgeJSStackPushPayload() -> Int32
}

extension _BridgedSwiftAssociatedValueEnum {
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self {
        bridgeJSStackPopPayload(_swift_js_pop_i32())
    }

    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_i32(bridgeJSStackPushPayload())
    }

    public static func bridgeJSStackPopAsOptional() -> Self? {
        let discriminator = _swift_js_pop_i32()
        if discriminator == -1 {
            return nil
        }
        return bridgeJSStackPopPayload(discriminator)
    }

    public static func bridgeJSStackPushAsOptional(_ value: consuming Self?) {
        switch consume value {
        case .none:
            _swift_js_push_i32(-1)
        case .some(let value):
            _swift_js_push_i32(value.bridgeJSStackPushPayload())
        }
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ caseId: Int32) -> Self {
        return bridgeJSStackPopPayload(caseId)
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() {
        bridgeJSStackPush()
    }

    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 {
        return bridgeJSStackPushPayload()
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ caseId: Int32) -> Self {
        return bridgeJSStackPopPayload(caseId)
    }
}

/// A protocol that Swift struct types conform to.
///
/// The conformance is automatically synthesized by the BridgeJS code generator.
public protocol _BridgedSwiftStruct: _BridgedSwiftTypeLoweredIntoVoidType, _BridgedSwiftStackType
where StackLiftResult == Self {
    // MARK: ExportSwift
    @_spi(BridgeJS) static func bridgeJSStackPop() -> Self
    @_spi(BridgeJS) consuming func bridgeJSStackPush() -> Void

    /// Initializes a Swift struct by copying the fields from a bridged JS object.
    init(unsafelyCopying jsObject: JSObject)
    /// Converts the struct into a bridged JS object by copying its fields.
    func toJSObject() -> JSObject
}

extension _BridgedSwiftStruct {
    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 {
        return toJSObject().bridgeJSLowerReturn()
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ objectId: Int32) -> Self {
        let jsObject = JSObject.bridgeJSLiftReturn(objectId)
        return Self(unsafelyCopying: jsObject)
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self {
        bridgeJSStackPop()
    }
    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() {
        bridgeJSStackPush()
    }
}

extension _BridgedSwiftEnumNoPayload where Self: RawRepresentable, RawValue == String {
    // MARK: ImportTS
    @_spi(BridgeJS) public consuming func bridgeJSWithLoweredParameter<T>(_ body: (Int32, Int32) -> T) -> T {
        rawValue.bridgeJSWithLoweredParameter(body)
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ id: Int32) -> Self {
        Self(rawValue: .bridgeJSLiftReturn(id))!
    }

    // MARK: ExportSwift
    @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ bytes: Int32, _ count: Int32) -> Self {
        Self(rawValue: .bridgeJSLiftParameter(bytes, count))!
    }
    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { rawValue.bridgeJSLowerReturn() }
}

extension _BridgedSwiftEnumNoPayload
where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType {
    // MARK: ImportTS
    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> RawValue.WasmCoreType {
        rawValue.bridgeJSLowerParameter()
    }
    @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: RawValue.WasmCoreType) -> Self {
        Self(rawValue: .bridgeJSLiftReturn(value))!
    }

    // MARK: ExportSwift
    @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ value: RawValue.WasmCoreType) -> Self {
        Self(rawValue: .bridgeJSLiftParameter(value))!
    }
    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> RawValue.WasmCoreType {
        rawValue.bridgeJSLowerReturn()
    }
}

// MARK: Wasm externs used by generated enum glue

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_init_memory")
private func _swift_js_init_memory_extern(_ sourceId: Int32, _ ptr: UnsafeMutablePointer<UInt8>)
#else
private func _swift_js_init_memory_extern(_ sourceId: Int32, _ ptr: UnsafeMutablePointer<UInt8>) {
    _onlyAvailableOnWasm()
}
#endif

/// Initializes WebAssembly memory with a Uint8Array referenced by `sourceId` at `ptr`.
/// Note that the ownership of the source Uint8Array id is taken by the callee, so callers
/// must not release the source Uint8Array id by themselves.
///
/// - Parameter sourceId: The object ID of the source Uint8Array.
/// - Parameter ptr: The pointer to the WebAssembly memory to initialize.
@_spi(BridgeJS) @inline(never) public func _swift_js_init_memory(_ sourceId: Int32, _ ptr: UnsafeMutablePointer<UInt8>)
{
    _swift_js_init_memory_extern(sourceId, ptr)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_push_string")
private func _swift_js_push_string_extern(_ ptr: UnsafePointer<UInt8>?, _ len: Int32)
#else
private func _swift_js_push_string_extern(_ ptr: UnsafePointer<UInt8>?, _ len: Int32) {
    _onlyAvailableOnWasm()
}
#endif

@_spi(BridgeJS) @inline(never) public func _swift_js_push_string(_ ptr: UnsafePointer<UInt8>?, _ len: Int32) {
    _swift_js_push_string_extern(ptr, len)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_push_i32")
private func _swift_js_push_i32_extern(_ value: Int32)
#else
private func _swift_js_push_i32_extern(_ value: Int32) {
    _onlyAvailableOnWasm()
}
#endif

@_spi(BridgeJS) @inline(never) public func _swift_js_push_i32(_ value: Int32) {
    _swift_js_push_i32_extern(value)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_push_f32")
private func _swift_js_push_f32_extern(_ value: Float32)
#else
private func _swift_js_push_f32_extern(_ value: Float32) {
    _onlyAvailableOnWasm()
}
#endif

@_spi(BridgeJS) @inline(never) public func _swift_js_push_f32(_ value: Float32) {
    _swift_js_push_f32_extern(value)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_push_f64")
private func _swift_js_push_f64_extern(_ value: Float64)
#else
private func _swift_js_push_f64_extern(_ value: Float64) {
    _onlyAvailableOnWasm()
}
#endif

@_spi(BridgeJS) @inline(never) public func _swift_js_push_f64(_ value: Float64) {
    _swift_js_push_f64_extern(value)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_pop_i32")
private func _swift_js_pop_i32_extern() -> Int32
#else
private func _swift_js_pop_i32_extern() -> Int32 {
    _onlyAvailableOnWasm()
}
#endif

@_spi(BridgeJS) @inline(never) public func _swift_js_pop_i32() -> Int32 {
    _swift_js_pop_i32_extern()
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_pop_f32")
private func _swift_js_pop_f32_extern() -> Float32
#else
private func _swift_js_pop_f32_extern() -> Float32 {
    _onlyAvailableOnWasm()
}
#endif

@_spi(BridgeJS) @inline(never) public func _swift_js_pop_f32() -> Float32 {
    _swift_js_pop_f32_extern()
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_pop_f64")
private func _swift_js_pop_f64_extern() -> Float64
#else
private func _swift_js_pop_f64_extern() -> Float64 {
    _onlyAvailableOnWasm()
}
#endif

@_spi(BridgeJS) @inline(never) public func _swift_js_pop_f64() -> Float64 {
    _swift_js_pop_f64_extern()
}

// MARK: Wasm externs used by type lowering/lifting

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_make_js_string")
private func _swift_js_make_js_string_extern(_ ptr: UnsafePointer<UInt8>?, _ len: Int32) -> Int32
#else
/// Creates a JavaScript string from UTF-8 data in WebAssembly memory
private func _swift_js_make_js_string_extern(_ ptr: UnsafePointer<UInt8>?, _ len: Int32) -> Int32 {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_make_js_string(_ ptr: UnsafePointer<UInt8>?, _ len: Int32) -> Int32 {
    _swift_js_make_js_string_extern(ptr, len)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_init_memory_with_result")
private func _swift_js_init_memory_with_result_extern(_ ptr: UnsafePointer<UInt8>?, _ len: Int32)
#else
/// Initializes WebAssembly memory with result data of JavaScript function call
private func _swift_js_init_memory_with_result_extern(_ ptr: UnsafePointer<UInt8>?, _ len: Int32) {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_init_memory_with_result(_ ptr: UnsafePointer<UInt8>?, _ len: Int32) {
    _swift_js_init_memory_with_result_extern(ptr, len)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_return_string")
private func _swift_js_return_string_extern(_ ptr: UnsafePointer<UInt8>?, _ len: Int32)
#else
/// Write a string to reserved string storage to be returned to JavaScript
private func _swift_js_return_string_extern(_ ptr: UnsafePointer<UInt8>?, _ len: Int32) {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_return_string(_ ptr: UnsafePointer<UInt8>?, _ len: Int32) {
    _swift_js_return_string_extern(ptr, len)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_retain")
private func _swift_js_retain_extern(_ id: Int32) -> Int32
#else
/// Retains a JavaScript object reference to ensure the object id
/// remains valid after the function returns
private func _swift_js_retain_extern(_ id: Int32) -> Int32 {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_retain(_ id: Int32) -> Int32 {
    _swift_js_retain_extern(id)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_return_optional_bool")
private func _swift_js_return_optional_bool_extern(_ isSome: Int32, _ value: Int32)
#else
/// Sets the optional bool for return value storage
private func _swift_js_return_optional_bool_extern(_ isSome: Int32, _ value: Int32) {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_return_optional_bool(_ isSome: Int32, _ value: Int32) {
    _swift_js_return_optional_bool_extern(isSome, value)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_get_optional_int_presence")
private func _swift_js_get_optional_int_presence_extern() -> Int32
#else
private func _swift_js_get_optional_int_presence_extern() -> Int32 {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_get_optional_int_presence() -> Int32 {
    _swift_js_get_optional_int_presence_extern()
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_get_optional_int_value")
private func _swift_js_get_optional_int_value_extern() -> Int32
#else
private func _swift_js_get_optional_int_value_extern() -> Int32 {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_get_optional_int_value() -> Int32 {
    _swift_js_get_optional_int_value_extern()
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_return_optional_int")
private func _swift_js_return_optional_int_extern(_ isSome: Int32, _ value: Int32)
#else
/// Sets the optional int for return value storage
private func _swift_js_return_optional_int_extern(_ isSome: Int32, _ value: Int32) {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_return_optional_int(_ isSome: Int32, _ value: Int32) {
    _swift_js_return_optional_int_extern(isSome, value)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_get_optional_string")
private func _swift_js_get_optional_string_extern() -> Int32
#else
private func _swift_js_get_optional_string_extern() -> Int32 {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_get_optional_string() -> Int32 {
    _swift_js_get_optional_string_extern()
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_return_optional_string")
private func _swift_js_return_optional_string_extern(_ isSome: Int32, _ ptr: UnsafePointer<UInt8>?, _ len: Int32)
#else
/// Write an optional string to reserved string storage to be returned to JavaScript
private func _swift_js_return_optional_string_extern(_ isSome: Int32, _ ptr: UnsafePointer<UInt8>?, _ len: Int32) {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_return_optional_string(_ isSome: Int32, _ ptr: UnsafePointer<UInt8>?, _ len: Int32) {
    _swift_js_return_optional_string_extern(isSome, ptr, len)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_return_optional_object")
private func _swift_js_return_optional_object_extern(_ isSome: Int32, _ objectId: Int32)
#else
/// Write an optional JSObject to reserved storage to be returned to JavaScript
private func _swift_js_return_optional_object_extern(_ isSome: Int32, _ objectId: Int32) {
    _onlyAvailableOnWasm()
}
#endif
@_spi(BridgeJS) @inline(never) public func _swift_js_return_optional_object(_ isSome: Int32, _ objectId: Int32) {
    _swift_js_return_optional_object_extern(isSome, objectId)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_get_optional_heap_object_pointer")
private func _swift_js_get_optional_heap_object_pointer_extern() -> UnsafeMutableRawPointer
#else
private func _swift_js_get_optional_heap_object_pointer_extern() -> UnsafeMutableRawPointer {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_get_optional_heap_object_pointer() -> UnsafeMutableRawPointer {
    _swift_js_get_optional_heap_object_pointer_extern()
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_return_optional_heap_object")
private func _swift_js_return_optional_heap_object_extern(_ isSome: Int32, _ pointer: UnsafeMutableRawPointer?)
#else
/// Write an optional Swift heap object to reserved storage to be returned to JavaScript
private func _swift_js_return_optional_heap_object_extern(_ isSome: Int32, _ pointer: UnsafeMutableRawPointer?) {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_return_optional_heap_object(_ isSome: Int32, _ pointer: UnsafeMutableRawPointer?) {
    _swift_js_return_optional_heap_object_extern(isSome, pointer)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_get_optional_float_presence")
private func _swift_js_get_optional_float_presence_extern() -> Int32
#else
private func _swift_js_get_optional_float_presence_extern() -> Int32 {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_get_optional_float_presence() -> Int32 {
    _swift_js_get_optional_float_presence_extern()
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_get_optional_float_value")
private func _swift_js_get_optional_float_value_extern() -> Float32
#else
private func _swift_js_get_optional_float_value_extern() -> Float32 {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_get_optional_float_value() -> Float32 {
    _swift_js_get_optional_float_value_extern()
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_return_optional_float")
private func _swift_js_return_optional_float_extern(_ isSome: Int32, _ value: Float32)
#else
/// Sets the optional float for return value storage
private func _swift_js_return_optional_float_extern(_ isSome: Int32, _ value: Float32) {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_return_optional_float(_ isSome: Int32, _ value: Float32) {
    _swift_js_return_optional_float_extern(isSome, value)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_get_optional_double_presence")
private func _swift_js_get_optional_double_presence_extern() -> Int32
#else
private func _swift_js_get_optional_double_presence_extern() -> Int32 {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_get_optional_double_presence() -> Int32 {
    _swift_js_get_optional_double_presence_extern()
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_get_optional_double_value")
private func _swift_js_get_optional_double_value_extern() -> Float64
#else
private func _swift_js_get_optional_double_value_extern() -> Float64 {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_get_optional_double_value() -> Float64 {
    _swift_js_get_optional_double_value_extern()
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_return_optional_double")
private func _swift_js_return_optional_double_extern(_ isSome: Int32, _ value: Float64)
#else
/// Sets the optional double for return value storage
private func _swift_js_return_optional_double_extern(_ isSome: Int32, _ value: Float64) {
    _onlyAvailableOnWasm()
}
#endif
@inline(never) func _swift_js_return_optional_double(_ isSome: Int32, _ value: Float64) {
    _swift_js_return_optional_double_extern(isSome, value)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_push_pointer")
private func _swift_js_push_pointer_extern(_ pointer: UnsafeMutableRawPointer)
#else
private func _swift_js_push_pointer_extern(_ pointer: UnsafeMutableRawPointer) {
    _onlyAvailableOnWasm()
}
#endif

@_spi(BridgeJS) @inline(never) public func _swift_js_push_pointer(_ pointer: UnsafeMutableRawPointer) {
    _swift_js_push_pointer_extern(pointer)
}

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "swift_js_pop_pointer")
private func _swift_js_pop_pointer_extern() -> UnsafeMutableRawPointer
#else
private func _swift_js_pop_pointer_extern() -> UnsafeMutableRawPointer {
    _onlyAvailableOnWasm()
}
#endif

@_spi(BridgeJS) @inline(never) public func _swift_js_pop_pointer() -> UnsafeMutableRawPointer {
    _swift_js_pop_pointer_extern()
}

// MARK: - UnsafePointer family

public protocol _BridgedSwiftUnsafePointerLike: _BridgedSwiftStackType {
    @_spi(BridgeJS) func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer
    @_spi(BridgeJS) static func bridgeJSFromUnsafeMutableRawPointer(_ pointer: UnsafeMutableRawPointer) -> Self
}

extension _BridgedSwiftUnsafePointerLike {
    // MARK: ImportTS
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> UnsafeMutableRawPointer {
        bridgeJSToUnsafeMutableRawPointer()
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ pointer: UnsafeMutableRawPointer) -> Self {
        bridgeJSFromUnsafeMutableRawPointer(pointer)
    }

    // MARK: ExportSwift
    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ pointer: UnsafeMutableRawPointer) -> Self {
        bridgeJSFromUnsafeMutableRawPointer(pointer)
    }
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self {
        bridgeJSLiftParameter(_swift_js_pop_pointer())
    }
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer {
        bridgeJSToUnsafeMutableRawPointer()
    }
    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        _swift_js_push_pointer(bridgeJSToUnsafeMutableRawPointer())
    }
}

extension UnsafeMutableRawPointer: _BridgedSwiftUnsafePointerLike {
    @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer { self }
    @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer(
        _ pointer: UnsafeMutableRawPointer
    ) -> UnsafeMutableRawPointer {
        pointer
    }
}

extension UnsafeRawPointer: _BridgedSwiftUnsafePointerLike {
    @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer {
        UnsafeMutableRawPointer(mutating: self)
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer(
        _ pointer: UnsafeMutableRawPointer
    ) -> UnsafeRawPointer {
        UnsafeRawPointer(pointer)
    }
}

extension OpaquePointer: _BridgedSwiftUnsafePointerLike {
    @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer {
        UnsafeMutableRawPointer(mutating: UnsafeRawPointer(self))
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer(
        _ pointer: UnsafeMutableRawPointer
    ) -> OpaquePointer {
        OpaquePointer(UnsafeRawPointer(pointer))
    }
}

extension UnsafePointer: _BridgedSwiftUnsafePointerLike {
    @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer {
        UnsafeMutableRawPointer(mutating: UnsafeRawPointer(self))
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer(
        _ pointer: UnsafeMutableRawPointer
    ) -> UnsafePointer<Pointee> {
        UnsafeRawPointer(pointer).assumingMemoryBound(to: Pointee.self)
    }
}

extension UnsafeMutablePointer: _BridgedSwiftUnsafePointerLike {
    @_spi(BridgeJS) @_transparent public func bridgeJSToUnsafeMutableRawPointer() -> UnsafeMutableRawPointer {
        UnsafeMutableRawPointer(self)
    }
    @_spi(BridgeJS) @_transparent public static func bridgeJSFromUnsafeMutableRawPointer(
        _ pointer: UnsafeMutableRawPointer
    ) -> UnsafeMutablePointer<Pointee> {
        pointer.assumingMemoryBound(to: Pointee.self)
    }
}

extension Optional {
    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter<Signature>() -> (
        isSome: Int32, value: Int32
    ) where Wrapped == JSTypedClosure<Signature> {
        switch consume self {
        case .none:
            return (isSome: 0, value: 0)
        case .some(let wrapped):
            return (isSome: 1, value: wrapped.bridgeJSLowerParameter())
        }
    }
}

extension Optional {
    @usableFromInline @_transparent func _bridgeJSLowerParameter<Payload>(
        noneValue: Payload,
        lowerWrapped: (Wrapped) -> Payload
    ) -> (isSome: Int32, value: Payload) {
        switch self {
        case .none:
            return (isSome: 0, value: noneValue)
        case .some(let wrapped):
            return (isSome: 1, value: lowerWrapped(wrapped))
        }
    }

    @usableFromInline @_transparent static func _bridgeJSLiftParameter<Payload>(
        _ isSome: Int32,
        _ payload: Payload,
        liftWrapped: (Payload) -> Wrapped
    ) -> Wrapped? {
        if isSome == 0 {
            return nil
        }
        return liftWrapped(payload)
    }

    @usableFromInline @_transparent func _bridgeJSLowerReturn<Payload>(
        noneValue: Payload,
        lowerWrapped: (Wrapped) -> Payload,
        write: (Int32, Payload) -> Void
    ) {
        switch self {
        case .none:
            write(0, noneValue)
        case .some(let wrapped):
            write(1, lowerWrapped(wrapped))
        }
    }
}

public protocol _BridgedSwiftOptionalScalarBridge: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType,
    _BridgedSwiftStackType
where StackLiftResult == Self {
    @_spi(BridgeJS) static func bridgeJSPopOptionalScalarPayload() -> WasmCoreType
    @_spi(BridgeJS) static var bridgeJSOptionalScalarNonePayload: WasmCoreType { get }
    @_spi(BridgeJS) static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: WasmCoreType)
}

public protocol _BridgedSwiftOptionalScalarSideChannelBridge: _BridgedSwiftOptionalScalarBridge {
    @_spi(BridgeJS) static func bridgeJSReadOptionalSideChannelPresence() -> Int32
    @_spi(BridgeJS) static func bridgeJSReadOptionalSideChannelPayload() -> WasmCoreType
}

private protocol _BridgedSwiftOptionalInt32SideChannelBridge: _BridgedSwiftOptionalScalarSideChannelBridge
where WasmCoreType == Int32 {}

extension _BridgedSwiftOptionalInt32SideChannelBridge {
    @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Int32 { _swift_js_pop_i32() }
    @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Int32 { 0 }
    @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Int32) {
        _swift_js_return_optional_int(isSome, value)
    }
    @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPresence() -> Int32 {
        _swift_js_get_optional_int_presence()
    }
    @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPayload() -> Int32 {
        _swift_js_get_optional_int_value()
    }
}

extension Bool: _BridgedSwiftOptionalScalarBridge {
    @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Int32 { _swift_js_pop_i32() }
    @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Int32 { 0 }
    @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Int32) {
        _swift_js_return_optional_bool(isSome, value)
    }
}

extension Int: _BridgedSwiftOptionalInt32SideChannelBridge {}
extension UInt: _BridgedSwiftOptionalInt32SideChannelBridge {}
extension Int8: _BridgedSwiftOptionalInt32SideChannelBridge {}
extension UInt8: _BridgedSwiftOptionalInt32SideChannelBridge {}
extension Int16: _BridgedSwiftOptionalInt32SideChannelBridge {}
extension UInt16: _BridgedSwiftOptionalInt32SideChannelBridge {}
extension Int32: _BridgedSwiftOptionalInt32SideChannelBridge {}
extension UInt32: _BridgedSwiftOptionalInt32SideChannelBridge {}

extension Float: _BridgedSwiftOptionalScalarSideChannelBridge {
    @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Float32 { _swift_js_pop_f32() }
    @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Float32 { 0.0 }
    @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Float32) {
        _swift_js_return_optional_float(isSome, value)
    }
    @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPresence() -> Int32 {
        _swift_js_get_optional_float_presence()
    }
    @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPayload() -> Float32 {
        _swift_js_get_optional_float_value()
    }
}

extension Double: _BridgedSwiftOptionalScalarSideChannelBridge {
    @_spi(BridgeJS) public static func bridgeJSPopOptionalScalarPayload() -> Float64 { _swift_js_pop_f64() }
    @_spi(BridgeJS) public static var bridgeJSOptionalScalarNonePayload: Float64 { 0.0 }
    @_spi(BridgeJS) public static func bridgeJSWriteOptionalReturn(_ isSome: Int32, _ value: Float64) {
        _swift_js_return_optional_double(isSome, value)
    }
    @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPresence() -> Int32 {
        _swift_js_get_optional_double_presence()
    }
    @_spi(BridgeJS) public static func bridgeJSReadOptionalSideChannelPayload() -> Float64 {
        _swift_js_get_optional_double_value()
    }
}

extension _BridgedAsOptional where Wrapped == JSValue {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> (
        isSome: Int32, kind: Int32, payload1: Int32, payload2: Double
    ) {
        switch asOptional {
        case .none:
            return (isSome: 0, kind: 0, payload1: 0, payload2: 0)
        case .some(let wrapped):
            let lowered = wrapped.bridgeJSLowerParameter()
            return (
                isSome: 1,
                kind: lowered.kind,
                payload1: lowered.payload1,
                payload2: lowered.payload2
            )
        }
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(
        _ isSome: Int32,
        _ kind: Int32,
        _ payload1: Int32,
        _ payload2: Double
    ) -> Self {
        if isSome == 0 {
            return Self(optional: nil)
        } else {
            return Self(optional: JSValue.bridgeJSLiftParameter(kind, payload1, payload2))
        }
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() {
        asOptional.bridgeJSStackPush()
    }
}

public protocol _BridgedSwiftTypeLoweredIntoVoidType {
    // MARK: ExportSwift
    consuming func bridgeJSLowerReturn() -> Void
}

// MARK: - _BridgedAsOptional (optional bridge implementations)

extension _BridgedAsOptional where Wrapped: _BridgedSwiftStackType, Wrapped.StackLiftResult == Wrapped {
    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self {
        Self(optional: Wrapped.bridgeJSStackPopAsOptional())
    }

    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        Wrapped.bridgeJSStackPushAsOptional(asOptional)
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self {
        Self(optional: Wrapped.bridgeJSStackPopAsOptional())
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> Self {
        Self(optional: Wrapped.bridgeJSStackPopAsOptional())
    }
}

extension _BridgedAsOptional
where Wrapped: _BridgedSwiftStackType, Wrapped.StackLiftResult == Wrapped, Wrapped: _BridgedSwiftTypeLoweredIntoVoidType
{
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 {
        switch asOptional {
        case .none:
            return 0
        case .some(let array):
            array.bridgeJSLowerReturn()
            return 1
        }
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void {
        Wrapped.bridgeJSStackPushAsOptional(asOptional)
    }
}

extension Optional: _BridgedSwiftStackType
where Wrapped: _BridgedSwiftStackType, Wrapped.StackLiftResult == Wrapped {
    public typealias StackLiftResult = Wrapped?

    @_spi(BridgeJS) public static func bridgeJSStackPop() -> Wrapped? {
        Wrapped.bridgeJSStackPopAsOptional()
    }

    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        Wrapped.bridgeJSStackPushAsOptional(self)
    }
}

extension _BridgedAsOptional where Wrapped: _BridgedSwiftOptionalScalarBridge {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> (
        isSome: Int32, value: Wrapped.WasmCoreType
    ) {
        switch asOptional {
        case .none:
            return (isSome: 0, value: Wrapped.bridgeJSOptionalScalarNonePayload)
        case .some(let wrapped):
            return (isSome: 1, value: wrapped.bridgeJSLowerParameter())
        }
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(
        _ isSome: Int32,
        _ wrappedValue: Wrapped.WasmCoreType
    ) -> Self {
        Self(optional: isSome == 0 ? nil : Wrapped.bridgeJSLiftParameter(wrappedValue))
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void {
        switch asOptional {
        case .none:
            Wrapped.bridgeJSWriteOptionalReturn(0, Wrapped.bridgeJSOptionalScalarNonePayload)
        case .some(let value):
            Wrapped.bridgeJSWriteOptionalReturn(1, value.bridgeJSLowerReturn())
        }
    }
}

extension _BridgedAsOptional where Wrapped: _BridgedSwiftOptionalScalarSideChannelBridge {
    @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self {
        let isSome = Wrapped.bridgeJSReadOptionalSideChannelPresence()
        if isSome == 0 {
            return Self(optional: nil)
        }
        return Self(optional: Wrapped.bridgeJSLiftReturn(Wrapped.bridgeJSReadOptionalSideChannelPayload()))
    }
}

extension _BridgedAsOptional where Wrapped == Bool {
    @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: Int32) -> Self {
        let opt: Bool? =
            switch value {
            case -1: nil
            case 0: false
            case 1: true
            default: nil  // Treat invalid values as null
            }
        return Self(optional: opt)
    }
}

extension _BridgedAsOptional where Wrapped == String {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSWithLoweredParameter<T>(
        _ body: (Int32, Int32, Int32) -> T
    ) -> T {
        switch asOptional {
        case .none:
            return body(0, 0, 0)
        case .some(let value):
            return value.bridgeJSWithLoweredParameter { bytes, count in
                return body(1, bytes, count)
            }
        }
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(
        _ isSome: Int32,
        _ bytes: Int32,
        _ count: Int32
    ) -> Self {
        Self(
            optional: Optional<Wrapped>._bridgeJSLiftParameter(
                isSome,
                (bytes, count),
                liftWrapped: { String.bridgeJSLiftParameter($0.0, $0.1) }
            )
        )
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self {
        let length = _swift_js_get_optional_string()
        if length < 0 {
            return Self(optional: nil)
        } else {
            return Self(optional: String.bridgeJSLiftReturn(length))
        }
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void {
        switch asOptional {
        case .none:
            _swift_js_return_optional_string(0, nil, 0)
        case .some(var value):
            value.withUTF8 { ptr in
                _swift_js_return_optional_string(1, ptr.baseAddress, Int32(ptr.count))
            }
        }
    }
}

extension _BridgedAsOptional where Wrapped == JSObject {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> (
        isSome: Int32, value: Int32
    ) {
        asOptional._bridgeJSLowerParameter(noneValue: 0, lowerWrapped: { $0.bridgeJSLowerParameter() })
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ objectId: Int32) -> Self {
        Self(
            optional: Optional<Wrapped>._bridgeJSLiftParameter(
                isSome,
                objectId,
                liftWrapped: JSObject.bridgeJSLiftParameter
            )
        )
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void {
        asOptional._bridgeJSLowerReturn(
            noneValue: 0,
            lowerWrapped: { $0.bridgeJSLowerReturn() },
            write: _swift_js_return_optional_object
        )
    }
}

extension _BridgedAsOptional where Wrapped: _BridgedSwiftProtocolWrapper {
    @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ objectId: Int32) -> Self {
        Self(
            optional: Optional<Wrapped>._bridgeJSLiftParameter(
                isSome,
                objectId,
                liftWrapped: Wrapped.bridgeJSLiftParameter
            )
        )
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void {
        switch asOptional {
        case .none:
            _swift_js_return_optional_object(0, 0)
        case .some(let wrapper):
            let retainedId: Int32 = wrapper.bridgeJSLowerReturn()
            _swift_js_return_optional_object(1, retainedId)
        }
    }
}

extension _BridgedAsOptional where Wrapped: _BridgedSwiftHeapObject {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> (
        isSome: Int32, pointer: UnsafeMutableRawPointer
    ) {
        switch asOptional {
        case .none:
            return (isSome: 0, pointer: UnsafeMutableRawPointer(bitPattern: 1)!)
        case .some(let value):
            return (isSome: 1, pointer: value.bridgeJSLowerParameter())
        }
    }

    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ pointer: UnsafeMutableRawPointer) -> Self {
        if pointer == UnsafeMutableRawPointer(bitPattern: 0) {
            return Self(optional: nil)
        } else {
            return Self(optional: Wrapped.bridgeJSLiftReturn(pointer))
        }
    }

    @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(
        _ isSome: Int32,
        _ pointer: UnsafeMutableRawPointer
    ) -> Self {
        Self(
            optional: Optional<Wrapped>._bridgeJSLiftParameter(
                isSome,
                pointer,
                liftWrapped: Wrapped.bridgeJSLiftParameter
            )
        )
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self {
        let pointer = _swift_js_get_optional_heap_object_pointer()
        if pointer == UnsafeMutableRawPointer(bitPattern: 0) {
            return Self(optional: nil)
        } else {
            return Self(optional: Wrapped.bridgeJSLiftReturn(pointer))
        }
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void {
        switch asOptional {
        case .none:
            _swift_js_return_optional_heap_object(0, nil)
        case .some(let value):
            let retainedPointer: UnsafeMutableRawPointer = value.bridgeJSLowerReturn()
            _swift_js_return_optional_heap_object(1, retainedPointer)
        }
    }
}

extension _BridgedAsOptional where Wrapped: _BridgedSwiftCaseEnum {
    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) {
        asOptional._bridgeJSLowerParameter(noneValue: 0, lowerWrapped: { $0.bridgeJSLowerParameter() })
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Self {
        Self(
            optional: Optional<Wrapped>._bridgeJSLiftParameter(
                isSome,
                wrappedValue,
                liftWrapped: Wrapped.bridgeJSLiftParameter
            )
        )
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ value: Int32) -> Self {
        if value == -1 {
            return Self(optional: nil)
        } else {
            return Self(optional: Wrapped.bridgeJSLiftReturn(value))
        }
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void {
        asOptional._bridgeJSLowerReturn(
            noneValue: 0,
            lowerWrapped: { $0.bridgeJSLowerReturn() },
            write: _swift_js_return_optional_int
        )
    }
}

extension _BridgedAsOptional
where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == String {
    @_spi(BridgeJS) @_transparent public consuming func bridgeJSWithLoweredParameter<T>(
        _ body: (Int32, Int32, Int32) -> T
    ) -> T {
        switch asOptional {
        case .none:
            return body(0, 0, 0)
        case .some(let wrapped):
            return wrapped.bridgeJSWithLoweredParameter { bytes, count in
                return body(1, bytes, count)
            }
        }
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(
        _ isSome: Int32,
        _ bytes: Int32,
        _ count: Int32
    ) -> Self {
        let optionalRawValue = Optional<String>.bridgeJSLiftParameter(isSome, bytes, count)
        return Self(optional: optionalRawValue.flatMap { Wrapped(rawValue: $0) })
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self {
        let length = _swift_js_get_optional_string()
        if length < 0 {
            return Self(optional: nil)
        } else {
            let rawValue = String.bridgeJSLiftReturn(length)
            return Self(optional: Wrapped(rawValue: rawValue))
        }
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void {
        let optionalRawValue: String? = asOptional?.rawValue
        optionalRawValue.bridgeJSLowerReturn()
    }
}

extension _BridgedAsOptional
where
    Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable,
    Wrapped.RawValue: _BridgedSwiftOptionalScalarBridge
{
    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (
        isSome: Int32, value: Wrapped.RawValue.WasmCoreType
    ) {
        let optionalRawValue: Wrapped.RawValue? = asOptional?.rawValue
        return optionalRawValue.bridgeJSLowerParameter()
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(
        _ isSome: Int32,
        _ wrappedValue: Wrapped.RawValue.WasmCoreType
    ) -> Self {
        let optionalRawValue = Optional<Wrapped.RawValue>.bridgeJSLiftParameter(isSome, wrappedValue)
        return Self(optional: optionalRawValue.flatMap { Wrapped(rawValue: $0) })
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void {
        let optionalRawValue: Wrapped.RawValue? = asOptional?.rawValue
        optionalRawValue.bridgeJSLowerReturn()
    }
}

extension _BridgedAsOptional
where
    Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: _BridgedSwiftRawValueEnum, Wrapped: RawRepresentable,
    Wrapped.RawValue: _BridgedSwiftStackType,
    Wrapped.RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType,
    Wrapped.RawValue.WasmCoreType == Int64
{
    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (
        isSome: Int32, value: Int64
    ) {
        switch asOptional {
        case .none:
            return (isSome: 0, value: 0)
        case .some(let wrapped):
            return (isSome: 1, value: wrapped.bridgeJSLowerParameter())
        }
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int64) -> Self {
        if isSome == 0 {
            return Self(optional: nil)
        }
        return Self(optional: Wrapped(rawValue: Wrapped.RawValue.bridgeJSLiftParameter(wrappedValue)))
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void {
        Wrapped.bridgeJSStackPushAsOptional(asOptional)
    }
}

extension _BridgedAsOptional
where
    Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable,
    Wrapped.RawValue: _BridgedSwiftOptionalScalarSideChannelBridge
{
    @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self {
        let optionalRawValue = Optional<Wrapped.RawValue>.bridgeJSLiftReturnFromSideChannel()
        return Self(optional: optionalRawValue.flatMap { Wrapped(rawValue: $0) })
    }
}

extension _BridgedAsOptional where Wrapped: _BridgedSwiftAssociatedValueEnum {
    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, caseId: Int32) {
        switch asOptional {
        case .none:
            return (isSome: 0, caseId: 0)
        case .some(let value):
            return (isSome: 1, caseId: value.bridgeJSLowerParameter())
        }
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ caseId: Int32) -> Self {
        if isSome == 0 {
            return Self(optional: nil)
        } else {
            return Self(optional: Wrapped.bridgeJSLiftParameter(caseId))
        }
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ caseId: Int32) -> Self {
        if caseId == -1 {
            return Self(optional: nil)
        } else {
            return Self(optional: Wrapped.bridgeJSStackPopPayload(caseId))
        }
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() {
        Wrapped.bridgeJSStackPushAsOptional(asOptional)
    }
}

extension _BridgedAsOptional where Wrapped: _BridgedSwiftStruct {
    @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32) -> Self {
        if isSome == 0 {
            return Self(optional: nil)
        } else {
            return Self(optional: Wrapped.bridgeJSStackPop())
        }
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void {
        Wrapped.bridgeJSStackPushAsOptional(asOptional)
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self {
        Self.bridgeJSStackPop()
    }
}

// MARK: - Array Support

extension Array: _BridgedSwiftTypeLoweredIntoVoidType
where Element: _BridgedSwiftStackType, Element.StackLiftResult == Element {}

extension Array: _BridgedSwiftStackType where Element: _BridgedSwiftStackType, Element.StackLiftResult == Element {
    public typealias StackLiftResult = [Element]

    @_spi(BridgeJS) public static func bridgeJSStackPop() -> [Element] {
        let count = Int(_swift_js_pop_i32())
        var result: [Element] = []
        result.reserveCapacity(count)
        for _ in 0..<count {
            result.append(Element.bridgeJSStackPop())
        }
        result.reverse()
        return result
    }

    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        let array = self
        for elem in array {
            elem.bridgeJSStackPush()
        }
        _swift_js_push_i32(Int32(array.count))
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> [Element] {
        bridgeJSStackPop()
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() {
        self.bridgeJSStackPush()
    }
    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() {
        self.bridgeJSStackPush()
    }
    @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> [Element] {
        bridgeJSStackPop()
    }
}

// MARK: - Dictionary Support

extension Dictionary: _BridgedSwiftStackType
where Key == String, Value: _BridgedSwiftStackType, Value.StackLiftResult == Value {
    public typealias StackLiftResult = [String: Value]

    @_spi(BridgeJS) public static func bridgeJSStackPop() -> [String: Value] {
        let count = Int(_swift_js_pop_i32())
        var result: [String: Value] = [:]
        result.reserveCapacity(count)
        for _ in 0..<count {
            let value = Value.bridgeJSStackPop()
            let key = String.bridgeJSStackPop()
            result[key] = value
        }
        return result
    }

    @_spi(BridgeJS) public consuming func bridgeJSStackPush() {
        let count = Int32(self.count)
        for (key, value) in self {
            key.bridgeJSStackPush()
            value.bridgeJSStackPush()
        }
        _swift_js_push_i32(count)
    }
}

extension Dictionary: _BridgedSwiftTypeLoweredIntoVoidType
where Key == String, Value: _BridgedSwiftStackType, Value.StackLiftResult == Value {
    @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> [String: Value] {
        bridgeJSStackPop()
    }
    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() {
        self.bridgeJSStackPush()
    }
    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() {
        self.bridgeJSStackPush()
    }
    @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> [String: Value] {
        bridgeJSStackPop()
    }
}

extension _BridgedAsOptional {
    @_spi(BridgeJS) public consuming func bridgeJSLowerParameter<Value>() -> Int32
    where Wrapped == Dictionary<String, Value>, Value: _BridgedSwiftStackType, Value.StackLiftResult == Value {
        switch asOptional {
        case .none:
            return 0
        case .some(let dict):
            dict.bridgeJSStackPush()
            return 1
        }
    }

    @_spi(BridgeJS) public static func bridgeJSLiftParameter<Value>(_ isSome: Int32) -> Self
    where Wrapped == Dictionary<String, Value>, Value: _BridgedSwiftStackType, Value.StackLiftResult == Value {
        if isSome == 0 {
            return Self(optional: nil)
        }
        return Self(optional: Dictionary<String, Value>.bridgeJSStackPop())
    }

    @_spi(BridgeJS) public static func bridgeJSLiftReturn<Value>() -> Self
    where Wrapped == Dictionary<String, Value>, Value: _BridgedSwiftStackType, Value.StackLiftResult == Value {
        let isSome = _swift_js_pop_i32()
        if isSome == 0 {
            return Self(optional: nil)
        }
        return Self(optional: Dictionary<String, Value>.bridgeJSStackPop())
    }

    @_spi(BridgeJS) public consuming func bridgeJSLowerReturn<Value>() -> Void
    where Wrapped == Dictionary<String, Value>, Value: _BridgedSwiftStackType, Value.StackLiftResult == Value {
        Wrapped.bridgeJSStackPushAsOptional(asOptional)
    }
}

// MARK: Async Promise Awaiting

/// Protocol for type-erasing `JSTypedClosure` in `_bjs_awaitPromise`.
///
/// The library cannot name concrete `JSTypedClosure<(Int) -> Void>` etc. because
/// those require per-module generated convenience inits. This protocol provides
/// access to the underlying JS object ref and cleanup.
@_spi(BridgeJS) public protocol _BridgeJSReleasableClosure {
    var jsObject: JSObject { get }
    func release()
}

@_spi(BridgeJS) extension JSTypedClosure: _BridgeJSReleasableClosure {}

/// Awaits a JavaScript Promise using typed resolve/reject `JSTypedClosure` callbacks.
///
/// The closure factories are dependency-injected because this library cannot
/// reference per-module generated `make_swift_closure_*` externs. The generated
/// code passes `{ JSTypedClosure<(T) -> Void>($0) }` which uses the per-module
/// convenience init.
///
/// - Parameters:
///   - makeResolveClosure: A factory that wraps a `(T) -> Void` Swift closure
///     into a typed `JSTypedClosure`, creating the corresponding JS function.
///   - makeRejectClosure: A factory that wraps a `(JSValue) -> Void` Swift closure
///     into a `JSTypedClosure`, for the rejection path.
///   - body: A closure that receives the resolve and reject JS object refs
///     (as `Int32`) and should pass them to the appropriate JS extern function.
/// - Returns: The resolved value of type `T` from the Promise.
/// - Throws: `JSException` if the Promise rejects.
@_spi(BridgeJS) public func _bjs_awaitPromise<T, R: _BridgeJSReleasableClosure, E: _BridgeJSReleasableClosure>(
    makeResolveClosure: (@escaping (sending T) -> Void) -> R,
    makeRejectClosure: (@escaping (sending JSValue) -> Void) -> E,
    _ body: (_ resolveRef: Int32, _ rejectRef: Int32) -> Void
) async throws(JSException) -> T {
    var resolveClosure: R?
    var rejectClosure: E?
    let result: Result<T, JSException> = await withCheckedContinuation { continuation in
        let resolve = makeResolveClosure { value in
            continuation.resume(returning: .success(value))
        }
        let reject = makeRejectClosure { value in
            continuation.resume(returning: .failure(JSException(value)))
        }
        resolveClosure = resolve
        rejectClosure = reject
        body(
            Int32(bitPattern: resolve.jsObject.id),
            Int32(bitPattern: reject.jsObject.id)
        )
    }
    resolveClosure?.release()
    rejectClosure?.release()
    return try result.get()
}

/// Void-returning overload of `_bjs_awaitPromise`.
///
/// Needed because `(Void) -> Void` is not the same as `() -> Void` in Swift (SE-0110),
/// so the generic overload cannot handle void returns.
@_spi(BridgeJS) public func _bjs_awaitPromise<R: _BridgeJSReleasableClosure, E: _BridgeJSReleasableClosure>(
    makeResolveClosure: (@escaping () -> Void) -> R,
    makeRejectClosure: (@escaping (sending JSValue) -> Void) -> E,
    _ body: (_ resolveRef: Int32, _ rejectRef: Int32) -> Void
) async throws(JSException) {
    var resolveClosure: R?
    var rejectClosure: E?
    let error: JSException? = await withCheckedContinuation { continuation in
        let resolve = makeResolveClosure {
            continuation.resume(returning: nil)
        }
        let reject = makeRejectClosure { value in
            continuation.resume(returning: JSException(value))
        }
        resolveClosure = resolve
        rejectClosure = reject
        body(
            Int32(bitPattern: resolve.jsObject.id),
            Int32(bitPattern: reject.jsObject.id)
        )
    }
    resolveClosure?.release()
    rejectClosure?.release()
    if let error {
        throw error
    }
}
