SwiftWasm Blog

Published on

What's new in SwiftWasm #5

Happy New Year everyone! Here's a digest of what happened with SwiftWasm in December of 2020, published with a slight delay (it's 2021 already after all 😅).

SwiftWasm community

One thing we forgot to mention in our November update is that the SwiftWasm community now has its own Discord server. In case you prefer Slack to Discord, we recommend you to join the #webassembly channel in the SwiftPM Slack workspace.

In December we saw a lot of projects built with SwiftWasm shared by the community. Here a few most noteworthy:

Good first issues

Ever wanted to contribute to SwiftWasm projects, but unsure where to start? Here's a list of issues that could be suitable for beginners:

Documentation

SwiftWasm book

We're working on tracking down all the possible edge cases when porting code from other platforms in the SwiftWasm book. Previously we were asked how to port code that depends on the Darwin module on Apple platforms or Glibc on Linux. We recommend using the WASILibc module, which obviously somewhat differs from libc on other platforms. We've added a corresponding note clarifying this to the book.

Toolchain

As the Swift team already announced the release process for the 5.4 version, we started preparing our corresponding SwiftWasm 5.4 release. The swiftwasm-release/5.4 branch in our fork now tracks the upstream release/5.4 branch, as we plan to tag our own 5.4.0 later this year.

Additionally, we made sure that the fork of our toolchain can be compiled on Apple Silicon Macs. While GitHub Actions doesn't provide CI agents for the M1 architecture, the SwiftWasm toolchain can be built locally for Apple Silicon, and we hope to provide a prebuilt distribution archive for it in some future release.

Experimental async/await support

@kateinoigakukun enabled experimental concurrency support in SwiftWasm and fixed several issues that previously prevented us from enabling async/await in development snapshots. Currently, starting with swift-wasm-DEVELOPMENT-SNAPSHOT-2021-01-02-a, the toolchain only supports a single-threaded task executor. This executor is suitable for usage in standalone WASI hosts such as Wasmer or Wasmtime. Unfortunately, it blocks the JavaScript event loop until all jobs are completed, and is unable to run any jobs created after the first event loop cycle. While this makes it unsuitable for JavaScript environments, we were able to work around that in JavaScriptKit as discussed in the next section.

Libraries

JavaScriptKit

@kateinoigakukun started implementing a Swift concurrency task executor integrated with the JavaScript event loop. There are still several issues, but it's working well as a proof of concept. This experimental API allows us to utilize async/await in SwiftWasm apps for browsers and Node.js like this:

import JavaScriptEventLoop
import JavaScriptKit

JavaScriptEventLoop.install()
let fetch = JSObject.global.fetch.function!.async

func printZen() async {
  let result = try! await fetch("https://api.github.com/zen").object!
  let text = try! await result.asyncing.text!()
  print(text)
}

JavaScriptEventLoop.runAsync {
  await printZen()
}

WebAssembly Micro Runtime

@kateinoigakukun published a Swift WebAssembly runtime package powered by the WebAssembly Micro Runtime project (WAMR). This allows us to remove Wasmer dependency from carton and embed the WebAssembly runtime in the carton binary for use in commands such as carton test.

We were also able to test this package on Apple Silicon and submit a PR upstream to make it work.

DOMKit

Our long-term goal is to make DOMKit the recommended library for type-safe interactions with Web APIs in SwiftWasm. While it's still at an early stage, we've updated it to JavaScriptKit 0.9 and added support for globalThis. In a separate PR we've cleaned up unused code and fixed an event handlers crash.

Tokamak

With enough changes to warrant a new release, we've published Tokamak 0.6.0, which introduced support for the Image view loading images bundled as SwiftPM resources, implemented by @j-f1. It also adds the PreferenceKey protocol and related modifiers. developed by @carson-katri.

Since then we've also added the PreviewProvider protocol, an implementation of TextEditor, and updated our example code in README.md for script injection. Additionally, a contribution from David Hunt added missing typealiases to TokamakDOM that should improve compatibility with SwiftUI, while Jed Fox removed redundant path element from SVG output.

Developer tools

carton

We'd like to welcome @thecb4, who is the latest addition to the carton maintainers team! Thanks to his work, project targets were restructured for better testability, and now test, dev, and bundle commands are covered with end-to-end tests.

There's ongoing work to integrate the WAMR package mentioned above with the carton test command. Also, carton now correctly handles system target dependencies in Package.swift.

On top of that, stack traces from Chrome and Safari are now supported in carton dev with proper symbol demangling, thanks to the work by @j-f1. Additionally, @yonihemi submitted a PR which integrates carton with libSwiftPM allowing us to reuse its model types.

Most of these changes were included in 0.9.0 and 0.9.1 releases published in December.

webidl2swift

webidl2swift is the foundation on which our DOMKit framework is built. Web API across all browsers is specified in the Web IDL format, which can then be parsed to generate type-safe bindings in Swift. The parser doesn't support all IDL files out there yet, but we've updated dependencies and updated the code generator to certain JavaScriptKit types that previously were deprecated.

WasmTransformer

There were a few changes to the WasmTransformer package, which we use in carton and intend to use in a few other dev tools. Specifically, we've generalized section info parsing across different transformers, implemented a basic section size profiler, and made the TypeSection type public to make it easier to analyze sections of WebAssembly binaries.

Gravity

We're excited to announce our new developer tool enabled by WasmTransformer. Gravity is a binary code size profiler for WebAssembly built with WasmTransformer, SwiftUI, and TCA. It's an application for macOS that allows you to open a WebAssembly binary and view the size of different sections. Contents of some of the sections is also parsed for further analysis.

Contributions

A lot of our progress with SwiftWasm wouldn't be possible without payments from our GitHub Sponsors. Their contribution is deeply appreciated and allows us to spend more time on SwiftWasm projects. You can see the list of sponsors and make your contribution on our SwiftWasm organization sponsorship page, or personal sponsorship pages of Carson Katri, Yuta Saito and Max Desiatov.

Thanks for reading! 👋