Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This directory contains performance benchmarks for JavaScriptKit.
Before running the benchmarks, you need to build the test suite:

```bash
JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk $SWIFT_SDK_ID js -c release
swift package --swift-sdk $SWIFT_SDK_ID js -c release
```

## Running Benchmarks
Expand Down
2 changes: 1 addition & 1 deletion Benchmarks/Sources/Generated/BridgeJS.Macros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// To update this file, just rebuild your project or run
// `swift package bridge-js`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func benchmarkHelperNoop() throws(JSException) -> Void

Expand Down
2 changes: 1 addition & 1 deletion Examples/ExportSwift/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This example demonstrates how to export Swift functions to JavaScript.

1. Build the project:
```sh
env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk $SWIFT_SDK_ID js --use-cdn
swift package --swift-sdk $SWIFT_SDK_ID js --use-cdn
```

2. Serve the files:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// To update this file, just rebuild your project or run
// `swift package bridge-js`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func createTS2Swift() throws(JSException) -> TS2Swift

Expand Down
2 changes: 1 addition & 1 deletion Examples/PlayBridgeJS/build.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
set -euxo pipefail
env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1}}" \
swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1}}" \
plugin --allow-writing-to-package-directory \
js --use-cdn --output ./Bundle -c "${1:-debug}"
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ unittest:
echo "SWIFT_SDK_ID is not set. Run 'swift sdk list' and pass a matching SDK, e.g. 'make unittest SWIFT_SDK_ID=<id>'."; \
exit 2; \
}
env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk "$(SWIFT_SDK_ID)" \
swift package --swift-sdk "$(SWIFT_SDK_ID)" \
$(TRACING_ARGS) \
--disable-sandbox \
js test --prelude ./Tests/prelude.mjs -Xnode --expose-gc
Expand Down
10 changes: 5 additions & 5 deletions Plugins/BridgeJS/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# BridgeJS

> [!IMPORTANT]
> This feature is still experimental, and the API may change frequently. Use at your own risk with `JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1` environment variable.
> This feature is still experimental, and the API may change frequently. Use at your own risk.

> [!NOTE]
> This documentation is intended for JavaScriptKit developers, not JavaScriptKit users. For user documentation, see [Exporting Swift to JavaScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-to-javascript) and [Importing TypeScript into Swift](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/importing-typescript-into-swift).
> This documentation is intended for JavaScriptKit developers, not JavaScriptKit users. For user documentation, see [Introducing BridgeJS](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/introducing-bridgejs), [Setting up BridgeJS](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/setting-up-bridgejs), [Exporting Swift to JavaScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-to-javascript), [Importing JavaScript into Swift](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/importing-javascript-into-swift), and [Generating bindings from TypeScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/generating-from-typescript).

## Overview

BridgeJS provides easy interoperability between Swift and JavaScript/TypeScript. It enables:

1. **Importing TypeScript APIs into Swift**: Use TypeScript/JavaScript APIs directly from Swift code
2. **Exporting Swift APIs to JavaScript**: Make your Swift APIs available to JavaScript code
1. **Export Swift to JavaScript** – Expose Swift functions, classes, and types to JavaScript; the plugin generates TypeScript definitions (`.d.ts`) for the exported API.
2. **Import JavaScript into Swift** – Make JavaScript/TypeScript APIs callable from Swift with macro-annotated bindings or bindings generated from a TypeScript declaration file (`bridge-js.d.ts`).

The workflow is:

Expand Down Expand Up @@ -161,7 +161,7 @@ Return values use direct Wasm returns for primitives, and imported intrinsic fun
- **Structs/Arrays/Enums**: Copy semantics - data serialized across boundary. No cleanup needed.
- **Closures**: Boxed on source side, released when GC'd on either side.

