Skip to content

BridgeJS: Support generic functions on exported Swift APIs - #24

Draft
krodak wants to merge 3 commits into
kr/protocol-refinement-upstreamfrom
kr/generics-export-side
Draft

krodak wants to merge 3 commits into
kr/protocol-refinement-upstreamfrom
kr/generics-export-side

Conversation

@krodak

@krodak krodak commented Sep 21, 2026 •

Copy link
Copy Markdown
Collaborator

Overview

Adds generic exported Swift functions and methods. Swift-owned scene graphs, document models, and registries can expose typed operations without a separate binding for every model type. JavaScript callers select concrete Swift types with generated BridgeTypes tokens.

Example

A scene maintained by Swift can expose checked lookups and collections:

@JS protocol SceneNode: BridgedSwiftGenericBridgeable {
    var id: String { get }
}

@JS final class Scene {
    private var nodes: [String: any SceneNode]

    init(nodes: [String: any SceneNode]) { self.nodes = nodes }

    @JS func find<T: SceneNode>(_ id: String) -> T? {
        nodes[id] as? T
    }

    @JS func all<T: SceneNode>() -> [T] {
        nodes.values.compactMap { $0 as? T }
    }
}

The application supplies scene; Camera and Light are exported final classes conforming to SceneNode:

import { BridgeTypes } from "./bridge-js.js";

const camera = scene.find("main-camera", BridgeTypes.Camera); // Camera | null
const lights = scene.all(BridgeTypes.Light); // Light[]
const wrongType = scene.find("main-camera", BridgeTypes.Light); // null

Swift checks the stored object against the requested type. The token also determines the TypeScript return type, avoiding unchecked casts or per-type methods such as findCamera and findLight.

Supported Forms

  • Supports T, [T], T?, and [String: T], mixed with concrete parameters and results.
  • Supports async/throwing exports and generic callback parameters, including escaping and async callbacks.
  • Preserves @JS protocol constraints in TypeScript and rejects unknown or non-conforming tokens before lowering arguments.
  • Exported generic initializers, generic nominal types, and Embedded Swift exports remain unsupported. Imported generic @JSClass initializers are unchanged.

Test Plan

  • BridgeJS codegen, diagnostics, and snapshot tests across SwiftSyntax 600-603.
  • npm run check:bridgejs-dts.
  • ./Utilities/bridge-js-generate.sh.
  • make unittest SWIFT_SDK_ID=swift-6.3.1-RELEASE_wasm BUILD_SYSTEM=native.

@krodak
krodak force-pushed the kr/generics-export-side branch 3 times, most recently from 6463336 to 317896e Compare September 22, 2026 09:00
@krodak
krodak force-pushed the kr/generics-export-side branch from 317896e to 5c72ff8 Compare September 22, 2026 14:22
@krodak
krodak changed the base branch from main to kr/protocol-refinement-upstream September 22, 2026 14:22

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant