Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork57
Swift framework to interact with JavaScript through WebAssembly.
License
swiftwasm/JavaScriptKit
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Swift framework to interact with JavaScript through WebAssembly.
This JavaScript code
constalert=window.alert;constdocument=window.document;constdivElement=document.createElement("div");divElement.innerText="Hello, world";constbody=document.body;body.appendChild(divElement);constpet={age:3,owner:{name:"Mike",},};alert("JavaScript is running on browser!");
Can be written in Swift using JavaScriptKit
import JavaScriptKitletdocument=JSObject.global.documentvardivElement= document.createElement("div")divElement.innerText="Hello, world"_= document.body.appendChild(divElement)structOwner:Codable{letname:String}structPet:Codable{letage:Intletowner:Owner}letjsPet=JSObject.global.petletswiftPet:Pet=tryJSValueDecoder().decode(from: jsPet)_=JSObject.global.alert!("Swift is running in the browser!")
Starting with SwiftWasm 5.5 you can useasync/await withJSPromise objects. This requiresa few additional steps though (you can skip these steps if your app depends onTokamak):
- Make sure that your target depends on
JavaScriptEventLoopin yourPackages.swift:
.target( name:"JavaScriptKitExample", dependencies:["JavaScriptKit",.product(name:"JavaScriptEventLoop",package:"JavaScriptKit"),])
- Add an explicit import in the code that executes *before you start using
awaitand/orTaskAPIs (most likely inmain.swift):
import JavaScriptEventLoop- Run this function *before you start using
awaitand/orTaskAPIs (again, most likely inmain.swift):
JavaScriptEventLoop.installGlobalExecutor()
Then you canawait on thevalue property ofJSPromise instances, like in the example below:
import JavaScriptKitimport JavaScriptEventLoopletalert=JSObject.global.alert.function!letdocument=JSObject.global.documentprivateletjsFetch=JSObject.global.fetch.function!func fetch(_ url:String)->JSPromise{JSPromise(jsFetch(url).object!)!}JavaScriptEventLoop.installGlobalExecutor()structResponse:Decodable{letuuid:String}varasyncButtonElement= document.createElement("button")asyncButtonElement.innerText="Fetch UUID demo"asyncButtonElement.onclick=.object(JSClosure{ _inTask{do{letresponse=tryawaitfetch("https://httpbin.org/uuid").valueletjson=tryawaitJSPromise(response.json().object!)!.valueletparsedResponse=tryJSValueDecoder().decode(Response.self, from: json)alert(parsedResponse.uuid)}catch{print(error)}}return.undefined})_= document.body.appendChild(asyncButtonElement)
If you need to execute Swift async functions that can be resumed by JS event loop in your XCTest suites, please addJavaScriptEventLoopTestSupport to your test target dependencies.
.testTarget( name: "MyAppTests", dependencies: [ "MyApp",+ "JavaScriptEventLoopTestSupport", ] )Linking this module automatically activates JS event loop based global executor by callingJavaScriptEventLoop.installGlobalExecutor()
- macOS 11 and Xcode 13.2 or later versions, which support Swift Concurrency back-deployment.To use earlier versions of Xcode on macOS 11 you'll have toadd
.unsafeFlags(["-Xfrontend", "-disable-availability-checking"])inPackage.swiftmanifest ofyour package that depends on JavaScriptKit. You can also use Xcode 13.0 and 13.1 on macOS Monterey,since this OS does not need back-deployment. - Swift 5.5 or later and Ubuntu 18.04 if you'd like to use Linux.Other Linux distributions are currently not supported.
Any recent browser thatsupports WebAssembly and requiredJavaScript features should work, which currently includes:
- Edge 84+
- Firefox 79+
- Chrome 84+
- Desktop Safari 14.1+
- Mobile Safari 14.8+
If you need to support older browser versions, you'll have to build withtheJAVASCRIPTKIT_WITHOUT_WEAKREFS flag, passing-Xswiftc -DJAVASCRIPTKIT_WITHOUT_WEAKREFS flagswhen compiling. This should lower browser requirements to these versions:
- Edge 16+
- Firefox 61+
- Chrome 66+
- (Mobile) Safari 12+
Not all of these versions are tested on regular basis though, compatibility reports are very welcome!
The easiest way to get started with JavaScriptKit in your browser app is withthecartonbundler. Add carton to your swift package dependencies:
dependencies: [+ .package(url: "https://github.com/swiftwasm/carton", from: "1.0.0"),],Now you can activate the package dependency through swift:
swift run carton devIf you have multiple products in your package, you can also used the product flag:
swift run carton dev --product MyAppWarning
- If you already use
cartonbefore 0.x.x versions via Homebrew, you can remove it withbrew uninstall cartonand install the new version as a SwiftPM dependency. - Also please remove the old
.builddirectory before using the newcarton
Legacy Installation
As a part of these stepsyou'll installcarton viaHomebrew on macOS (you can also use theghcr.io/swiftwasm/cartonDocker image if you prefer to run the build steps on Linux). Assuming you already have Homebrewinstalled, you can create a new app that uses JavaScriptKit by following these steps:
- Install
carton:
brew install swiftwasm/tap/cartonIf you hadcarton installed before this, make sure you have version 0.6.1 or greater:
carton --version- Create a directory for your project and make it current:
mkdir SwiftWasmApp && cd SwiftWasmApp- Initialize the project from a template with
carton:
carton init --template basic- Build the project and start the development server,
carton devcan be kept runningduring development:
carton devOpenhttp://127.0.0.1:8080/ in your browser and a developer consolewithin it. You'll seeHello, world! output in the console. You can edit the app source code inyour favorite editor and save it,carton will immediately rebuild the app and reload allbrowser tabs that have the app open.
You can also build your project with webpack.js and a manually installed SwiftWasm toolchain. Pleasesee the following sections and theExampledirectory for more information in this more advanced use case.
This library only supportsswiftwasm/swift toolchain distribution.The toolchain can be installed viaswiftenv, inthe same way as the official Swift nightly toolchain.
You have to install the toolchain manually when working on the source code of JavaScriptKit itself,especially if you change anything in the JavaScript runtime parts. This is because the runtime parts areembedded incarton and currently can't be replaced dynamically with the JavaScript code you'veupdated locally.
Just pass a toolchain archive URL forthe latest SwiftWasm 5.6release appropriate for your platform:
$ swiftenv install"https://github.com/swiftwasm/swift/releases/download/swift-wasm-5.6.0-RELEASE/swift-wasm-5.6.0-RELEASE-macos_$(uname -m).pkg"You can also use theinstall-toolchain.sh helper script that uses a hardcoded toolchain snapshot:
$ ./scripts/install-toolchain.sh$ swift --versionSwift version 5.6 (swiftlang-5.6.0)Target: arm64-apple-darwin20.6.0
Become a gold or platinum sponsor and contact maintainers to add your logo on our README on Github with a link to your site.

About
Swift framework to interact with JavaScript through WebAssembly.
Topics
Resources
License
Code of conduct
Contributing
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.