For detailed semantics, see the [How It Works sections](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-class#How-It-Works) in the user documentation.
For detailed semantics, see the [How It Works sections](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-class#how-it-works) in the user documentation.

## Testing

Expand Down
2 changes: 1 addition & 1 deletion Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export function run(filePath, options) {
"// To update this file, just rebuild your project or run",
"// `swift package bridge-js`.",
"",
"@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit",
"@_spi(BridgeJS) import JavaScriptKit",
"",
"",
].join("\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ exports[`ts2swift > snapshots Swift output for ArrayParameter.d.ts > ArrayParame
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func processNumbers(_ values: [Double]) throws(JSException) -> Void

Expand All @@ -30,7 +30,7 @@ exports[`ts2swift > snapshots Swift output for Async.d.ts > Async 1`] = `
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func asyncReturnVoid() throws(JSException) -> JSPromise

Expand All @@ -55,7 +55,7 @@ exports[`ts2swift > snapshots Swift output for Documentation.d.ts > Documentatio
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

/// Return a greeting for a user.
///
Expand Down Expand Up @@ -112,7 +112,7 @@ exports[`ts2swift > snapshots Swift output for Interface.d.ts > Interface 1`] =
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func returnAnimatable() throws(JSException) -> Animatable

Expand All @@ -130,7 +130,7 @@ exports[`ts2swift > snapshots Swift output for InvalidPropertyNames.d.ts > Inval
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func createArrayBuffer() throws(JSException) -> ArrayBufferLike

Expand Down Expand Up @@ -178,7 +178,7 @@ exports[`ts2swift > snapshots Swift output for MultipleImportedTypes.d.ts > Mult
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func createDatabaseConnection(_ config: JSValue) throws(JSException) -> DatabaseConnection

Expand Down Expand Up @@ -215,7 +215,7 @@ exports[`ts2swift > snapshots Swift output for ObjectLikeTypes.d.ts > ObjectLike
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func acceptObject(_ v: JSObject) throws(JSException) -> Void
"
Expand All @@ -228,7 +228,7 @@ exports[`ts2swift > snapshots Swift output for OptionalNullUndefined.d.ts > Opti
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func roundTripNumberNull(_ value: Optional<Double>) throws(JSException) -> Optional<Double>

Expand Down Expand Up @@ -269,7 +269,7 @@ exports[`ts2swift > snapshots Swift output for PrimitiveParameters.d.ts > Primit
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func check(_ a: Double, _ b: Bool) throws(JSException) -> Void
"
Expand All @@ -282,7 +282,7 @@ exports[`ts2swift > snapshots Swift output for PrimitiveReturn.d.ts > PrimitiveR
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func checkNumber() throws(JSException) -> Double

Expand All @@ -297,7 +297,7 @@ exports[`ts2swift > snapshots Swift output for ReExportFrom.d.ts > ReExportFrom
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func jsRoundTripNumber(_ v: Double) throws(JSException) -> Double

Expand All @@ -315,7 +315,7 @@ exports[`ts2swift > snapshots Swift output for RecordDictionary.d.ts > RecordDic
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func takeRecord(_ value: [String: Double]) throws(JSException) -> Void

Expand Down Expand Up @@ -345,7 +345,7 @@ exports[`ts2swift > snapshots Swift output for StringEnum.d.ts > StringEnum 1`]
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

enum FeatureFlag: String {
case foo = "foo"
Expand All @@ -366,7 +366,7 @@ exports[`ts2swift > snapshots Swift output for StringParameter.d.ts > StringPara
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func checkString(_ a: String) throws(JSException) -> Void

Expand All @@ -381,7 +381,7 @@ exports[`ts2swift > snapshots Swift output for StringReturn.d.ts > StringReturn
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func checkString() throws(JSException) -> String
"
Expand All @@ -394,7 +394,7 @@ exports[`ts2swift > snapshots Swift output for TS2SkeletonLike.d.ts > TS2Skeleto
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func createTS2Skeleton() throws(JSException) -> TypeScriptProcessor

Expand All @@ -420,7 +420,7 @@ exports[`ts2swift > snapshots Swift output for TypeAlias.d.ts > TypeAlias 1`] =
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func checkSimple(_ a: Double) throws(JSException) -> Void
"
Expand All @@ -433,7 +433,7 @@ exports[`ts2swift > snapshots Swift output for TypeAliasObject.d.ts > TypeAliasO
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func console() throws(JSException) -> Console

Expand All @@ -452,7 +452,7 @@ exports[`ts2swift > snapshots Swift output for TypeScriptClass.d.ts > TypeScript
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSClass struct Greeter {
@JSGetter var name: String
Expand All @@ -473,7 +473,7 @@ exports[`ts2swift > snapshots Swift output for VoidParameterVoidReturn.d.ts > Vo
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

@JSFunction func check() throws(JSException) -> Void
"
Expand All @@ -486,7 +486,7 @@ exports[`ts2swift > snapshots Swift output for WebIDLDOMDocs.d.ts > WebIDLDOMDoc
// To update this file, just rebuild your project or run
// \`swift package bridge-js\`.

@_spi(Experimental) @_spi(BridgeJS) import JavaScriptKit
@_spi(BridgeJS) import JavaScriptKit

/// [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document)
@JSGetter var document: Document
Expand Down
5 changes: 0 additions & 5 deletions Plugins/PackageToJS/Sources/PackageToJS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -589,11 +589,6 @@ struct PackagingPlanner {
packageInputs.append(packageJsonTask)

if skeletons.count > 0 {
if ProcessInfo.processInfo.environment["JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS"] == nil {
fatalError(
"BridgeJS is still an experimental feature. Set the environment variable JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 to enable."
)
}
let bridgeJs = outputDir.appending(path: "bridge-js.js")
let bridgeDts = outputDir.appending(path: "bridge-js.d.ts")
packageInputs.append(
Expand Down
44 changes: 24 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ _ = document.body.appendChild(button)

BridgeJS provides easy interoperability between Swift and JavaScript/TypeScript. It enables:

- **Exporting Swift APIs to JavaScript**: Make your Swift code callable from JavaScript
- **Importing TypeScript APIs into Swift**: Use JavaScript APIs with type safety in Swift
- **Export Swift to JavaScript** – Expose Swift functions, classes, and types to JavaScript; the plugin also generates TypeScript definitions (`.d.ts`) for the exported API.
- **Import JavaScript into Swift** – Make JavaScript/TypeScript APIs (functions, classes, globals like `document` or `console`) callable from Swift with type-safe bindings. You can declare bindings with macros in Swift or generate them from a TypeScript declaration file (`bridge-js.d.ts`).

For architecture details, see the [BridgeJS Plugin README](Plugins/BridgeJS/README.md).
For architecture details, see the [BridgeJS Plugin README](Plugins/BridgeJS/README.md). For package and build setup, see [Setting up BridgeJS](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/setting-up-bridgejs) in the documentation.

### Exporting Swift to JavaScript

Mark Swift code with `@JS` to make it callable from JavaScript:
Mark Swift code with `@JS` (the ``JS(namespace:enumStyle:)`` attribute) to make it callable from JavaScript:

```swift
import JavaScriptKit
Expand All @@ -81,32 +81,36 @@ console.log(greeter.greet()); // "Hello, World!"

**Learn more:** [Exporting Swift to JavaScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/exporting-swift-to-javascript)

### Importing TypeScript into Swift
### Importing JavaScript into Swift

Define TypeScript interfaces and BridgeJS generates type-safe Swift bindings:
Declare bindings in Swift with macros such as `@JSFunction`, `@JSClass`, `@JSGetter`, and `@JSSetter`:

```typescript
// bridge-js.d.ts
interface Document {
title: string;
getElementById(id: string): HTMLElement;
createElement(tagName: string): HTMLElement;
```swift
import JavaScriptKit

@JSClass struct Document {
@JSFunction func getElementById(_ id: String) throws(JSException) -> HTMLElement
@JSFunction func createElement(_ tagName: String) throws(JSException) -> HTMLElement
}
@JSGetter(from: .global) var document: Document

export function getDocument(): Document;
```
@JSClass struct HTMLElement {
@JSGetter var innerText: String
@JSSetter func setInnerText(_ newValue: String) throws(JSException)
@JSFunction func appendChild(_ child: HTMLElement) throws(JSException)
}

**Swift usage:**
```swift
@JS func run() throws(JSException) {
let document = try getDocument()
try document.setTitle("My Swift App")
let button = try document.createElement("button")
let button = document.createElement("button")!
try button.setInnerText("Click Me")
let container = document.getElementById("app")!
container.appendChild(button)
}
```

**Learn more:** [Importing TypeScript into Swift](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/importing-typescript-into-swift)
You can also generate the same macro-annotated Swift from a TypeScript file (`bridge-js.d.ts`). See [Generating bindings from TypeScript](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/generating-from-typescript) in the documentation.

**Learn more:** [Importing JavaScript into Swift](https://swiftpackageindex.com/swiftwasm/JavaScriptKit/documentation/javascriptkit/importing-javascript-into-swift)

### Try It Online

Expand Down
Loading