Skip to content

Commit b5fe11b

Browse files
committed
BridgeJS: Exercise generic imports under Embedded Swift
1 parent ca567cf commit b5fe11b

5 files changed

Lines changed: 34 additions & 3 deletions

File tree

Examples/Embedded/Package.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ let package = Package(
1616
swiftSettings: [
1717
.enableExperimentalFeature("Extern")
1818
],
19+
plugins: [
20+
.plugin(name: "BridgeJS", package: "JavaScriptKit")
21+
]
1922
)
2023
],
2124
swiftLanguageModes: [.v5]

Examples/Embedded/Sources/EmbeddedApp/main.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
import JavaScriptKit
22

3+
// BridgeJS generic imports work under Embedded Swift: `echoValue` is
4+
// implemented in JavaScript (see index.html) and a single piece of generated
5+
// glue serves every conforming type, selected by a runtime type ID.
6+
@JS struct CounterLabel {
7+
var count: Int
8+
var text: String
9+
}
10+
11+
@JSFunction func echoValue<T: BridgedSwiftGenericBridgeable>(_ value: T) throws(JSException) -> T
12+
313
let alert = JSObject.global.alert.object!
414
let document = JSObject.global.document
515

@@ -46,6 +56,17 @@ _ = encoderContainer.appendChild(textInputElement)
4656
_ = encoderContainer.appendChild(encodeResultElement)
4757
_ = document.body.appendChild(encoderContainer)
4858

59+
let genericResultElement = document.createElement("pre")
60+
do {
61+
let number = try echoValue(42)
62+
let text = try echoValue("hello")
63+
let label = try echoValue(CounterLabel(count: number, text: text))
64+
genericResultElement.innerText = .string("Generic import round-trip: \(label.text) \(label.count)")
65+
} catch {
66+
genericResultElement.innerText = "Generic import round-trip failed"
67+
}
68+
_ = document.body.appendChild(genericResultElement)
69+
4970
func print(_ message: String) {
5071
_ = JSObject.global.console.log(message)
5172
}

Examples/Embedded/index.html

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,14 @@
88
<body>
99
<script type="module">
1010
import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js";
11-
init();
11+
init({
12+
getImports() {
13+
return {
14+
// Implements the generic `echoValue` imported by main.swift.
15+
echoValue: (value) => value,
16+
};
17+
},
18+
});
1219
</script>
1320
</body>
1421

Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Internals/Design-Rationale.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ BridgeJS avoids this by generating **separate** access paths per property or met
3434

3535
## Generic imports
3636

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.
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. Because this path avoids existentials entirely, it also works under Embedded Swift; the Embedded example (`Examples/Embedded`) exercises a generic import, including a `@JS struct` round-trip.
3838

3939
## Generic exports
4040

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,4 @@ The generic parameter may be used bare (`T`) or wrapped in `[T]`, `T?`, or `[Str
4949

5050
The generic argument must be a primitive or a type defined in the same module as the generic function. Using a `@JS` type from another module as the generic argument is not supported yet: at an imported `@JSFunction` call site this surfaces as a Swift conformance error, and an exported `@JS` function traps at runtime when passed such a type's token.
5151

52-
Exported generic functions additionally require runtime existential support, so they are not available under Embedded Swift. Imported generics remain available there.
52+
Exported generic functions additionally require runtime existential support, so they are not available under Embedded Swift. Imported generics remain available there and are exercised by the Embedded example (`Examples/Embedded`).

0 commit comments

Comments
 (0)