{"id":13461776,"url":"https://github.com/swiftwasm/JavaScriptKit","last_synced_at":"2025-03-24T22:34:56.623Z","repository":{"id":38383613,"uuid":"244832006","full_name":"swiftwasm/JavaScriptKit","owner":"swiftwasm","description":"Swift framework to interact with JavaScript through WebAssembly.","archived":false,"fork":false,"pushed_at":"2024-05-08T13:20:52.000Z","size":3587,"stargazers_count":617,"open_issues_count":13,"forks_count":42,"subscribers_count":15,"default_branch":"main","last_synced_at":"2024-05-13T15:08:04.819Z","etag":null,"topics":["javascript","swift","swiftwasm","webassembly"],"latest_commit_sha":null,"homepage":"https://swiftpackageindex.com/swiftwasm/JavaScriptKit/main/documentation/javascriptkit","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/swiftwasm.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["swiftwasm"],"patreon":null,"open_collective":"swiftwasm","ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2020-03-04T07:10:29.000Z","updated_at":"2024-06-05T17:40:25.141Z","dependencies_parsed_at":"2024-05-13T15:18:08.223Z","dependency_job_id":null,"html_url":"https://github.com/swiftwasm/JavaScriptKit","commit_stats":{"total_commits":369,"total_committers":16,"mean_commits":23.0625,"dds":0.4363143631436315,"last_synced_commit":"384d6686939a0ab7103b00ab942b3a3edc7f46e3"},"previous_names":["kateinoigakukun/javascriptkit"],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftwasm%2FJavaScriptKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftwasm%2FJavaScriptKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftwasm%2FJavaScriptKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftwasm%2FJavaScriptKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/swiftwasm","download_url":"https://codeload.github.com/swiftwasm/JavaScriptKit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245366204,"owners_count":20603438,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","swift","swiftwasm","webassembly"],"created_at":"2024-07-31T11:00:57.313Z","updated_at":"2025-03-24T22:34:51.611Z","avatar_url":"https://github.com/swiftwasm.png","language":"Swift","readme":"# JavaScriptKit\n\n![Run unit tests](https://github.com/swiftwasm/JavaScriptKit/workflows/Run%20unit%20tests/badge.svg?branch=main)\n\nSwift framework to interact with JavaScript through WebAssembly.\n\n## Getting started\n\nThis JavaScript code\n\n```javascript\nconst alert = window.alert;\nconst document = window.document;\n\nconst divElement = document.createElement(\"div\");\ndivElement.innerText = \"Hello, world\";\nconst body = document.body;\nbody.appendChild(divElement);\n\nconst pet = {\n  age: 3,\n  owner: {\n    name: \"Mike\",\n  },\n};\n\nalert(\"JavaScript is running on browser!\");\n```\n\nCan be written in Swift using JavaScriptKit\n\n```swift\nimport JavaScriptKit\n\nlet document = JSObject.global.document\n\nvar divElement = document.createElement(\"div\")\ndivElement.innerText = \"Hello, world\"\n_ = document.body.appendChild(divElement)\n\nstruct Owner: Codable {\n  let name: String\n}\n\nstruct Pet: Codable {\n  let age: Int\n  let owner: Owner\n}\n\nlet jsPet = JSObject.global.pet\nlet swiftPet: Pet = try JSValueDecoder().decode(from: jsPet)\n\n_ = JSObject.global.alert!(\"Swift is running in the browser!\")\n```\n\n### `async`/`await`\n\nStarting with SwiftWasm 5.5 you can use `async`/`await` with `JSPromise` objects. This requires\na few additional steps though (you can skip these steps if your app depends on\n[Tokamak](https://tokamak.dev)):\n\n1. Make sure that your target depends on `JavaScriptEventLoop` in your `Packages.swift`:\n\n```swift\n.target(\n    name: \"JavaScriptKitExample\",\n    dependencies: [\n        \"JavaScriptKit\",\n        .product(name: \"JavaScriptEventLoop\", package: \"JavaScriptKit\"),\n    ]\n)\n```\n\n2. Add an explicit import in the code that executes **before* you start using `await` and/or `Task`\nAPIs (most likely in `main.swift`):\n\n```swift\nimport JavaScriptEventLoop\n```\n\n3. Run this function **before* you start using `await` and/or `Task` APIs (again, most likely in\n`main.swift`):\n\n```swift\nJavaScriptEventLoop.installGlobalExecutor()\n```\n\nThen you can `await` on the `value` property of `JSPromise` instances, like in the example below:\n\n```swift\nimport JavaScriptKit\nimport JavaScriptEventLoop\n\nlet alert = JSObject.global.alert.function!\nlet document = JSObject.global.document\n\nprivate let jsFetch = JSObject.global.fetch.function!\nfunc fetch(_ url: String) -\u003e JSPromise {\n    JSPromise(jsFetch(url).object!)!\n}\n\nJavaScriptEventLoop.installGlobalExecutor()\n\nstruct Response: Decodable {\n    let uuid: String\n}\n\nvar asyncButtonElement = document.createElement(\"button\")\nasyncButtonElement.innerText = \"Fetch UUID demo\"\nasyncButtonElement.onclick = .object(JSClosure { _ in\n    Task {\n        do {\n            let response = try await fetch(\"https://httpbin.org/uuid\").value\n            let json = try await JSPromise(response.json().object!)!.value\n            let parsedResponse = try JSValueDecoder().decode(Response.self, from: json)\n            alert(parsedResponse.uuid)\n        } catch {\n            print(error)\n        }\n    }\n\n    return .undefined\n})\n\n_ = document.body.appendChild(asyncButtonElement)\n```\n\n### `JavaScriptEventLoop` activation in XCTest suites\n\nIf you need to execute Swift async functions that can be resumed by JS event loop in your XCTest suites, please add `JavaScriptEventLoopTestSupport` to your test target dependencies.\n\n```diff\n .testTarget(\n   name: \"MyAppTests\",\n   dependencies: [\n     \"MyApp\",\n+    \"JavaScriptEventLoopTestSupport\",\n   ]\n )\n```\n\nLinking this module automatically activates JS event loop based global executor by calling `JavaScriptEventLoop.installGlobalExecutor()`\n\n\n## Requirements \n\n### For developers\n\n- macOS 11 and Xcode 13.2 or later versions, which support Swift Concurrency back-deployment. \nTo use earlier versions of Xcode on macOS 11 you'll have to \nadd `.unsafeFlags([\"-Xfrontend\", \"-disable-availability-checking\"])` in `Package.swift` manifest of\nyour package that depends on JavaScriptKit. You can also use Xcode 13.0 and 13.1 on macOS Monterey,\nsince this OS does not need back-deployment.\n- [Swift 5.5 or later](https://swift.org/download/) and Ubuntu 18.04 if you'd like to use Linux.\n  Other Linux distributions are currently not supported.\n\n### For users of apps depending on JavaScriptKit\n\nAny recent browser that [supports WebAssembly](https://caniuse.com/#feat=wasm) and required \nJavaScript features should work, which currently includes:\n\n- Edge 84+\n- Firefox 79+\n- Chrome 84+\n- Desktop Safari 14.1+\n- Mobile Safari 14.8+\n\nIf you need to support older browser versions, you'll have to build with\nthe `JAVASCRIPTKIT_WITHOUT_WEAKREFS` flag, passing `-Xswiftc -DJAVASCRIPTKIT_WITHOUT_WEAKREFS` flags\nwhen compiling. This should lower browser requirements to these versions:\n\n- Edge 16+\n- Firefox 61+\n- Chrome 66+\n- (Mobile) Safari 12+\n\nNot all of these versions are tested on regular basis though, compatibility reports are very welcome!\n\n## Usage in a browser application\n\nThe easiest way to get started with JavaScriptKit in your browser app is with [the `carton`\nbundler](https://carton.dev). Add carton to your swift package dependencies:\n\n```diff\ndependencies: [\n+    .package(url: \"https://github.com/swiftwasm/carton\", from: \"1.0.0\"),\n],\n```\n\nNow you can activate the package dependency through swift:\n\n```\nswift run carton dev\n```\n\nIf you have multiple products in your package, you can also used the product flag:\n\n```\nswift run carton dev --product MyApp\n```\n\n\u003e [!WARNING]\n\u003e - If you already use `carton` before 0.x.x versions via Homebrew, you can remove it with `brew uninstall carton` and install the new version as a SwiftPM dependency.\n\u003e - Also please remove the old `.build` directory before using the new `carton`\n\n\u003cdetails\u003e\u003csummary\u003eLegacy Installation\u003c/summary\u003e\n\n---\n\nAs a part of these steps\nyou'll install `carton` via [Homebrew](https://brew.sh/) on macOS (you can also use the\n[`ghcr.io/swiftwasm/carton`](https://github.com/orgs/swiftwasm/packages/container/package/carton)\nDocker image if you prefer to run the build steps on Linux). Assuming you already have Homebrew\ninstalled, you can create a new app that uses JavaScriptKit by following these steps:\n\n1. Install `carton`:\n\n```\nbrew install swiftwasm/tap/carton\n```\n\nIf you had `carton` installed before this, make sure you have version 0.6.1 or greater:\n\n```\ncarton --version\n```\n\n2. Create a directory for your project and make it current:\n\n```\nmkdir SwiftWasmApp \u0026\u0026 cd SwiftWasmApp\n```\n\n3. Initialize the project from a template with `carton`:\n\n```\ncarton init --template basic\n```\n\n4. Build the project and start the development server, `carton dev` can be kept running\n   during development:\n\n```\ncarton dev\n```\n\n---\n\n\u003c/details\u003e\n\nOpen [http://127.0.0.1:8080/](http://127.0.0.1:8080/) in your browser and a developer console\nwithin it. You'll see `Hello, world!` output in the console. You can edit the app source code in\nyour favorite editor and save it, `carton` will immediately rebuild the app and reload all\nbrowser tabs that have the app open.\n\nYou can also build your project with webpack.js and a manually installed SwiftWasm toolchain. Please\nsee the following sections and the [Example](https://github.com/swiftwasm/JavaScriptKit/tree/main/Example)\ndirectory for more information in this more advanced use case.\n\n## Manual toolchain installation\n\nThis library only supports [`swiftwasm/swift`](https://github.com/swiftwasm/swift) toolchain distribution.\nThe toolchain can be installed via [`swiftenv`](https://github.com/kylef/swiftenv), in\nthe same way as the official Swift nightly toolchain.\n\nYou have to install the toolchain manually when working on the source code of JavaScriptKit itself,\nespecially if you change anything in the JavaScript runtime parts. This is because the runtime parts are\nembedded in `carton` and currently can't be replaced dynamically with the JavaScript code you've\nupdated locally.\n\nJust pass a toolchain archive URL for [the latest SwiftWasm 5.6\nrelease](https://github.com/swiftwasm/swift/releases/tag/swift-wasm-5.6.0-RELEASE) appropriate for your platform:\n\n```sh\n$ 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\"\n```\n\nYou can also use the `install-toolchain.sh` helper script that uses a hardcoded toolchain snapshot:\n\n```sh\n$ ./scripts/install-toolchain.sh\n$ swift --version\nSwift version 5.6 (swiftlang-5.6.0)\nTarget: arm64-apple-darwin20.6.0\n```\n\n## Sponsoring\n\n[Become a gold or platinum sponsor](https://github.com/sponsors/swiftwasm/) and contact maintainers to add your logo on our README on Github with a link to your site.\n\n\n\u003ca href=\"https://www.emergetools.com/\"\u003e\n  \u003cimg src=\"https://github.com/swiftwasm/swift/raw/swiftwasm-distribution/assets/sponsors/emergetools.png\" width=\"30%\"\u003e\n\u003c/a\u003e\n","funding_links":["https://github.com/sponsors/swiftwasm","https://opencollective.com/swiftwasm","https://github.com/sponsors/swiftwasm/"],"categories":["Swift"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswiftwasm%2FJavaScriptKit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswiftwasm%2FJavaScriptKit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswiftwasm%2FJavaScriptKit/lists"}