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
{{ message }}
Repository navigation
Commit 4680860
Browse filesBrowse the repository at this point in the historyBrowse files
BridgeJS: Recognize cross-module extension conformances to @js protocols
A module may declare that a @js type exported by one of its dependencies
conforms to a @js protocol it defines:
// ModuleB, depending on ModuleA
@js protocol GraphNode { var id: String { get } }
extension Building: GraphNode {} // Building is ModuleA's @js struct
@js public func store<T: BridgedSwiftGenericBridgeable & GraphNode>(_ n: T) -> T { n }
The Swift compiler sees the retroactive conformance directly, so the
generic thunk already accepted ModuleA's type — but the JS-side token
check did not: the conformance was declared in ModuleB's sources while
the token belongs to ModuleA, and neither skeleton recorded it, so a
valid call threw a spurious TypeError.
Extension conformances whose target does not resolve in-module are now
resolved against the external module index and recorded in the skeleton
(externalJSProtocolConformances, keyed by the conformer's token). The
link layer sees every module's skeleton, merges those records into the
defining module's token entry, and the refinement closure applies on
top. The conformance audit likewise treats an extension on a
dependency's @js class as bridgeable instead of flagging it.
Copy file name to clipboardExpand all lines: Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Function.md
+17Lines changed: 17 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -297,6 +297,23 @@ export type Exports = {
297
297
298
298
TypeScript checks the constraint at compile time, but `BridgeType` tokens are erased at runtime, so the generated JavaScript wrapper enforces it again when the call crosses the bridge: the token's type is validated against the required protocols and a non-conforming token throws a catchable `TypeError` *before* the call enters WebAssembly, e.g. `BridgeJS:type'Int'doesnotconformtorequiredprotocol'GraphNode'`. Because nothing has been lowered yet, the shared value stack stays balanced and later calls are unaffected. (The Swift entry thunk repeats the check with a conditional metatype cast as defense-in-depth, but through the generated wrapper that trap is unreachable.)
299
299
300
+
Conformances count no matter how they are declared: on the type itself, in an extension in the same module, or in an extension on a `@JS` type exported by a dependency module (a retroactive conformance). Protocol refinement is honored too — a conformer of `@JSprotocolRefined:Base` satisfies a constraint on `Base`, exactly as it does in Swift (see <doc:Exporting-Swift-Protocols>):
301
+
302
+
```swift
303
+
@JSprotocolSite:GraphNode { // Site refines GraphNode
304
+
var region:String { get }
305
+
}
306
+
307
+
@JSstructCampus: Site { // conforms to Site, and therefore GraphNode
Generics also work on methods. On a `@JS` class or struct they apply to both instance and static methods. A `@JS enum` (including a namespace-style enum) has no instance methods in BridgeJS, so generics there apply to static methods only. The constraint, the trailing `BridgeType` token, and the generic-or-`Void` return rule all carry over unchanged.
0 commit comments