Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8a1007e

Browse files
Merge pull request #330 from swiftwasm/yt/import-export
Introduce BridgeJS, a declarative JS interop system
2 parents f40912a + 9752c5a commit 8a1007e

File tree

131 files changed

+7046
-103
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+7046
-103
lines changed

‎.github/workflows/test.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ jobs:
5757
make regenerate_swiftpm_resources
5858
git diff --exit-code Sources/JavaScriptKit/Runtime
5959
- run: swift test --package-path ./Plugins/PackageToJS
60+
- run: swift test --package-path ./Plugins/BridgeJS
6061

6162
native-build:
6263
# Check native build to make it easy to develop applications by Xcode

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ xcuserdata/
1010
Examples/*/Bundle
1111
Examples/*/package-lock.json
1212
Package.resolved
13+
Plugins/BridgeJS/Sources/JavaScript/package-lock.json

‎Examples/ExportSwift/Package.swift‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// swift-tools-version:6.0
2+
3+
import PackageDescription
4+
5+
let package = Package(
6+
name: "MyApp",
7+
platforms: [
8+
.macOS(.v14)
9+
],
10+
dependencies: [.package(name: "JavaScriptKit", path: "../../")],
11+
targets: [
12+
.executableTarget(
13+
name: "MyApp",
14+
dependencies: [
15+
"JavaScriptKit"
16+
],
17+
swiftSettings: [
18+
.enableExperimentalFeature("Extern")
19+
],
20+
plugins: [
21+
.plugin(name: "BridgeJS", package: "JavaScriptKit")
22+
]
23+
)
24+
]
25+
)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import JavaScriptKit
2+
3+
// Mark functions you want to export to JavaScript with the @JS attribute
4+
// This function will be available as `renderCircleSVG(size)` in JavaScript
5+
@JS public func renderCircleSVG(size: Int) -> String {
6+
let strokeWidth = 3
7+
let strokeColor = "black"
8+
let fillColor = "red"
9+
let cx = size / 2
10+
let cy = size / 2
11+
let r = (size / 2) - strokeWidth
12+
var svg = "<svg width=\"\(size)px\" height=\"\(size)px\">"
13+
svg +=
14+
"<circle cx=\"\(cx)\" cy=\"\(cy)\" r=\"\(r)\" stroke=\"\(strokeColor)\" stroke-width=\"\(strokeWidth)\" fill=\"\(fillColor)\" />"
15+
svg += "</svg>"
16+
return svg
17+
}
18+
19+
// Classes can also be exported using the @JS attribute
20+
// This class will be available as a constructor in JavaScript: new Greeter("name")
21+
@JS class Greeter {
22+
var name: String
23+
24+
// Use @JS for initializers you want to expose
25+
@JS init(name: String) {
26+
self.name = name
27+
}
28+
29+
// Methods need the @JS attribute to be accessible from JavaScript
30+
// This method will be available as greeter.greet() in JavaScript
31+
@JS public func greet() -> String {
32+
"Hello, \(name)!"
33+
}
34+
}

‎Examples/ExportSwift/index.html‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<title>Getting Started</title>
6+
</head>
7+
8+
<body>
9+
<script type="module" src="index.js"></script>
10+
</body>
11+
12+
</html>

‎Examples/ExportSwift/index.js‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js";
2+
const { exports } = await init({});
3+
4+
const Greeter = exports.Greeter;
5+
const greeter = new Greeter("World");
6+
const circle = exports.renderCircleSVG(100);
7+
8+
// Display the results
9+
const textOutput = document.createElement("div");
10+
textOutput.innerText = greeter.greet()
11+
document.body.appendChild(textOutput);
12+
const circleOutput = document.createElement("div");
13+
circleOutput.innerHTML = circle;
14+
document.body.appendChild(circleOutput);

‎Examples/ImportTS/Package.swift‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// swift-tools-version:6.0
2+
3+
import PackageDescription
4+
5+
let package = Package(
6+
name: "MyApp",
7+
platforms: [
8+
.macOS(.v10_15),
9+
.iOS(.v13),
10+
.tvOS(.v13),
11+
.watchOS(.v6),
12+
.macCatalyst(.v13),
13+
],
14+
dependencies: [.package(name: "JavaScriptKit", path: "../../")],
15+
targets: [
16+
.executableTarget(
17+
name: "MyApp",
18+
dependencies: [
19+
"JavaScriptKit"
20+
],
21+
swiftSettings: [
22+
.enableExperimentalFeature("Extern")
23+
],
24+
plugins: [
25+
.plugin(name: "BridgeJS", package: "JavaScriptKit")
26+
]
27+
)
28+
]
29+
)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Function definition to expose console.log to Swift
2+
// Will be imported as a Swift function: consoleLog(message: String)
3+
export function consoleLog(message: string): void
4+
5+
// TypeScript interface types are converted to Swift structs
6+
// This defines a subset of the browser's HTMLElement interface
7+
type HTMLElement = Pick<globalThis.HTMLElement, "innerText"> & {
8+
// Methods with object parameters are properly handled
9+
appendChild(child: HTMLElement): void
10+
}
11+
12+
// TypeScript object type with read-only properties
13+
// Properties will become Swift properties with appropriate access level
14+
type Document = {
15+
// Regular property - will be read/write in Swift
16+
title: string
17+
// Read-only property - will be read-only in Swift
18+
readonly body: HTMLElement
19+
// Method returning an object - will become a Swift method returning an HTMLElement
20+
createElement(tagName: string): HTMLElement
21+
}
22+
// Function returning a complex object
23+
// Will be imported as a Swift function: getDocument() -> Document
24+
export function getDocument(): Document

‎Examples/ImportTS/Sources/main.swift‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import JavaScriptKit
2+
3+
// This function is automatically generated by the @JS plugin
4+
// It demonstrates how to use TypeScript functions and types imported from bridge.d.ts
5+
@JS public func run() {
6+
// Call the imported consoleLog function defined in bridge.d.ts
7+
consoleLog("Hello, World!")
8+
9+
// Get the document object - this comes from the imported getDocument() function
10+
let document = getDocument()
11+
12+
// Access and modify properties - the title property is read/write
13+
document.title = "Hello, World!"
14+
15+
// Access read-only properties - body is defined as readonly in TypeScript
16+
let body = document.body
17+
18+
// Create a new element using the document.createElement method
19+
let h1 = document.createElement("h1")
20+
21+
// Set properties on the created element
22+
h1.innerText = "Hello, World!"
23+
24+
// Call methods on objects - appendChild is defined in the HTMLElement interface
25+
body.appendChild(h1)
26+
}

‎Examples/ImportTS/index.html‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<title>Getting Started</title>
6+
</head>
7+
8+
<body>
9+
<script type="module" src="index.js"></script>
10+
11+
<div id="exports-result"></div>
12+
<div id="imports-result"></div>
13+
<pre id="code"></pre>
14+
</body>
15+
16+
</html>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /