You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/Design-Rationale.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,6 +32,14 @@ So even if you cache the property name (e.g. with `CachedJSStrings`), you are st
32
32
33
33
BridgeJS avoids this by generating **separate** access paths per property or method. Each generated getter/setter or function call has a stable shape at the engine level, so the IC can stay monomorphic or polymorphic and the fast path is used.
34
34
35
+
## Generic imports
36
+
37
+
An imported generic `@JSFunction` (`func parse<T: _BridgedSwiftGenericBridgeable>(...)`) lets one piece of glue serve many concrete types. The generic value crosses using the type's own stack ABI, and a runtime type ID (interned once via `swift_js_resolve_type_id`) selects the matching JS codec, so the type-agnostic glue can lower and lift the right representation without a specialized path per call site.
38
+
39
+
## Generic exports
40
+
41
+
An exported generic `@JS` function reuses the same stack ABI and codec table, with the dispatch reversed. The WebAssembly entry point is a concrete `@_expose` thunk that takes the runtime type ID as a trailing `Int32`. It looks the ID up in a codegen-emitted registry of `_BridgedSwiftGenericBridgeable` types, reifies `T` through an opened existential, and runs an unspecialized helper that pops the argument from the stack, calls your function, and pushes the result. The JavaScript wrapper resolves the `BridgeType<T>` token to the same interned ID and uses the matching codec to lower the argument and lift the return. Because this depends on existential types, generic exports are excluded under Embedded Swift.
42
+
35
43
## What to read next
36
44
37
45
- ABI and binary interface details will be documented in this section as they stabilize.
Copy file name to clipboardExpand all lines: Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Function.md
+72-1Lines changed: 72 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -136,6 +136,77 @@ export type Exports = {
136
136
}
137
137
```
138
138
139
+
### Generic functions
140
+
141
+
A `@JS` function can be generic over a type parameter constrained to `_BridgedSwiftGenericBridgeable`. The concrete type chosen at the call site crosses the bridge:
142
+
143
+
```swift
144
+
importJavaScriptKit
145
+
146
+
@JSpublicfuncidentity<T: _BridgedSwiftGenericBridgeable>(_value: T) -> T {
147
+
returnvalue
148
+
}
149
+
```
150
+
151
+
`T` must be a bridgeable type: a supported primitive (`Bool`, any fixed-width integer such as `Int`/`UInt`/`Int8`…`UInt64`, `Float`, `Double`, `String`, or `JSValue`), or a `@JS` struct, `final @JSclass`, or `@JSenum` in your module. You do not write any conformance yourself; marking a type `@JS` makes it usable as `T` (see <doc:Supported-Types>).
152
+
153
+
Because TypeScript erases generics, the JavaScript caller passes a `BridgeType<T>` token as the last argument so the bridge can select the right type at runtime. The tokens come from a generated `BridgeTypes` map exported at the top level of `bridge-js.js`; import it directly rather than reading it from the `exports` object:
154
+
155
+
```javascript
156
+
import { BridgeTypes } from"./bridge-js.js";
157
+
158
+
const x =exports.identity(42, BridgeTypes.Int);
159
+
const p =exports.identity({ x: 1, y: 2 }, BridgeTypes.MyPoint);
160
+
```
161
+
162
+
Concrete parameters keep their positions; the token is always appended last. The non-generic parameters of a generic `@JS` function may be any supported bridged type, including value types such as `@JS` structs, arrays, dictionaries, and associated-value enums alongside the generic parameter. The generated TypeScript declarations look like:
A single bare `T` may be used in more than one parameter, such as `pair<T>(_a:T, _b:T) -> T`; each generic value is lowered with the same token, and the arguments are not reordered.
173
+
174
+
A function may also declare multiple distinct generic parameters, such as `combine<T, U>(_a:T, _b:U) -> T`. Each distinct generic parameter takes its own `BridgeType` token, appended after the regular arguments in declaration order, and each generic value crosses the bridge with its own type's codec:
175
+
176
+
```swift
177
+
@JSpublicfunccombine<T:_BridgedSwiftGenericBridgeable, U:_BridgedSwiftGenericBridgeable>(_a:T, _b:U) -> T {
178
+
a
179
+
}
180
+
```
181
+
182
+
```javascript
183
+
import { BridgeTypes } from"./bridge-js.js";
184
+
185
+
const first =exports.combine(7, "hello", BridgeTypes.Int, BridgeTypes.String);
The result must be one of the declared generic parameters (such as `T` or `U`), a supported wrapper of one (`[T]`, `T?`, `[String: T]`), or `Void`. A generic parameter that is never used in any parameter is rejected, and returning a concrete non-`Void` type from a generic `@JS` function is not supported. Generic `@JS` functions must be top-level and synchronous (see <doc:Unsupported-Features>).
Copy file name to clipboardExpand all lines: Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Importing-JavaScript/Importing-JS-Function.md
+31-1Lines changed: 31 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -41,11 +41,41 @@ If you used `from: .global`, do not pass the function in `getImports()`; the run
41
41
42
42
Bound functions are `throws(JSException)`. Call them with `try` or `try?`; they throw when the JavaScript implementation throws.
43
43
44
+
## Generic functions
45
+
46
+
A `@JSFunction` can be generic over a type parameter constrained to `_BridgedSwiftGenericBridgeable`. The concrete type chosen at the call site then crosses the bridge:
47
+
48
+
```swift
49
+
@JSFunctionfuncparse<T: _BridgedSwiftGenericBridgeable>(_json: String) throws(JSException) -> T
50
+
51
+
let user: User =tryparse(jsonString)
52
+
```
53
+
54
+
`T` must be a bridgeable type: a supported primitive (`Bool`, any fixed-width integer such as `Int`/`UInt`/`Int8`…`UInt64`, `Float`, `Double`, `String`, or `JSValue`), or a `@JS` struct, `final @JS class`, or `@JS enum` in your module. You do not write any conformance yourself; marking a type `@JS` makes it usable as `T` (see <doc:Supported-Types>). Generics are not supported for `async`, `@JSClass` members, or `where` clauses (see <doc:Unsupported-Features>).
55
+
56
+
A generic type parameter may be used in more than one parameter, an imported function may declare more than one distinct generic parameter, and a generic result type may be used on a function that takes no generic parameters (the JavaScript implementation produces the value):
57
+
58
+
```swift
59
+
@JSFunctionfuncpickFirst<T: _BridgedSwiftGenericBridgeable>(_a: T, _b: T) throws(JSException) -> T
60
+
61
+
@JSFunctionfuncmakeValue<T: _BridgedSwiftGenericBridgeable>() throws(JSException) -> T
62
+
63
+
@JSFunctionfunccombine<T: _BridgedSwiftGenericBridgeable, U: _BridgedSwiftGenericBridgeable>(_a: T, _b: U) throws(JSException) -> U
64
+
```
65
+
66
+
The generic parameter may also be wrapped as `[T]`, `T?`, or `[String: T]` in parameters and the result:
Copy file name to clipboardExpand all lines: Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md
+12Lines changed: 12 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,6 +31,18 @@ When using `JSTypedArray<T>` (or convenience typealiases) in `@JS` signatures, t
31
31
32
32
See <doc:Exporting-Swift-Array> for usage details.
33
33
34
+
## Generic type parameters
35
+
36
+
A generic type parameter constrained to `_BridgedSwiftGenericBridgeable` is supported as a parameter or result type in both directions: an imported `@JSFunction` (see <doc:Importing-JS-Function>) and an exported `@JS` function (see <doc:Exporting-Swift-Function>). The types that satisfy that constraint are:
37
+
38
+
-`Bool`, `Float`, `Double`, `String`, and `JSValue`
39
+
- every fixed-width integer: `Int`, `UInt`, `Int8`/`Int16`/`Int32`/`Int64`, and `UInt8`/`UInt16`/`UInt32`/`UInt64`
40
+
- any `@JS` struct, `final @JS class`, or `@JS enum` (case, raw-value, or associated-value) in your module
41
+
42
+
You do not write the conformance by hand: marking a type `@JS` (or using a built-in primitive) is what makes it usable as the generic argument.
43
+
44
+
The generic parameter may be used bare (`T`) or wrapped in `[T]`, `T?`, or `[String: T]`. Other or nested wrappings (for example `[T?]`, `[[T]]`, or `[Int: T]`) are not supported. `JSObject` cannot be used as the generic argument; use `JSValue` instead.
Copy file name to clipboardExpand all lines: Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md
+14Lines changed: 14 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -34,3 +34,17 @@ While using `@JS` types from another Swift module is supported, it is not possib
34
34
### Exporting Swift: types from another Swift package
35
35
36
36
Types defined in a separate Swift package cannot yet be referenced from `@JS` declarations in your package.
37
+
38
+
## Generics
39
+
40
+
Generic functions are supported in both directions, through a type parameter constrained to `_BridgedSwiftGenericBridgeable`: an imported `@JSFunction` (see <doc:Importing-JS-Function>) and an exported `@JS` function (see <doc:Exporting-Swift-Function>). A function may declare one or more distinct generic parameters, such as `combine<T, U>(_ a: T, _ b: U) -> T`. The following forms are not supported and produce build-time diagnostics:
41
+
42
+
-`async` generic functions.
43
+
- Generic methods inside `@JSClass` types or static members (generics are top-level only).
44
+
-`where` clauses on a generic declaration.
45
+
- A declared generic parameter that is not used in any parameter.
46
+
- An exported generic function that returns a concrete, non-`Void` type. The result of an exported generic function must be one of the declared generic parameters or `Void`.
47
+
48
+
The generic parameter may be used bare (`T`) or wrapped in `[T]`, `T?`, or `[String: T]`. Nested or other wrappings, such as `[T?]`, `[[T]]`, `T??`, or `[Int: T]`, are not supported and produce build-time diagnostics. `JSObject` cannot be used as the generic argument (it is a non-final class); use `JSValue` instead.
49
+
50
+
Exported generic functions additionally require runtime existential support, so they are not available under Embedded Swift. Imported generics remain available there.
0 commit comments