Skip to content

Commit 07ab30d

Browse files
Removed @JS protocol support and migrated guidance/tests to @JSClass interfaces.
- `Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift` now rejects `@JS protocol` with a clear diagnostic pointing to `@JSClass struct`; updated `ImportTS.swift` messaging accordingly. - Dropped protocol fixtures/snapshots (`Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Protocol.swift` and related snapshots); README/type-modeling notes now steer interface modeling toward `@JSClass` (`Plugins/BridgeJS/README.md`). - Rewrote the DocC article to document `@JSClass` interface usage and migration steps (`Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Protocols.md`). - Removed protocol-based runtime APIs/tests, refreshed JS harness, and regenerated bridge outputs to align (`Tests/BridgeJSRuntimeTests/ExportAPITests.swift`, `Tests/prelude.mjs`, `Tests/BridgeJSRuntimeTests/Generated/*`). Tests run: - `swift test --package-path Plugins/BridgeJS`
1 parent b0bf4a3 commit 07ab30d

File tree

11 files changed

+2010
-6806
lines changed

11 files changed

+2010
-6806
lines changed

Plugins/BridgeJS/README.md

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ graph LR
8989
| `@JS enum` (case) | const object + tag type | Copy (integer) ||
9090
| `@JS enum` (raw value) | const object + tag type | Copy (raw value) ||
9191
| `@JS enum` (associated) | discriminated union | Copy (fields via stacks) ||
92-
| `@JS protocol` | `interface` | Reference (wrapper) ||
9392
| `Optional<T>` | `T \| null` | Depends on T ||
9493
| `(T) -> U` | `(arg: T) => U` | Reference (boxed) ||
9594
| `JSObject` | `any` / `object` | Reference ||
@@ -111,19 +110,7 @@ graph LR
111110
## Type Modeling
112111

113112
TypeScript uses [structural subtyping](https://www.typescriptlang.org/docs/handbook/type-compatibility.html), but Swift doesn't directly offer it. We can't map every TypeScript type to Swift, so we made several give-ups and heuristics.
114-
115-
### `interface`
116-
117-
We intentionally don't simulate TS's `interface` with Swift's `protocol` even though they are quite similar for the following reasons:
118-
119-
* Adding a protocol conformance for each `interface` implementation adds binary size cost in debug build because it's not easy to DCE.
120-
* No straightforward way to represent the use of `interface` type on the return type position of TS function. Which concrete type it should it be?
121-
* For Embedded Swift, we should avoid use of existential type as much as possible.
122-
123-
Instead of simulating the subtyping-rule with Swift's `protocol`, we represent each `interface` with Swift's struct.
124-
In this way, we lose implicit type coercion but it makes things simpler and clear.
125-
126-
TBD: Consider providing type-conversion methods to simulate subtyping rule like `func asIface()`
113+
Use `@JSClass` structs to model JavaScript interfaces that you want to consume from Swift.
127114

128115
### Anonymous type literals
129116

Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ extension BridgeType {
884884
throw BridgeJSCoreError(
885885
"""
886886
swiftHeapObject '\(className)' is not supported in TypeScript imports.
887-
Swift classes can only be used in @JS protocols where Swift owns the instance.
887+
Pass Swift instances through exported @JS classes or structs instead.
888888
"""
889889
)
890890
case .exportSwift:

Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift

Lines changed: 4 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,59 +1422,14 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
14221422
}
14231423

14241424
override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind {
1425-
guard let jsAttribute = node.attributes.firstJSAttribute else {
1426-
return .skipChildren
1427-
}
1428-
1429-
let name = node.name.text
1430-
1431-
let namespaceResult = resolveNamespace(from: jsAttribute, for: node, declarationType: "protocol")
1432-
guard namespaceResult.isValid else {
1425+
guard node.attributes.firstJSAttribute != nil else {
14331426
return .skipChildren
14341427
}
1435-
_ = computeExplicitAtLeastInternalAccessControl(
1436-
for: node,
1437-
message: "Protocol visibility must be at least internal"
1438-
)
1439-
1440-
let protocolUniqueKey = makeKey(name: name, namespace: namespaceResult.namespace)
1441-
1442-
exportedProtocolByName[protocolUniqueKey] = ExportedProtocol(
1443-
name: name,
1444-
methods: [],
1445-
properties: [],
1446-
namespace: namespaceResult.namespace
1447-
)
1448-
1449-
stateStack.push(state: .protocolBody(name: name, key: protocolUniqueKey))
1450-
1451-
var methods: [ExportedFunction] = []
1452-
for member in node.memberBlock.members {
1453-
if let funcDecl = member.decl.as(FunctionDeclSyntax.self) {
1454-
if let exportedFunction = visitProtocolMethod(
1455-
node: funcDecl,
1456-
protocolName: name,
1457-
namespace: namespaceResult.namespace
1458-
) {
1459-
methods.append(exportedFunction)
1460-
}
1461-
} else if let varDecl = member.decl.as(VariableDeclSyntax.self) {
1462-
_ = visitProtocolProperty(node: varDecl, protocolName: name, protocolKey: protocolUniqueKey)
1463-
}
1464-
}
14651428

1466-
let exportedProtocol = ExportedProtocol(
1467-
name: name,
1468-
methods: methods,
1469-
properties: exportedProtocolByName[protocolUniqueKey]?.properties ?? [],
1470-
namespace: namespaceResult.namespace
1429+
diagnose(
1430+
node: node,
1431+
message: "@JS protocol has been removed. Use @JSClass struct to model JavaScript interfaces."
14711432
)
1472-
1473-
exportedProtocolByName[protocolUniqueKey] = exportedProtocol
1474-
exportedProtocolNames.append(protocolUniqueKey)
1475-
1476-
stateStack.pop()
1477-
14781433
return .skipChildren
14791434
}
14801435

Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Protocol.swift

Lines changed: 0 additions & 116 deletions
This file was deleted.

0 commit comments

Comments
 (0)