Skip to content

Commit 5c72ff8

Browse files
committed
Docs: Describe generic Swift exports
1 parent 69eec90 commit 5c72ff8

10 files changed

Lines changed: 75 additions & 8 deletions

File tree

‎Plugins/BridgeJS/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ graph LR
9898
| `Dictionary<K, V>` | `Record<K, V>` | - | [#495](https://github.com/swiftwasm/JavaScriptKit/issues/495) |
9999
| `Set<T>` | `Set<T>` | - | [#397](https://github.com/swiftwasm/JavaScriptKit/issues/397) |
100100
| `Foundation.URL` | `string` | - | [#496](https://github.com/swiftwasm/JavaScriptKit/issues/496) |
101-
| Generic function or method (`T`, `[T]`, `T?`, `[String: T]`) | `<T>(value: T): T` | Depends on `T` | ✅ imports only ([#398](https://github.com/swiftwasm/JavaScriptKit/issues/398) for exports) |
101+
| Generic function or method (`T`, `[T]`, `T?`, `[String: T]`) | `<T>(value: T): T` (imports); exports add `BridgeType<T>` tokens | Depends on `T` | ✅ ([exports](../../Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Generics.md), [imports](../../Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Function.md)) |
102102

103103
### Import-specific (TypeScript -> Swift)
104104

‎Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Configure your package and build for JavaScript as described in <doc:Setting-up-
1515
## Topics
1616

1717
- <doc:Exporting-Swift-Function>
18+
- <doc:Exporting-Swift-Generics>
1819
- <doc:Exporting-Swift-Class>
1920
- <doc:Exporting-Swift-Struct>
2021
- <doc:Exporting-Swift-Array>

‎Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Class.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,5 @@ Identity mode improves performance for reuse-heavy workloads (same objects cross
234234
| Static/class methods: `static func`, `class func` | ✅ (See <doc:Exporting-Swift-Static-Functions> ) |
235235
| Extension methods/properties | ✅ |
236236
| Subscripts: `subscript()` | ❌ |
237-
| Generics | ❌ |
237+
| Generic methods (instance and static; see <doc:Exporting-Swift-Generics>) | ✅ |
238+
| Generic classes: `class Box<T>` | ❌ |

‎Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,4 +544,5 @@ This differs from classes, which use reference semantics and share state across
544544
| Associated values: Arrays | ✅ |
545545
| Associated values: Optionals of all supported types | ✅ |
546546
| Extension static functions/properties | ✅ |
547-
| Generics | ❌ |
547+
| Generic static methods (see <doc:Exporting-Swift-Generics>) | ✅ |
548+
| Generic enums: `enum Result<T>` | ❌ |

‎Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Function.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,6 @@ export type Exports = {
169169
| Throwing JS exception: `func x() throws(JSException)` | ✅ |
170170
| Throwing any exception: `func x() throws` | ❌ |
171171
| Async methods: `func x() async` | ✅ |
172-
| Generics | ❌ |
172+
| Generic functions (see <doc:Exporting-Swift-Generics>) | ✅ |
173173
| Opaque types: `func x() -> some P`, `func y(_: some P)` | ❌ |
174-
| Default parameter values: `func x(_ foo: String = "")` | ✅ (See <doc:Exporting-Swift-Default-Parameters>) |
174+
| Default parameter values: `func x(_ foo: String = "")` | ✅ (See <doc:Exporting-Swift-Default-Parameters>) |
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Exporting Generic Swift APIs
2+
3+
Expose generic functions, methods, and callback parameters to JavaScript.
4+
5+
## Overview
6+
7+
Constrain each type parameter to `BridgedSwiftGenericBridgeable`. JavaScript callers select its concrete Swift type with a token from the generated `BridgeTypes` export.
8+
9+
```swift
10+
import JavaScriptKit
11+
12+
@JS public final class ValueStore {
13+
private var values: [String: any BridgedSwiftGenericBridgeable] = [:]
14+
15+
@JS public init() {}
16+
17+
@JS public func put<T: BridgedSwiftGenericBridgeable>(_ key: String, _ value: T) {
18+
values[key] = value
19+
}
20+
21+
@JS public func get<T: BridgedSwiftGenericBridgeable>(_ key: String) -> T? {
22+
values[key] as? T
23+
}
24+
}
25+
```
26+
27+
```javascript
28+
import { BridgeTypes } from "./bridge-js.js";
29+
30+
const store = new exports.ValueStore();
31+
store.put("count", 42, BridgeTypes.Int);
32+
store.put("title", "Draft", BridgeTypes.String);
33+
store.get("count", BridgeTypes.Int); // 42
34+
store.get("title", BridgeTypes.String); // "Draft"
35+
store.get("count", BridgeTypes.String); // null: stored as Int
36+
store.release();
37+
```
38+
39+
Pass one token per generic parameter after the regular arguments, in declaration order. Tokens use Swift names and underscore-separated namespaces, such as `BridgeTypes.API_Building`, even when the type has a separate JavaScript name. Import `BridgeTypes` from the generated module, not the `exports` object.
40+
41+
The token selects the concrete return type, including for return-only generics such as `get`. Generic values may use `T`, `[T]`, `T?`, or `[String: T]`, mixed with concrete parameters and results. See <doc:Supported-Types> for types usable as `T`.
42+
43+
### Async functions and callbacks
44+
45+
Generic exports and their callback parameters may be `async` or `throws(JSException)`. Callbacks can use the same generic types; an `@escaping` callback stays alive until Swift releases it and must run on the same JavaScript runtime/thread. Use `throws(JSException)` for callbacks that throw or reject a promise.
46+
47+
### Protocol constraints
48+
49+
Add `@JS` protocol constraints with `T: BridgedSwiftGenericBridgeable & GraphNode`, or use `T: GraphNode` if `GraphNode` inherits `BridgedSwiftGenericBridgeable` (see <doc:Exporting-Swift-Protocols>). Constraints are preserved in TypeScript; unknown or non-conforming tokens throw `TypeError` before arguments cross the bridge.
50+
51+
Exported generic initializers are unsupported; use an ordinary initializer as above or a generic factory method. Imported generic `@JSClass` initializers remain supported (see <doc:Importing-JS-Function>). See <doc:Unsupported-Features> for other export restrictions.

‎Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Functions.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,5 +162,5 @@ const result: string = Utils.String.uppercase("world");
162162
| Class `class func` | ✅ |
163163
| Enum `static func` | ✅ |
164164
| Namespace enum `static func` | ✅ |
165-
| Generic static functions | ❌ |
165+
| Generic static functions (see <doc:Exporting-Swift-Generics>) | ✅ |
166166
| Protocol static requirements | ❌ |

‎Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Struct.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ This differs from classes, which use reference semantics and share state across
169169
| Static properties | ✅ |
170170
| Extension methods/properties | ✅ |
171171
| Property observers (`willSet`, `didSet`) | ❌ |
172-
| Generics | ❌ |
172+
| Generic methods (instance and static; see <doc:Exporting-Swift-Generics>) | ✅ |
173+
| Generic structs: `struct Pair<T>` | ❌ |
173174
| Conformances | ❌ |
174175

175176
## See Also

‎Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ See <doc:Exporting-Swift-Array> for usage details.
3333

3434
## Generic type parameters
3535

36-
An imported `@JSFunction` can be generic over a type parameter constrained to `BridgedSwiftGenericBridgeable` (see <doc:Importing-JS-Function>); exported `@JS` functions cannot yet. The constraint is satisfied by all supported primitives, `String`, `JSValue`, and any `@JS` struct, `@JS` enum, or `final @JS class`, including ones from another linked module. Do not write the conformance by hand; marking the type `@JS` is what provides it, together with the JavaScript side of the bridge.
36+
Imported `@JSFunction` and exported `@JS` functions support type parameters constrained to `BridgedSwiftGenericBridgeable`. The constraint is satisfied by all supported primitives (including fixed-width integers), `String`, `JSValue`, and any `@JS` struct, `@JS` enum, or `final @JS class`, including ones from another linked module. Do not write the conformance by hand; marking the type `@JS` provides it together with the JavaScript bridge.
37+
38+
See <doc:Exporting-Swift-Generics> and <doc:Importing-JS-Function> for supported forms and constraints.
3739

3840
## See Also
3941

‎Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,13 @@ While using `@JS` types from another Swift module is supported, it is not possib
5555
### Exporting Swift: types from another Swift package
5656

5757
Types defined in a separate Swift package cannot yet be referenced from `@JS` declarations in your package.
58+
59+
## Generic exports
60+
61+
<doc:Exporting-Swift-Generics> supports functions and methods, not generic initializers, generic nominal types, or generic protocol requirements. Other unsupported forms:
62+
63+
- Embedded Swift, `where` clauses, default parameter values, unused generic parameters, and constraints lacking bridgeability or using non-`@JS` protocols.
64+
- Returned, nested, `@Sendable`, or `inout` generic callbacks, including callbacks with `inout` parameters.
65+
- Generic metatypes (`T.Type`), associated types (`T.Element`), and containers beyond `T`, `[T]`, `T?`, or `[String: T]`. Use `JSValue`, not `JSObject`, as a generic argument.
66+
67+
Type tokens, Swift type names, and protocol names must be unique across linked modules; JavaScript namespaces do not disambiguate them. Direct WebAssembly calls with arbitrary type IDs are unsupported. For import support, including generic `@JSClass` initializers, see <doc:Importing-JS-Function>.

0 commit comments

Comments
 (0)