# How far can i get with Swift WebAssembly in 30 minutes?

**URL:** <https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305>\
**Category:** Swift for WebAssembly\
**Created:** [January 20, 2025, 1:41am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305 "2025-01-20T01:41:30Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [January 20, 2025, 1:41am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/1 "2025-01-20T01:41:31Z")

</div>

i’m posting this because i am Completely New to Swift WebAssembly, and i’ve wanted to learn it for a while now, so i figured i would give myself 30 minutes to see how far i could get with Swift WebAssembly and document what i saw along the way in the hopes it might illuminate ways to improve the “onboarding” process even more.

* * *

## 😁 i’m gonna google `swift webassembly`

so i start by googling 'swift webassembly', and i write this down because a lot of times the _helpful_ Swift documentation does not show up on the first, or third page of Google search results. but luckily, this does not happen here. the very first result is [swiftwasm.org](http://swiftwasm.org)!

 ![Firefox_Screenshot_2025-01-19T23-55-53.980Z](https://global.discourse-cdn.com/swift/original/3X/5/3/53a5b7e48a6ec836d7689cd9ea5148a0887b8f51.png)

the website is really pretty. i like this a lot. A+ to whoever came up with this design.

 ![Firefox_Screenshot_2025-01-20T00-35-50.874Z](https://global.discourse-cdn.com/swift/original/3X/f/4/f4d4fb305e11fe2b54731bfc656c88b45cfc9cca.png)

## 😁 does the fiddle work?

this website has a fiddle on the home page, which is great, and even better, _the fiddle works_ when i click **Run**. marvelous!

 ![Firefox_Screenshot_2025-01-19T23-58-18.412Z](https://global.discourse-cdn.com/swift/original/3X/7/0/70c41d8f0a7b20d6cc6f326f0adbd7663a565d66.png)

## 😰 how to get started…

the next thing i did was click the [how to get started](https://book.swiftwasm.org/getting-started/browser-app.html) link above the fiddle, which takes me to the middle of this TSPL-like documentation website.

it tells me that i need to use something called the “Tokamak UI framework”, which is similar to SwiftUI, apparently.

in the next paragraph it tells me i can’t start using Tokamak UI either, first i have to start using another framework called “carton” before i can start using Tokamak UI, and that it will be Very Very Painful to use Swift WebAssembly without this framework.

 ![Firefox_Screenshot_2025-01-19T23-59-57.489Z](https://global.discourse-cdn.com/swift/original/3X/2/2/22fab7cd8d43b6730d12064331014e11705d4767.png)

i suppose whoever wrote this is correct. i will Eventually Have To start using Tokamak UI and `carton`, because this is how real swiftwasm apps are built. but i do not want to build a Real Application yet, i just want to get to hello world.

luckily, when i Look To My Left, i see that the link dropped me off in some intermediate chapter called **Creating a browser app** , and that there is an earlier chapter called **Hello, World** so i just jump over to that.

 ![Firefox_Screenshot_2025-01-20T00-00-52.655Z](https://global.discourse-cdn.com/swift/original/3X/5/0/506b75d3376f8bb479a1803cd2dd6f586d872dee.png)

## 🧐 hello world!

okay, so this is what i was actually looking for.

 ![Firefox_Screenshot_2025-01-20T00-02-11.126Z](https://global.discourse-cdn.com/swift/original/3X/e/0/e056c6708e7cf9882cff310c6bad76a2a662df0e.png)

now, i’m not playing dumb, and i can see that there is a preceeding chapter called **Installation** , which suggests i would need to install something to make this work. but for the sake of science, i want to know what happens when i run these commands with the Swift toolchain i already have.

```plaintext
$ swiftc -target wasm32-unknown-wasi hello.swift -o hello.wasm
error: missing external dependency '/home/ubuntu/x86_64/6.0.3/usr/lib/swift/wasi/static-executable-args.lnk'

```

okay, nothing surprising here. it needs some SDK and i have not installed it.

## 💀 is this thing still maintained?

so i go to the **Installation** page, and it tells me to install SwiftWasm 5.10, which is based on the `swift-5.10.0-RELEASE` toolchain.

this is not the `swift-6.0.3-RELEASE` toolchain we are using today, and it’s not even the `swift-5.10.1-RELEASE` patch release that came out after the original 5.10 release.

i have seen this movie many times before, so my first thought is: _is this project still maintained?_

 ![Firefox_Screenshot_2025-01-20T00-04-39.640Z](https://global.discourse-cdn.com/swift/original/3X/c/5/c55ddcafa1c87a822b664e1f7f6f83ae3fd3e3ad.png)

 ![Firefox_Screenshot_2025-01-20T00-05-49.320Z](https://global.discourse-cdn.com/swift/original/3X/9/3/9395c14002bd5c5977998d2965639cff2f129ae8.png)

but when i go to the actual GitHub repository, i see that the project is indeed actively maintained, and they have nightlies tracking Swift 6.1.

 ![Firefox_Screenshot_2025-01-20T00-06-33.581Z](https://global.discourse-cdn.com/swift/original/3X/8/e/8eb855f0241918b4d036a3cfb54b669b46106638.png)

i click through a few more links and find the 6.0.2 release, which is not the 6.0.3 release, but that’s Close Enough for me.

 ![Firefox_Screenshot_2025-01-20T00-07-23.891Z](https://global.discourse-cdn.com/swift/original/3X/4/e/4e5f00d72484fb63a0cdf6983159ef4dda537f2f.png)  
 ![Firefox_Screenshot_2025-01-20T00-08-23.177Z](https://global.discourse-cdn.com/swift/original/3X/7/e/7e63d67fea2dab31831f4cd6d54fb0ee41be6a36.png)

now i took a lot of screenshots to document the path i took, but truth be told, i did not have a hard time locating the latest swiftwasm release. the only point where they really could have potentially lost me was when reading the original anachronistic installation guide, which made me think the project was no longer active.

## 😁 installing the sdk

i run the command that’s shown next to the release card, and it works! great!

```bash
$ swift sdk install https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.0.2-RELEASE/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip --checksum 6ffedb055cb9956395d9f435d03d53ebe9f6a8d45106b979d1b7f53358e1dcb4
Downloading a Swift SDK bundle archive from `https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.0.2-RELEASE/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip`...
                                                                                               Downloading
100% [=====================================================================================================================================================================================]
Downloading swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip

Swift SDK bundle archive successfully downloaded from `https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.0.2-RELEASE/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip`.
Verifying if checksum of the downloaded archive is valid...
Downloaded archive has a valid checksum.
Swift SDK bundle at `https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.0.2-RELEASE/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip` is assumed to be an archive, unpacking...
Swift SDK bundle at `https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.0.2-RELEASE/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip` successfully installed as swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.
$ swift sdk list
6.0.2-RELEASE-wasm32-unknown-wasi

```

## 🤔 using the sdk

i re-ran the command from the Hello World tutorial, to see if it works this time. it doesn’t.

```bash
$ swiftc -target wasm32-unknown-wasi hello.swift -o hello.wasm
error: missing external dependency '/home/ubuntu/x86_64/6.0.3/usr/lib/swift/wasi/static-executable-args.lnk'

```

i also tried fuzzing the arguments for a few seconds, unsuccessfully.

```bash
$ swiftc --swift-sdk wasm32-unknown-wasi -target wasm32-unknown-wasi hello.swift -o hello.wasm
error: unknown argument: '--swift-sdk'
$ swiftc -swift-sdk wasm32-unknown-wasi -target wasm32-unknown-wasi hello.swift -o hello.wasm
error: unknown argument: '-swift-sdk'
$ swiftc -sdk wasm32-unknown-wasi -target wasm32-unknown-wasi hello.swift -o hello.wasm
warning: no such SDK: wasm32-unknown-wasi
error: missing external dependency '/home/ubuntu/x86_64/6.0.3/usr/lib/swift/wasi/static-executable-args.lnk'
$ swiftc -sdk 6.0.2-RELEASE-wasm32-unknown-wasi -target wasm32-unknown-wasi hello.swift -o hello.wasm
warning: no such SDK: 6.0.2-RELEASE-wasm32-unknown-wasi
error: missing external dependency '/home/ubuntu/x86_64/6.0.3/usr/lib/swift/wasi/static-executable-args.lnk'

```

luckily, i already knew that Swift SDKs are related to SwiftPM, so i didn’t waste too much time trying to get `swiftc` to work. (but not everyone knows that? maybe? who knows…)

i noticed there were example commands for how to build things with the SDK and SwiftPM, and i am Not Allergic to SwiftPM, so i then spent a minute or two creating a rudimentary SwiftPM layout with my Hello World program in a SwiftPM executable target.

 ![Firefox_Screenshot_2025-01-20T00-12-05.612Z](https://global.discourse-cdn.com/swift/original/3X/1/6/160754081aebab13eb933025c31fa5e9a18536fc.png)

 ![Firefox_Screenshot_2025-01-20T00-15-51.189Z](https://global.discourse-cdn.com/swift/original/3X/5/0/502991e7bd3e59d6792f52c2e889149bed23f571.png)

## 🥳 using SwiftPM

like many build systems, SwiftPM has a funny tendency to say that it failed when it actually successfully built an executable, and swiftwasm is no exception. it Just Works, even though at first glance, it looks like it didn’t.

```bash
$ swift build --swift-sdk wasm32-unknown-wasi 
Building for debugging...
warning: Could not read SDKSettings.json for SDK at: /home/ubuntu/.swiftpm/swift-sdks/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle/6.0.2-RELEASE-wasm32-unknown-wasi/wasm32-unknown-wasi/WASI.sdk
<unknown>:0: warning: libc not found for 'wasm32-unknown-wasi'; C stdlib may be unavailable

Build complete! (2.05s)
$ swift build -c release --swift-sdk wasm32-unknown-wasi 
Building for production...
warning: Could not read SDKSettings.json for SDK at: /home/ubuntu/.swiftpm/swift-sdks/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle/6.0.2-RELEASE-wasm32-unknown-wasi/wasm32-unknown-wasi/WASI.sdk
warning: Could not read SDKSettings.json for SDK at: /home/ubuntu/.swiftpm/swift-sdks/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle/6.0.2-RELEASE-wasm32-unknown-wasi/wasm32-unknown-wasi/WASI.sdk
[5/5] Linking test.wasm
Build complete! (0.90s)

```

```bash
$ ls .build/release
ModuleCache description.json swift-version--75355AAB4E86B17C.txt test.build test.product test.wasm

```

## 😔 running the binary

i’m probably not going to get to Firefox in 30 minutes, but i at least want to try running this thing using `wasmtime`.

so i go to [docs.wasmtime.dev](https://docs.wasmtime.dev/cli-install.html) and run the command they tell me to run, and it doesn’t work.

```bash
$ curl https://wasmtime.dev/install.sh -sSf | bash
  Installing latest version of Wasmtime (v28.0.1)
    Checking for existing Wasmtime installation
    Fetching archive for Linux, version v28.0.1
https://github.com/bytecodealliance/wasmtime/releases/download/v28.0.1/wasmtime-v28.0.1-x86_64-linux.tar.xz 
######################################################################## 100.0%
    Creating directory layout
  Extracting Wasmtime binaries
tar (child): xz: Cannot exec: No such file or directory
tar (child): Error is not recoverable: exiting now
tar: Child returned status 2
tar: Error is not recoverable: exiting now
cp: cannot stat '/tmp/tmp.vcHYenQBsa/wasmtime-v28.0.1-x86_64-linux/wasmtime': No such file or directory
cp: cannot stat '/tmp/tmp.vcHYenQBsa/wasmtime-v28.0.1-x86_64-linux/LICENSE': No such file or directory
cp: cannot stat '/tmp/tmp.vcHYenQBsa/wasmtime-v28.0.1-x86_64-linux/README.md': No such file or directory

```

i do a little debugging and i realize this is because GitHub uses an HTTP redirect (presumably to protect itself from scrapers), and the `curl` command is missing an `-L` option.

```bash
$ curl https://github.com/bytecodealliance/wasmtime/releases/download/v28.0.1/wasmtime-v28.0.1-x86_64-linux.tar.xz -o wasmtime-v28.0.1-x86_64-linux.tar.xz
  % Total % Received % Xferd Average Speed Time Time Time Current
                                 Dload Upload Total Spent Left Speed
  0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
$ ls
Package.swift Sources wasmtime-v28.0.1-x86_64-linux.tar.xz
$ ls -l
total 8
-rw-r--r-- 1 ubuntu ubuntu 274 Jan 20 00:19 Package.swift
drwxr-xr-x 3 ubuntu ubuntu 4096 Jan 20 00:16 Sources
-rw-r--r-- 1 ubuntu ubuntu 0 Jan 20 00:23 wasmtime-v28.0.1-x86_64-linux.tar.xz

```

```swift
$ curl -L https://github.com/bytecodealliance/wasmtime/releases/download/v28.0.1/wasmtime-v28.0.1-x86_64-linux.tar.xz -o wasmtime-v28.0.1-x86_64-linux.tar.xz
  % Total % Received % Xferd Average Speed Time Time Time Current
                                 Dload Upload Total Spent Left Speed
  0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
  0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 8605k 100 8605k 0 0 14.4M 0 --:--:-- --:--:-- --:--:-- 14.4M

```

i peer into the `install.sh` script, and i confirm that it is indeed missing an `-L` option, but then again i did not write this script, and i only spent a few seconds looking at it, so who knows.

EDIT: or not! it does actually have a `--location` option, which is long for `-L`. the mystery deepens.

```bash
download_release_from_repo() {
  local version="$1"
  local arch="$2"
  local os_info="$3"
  local tmpdir="$4"
  local postfix=$(release_file_postfix $os_info)
  local filename="wasmtime-$version-$arch-$os_info.$postfix"
  local download_file="$tmpdir/$filename"
  local archive_url="$(release_url)/download/$version/$filename"
  info $archive_url

  curl --progress-bar --show-error --location --fail "$archive_url" \
       --output "$download_file" && echo "$download_file"
}

```

i manage to get a hold of the `wasmtime` binary, and i use it to execute the binary i built with SwiftPM. it works! **beautiful!**

```bash
$ wasmtime-v28.0.1-x86_64-linux/wasmtime .build/release/test.wasm 
Hi Barbie!

```

## conclusion

overall, i would say i had a **very positive** experience in my first 30 minutes of Swift WebAssembly. the bad parts were… Poor/Stale Documentation (shocker), and a very bumpy path to installing the wasm runtime. but the second problem isn’t really _Swift_ WebAssembly’s responsibility, it’s just WebAssembly’s responsibility. and the first problem isn’t any defect in the underlying technology, we just need to update those docs, and maybe change a couple links to point to the beginning of the tutorial, instead of a chapter in the middle of the book.

hopefully i have time later to actually run stuff in a browser and explore this Tokamak UI thing.

great job to everyone who worked on Swift WebAssembly! this was truly a refreshing experience 😃

---

<div class="post-metadata">

**Author:** ![austintatious](https://avatars.discourse-cdn.com/v4/letter/a/ce73a5/32.png) [@austintatious](https://forums.swift.org/u/austintatious)\
**Post date:** [January 20, 2025, 3:22am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/2 "2025-01-20T03:22:15Z")

</div>

You're right. A lot of that needs to be re-written. Even I go to it and get confused about what does and doesn't work.

I don't use Tokamak at all. It didn't really exist when I started building my own UI framework, but also I hate SwiftUI. I wonder if better documentation would make me choose otherwise.

I have never gotten SwiftWASM to run properly on a mac. (I also give up too early, tbf) so I build on Ubuntu. I did learn that I need to make a new Ubuntu instance before using a new version of SwiftWASM because sometimes it just doesn't work for various reasons I can never explain. But I think that has happened significantly less than it did a few years ago.

Using carton has improved a lot. I really enjoy all the new debugging features they have added. When they switched over to carton being a plugin, it did confuse me a lot (again a documentation problem).

For context, I use SwiftWAM for a real-life production app running in a real website that is required for customers to login.

I ended up building an entirely proprietary Framework that is extremely similar to UIKit and actually vends UIKit on iOS and HTMLElements on Web (It also vends GTK on Linux, but I've abandoned progress on it, because I couldn't get a lot of GTK to work properly. I actually started to work on bridging it to GNUStep so I could get an interface on Linux going, it was just a lot.) It manages creates nearly identical user interfaces (and highly complex) on both iOS and Web. I am still in shock every day how wonderfully it works. I went so far as to build a layout system for this UI framework that works almost identically to HTML/CSS layout rules instead of trying to get constraint based layout or SwiftUI style layout working on Web.

I ended up having to re-write a lot of Foundation/XML/Networking to work on WASM (I have my own versions of URLRequest, URLSession, XMLParser, NSAttributedString, et cetera on SwiftWASM), but it was all well worth it.

The app is an interface to some proprietary software that runs a business, billing, contracts, online curriculum building. It includes a desktop-class publishing tools as well. And it's all a front-end to a server also written in Swift.

I have found SwiftWASM to be the most important piece of technology, and I desperately fear it going away or being abandoned.

---

<div class="post-metadata">

**Author:** ![kateinoigakukun](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kateinoigakukun/32/16706_2.png) [@kateinoigakukun](https://forums.swift.org/u/kateinoigakukun)\
**Post date:** [January 20, 2025, 6:28am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/3 "2025-01-20T06:28:11Z")

</div>

Hello all,

Thank you for the feedback regarding the documentation. I apologize that it was outdated and confusing.

While the SwiftWasm project itself is actively maintained including feature additions (such as recent [multi-threading support](https://github.com/swiftwasm/JavaScriptKit/tree/main/Examples/Multithreading) and [code coverage support](https://github.com/llvm/llvm-project/pull/111332)), I admit that I haven't been able to dedicate enough time to keeping the guides up-to-date.

I expect to have more time to work on this project starting around mid-February but contributions, including a documentation overhaul, are always welcome!

I'm thrilled to hear that you're using SwiftWasm in a real-life production app, and it's very encouraging to know that it's working well for you.

---

<div class="post-metadata">

**Author:** ![svanimpe](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/svanimpe/32/38963_2.png) [@svanimpe](https://forums.swift.org/u/svanimpe)\
**Post date:** [January 20, 2025, 7:00am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/4 "2025-01-20T07:00:39Z")

</div>

@taylorswift: Last year I built a set of example projects to guide people through SwiftWasm step-by-step. They may save you some time, as they should address most of the common pitfalls. I also gave a talk about them:

- Examples: [GitHub - pwsacademy/swiftwasm-examples: Examples of Swift for WebAssembly](https://github.com/pwsacademy/swiftwasm-examples)
- Conference talks: [2024: A Year In Conferences | PWS Academy](https://www.pwsacademy.org/posts/swiftwasm-conferences.html)

---

<div class="post-metadata">

**Author:** ![Finagolfin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/finagolfin/32/34388_2.png) [@Finagolfin](https://forums.swift.org/u/Finagolfin)\
**Post date:** [January 20, 2025, 9:29am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/5 "2025-01-20T09:29:39Z")

</div>

You'll probably want to add a SDKSettings.json to your wasm SDK, [just like the static Musl SDK does](https://github.com/swiftlang/swift-docker/blob/d2dffef049187e662b5a8e0bed549bca7ebacc8c/swift-ci/sdks/static-linux/scripts/build.sh#L299) and which [my Android SDK bundle followed](https://github.com/finagolfin/swift-android-sdk/blob/2c349c5bb91feb87359fc85ee8ca4e0908c80241/.github/workflows/sdks.yml#L257). That'll stop those warnings that @taylorswift reported above from getting spit out.

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [January 21, 2025, 2:31am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/6 "2025-01-21T02:31:25Z")

</div>

thanks everyone for the tips!

## 💣 running carton

i tried tonight to follow @svanimpe ’s [example](https://github.com/pwsacademy/swiftwasm-examples/blob/main/basics/README.md), trying to use `carton` to run a minimal example, and very quickly ran into the sobering reality which is that `carton` does not support my operating system, Ubuntu 24.04.

```bash
$ swift run carton dev --custom-index-page Web/index.html

```

```plaintext
Building for debugging...
[1/1] Write swift-version--75355AAB4E86B17C.txt
Build of product 'carton' complete! (0.54s)
- checking Swift compiler path: /home/ubuntu/.carton/sdk/wasm-6.0.2-RELEASE/usr/bin/swift
- checking Swift compiler path: /home/ubuntu/.swiftenv/versions/wasm-6.0.2-RELEASE/usr/bin/swift
Fetching release assets from https://api.github.com/repos/swiftwasm/swift/releases/tags/swift-wasm-6.0.2-RELEASE
Response contained body, parsing it now...
Swift/ErrorType.swift:253: Fatal error: Error raised at top level: This version of the operating system is not supported

💣 Program crashed: Illegal instruction at 0x00007c1401ee299f

Thread 4 crashed:

0 0x00007c1401ee299f _assertionFailure(_:_:file:line:flags:) + 351 in libswiftCore.so
1 0x00007c1401f32e1e swift_errorInMain + 829 in libswiftCore.so
2 async_MainTY2_ + 41 in carton at /swift/wasm-test/.build/checkouts/carton/Sources/carton/main.swift:35:11

    33│ import CartonDriver
    34│ 
    35│ try await main(arguments: CommandLine.arguments)                                                                                                                                                                            
      │ ▲
    36│

Backtrace took 0.03s

Press space to interact, D to debug, or any other key to quit (23s) 

```

Swift makes this look a lot worse than really is, because it insists on backtracing the crash it exits with whenever it catches an error thrown from `main`. this is actually a controlled exit thrown from here:

> <https://github.com/swiftwasm/carton/blob/1.1.3/Sources/SwiftToolchain/ToolchainManagement.swift#L240-L251>

Swift on WebAssembly [does not actually distribute](https://github.com/swiftwasm/swift/releases/tag/swift-wasm-6.0.2-RELEASE) binaries for Ubuntu 24.04. but surely we have seen that Swift on WebAssembly is capable of running on Ubuntu 24.04. so i modified the code to acquire the `ubuntu22.04` binary on Ubuntu 24.04, which assumes that libc on Ubuntu 24.04 is compatible with libc on Ubuntu 22.04.

[https://github.com/swiftwasm/carton/compare/main...tayloraswift:carton:main#diff-5b71ec4e1662c7c01397497dd3264abd271a59c705c6ae5a0e97bbddaabe84d6R256-R257](https://github.com/swiftwasm/carton/compare/main...tayloraswift:carton:main#diff-5b71ec4e1662c7c01397497dd3264abd271a59c705c6ae5a0e97bbddaabe84d6R256-R257)

```swift
          case "24.04":
            return "ubuntu22.04"

```

this worked, and i was able to use this modified carton to run the `carton dev` command.

## 🚦 on localhost

the `carton dev` command complains effusively about `Sendable` violations. it takes everything Swift Concurrency thinks is wrong about Carton, and `swift-nio/Sources/NIOCore/ChannelPipeline.swift` and prints it to the console. SwiftPM prints multiple copies of each warning, making it difficult to tell what is really going on.

in the end though, `carton dev` successfully starts up a server on `localhost:8080`.

when i look at the page, at first there is no sign the WebAssembly is running, but after a short moment, it appears. in the web inspector network tab, it shows that the WebAssembly is 59.96 MB in size.

although that is very hefty, surely this is just the debug binary size, and the release WebAssembly will be much smaller… right?

## ⚙ optimizing the binary

i want to know how small the production WebAssembly is, so i try running the `bundle` command, which is supposed to be the “release mode”.

```bash
$ swift run carton bundle --custom-index-page Web/index.html

```

```plaintext
Build of product 'Hello' complete! (6.72s)
Right after building the main binary size is 56.59 MB

After stripping debug info the main binary size is 49.96 MB

Running wasm-opt -Os --enable-bulk-memory --enable-sign-ext /swift/wasm-test/Bundle/main.wasm -o /swift/wasm-test/Bundle/main.wasm
wasm-opt -Os --enable-bulk-memory --enable-sign-ext /swift/wasm-test/Bundle/main.wasm -o /swift/wasm-test/Bundle/main.wasm

wasm-opt process failed.

Warning: wasm-opt failed to optimize the binary, falling back to the original binary.
If you don't have wasm-opt installed, you can install wasm-opt by running `brew install binaryen`, `apt-get install binaryen` or `npm install -g binaryen`
Copying resources to /swift/wasm-test/Bundle/JavaScriptKit_JavaScriptKit.resources
Bundle successfully generated at /swift/wasm-test/Bundle

```

okay, that’s not good. the production mode binary is 56.59 MB, which is only 3 MB smaller than the debug binary. stripping debug symbols takes it down to 49.96 MB, but that’s still enormous!

but it also looks like there’s another pass that needs to run, which requires installing some other tool `binaryen`. this step takes it down to 44.77 MB.

```plaintext
Build of product 'Hello' complete! (0.51s)
Right after building the main binary size is 56.59 MB

After stripping debug info the main binary size is 49.96 MB

Running wasm-opt -Os --enable-bulk-memory --enable-sign-ext /swift/wasm-test/Bundle/main.wasm -o /swift/wasm-test/Bundle/main.wasm
wasm-opt -Os --enable-bulk-memory --enable-sign-ext /swift/wasm-test/Bundle/main.wasm -o /swift/wasm-test/Bundle/main.wasm
`wasm-opt` process finished successfully
After stripping debug info the main binary size is 44.77 MB

Copying resources to /swift/wasm-test/Bundle/JavaScriptKit_JavaScriptKit.resources
Bundle successfully generated at /swift/wasm-test/Bundle

```

perhaps this code is very repetitive. i wonder what would happen if we used `gzip` on this?

```swift
$ gzip -9 Bundle/Hello.04ebb5a28d0d45fc.wasm 
$ ls -l Bundle/
total 17408
-rw-r--r-- 1 ubuntu ubuntu 17683279 Jan 21 02:07 Hello.04ebb5a28d0d45fc.wasm.gz
drwxr-xr-x 3 ubuntu ubuntu 4096 Jan 21 02:07 JavaScriptKit_JavaScriptKit.resources
-rw-r--r-- 1 ubuntu ubuntu 56740 Jan 21 02:08 app.d38bdc6abc41d009.js
-rw-r--r-- 1 ubuntu ubuntu 337 Jan 21 02:08 index.html
-rw-r--r-- 1 ubuntu ubuntu 1614 Jan 21 02:08 index.js
-rw-r--r-- 1 ubuntu ubuntu 62313 Jan 21 02:08 intrinsics.js
-rw-r--r-- 1 ubuntu ubuntu 46 Jan 21 02:08 package.json

```

alright, so effective baseline Hello World size is 17.7 MB compressed.

## 🏖 what now?

17.7 MB is not unworkable if the WebAssembly is the entire web app. you can host this statically, serve it through a CDN, and walk users through updates as they roll out. in a lot of ways, this is no more annoying than updating an iOS app.

on the other extreme, it [seems to be possible](https://forums.swift.org/t/some-feedback-from-my-short-experience-with-swiftwasm/69605/5) to get ultralight binaries by going the Embedded route. but a lot of this seems geared towards folks who are trying to ship WebAssembly on the scale of [500 KB or less](https://forums.swift.org/t/swift-wasm-binary-sizes/51533) (200 KB compressed?).

i’m curious to know if there is a way to target WebAssembly in the range of 5–10 MB uncompressed, that avoids dependencies such as Foundation, while not being restricted completely to the Embedded subset of the language. does such a thing exist?

you can’t really integrate something that is 17.7 MB into an existing web application, that kind of overhead is only justifiable if you are starting from scratch and the WebAssembly is the entire application. i want to know if it is possible to incrementally adopt WebAssembly with the eventual goal of having it replace the rest of the application.

---

<div class="post-metadata">

**Author:** ![austintatious](https://avatars.discourse-cdn.com/v4/letter/a/ce73a5/32.png) [@austintatious](https://forums.swift.org/u/austintatious)\
**Post date:** [January 21, 2025, 5:18am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/7 "2025-01-21T05:18:38Z")

</div>

> [@taylorswift](#):
>
> i’m curious to know if there is a way to target WebAssembly in the range of 5–10 MB uncompressed, that avoids dependencies such as Foundation, while not being restricted completely to the Embedded subset of the language. does such a thing exist?

There has been a lot of discussion on this topic on github, [https://github.com/swiftwasm/swift/issues/7](https://github.com/swiftwasm/swift/issues/7) as it was definitely an ongoing issue.

> [@taylorswift](#):
>
> 17.7 MB is not unworkable if the WebAssembly is the entire web app.

You're right. Althought today I don't worry about it as much, phone speeds have improved a lot since 2020 and so have download speeds. Still, definitely some room for improvement.

> [@taylorswift](#):
>
> alright, so effective baseline Hello World size is 17.7 MB compressed.

I am a little perplexed at this, the wasm file that I host is only 18.8mb. It's not compressed into a gzip/zip. I just tried to compress it, and it's 5mb compressed.

My output is

```swift
`wasm-opt` process finished successfully
After stripping debug info the main binary size is 17.92mb

```

My project is quite large. 300k-500k lines of code. I compared the output and they looked the same, so I am wondering where the large difference is coming form. (this often means I need sleep).

---

<div class="post-metadata">

**Author:** ![svanimpe](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/svanimpe/32/38963_2.png) [@svanimpe](https://forums.swift.org/u/svanimpe)\
**Post date:** [January 21, 2025, 9:02am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/8 "2025-01-21T09:02:35Z")

</div>

> [@taylorswift](#):
>
> i tried tonight to follow @svanimpe ’s [example](https://github.com/pwsacademy/swiftwasm-examples/blob/main/basics/README.md), trying to use `carton` to run a minimal example, and very quickly ran into the sobering reality which is that `carton` does not support my operating system, Ubuntu 24.04.

Thanks for reporting this. I just realized I forgot to check the examples on Ubuntu 24.04. I started out on 22.04, then switched to macOS in early 2024.

Does it work with nightly builds? For SwiftWasm, I always used nightlies, not releases.

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [January 21, 2025, 11:24pm UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/9 "2025-01-21T23:24:07Z")

</div>

> [@austintatious](#):
>
> I am a little perplexed at this, the wasm file that I host is only 18.8mb. It's not compressed into a gzip/zip. I just tried to compress it, and it's 5mb compressed.

i tried to debug this today, by replicating @svanimpe ’s example project as closely as i could.

```bash
$ git clone https://github.com/pwsacademy/swiftwasm-examples
$ cd swiftwasm-examples/
$ cd basics/
$ swift run carton bundle --custom-index-page Web/index.html

```

i was again loudly reminded with a crash and stack trace that `carton` does not support my Operating System. why Swift performs seppuku when [throwing from main](https://forums.swift.org/t/another-taylorswift-post-mortem/73139) is something i fail to understand since Swift 5.9. but that is hardly `carton`’s fault.

i switched the dependency in `Package.swift` over to my local fork, and everything went smoothly, `Sendable` noise notwithstanding.

> **Swift Concurrency noise**
>
> ```plaintext
> $ swift run carton bundle --custom-index-page Web/index.html
> Updating https://github.com/swiftwasm/JavaScriptKit
> Updating https://github.com/apple/swift-nio.git
> Updating https://github.com/swiftwasm/WasmTransformer
> Updating https://github.com/apple/swift-argument-parser.git
> Updated https://github.com/swiftwasm/JavaScriptKit (0.24s)
> Updated https://github.com/swiftwasm/WasmTransformer (0.27s)
> Updated https://github.com/apple/swift-argument-parser.git (0.27s)
> Updated https://github.com/apple/swift-nio.git (0.41s)
> Computing version for https://github.com/swiftwasm/JavaScriptKit
> Computed https://github.com/swiftwasm/JavaScriptKit at 0.21.0 (0.01s)
> Computing version for https://github.com/swiftwasm/WasmTransformer
> Computed https://github.com/swiftwasm/WasmTransformer at 0.5.0 (0.00s)
> Computed https://github.com/swiftwasm/JavaScriptKit at 0.21.0 (0.00s)
> Computing version for https://github.com/apple/swift-argument-parser.git
> Computed https://github.com/apple/swift-argument-parser.git at 1.3.1 (0.01s)
> Computing version for https://github.com/apple/swift-nio.git
> Computed https://github.com/apple/swift-nio.git at 2.79.0 (0.01s)
> Updating https://github.com/apple/swift-atomics.git
> Updating https://github.com/apple/swift-system.git
> Updating https://github.com/apple/swift-collections.git
> Updated https://github.com/apple/swift-collections.git (0.28s)
> Updated https://github.com/apple/swift-atomics.git (0.28s)
> Updated https://github.com/apple/swift-system.git (0.28s)
> Computing version for https://github.com/apple/swift-system.git
> Computed https://github.com/apple/swift-system.git at 1.4.0 (0.00s)
> Computing version for https://github.com/apple/swift-atomics.git
> Computed https://github.com/apple/swift-atomics.git at 1.2.0 (0.01s)
> Computing version for https://github.com/apple/swift-collections.git
> Computed https://github.com/apple/swift-collections.git at 1.1.4 (0.01s)
> Building for debugging...
> /swift/carton/Sources/SwiftToolchain/AsyncFileDownload.swift:36:9: warning: non-final class 'FileDownloadDelegate' cannot conform to 'Sendable'; use '@unchecked Sendable'; this is an error in the Swift 6 language mode
> 34 | public var receivedBytes: Int
> 35 | }
> 36 | class FileDownloadDelegate: NSObject, URLSessionDownloadDelegate {
> | `- warning: non-final class 'FileDownloadDelegate' cannot conform to 'Sendable'; use '@unchecked Sendable'; this is an error in the Swift 6 language mode
> 37 | let path: String
> 38 | let onTotalBytes: (Int) -> Void
> 
> /swift/carton/Sources/SwiftToolchain/AsyncFileDownload.swift:38:9: warning: stored property 'onTotalBytes' of 'Sendable'-conforming class 'FileDownloadDelegate' has non-sendable type '(Int) -> Void'; this is an error in the Swift 6 language mode
> 36 | class FileDownloadDelegate: NSObject, URLSessionDownloadDelegate {
> 37 | let path: String
> 38 | let onTotalBytes: (Int) -> Void
> | |- warning: stored property 'onTotalBytes' of 'Sendable'-conforming class 'FileDownloadDelegate' has non-sendable type '(Int) -> Void'; this is an error in the Swift 6 language mode
> | `- note: a function type must be marked '@Sendable' to conform to 'Sendable'
> 39 | let continuation: AsyncThrowingStream<Progress, Error>.Continuation
> 40 | var totalBytesToDownload: Int?
> 
> /swift/carton/Sources/SwiftToolchain/AsyncFileDownload.swift:40:9: warning: stored property 'totalBytesToDownload' of 'Sendable'-conforming class 'FileDownloadDelegate' is mutable; this is an error in the Swift 6 language mode
> 38 | let onTotalBytes: (Int) -> Void
> 39 | let continuation: AsyncThrowingStream<Progress, Error>.Continuation
> 40 | var totalBytesToDownload: Int?
> | `- warning: stored property 'totalBytesToDownload' of 'Sendable'-conforming class 'FileDownloadDelegate' is mutable; this is an error in the Swift 6 language mode
> 41 | 
> 42 | init(
> /swift/carton/Sources/SwiftToolchain/AsyncFileDownload.swift:36:9: warning: non-final class 'FileDownloadDelegate' cannot conform to 'Sendable'; use '@unchecked Sendable'; this is an error in the Swift 6 language mode
> 34 | public var receivedBytes: Int
> 35 | }
> 36 | class FileDownloadDelegate: NSObject, URLSessionDownloadDelegate {
> | `- warning: non-final class 'FileDownloadDelegate' cannot conform to 'Sendable'; use '@unchecked Sendable'; this is an error in the Swift 6 language mode
> 37 | let path: String
> 38 | let onTotalBytes: (Int) -> Void
> 
> /swift/carton/Sources/SwiftToolchain/AsyncFileDownload.swift:38:9: warning: stored property 'onTotalBytes' of 'Sendable'-conforming class 'FileDownloadDelegate' has non-sendable type '(Int) -> Void'; this is an error in the Swift 6 language mode
> 36 | class FileDownloadDelegate: NSObject, URLSessionDownloadDelegate {
> 37 | let path: String
> 38 | let onTotalBytes: (Int) -> Void
> | |- warning: stored property 'onTotalBytes' of 'Sendable'-conforming class 'FileDownloadDelegate' has non-sendable type '(Int) -> Void'; this is an error in the Swift 6 language mode
> | `- note: a function type must be marked '@Sendable' to conform to 'Sendable'
> 39 | let continuation: AsyncThrowingStream<Progress, Error>.Continuation
> 40 | var totalBytesToDownload: Int?
> 
> /swift/carton/Sources/SwiftToolchain/AsyncFileDownload.swift:40:9: warning: stored property 'totalBytesToDownload' of 'Sendable'-conforming class 'FileDownloadDelegate' is mutable; this is an error in the Swift 6 language mode
> 38 | let onTotalBytes: (Int) -> Void
> 39 | let continuation: AsyncThrowingStream<Progress, Error>.Continuation
> 40 | var totalBytesToDownload: Int?
> | `- warning: stored property 'totalBytesToDownload' of 'Sendable'-conforming class 'FileDownloadDelegate' is mutable; this is an error in the Swift 6 language mode
> 41 | 
> 42 | init(
> [29/29] Linking carton
> Build of product 'carton' complete! (2.99s)
> - checking Swift compiler path: /home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a/usr/bin/swift
> - checking Swift compiler path: /home/ubuntu/.swiftenv/versions/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a/usr/bin/swift
> Fetching release assets from https://api.github.com/repos/swiftwasm/swift/releases/tags/swift-wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a
> Response contained body, parsing it now...
> Response successfully parsed, choosing from this number of assets: 10
> Local installation of Swift version wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a not found
> Swift toolchain/SDK download URL: https://github.com/swiftwasm/swift/releases/download/swift-wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a/swift-wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a-ubuntu22.04_x86_64.tar.gz
> Archive size is 1042 MB
> Downloading the archive
> 99% [=================================================================================================================================================================================================================---]
> saving to /home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a.gz
> Download completed successfully
> Unpacking the archive: /usr/bin/tar xzf /home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a.gz --strip-components=1 --directory /home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a
> Running "/usr/bin/tar" "xzf" "/home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a.gz" "--strip-components=1" "--directory" "/home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a"
> - checking Swift compiler path: /home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a/usr/bin/swift
> Inferring basic settings...
> - swift executable: /home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a/usr/bin/swift
> Swift version 6.1-dev (LLVM f4b733c38006ec1, Swift 5c7509bef50dbd7)
> Target: x86_64-unknown-linux-gnu
> Running "/home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a/usr/bin/swift" "package" "--triple" "wasm32-unknown-wasi" "--scratch-path" "/swift/wasm-test/swiftwasm-examples/basics/.build/carton" "--disable-sandbox" "plugin" "carton-bundle" "--output" "Bundle" "--custom-index-page" "Web/index.html"
> Building for debugging...
> /swift/carton/Sources/CartonHelpers/Basics/Condition.swift:11:19: warning: '@preconcurrency' attribute on module 'Foundation' has no effect
> 9 | */
> 10 | #if !_runtime(_ObjC)
> 11 | @preconcurrency import Foundation
> | `- warning: '@preconcurrency' attribute on module 'Foundation' has no effect
> 12 | #else
> 13 | import Foundation
> 
> /swift/carton/Sources/CartonHelpers/Basics/FileInfo.swift:12:19: warning: '@preconcurrency' attribute on module 'Foundation' has no effect
> 10 | 
> 11 | #if !_runtime(_ObjC)
> 12 | @preconcurrency import Foundation
> | `- warning: '@preconcurrency' attribute on module 'Foundation' has no effect
> 13 | #else
> 14 | import Foundation
> /swift/carton/Sources/CartonHelpers/Basics/Condition.swift:11:19: warning: '@preconcurrency' attribute on module 'Foundation' has no effect
> 9 | */
> 10 | #if !_runtime(_ObjC)
> 11 | @preconcurrency import Foundation
> | `- warning: '@preconcurrency' attribute on module 'Foundation' has no effect
> 12 | #else
> 13 | import Foundation
> 
> /swift/carton/Sources/CartonHelpers/Basics/FileInfo.swift:12:19: warning: '@preconcurrency' attribute on module 'Foundation' has no effect
> 10 | 
> 11 | #if !_runtime(_ObjC)
> 12 | @preconcurrency import Foundation
> | `- warning: '@preconcurrency' attribute on module 'Foundation' has no effect
> 13 | #else
> 14 | import Foundation
> /swift/carton/Sources/CartonHelpers/Basics/Process/Process.swift:20:22: warning: using '@_implementationOnly' without enabling library evolution for 'CartonHelpers' may lead to instability during execution
> 18 | #endif
> 19 | 
> 20 | @_implementationOnly import TSCclibc
> | `- warning: using '@_implementationOnly' without enabling library evolution for 'CartonHelpers' may lead to instability during execution
> 21 | import TSCLibc
> 22 | import Dispatch
> 
> /swift/carton/Sources/CartonHelpers/Basics/Process/ProcessEnv.swift:72:36: warning: conformance of 'Dictionary<Key, Value>' to protocol 'Sendable' conflicts with that stated in the type's module 'Swift' and will be ignored; there cannot be more than one conformance, even with different conditional bounds
> 70 | }
> 71 | 
> 72 | extension ProcessEnvironmentBlock: Sendable {}
> | `- warning: conformance of 'Dictionary<Key, Value>' to protocol 'Sendable' conflicts with that stated in the type's module 'Swift' and will be ignored; there cannot be more than one conformance, even with different conditional bounds
> 73 | 
> 74 | /// Provides functionality related a process's environment.
> 
> Swift.Dictionary:1:11: note: 'Dictionary<Key, Value>' declares conformance to protocol 'Sendable' here
> 1 | extension Dictionary : @unchecked Sendable where Key : Sendable, Value : Sendable {
> | `- note: 'Dictionary<Key, Value>' declares conformance to protocol 'Sendable' here
> 2 | }
> /swift/carton/Sources/CartonHelpers/Basics/Process/ProcessEnv.swift:72:36: warning: conformance of 'Dictionary<Key, Value>' to protocol 'Sendable' conflicts with that stated in the type's module 'Swift' and will be ignored; there cannot be more than one conformance, even with different conditional bounds
> 70 | }
> 71 | 
> 72 | extension ProcessEnvironmentBlock: Sendable {}
> | `- warning: conformance of 'Dictionary<Key, Value>' to protocol 'Sendable' conflicts with that stated in the type's module 'Swift' and will be ignored; there cannot be more than one conformance, even with different conditional bounds
> 73 | 
> 74 | /// Provides functionality related a process's environment.
> 
> Swift.Dictionary:1:11: note: 'Dictionary<Key, Value>' declares conformance to protocol 'Sendable' here
> 1 | extension Dictionary : @unchecked Sendable where Key : Sendable, Value : Sendable {
> | `- note: 'Dictionary<Key, Value>' declares conformance to protocol 'Sendable' here
> 2 | }
> /swift/carton/Sources/CartonHelpers/Basics/Process/ProcessEnv.swift:72:36: warning: conformance of 'Dictionary<Key, Value>' to protocol 'Sendable' conflicts with that stated in the type's module 'Swift' and will be ignored; there cannot be more than one conformance, even with different conditional bounds
> 70 | }
> 71 | 
> 72 | extension ProcessEnvironmentBlock: Sendable {}
> | `- warning: conformance of 'Dictionary<Key, Value>' to protocol 'Sendable' conflicts with that stated in the type's module 'Swift' and will be ignored; there cannot be more than one conformance, even with different conditional bounds
> 73 | 
> 74 | /// Provides functionality related a process's environment.
> 
> Swift.Dictionary:1:11: note: 'Dictionary<Key, Value>' declares conformance to protocol 'Sendable' here
> 1 | extension Dictionary : @unchecked Sendable where Key : Sendable, Value : Sendable {
> | `- note: 'Dictionary<Key, Value>' declares conformance to protocol 'Sendable' here
> 2 | }
> /swift/carton/Sources/CartonHelpers/Basics/Thread.swift:54:41: warning: converting non-sendable function value to '@Sendable () -> Void' may introduce data races
> 52 | }
> 53 | 
> 54 | self.thread = ThreadImpl(block: theTask)
> | `- warning: converting non-sendable function value to '@Sendable () -> Void' may introduce data races
> 55 | }
> 56 | 
> /swift/carton/Sources/CartonHelpers/Basics/Thread.swift:54:41: warning: converting non-sendable function value to '@Sendable () -> Void' may introduce data races
> 52 | }
> 53 | 
> 54 | self.thread = ThreadImpl(block: theTask)
> | `- warning: converting non-sendable function value to '@Sendable () -> Void' may introduce data races
> 55 | }
> 56 | 
> /swift/carton/Sources/CartonHelpers/Basics/Process/Process.swift:20:22: warning: using '@_implementationOnly' without enabling library evolution for 'CartonHelpers' may lead to instability during execution
> 18 | #endif
> 19 | 
> 20 | @_implementationOnly import TSCclibc
> | `- warning: using '@_implementationOnly' without enabling library evolution for 'CartonHelpers' may lead to instability during execution
> 21 | import TSCLibc
> 22 | import Dispatch
> /swift/carton/Sources/CartonHelpers/Basics/Process/Process.swift:20:22: warning: using '@_implementationOnly' without enabling library evolution for 'CartonHelpers' may lead to instability during execution
> 18 | #endif
> 19 | 
> 20 | @_implementationOnly import TSCclibc
> | `- warning: using '@_implementationOnly' without enabling library evolution for 'CartonHelpers' may lead to instability during execution
> 21 | import TSCLibc
> 22 | import Dispatch
> [56/56] Linking carton-frontend-slim-tool
> Build of product 'carton-frontend-slim' complete! (5.01s)
> Building "HelloSwiftWasm"
> Building for production...
> [0/2] Write swift-version-22C80AB982ED8698.txt
> 
> ```

```plaintext
Build of product 'HelloSwiftWasm' complete! (0.86s)
Right after building the main binary size is 8.12 MB

After stripping debug info the main binary size is 5.79 MB

Running wasm-opt -Os --enable-bulk-memory --enable-sign-ext /swift/wasm-test/swiftwasm-examples/basics/Bundle/main.wasm -o /swift/wasm-test/swiftwasm-examples/basics/Bundle/main.wasm
wasm-opt -Os --enable-bulk-memory --enable-sign-ext /swift/wasm-test/swiftwasm-examples/basics/Bundle/main.wasm -o /swift/wasm-test/swiftwasm-examples/basics/Bundle/main.wasm
`wasm-opt` process finished successfully
After stripping debug info the main binary size is 3.71 MB

Copying resources to /swift/wasm-test/swiftwasm-examples/basics/Bundle/JavaScriptKit_JavaScriptKit.resources
Bundle successfully generated at /swift/wasm-test/swiftwasm-examples/basics/Bundle

```

wow! that’s exactly what i was looking for! now, 3.71 MB uncompressed isn’t _nothing_, but that is definitely something i can work with 😃

now the question becomes: why does this build produce a 3.71 MB binary, but the other one produces a 56 MB binary?

## 🤔 what is different about this build?

now i skim through that Concurrency-laden output from earlier, and immediately something sticks out to me.

```plaintext
Build of product 'carton' complete! (2.99s)
- checking Swift compiler path: /home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a/usr/bin/swift
- checking Swift compiler path: /home/ubuntu/.swiftenv/versions/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a/usr/bin/swift
Fetching release assets from https://api.github.com/repos/swiftwasm/swift/releases/tags/swift-wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a
Response contained body, parsing it now...
Response successfully parsed, choosing from this number of assets: 10
Local installation of Swift version wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a not found
Swift toolchain/SDK download URL: https://github.com/swiftwasm/swift/releases/download/swift-wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a/swift-wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a-ubuntu22.04_x86_64.tar.gz
Archive size is 1042 MB
                                                                                                        Downloading the archive
99% [=================================================================================================================================================================================================================---]
saving to /home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a.gz
Download completed successfully
Unpacking the archive: /usr/bin/tar xzf /home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a.gz --strip-components=1 --directory /home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a
Running "/usr/bin/tar" "xzf" "/home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a.gz" "--strip-components=1" "--directory" "/home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a"
- checking Swift compiler path: /home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a/usr/bin/swift
Inferring basic settings...
- swift executable: /home/ubuntu/.carton/sdk/wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a/usr/bin/swift
Swift version 6.1-dev (LLVM f4b733c38006ec1, Swift 5c7509bef50dbd7)

```

it’s not using a release toolchain, it’s using some random nightly `DEVELOPMENT-SNAPSHOT-2024-10-27-a`.

that’s “bad”. a lot of libraries crash the compiler when built with nightlies, because the nightlies have compiler assertions enabled. there is often nothing you can do when you have a library that is crashing the compiler. and even if all your libraries build with the nightly, you can forget about using sourcekit-lsp or any other “modern” IDE tools. one lesson this Swiftie learned brutally and repeatedly early in her career is that if you are relying on nightly Swift toolchains, you are going to have a very tough time getting anything done.

but is it really the nightly toolchain that is key to achieving reasonable binary size? let’s find out…

## 😩 it’s the `.swift-version`, stupid

so it looks like `carton` is using swiftenv, and there is a `.swift-version` file in the repo that contains the string `wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a`, so that’s probably where the nightly is coming from.

i try replacing this with `6.0.3-RELEASE`, even though i know there is no such thing as swiftwasm 6.0.3. to my surprise, this works, and causes swiftenv to download Swift 6.0.2, which is probably what i would have done too. hooray?

```plaintext
$ swift run carton bundle --custom-index-page Web/index.html
Building for debugging...
[1/1] Write swift-version--75355AAB4E86B17C.txt
Build of product 'carton' complete! (0.27s)
- checking Swift compiler path: /home/ubuntu/.carton/sdk/wasm-6.0.2-RELEASE/usr/bin/swift
- checking Swift compiler path: /home/ubuntu/.swiftenv/versions/wasm-6.0.2-RELEASE/usr/bin/swift
Fetching release assets from https://api.github.com/repos/swiftwasm/swift/releases/tags/swift-wasm-6.0.2-RELEASE
Response contained body, parsing it now...
Response successfully parsed, choosing from this number of assets: 8
Local installation of Swift version wasm-6.0.2-RELEASE not found
Swift toolchain/SDK download URL: https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.0.2-RELEASE/swift-wasm-6.0.2-RELEASE-ubuntu22.04_x86_64.tar.gz
Archive size is 908 MB
                                                                                                        Downloading the archive
99% [=================================================================================================================================================================================================================---]
saving to /home/ubuntu/.carton/sdk/wasm-6.0.2-RELEASE.gz
Download completed successfully
Unpacking the archive: /usr/bin/tar xzf /home/ubuntu/.carton/sdk/wasm-6.0.2-RELEASE.gz --strip-components=1 --directory /home/ubuntu/.carton/sdk/wasm-6.0.2-RELEASE
Running "/usr/bin/tar" "xzf" "/home/ubuntu/.carton/sdk/wasm-6.0.2-RELEASE.gz" "--strip-components=1" "--directory" "/home/ubuntu/.carton/sdk/wasm-6.0.2-RELEASE"
- checking Swift compiler path: /home/ubuntu/.carton/sdk/wasm-6.0.2-RELEASE/usr/bin/swift
Inferring basic settings...
- swift executable: /home/ubuntu/.carton/sdk/wasm-6.0.2-RELEASE/usr/bin/swift
Swift version 6.0.2 (swift-6.0.2-RELEASE)

```

```plaintext
Build of product 'HelloSwiftWasm' complete! (7.75s)
Right after building the main binary size is 56.56 MB

After stripping debug info the main binary size is 49.95 MB

Running wasm-opt -Os --enable-bulk-memory --enable-sign-ext /swift/wasm-test/swiftwasm-examples/basics/Bundle/main.wasm -o /swift/wasm-test/swiftwasm-examples/basics/Bundle/main.wasm
wasm-opt -Os --enable-bulk-memory --enable-sign-ext /swift/wasm-test/swiftwasm-examples/basics/Bundle/main.wasm -o /swift/wasm-test/swiftwasm-examples/basics/Bundle/main.wasm
`wasm-opt` process finished successfully
After stripping debug info the main binary size is 44.77 MB

Copying resources to /swift/wasm-test/swiftwasm-examples/basics/Bundle/JavaScriptKit_JavaScriptKit.resources
Bundle successfully generated at /swift/wasm-test/swiftwasm-examples/basics/Bundle

```

…and there it is. the release toolchain cannot produce WebAssembly binaries of reasonable size. only the unstable nightly toolchains can do this.

so i guess the basic tradeoff here is that if you want to do Serious WebAssembly with Swift, you must use nightly toolchains. but we know that we cannot do Serious Development with nightly toolchains, because they cannot compile libraries, and their sourcekit-lsp does not work while editing code. so it seems that Swift on WebAssembly is in a sort of catch-22.

theoretically, we could mitigate this problem by distributing nightlies that are built with `noassert`, like the release toolchains on Linux, or the Xcode toolchains on macOS. does such a thing exist?

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [January 21, 2025, 11:36pm UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/10 "2025-01-21T23:36:54Z")

</div>

I will repeat that every assertion failure is a potential miscompile, and therefore you cannot do Serious Development with a `noassert` toolchain _if your reason for doing so is to avoid assertions._

---

<div class="post-metadata">

**Author:** ![stackotter](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stackotter/32/20670_2.png) [@stackotter](https://forums.swift.org/u/stackotter)\
**Post date:** [January 21, 2025, 11:40pm UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/11 "2025-01-21T23:40:28Z")

</div>

> [@taylorswift](#):
>
> I’m curious to know if there is a way to target WebAssembly in the range of 5–10 MB uncompressed, that avoids dependencies such as Foundation, while not being restricted completely to the Embedded subset of the language. does such a thing exist?

A while back I made a toy interpreted programming language called [galah](https://github.com/stackotter/galah), and used SwiftWasm to set up [an online playground](https://stackotter.github.io/galah/) for it. The galah interpreter Wasm builds to 9.6mb, optimizes down to 4.3mb, and gzips down to 1.6mb! I believe that the secret is avoiding Foundation.

```sh
swift build \
    --swift-sdk 5.10-SNAPSHOT-2024-04-09-a-wasm \
    --product GalahWeb
cp .build/debug/GalahWeb.wasm .

wasm-strip GalahWeb.wasm
wasm-opt -Oz GalahWeb.wasm -o GalahWeb.wasm

gzip -9 GalahWeb.wasm

```

Carton didn't want to work for me at the time, so I just manually pulled the SwiftWasm JS runtime files into my static site and made my own index.html. All of the files for the static website are located [in this directory](https://github.com/stackotter/galah/tree/main/static).

* * *

## Painpoints

To continue the theme of this thread, here are a few pain points I've encountered and failed to resolve.

### Invalid WASM binary produced most of the time

In my setup, the wasm binary produced by SwiftPM almost always has the first big chunk of it zeroed out, making it invalid and leading to "bad magic bytes" when I attempt to strip/optimize it. It only seems to produce a valid wasm binary if I first do a release build, which fails due to missing symbols in `swiftrt.o`, and then switch back to doing a debug build. It then proceeds to fail again if I repeat the exact same debug build. Clean builds also don't help.

### Release builds don't work (with the only SDK I've gotten working, see next section)

As mentioned in the previous section, release builds fail with a ton of `ld` errors referencing `swiftrt.o`. I understand that this may have been resolved in the time since Swift 5.10, however 5.10 is the only SwiftWasm SDK version that I've gotten working so far.

```swift
wasm-ld: error: /Users/stackotter/Library/org.swift.swiftpm/swift-sdks/swift-wasm-5.10-SNAPSHOT-2024-04-09-a-macos_arm64.artifactbundle/5.10-SNAPSHOT-2024-04-09-a-wasm/wasm32-unknown-wasi/swift.xctoolchain/usr/lib/swift_static/wasi/wasm32/swiftrt.o: undefined symbol: __stop_swift5_protocols
wasm-ld: error: /Users/stackotter/Library/org.swift.swiftpm/swift-sdks/swift-wasm-5.10-SNAPSHOT-2024-04-09-a-macos_arm64.artifactbundle/5.10-SNAPSHOT-2024-04-09-a-wasm/wasm32-unknown-wasi/swift.xctoolchain/usr/lib/swift_static/wasi/wasm32/swiftrt.o: undefined symbol: __start_swift5_protocols

```

### Can't get 6.0.2 toolchain working

I've installed the 6.0.2 SwiftWasm SDK to check if it fixes any of the above issues, and can't get it to work at all. When I swap out `--swift-sdk 5.10-SNAPSHOT-2024-04-09-a-wasm` with `--swift-sdk 6.0.2-RELEASE-wasm32-unknown-wasi` Swift spits out `No available targets are compatible with triple "wasm32-unknown-wasi"` and exits basically immediately. The command-line I'm using matches the example I detailed earlier.

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [January 22, 2025, 12:03am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/12 "2025-01-22T00:03:59Z")

</div>

> [@jrose](#):
>
> I will repeat that every assertion failure is a potential miscompile, and therefore you cannot do Serious Development with a `noassert` toolchain _if your reason for doing so is to avoid assertions._

and again, you are correct, and yet i believe that building software is about finding solutions to problems, not about persuading myself and others why something is impossible to attempt. so when i find myself with two alternatives,

1. ship something that might contain miscompiles
2. ship nothing at all

the question i am really asking myself is whether i am going to give up and use a different language or whether i am going to build something.

now the situation here is not _quite_ that dramatic. instead of shipping nothing at all, you could ship the 17 MB compressed binary. but nobody is going to wait for that to load unless it’s the literal _entire app_ and they are already strongly committed to using that app. if you’re just adding a small WebAssembly component to an existing website, you are Shipping Nothing in spirit, because your visitors have likely already navigated away from the page by the time the WebAssembly has loaded.

as to potential miscompiled binaries, there is really a world of difference between miscompiled server code and miscompiled client code. you should never really be relying on client code to be responsible for anything security-essential, and if the client code misbehaves, the worst thing that can happen is the app just doesn’t work for the user. which is the same thing that would have occurred if you had Shipped Nothing.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [January 22, 2025, 12:09am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/13 "2025-01-22T00:09:16Z")

</div>

> [@taylorswift](#):
>
> the worst thing that can happen is the app just doesn’t work for the user. which is the same thing that would have occurred if you had Shipped Nothing.

Leaving aside that I work on an e2ee app where there are _very bad_ consequences for client-side miscompiles, it is definitely worse than Shipping Nothing if the user spends 40 hours with your app and then it deletes all of the user’s data irrecoverably. If you had Shipped Nothing, they would have spent those 40 hours somewhere else.

The developer’s time may be more important than the compiler engineer’s, but the user’s is more important than either. “Swift cannot be used for Serious Development in Web Assembly (yet)” is a reasonable take if the alternative is potential user data loss. (There might always be bugs in software, so it’s always a _possibility,_ but “I found a bug but it doesn’t seem to affect my use case” is pretty damn cavalier for “Serious Development”.)

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [January 22, 2025, 12:18am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/14 "2025-01-22T00:18:48Z")

</div>

> [@jrose](#):
>
> If you had Shipped Nothing, they would have spent those 40 hours somewhere else.

well… that’s my point exactly isn’t it?

let’s not go to the extreme of assuming every app has users who are using it for 40 hours without once saving, a lot of apps that turn over a lot of revenue are Calculator-like apps where the visitors land on the page, drag and drop some file, get some output, and immediately bounce.

if the app crashes, they bounce and go to the next Google search result. if the app takes more than 5s to load, they bounce and go to the next Google search result. i imagine that web apps that users are entrusting with irrecoverable data make up a small proportion of all web apps.

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [January 22, 2025, 2:59am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/15 "2025-01-22T02:59:17Z")

</div>

anyway, getting this thread back on track…  
the next thing i am going to aim to do today is:

~ actually get an app that Does Something running in Firefox ~

of course before i build an app i first need to come up with an idea for an app.

## 💭 brainstorming an app

now i work a lot with MongoDB lately, and something i’ve complained about to anyone else who will listen is that is no online BSON inspector known to Google.

![Firefox_Screenshot_2025-01-22T00-40-53.010Z](https://global.discourse-cdn.com/swift/original/3X/b/7/b71ac35c7e26917ba1dc38e77fc6d670a0613ff7.png)

if you install the MongoDB developer tools, you can convert the BSON to Extended JSON, and look at the JSON, but that only really works for very small BSON. for comparison, the [BSON on Swiftinit](https://swiftinit.org/tags/swift-syntax) can be many megabytes in size, and contains a lot of BSON-specific structures that are not particularly readable when converted to JSON.

 ![Screenshot from 2025-01-21 18-44-51](https://global.discourse-cdn.com/swift/original/3X/2/5/257038df8f294c32a63c34247a4e1f077183a5a2.png)

i could write a web app in JavaScript, but parsing BSON with JavaScript is probably going to be slow, and i want this to work with giant BSON blobs like the ones on Swiftinit.

i could parse the BSON server-side, and return the rendered HTML to the user that way, but then i would have to stand up a server which would then become the bottleneck. so this sounds like the type of problem that Swift on WebAssembly could really help with.

## 😁 setting up my project

it sounds like Swift on WebAssembly requires a nightly toolchain to get binaries of a reasonable size, so i add a `.swift-version` to my project, and i figure that since i have already resigned to using a nightly toolchain, i might as well use the most recent nightly toolchain available, so i replace `wasm-DEVELOPMENT-SNAPSHOT-2024-10-27-a` from the example project with `wasm-6.1-SNAPSHOT-2025-01-18-a`, which is the most recent one they have listed [on GitHub](https://github.com/swiftwasm/swift/releases).

i need to use JavaScriptKit to do anything that involves DOM, so my Package.swift looks like this, like the example:

```swift
// swift-tools-version:6.0
import PackageDescription

let package:Package = .init(name: "test",
    products: [
    ],
    dependencies: [
        // .package(url: "https://github.com/swiftwasm/carton", from: "1.1.3"),
        .package(path: "../carton"),
        .package(url: "https://github.com/swiftwasm/JavaScriptKit", from: "0.21.0"),
    ],
    targets: [
        .executableTarget(name: "BSONViewer",
            dependencies: [
            .product(name: "JavaScriptKit", package: "JavaScriptKit"),
        ]),
    ])

```

and in `BSONViewer`, i’ve kept the placeholder code:

```swift
import JavaScriptKit

let document = JSObject.global.document
var div = document.createElement("div")
div.innerHTML = "Hi Barbie!"
_ = document.body.appendChild(div)

```

```bash
$ swift run carton dev --custom-index-page Web/index.html

```

i get a bunch of `Sendable` noise, like with the older toolchain, and i also get these, which sound benign at least.

```plaintext
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/lib_FoundationCollections.a: archive member '_FoundationCollections.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/libFoundation.a: archive member 'Foundation.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/libFoundationEssentials.a: archive member 'FoundationEssentials.autolink' is neither Wasm object file nor LLVM bitcode
wasm-ld: warning: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/lib/swift_static/wasi/libFoundationInternationalization.a: archive member 'FoundationInternationalization.autolink' is neither Wasm object file nor LLVM bitcode

```

but it Does Work, and i can see that i really can manipulate DOM with JavaScriptKit, which is cool!

 ![Firefox_Screenshot_2025-01-22T00-57-23.734Z](https://global.discourse-cdn.com/swift/original/3X/9/4/948d7f61b242b4248235fb81b91e039f26bb50c8.png)

## 🥳 do i really need Tokamak UI?

i barely know anything about [JavaScriptKit](https://github.com/swiftwasm/JavaScriptKit), but at first glance, it does not include an HTML renderer, which is perfect because it would have really sucked if JavaScriptKit forced me to use a particular HTML rendering framework.

i’ve heard about [Tokamak UI](https://github.com/TokamakUI/Tokamak), but i also know from this thread that @austintatious is doing Cool Stuff with Swift on WebAssembly without using Tokamak at all, so i am very curious: _do i really need Tokamak to do Serious WebAssembly?_

i take a look at its GitHub README, which is a pretty good README as far as GitHub READMEs go, because it tells me all of the important information i need to know about the framework without going into excessive detail.

 ![Firefox_Screenshot_2025-01-22T01-08-37.643Z](https://global.discourse-cdn.com/swift/original/3X/9/e/9e4198c700f2d88f0732f6e08d21b8d6be562cd3.png)

- it tells me that it has _a lot of current users_ (66 on the Discord!), which makes me want to use the framework.

- it tells me that it is _incomplete_, which does not make me want to use the framework.

- it tells me that it’s designed to mimic SwiftUI, which i guess would be a huge plus if i were porting a SwiftUI app, but i am not doing that, so that doesn’t apply to me.

so i imagine the algorithm for choosing Tokamak is: “_if you are invested in SwiftUI, then Definitely Yes; otherwise, Explore Your Alternatives._”

i scroll down a bit more, and i see that Tokamak does HTML rendering. that confirms that i was hoping for — JavaScriptKit does JavaScript interop, and Tokamak does HTML rendering (along with some “modern” front-end reacty stuff i don’t need just yet.) so this is Very Good. the Layering Makes Sense. neat!

## 😁 can i bring my own HTML renderer?

the HTML example on the Tokamak README looks like this:

```swift
struct SVGCircle: View {
  var body: some View {
    HTML("svg", ["width": "100", "height": "100"]) {
      HTML("circle", [
        "cx": "50", "cy": "50", "r": "40",
        "stroke": "green", "stroke-width": "4", "fill": "yellow",
      ])
    }
  }
}

```

not bad, but i would much rather use [swift-dom](https://github.com/tayloraswift/swift-dom).

the first thing i notice when i go back to my code is that sourcekit-lsp is not online. but i had already been warned about this, and apparently you have to build the project for the host to enable syntax highlighting.

 ![Screenshot from 2025-01-21 19-23-52](https://global.discourse-cdn.com/swift/original/3X/a/6/a600bbf93f5982578d8b03cd91cf4a07c995f45a.png)

 ![Screenshot from 2025-01-21 19-24-49](https://global.discourse-cdn.com/swift/original/3X/5/4/54a72f237d5787e746316a4d0f6ad7943715b088.png)

this is annoying but not the worst thing in the world. let’s make some HTML!

```swift
let html:HTML = .init
{
    $0[.svg, { $0.width = "100" ; $0.height = "100" }]
    {
        $0[.circle]
        {
            $0.cx = "50"
            $0.cy = "50"
            $0.r = "40"
            $0.stroke = "green"
            $0.stroke_width = "4"
            $0.fill = "yellow"
        }
    }
}

```

the first thing i try to do is render this HTML to a string, since that’s what it looked like i was doing in the example code. but that doesn’t work.

```swift
div.innerHTML = "\(html)"
// Cannot assign value of type 'String' to type 'JSValue'

```

okay, so we weren’t actually assigning a string to `innerHTML`, it was going through some kind of `ExpressibleByStringLiteral` sugar that doesn’t support string interpolations. code completion leads me to this instead:

```swift
div.innerHTML = .string("\(html)")

```

i suspect JavaScriptKit cannot bridge a native Swift `String` to JavaScript, so there is probably a buffer copy going on here. [`HTML`](https://swiftinit.org/docs/swift-dom/dom/html) stores its content as a plain old `[UInt8]`, and provides it through [`HTML.utf8`](https://swiftinit.org/docs/swift-dom/dom/html.utf8) so i wonder if there is a way to copy directly to a JavaScript string without converting to `String` in between. but that is a problem for another day.

## 🙁 previewing with `carton`

i re-run `carton dev` and reload the browser tab and… nothing loads

 ![image](https://global.discourse-cdn.com/swift/original/3X/5/a/5a7e416fce6517143d62d921b9f31ea40a5281e4.png)

in the VSCode terminal, i see this:

```plaintext
open browser failed: Executable xdg-open not found in PATHINFO [org.swiftwasm.carton.dev-server] GET /
INFO [org.swiftwasm.carton.dev-server] GET /dev.js
INFO [org.swiftwasm.carton.dev-server] GET /main.wasm
INFO [org.swiftwasm.carton.dev-server] GET /favicon.ico
INFO [org.swiftwasm.carton.dev-server] GET /JavaScriptKit_JavaScriptKit.resources/Runtime/index.mjs
INFO [org.swiftwasm.carton.dev-server] GET /
INFO [org.swiftwasm.carton.dev-server] GET /dev.js
INFO [org.swiftwasm.carton.dev-server] GET /main.wasm
INFO [org.swiftwasm.carton.dev-server] GET /favicon.ico
INFO [org.swiftwasm.carton.dev-server] GET /JavaScriptKit_JavaScriptKit.resources/Runtime/index.mjs

An error occurred, here's a stack trace for it:

An error occurred, here's a stack trace for it:

```

i reload the page, and this time it loads successfully. the circle is there!

 ![image](https://global.discourse-cdn.com/swift/original/3X/f/0/f063dcb4fc918f0592f8a84bf230604e2e87b4ea.png)

i would brush off the failed page load as a one-time thing, but as i use `carton` more and more, i notice it continuing to happen. moreover, sometimes the WebAssembly just doesn’t load at all while Firefox says it’s “transferring data”, forever. it almost feels like there is some kind of browser session state that `carton` has, because it will only start loading when i open the URL in a Private Browsing Window.

so from now on, i just use Private Browsing to preview WebAssembly with `carton`.

## 🤔 implementing drag-and-drop

let’s try and add some event handlers to that `div`!

this is Pretty Tough. `JavaScriptKit` relies almost entirely on `@dynamicMemberLookup`, which means no code completion.

the API is not intuitive. this does not compile:

```swift
div.addEventListener("dragover") 
{
    $0.preventDefault()
}
// error: Extra trailing closure passed in call

```

the diagnostic doesn’t give me any leads at all. that function is `@dynamicCallable`, so there is no signature when i hover over it in VSCode. i jump back over @svanimpe ’s examples, and am lucky enough to come across [`connect-four/Front-end/Sources/WebUI.swift`](https://github.com/pwsacademy/swiftwasm-examples/blob/main/connect-four/Front-end/Sources/WebUI.swift) which has an example of how to call `addEventListener`:

> <https://github.com/pwsacademy/swiftwasm-examples/blob/main/connect-four/Front-end/Sources/WebUI.swift#L16C1-L29C11>

**thank you Steven!** now i have this:

```swift
_ = div.addEventListener("dragover", JSClosure.init
{
    $0[0].preventDefault()
})

```

## 😎 printing things to the console

i then tried printing a message to the terminal

```swift
_ = div.addEventListener("dragover", JSClosure.init
{
    print("DRAGGED")
    $0[0].preventDefault()
})

```

that didn’t compile, which i didn’t understand at first, because i thought this was a `Void`-returning function, but it turns out that `preventDefault` returns a `JSValue`, which was being used as the closure return type because of Swift’s implicit return syntax. (_please_, let us not add any more implicit syntax to the language!)

it seems JavaScript does not have `Void` functions, so we must explicitly return `.undefined`.

weird at first, but it makes sense and you get used to it over time.

```swift
_ = div.addEventListener("dragover", JSClosure.init
{
    print("DRAGGED")
    _ = $0[0].preventDefault()
    return .undefined
})

```

funny enough, Swift WebAssembly is smart enough to connect `Swift.print` to `console.log`, so the print actually worked, even though i didn’t really expect it to. neat!

## 😰 the drop handler

next up is the drop handler!

JavaScriptKit is really hard to use. it has its patterns, which make sense after a while, but it was very unintuitive as someone Completely New to the framework. i often found myself tunneling through the source code for JavaScriptKit to figure out how to do basic things with this library.

```swift
_ = div.addEventListener("drop", JSClosure.init
{
    print("DROPPED")
    let event:JSValue = $0[0]
    _ = event.preventDefault()

    guard
    case .object(let data) = event.dataTransfer
    else
    {
        return .undefined
    }

    print(data)
    print(data.files)

    guard data.files.length == 1
    else
    {
        print("Need exactly one file")
        return .undefined
    }

    return .undefined
})

```

one thing that stumped me for a really long time was how to call functions.

```swift
guard
case .object(let file) = data.files[0],
case .object(let promise) = file.bytes()
else
{
    print("Not a file")
    return .undefined
}

```

```plaintext
Value of optional type '((any ConvertibleToJSValue...) -> JSValue)?' 
must be unwrapped to a value of type 
'(any ConvertibleToJSValue...) -> JSValue'

App.swift(55, 38): Coalesce using '??' to provide a default when the optional value contains 'nil'
App.swift(55, 38): Force-unwrap using '!' to abort execution if the optional value contains 'nil'

```

…huh?

as it turns out, `file.bytes` is not a real instance method, it’s a functor thing you have to unwrap with optional chaining, even though this is not required anywhere else.

```diff
- case .object(let promise) = file.bytes()
+ case .object(let promise)? = file.bytes?()

```

## 🫨 typechecking with JavaScriptKit

typechecking with JavaScriptKit is really, really confusing.

the next few lines i wrote were this:

```swift
    promise.then?(JSClosure.init
    {
        guard case .object(let typedArray) = $0
        else
        {
            print("Not bytes")
            return .undefined
        }

        return .undefined
    })

```

that suddenly caused the code i had written 30 lines above to stop type checking!

 ![image](https://global.discourse-cdn.com/swift/original/3X/a/2/a2eb5d97bd19e06df4e3a881a84b350b5e9f65e4.png)

```plaintext
/swift/wasm-test/Sources/BSONViewer/App.swift:40:17: error: value of tuple type '()' has no member 'undefined'
38 | else
39 | {
40 | return .undefined
   | `- error: value of tuple type '()' has no member 'undefined'
41 | }

```

…what? `value of tuple type '()' has no member 'undefined'`?

of course, the actual problem was i had forgotten `JSClosure` passes an array of arguments instead of a single argument.

```diff
    promise.then?(JSClosure.init
    {
- guard case .object(let typedArray) = $0
+ guard case .object(let typedArray) = $0[0]

```

but that had nothing to do with tuples having members `undefined`, and it was in a completely different scope of the code.

i spent a lot of time trying to figure out what was going wrong here. i also spent some time trying to figure out how to convert a [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) to a `[UInt8]`, but i suppose that is a less common use case.

```swift
        let bytes:[UInt8] = JSTypedArray<UInt8>.init(
            unsafelyWrapping: typedArray).withUnsafeBytes
        {
            [UInt8].init($0)
        }

```

i learned how to do this by [searching GitHub for `'Uint8Array'`](https://github.com/search?q=repo%3Aswiftwasm%2FJavaScriptKit%20Uint8Array&type=code) and skimming the source code of [`JSTypedArray.swift`](https://github.com/swiftwasm/JavaScriptKit/blob/91350448aa5302269ee73664b1c32cb21ea6820c/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift#L166).

## 💣 parsing BSON with Swift WebAssembly

okay, pretty cool! i can get raw bytes from drag and drop files with WebAssembly! now let’s parse some BSON!

i hook up swift-bson to Package.swift, and bind the array to `BSON.Document` in the app code.

```swift
.package(url: "https://github.com/tayloraswift/swift-bson", from: "1.0.0"),

```

```swift
.executableTarget(name: "BSONViewer",
            dependencies: [
            .product(name: "JavaScriptKit", package: "JavaScriptKit"),
            .product(name: "BSON", package: "swift-bson"),
            .product(name: "HTML", package: "swift-dom"),
        ]),

```

```swift
        let bson:BSON.Document = .init(bytes: bytes[...])

```

i build it on the host, so far so good!

```plaintext
$ swift build
Building for debugging...
/swift/wasm-test/Sources/BSONViewer/App.swift:78:13: warning: immutable value 'bson' was never used; consider replacing with '_' or removing it
76 | }
77 | 
78 | let bson:BSON.Document = .init(bytes: bytes[...])
   | `- warning: immutable value 'bson' was never used; consider replacing with '_' or removing it
79 | 
80 | return .undefined
/swift/wasm-test/Sources/BSONViewer/App.swift:78:13: warning: immutable value 'bson' was never used; consider replacing with '_' or removing it
76 | }
77 | 
78 | let bson:BSON.Document = .init(bytes: bytes[...])
   | `- warning: immutable value 'bson' was never used; consider replacing with '_' or removing it
79 | 
80 | return .undefined
[12/12] Linking BSONViewer
Build complete! (1.73s)

```

now let’s build for WebAssembly…

```plaintext
$ swift run carton dev --custom-index-page Web/index.html
Building for debugging...
[1/1] Write swift-version--75355AAB4E86B17C.txt
Build of product 'carton' complete! (0.76s)
- checking Swift compiler path: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/bin/swift
Inferring basic settings...
- swift executable: /home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/bin/swift
Swift version 6.1-dev (LLVM 38a3fc37c5f5e7a, Swift eedae18ae4df60a)
Target: x86_64-unknown-linux-gnu
Running "/home/ubuntu/.carton/sdk/wasm-6.1-SNAPSHOT-2025-01-18-a/usr/bin/swift" "package" "--triple" "wasm32-unknown-wasi" "--scratch-path" "/swift/wasm-test/.build/carton" "--disable-sandbox" "plugin" "carton-dev" "--custom-index-page" "Web/index.html" "--pid" "170487"
Building for debugging...
[1/1] Write swift-version-5F410D2014D93A3.txt
Build of product 'carton-frontend' complete! (1.09s)
Building "BSONViewer"
Building for debugging...
[0/16] Write sources
[8/22] Write swift-version-5F410D2014D93A3.txt
...
[175/207] Compiling BSONDecoding BSON.TracingDecoder.swift
error: compile command failed due to signal 6 (use -v to see invocation)
Failed to reconstruct type for $sSY_s8SendablepSS8RawValueSYRts_XPXmTD
Original type:
(existential_metatype_type thick
  (protocol_composition_type
    (parameterized_protocol_type
      (base=protocol_type decl="Swift.(file).RawRepresentable")
      (struct_type decl="Swift.(file).String"))
    (protocol_type decl="Swift.(file).Sendable")))
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
Pass '-Xfrontend -disable-round-trip-debug-types' to disable this assertion.
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
Stack dump:
0. Program arguments: ...
1. Swift version 6.1-dev (LLVM 38a3fc37c5f5e7a, Swift eedae18ae4df60a)
2. Compiling with the current language version
3. While evaluating request IRGenRequest(IR Generation for file "/swift/wasm-test/.build/carton/checkouts/swift-bson/Sources/BSONDecoding/Decoding/BSON.KeyspaceError.swift")
4. While emitting IR SIL function "@$s7BSONABI4BSONO12BSONDecodingE13KeyspaceErrorV5spaceSY_s8SendablepSS8RawValueSYRts_XPXpvg".
 for getter for space (at /swift/wasm-test/.build/carton/checkouts/swift-bson/Sources/BSONDecoding/Decoding/BSON.KeyspaceError.swift:15:13)
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0 swift-frontend 0x000060c2a8fd7157
1 swift-frontend 0x000060c2a8fd4d0e
2 swift-frontend 0x000060c2a8fd77fa
3 libc.so.6 0x0000733ce7045320
4 libc.so.6 0x0000733ce709eb1c pthread_kill + 284
5 libc.so.6 0x0000733ce704526e gsignal + 30
6 libc.so.6 0x0000733ce70288ff abort + 223
7 swift-frontend 0x000060c2a211f51e
8 swift-frontend 0x000060c2a211f8bd
9 swift-frontend 0x000060c2a21166a2
10 swift-frontend 0x000060c2a2117282
11 swift-frontend 0x000060c2a2134b45
12 swift-frontend 0x000060c2a2133f2f
13 swift-frontend 0x000060c2a1fd23ff
14 swift-frontend 0x000060c2a1e4ccc9
15 swift-frontend 0x000060c2a1ebde33
16 swift-frontend 0x000060c2a1ebdd89
17 swift-frontend 0x000060c2a1e56e8f
18 swift-frontend 0x000060c2a1e4f50e
19 swift-frontend 0x000060c2a19d6b79
20 swift-frontend 0x000060c2a19d2812
21 swift-frontend 0x000060c2a19d154b
22 swift-frontend 0x000060c2a19e1ff5
23 swift-frontend 0x000060c2a19d43f5
24 swift-frontend 0x000060c2a19d34ac
25 swift-frontend 0x000060c2a17ab803
26 libc.so.6 0x0000733ce702a1ca
27 libc.so.6 0x0000733ce702a28b __libc_start_main + 139
28 swift-frontend 0x000060c2a17aa885

```

well, we were always going to run into this sooner or later. kids, this is why we don’t use nightly toolchains!

## 🥲 marty, we have to go back!!!

okay, so `wasm-6.1-SNAPSHOT-2025-01-18-a` was always going to be a gamble, and we can’t use `6.0.2-RELEASE` in production, but for curiosity’s sake, i at least want to know if my code does the thing i’m expecting it to.

so i switch my `.swift-version` back to `6.0.2-RELEASE`. i add a couple lines to dump the BSON to the console:

```swift
        let bson:BSON.Document = .init(bytes: bytes[...])
        print(bytes.count)
        print("\(bson)")

```

i drag and drop a random BSON file i had lying around, and boom! it shows up!

 ![image](https://global.discourse-cdn.com/swift/original/3X/6/f/6fa39d672859aa51489e9df391acf8ae5e357d41.png)

## 🤔 conclusions

we are so close. _so close_. i have learned how to run Swift Code that depends on Real Swift Libraries directly in Firefox. this is really cool!

but the binaries are quite large. they take a very long time to download, which severely limits their practical applications.

these problems can be mitigated _in theory_ by using experimental Swift compiler features, but this fails when you try to use Swift on WebAssembly to build anything bigger than a minimal test project.

i am very interested in hearing from anyone using Swift on WebAssembly in production who has figured out a way to work around the frequent compiler crashes.

---

<div class="post-metadata">

**Author:** ![j-f1](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/j-f1/32/12287_2.png) [@j-f1](https://forums.swift.org/u/j-f1)\
**Post date:** [January 22, 2025, 3:59am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/16 "2025-01-22T03:59:39Z")

</div>

To mitigate some of the difficulties with types in JavaScriptKit, you could try using [WebAPIKit](https://github.com/swiftwasm/WebAPIKit). I was unfortunately never able to get it to a fully finished state but it should provide “type-safe” access to all the symbols defined by the various web specifications. You can start off with `globalThis` from `import DOM` which has all the global variables in JS available like `document`. The methods are all properly typed so you can use things like trailing closures. There’s still no documentation so it works best if you have MDN open in another tab while using it, though. (A neat extension would be to scrape the intro paragraphs from there to generate doc comments!)

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [January 22, 2025, 4:08am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/17 "2025-01-22T04:08:29Z")

</div>

i isolated the compiler crash to this reproducer

```swift
var x:any (Sequence<String> & Sendable).Type

```

> <https://github.com/swiftlang/swift/issues/78802>
>
> \### Description
> 
> the test program below crashes on \`swift-DEVELOPMENT-SNAPSHOT-2…025-01-10\`. this only happens when using \`-g\`, which SwiftPM uses
> 
> it also crashes \[on Fiddle\](https://swiftfiddle.com/td7c6w7crzaubmzflrkj3wxvuq)
> 
> \### Reproduction
> 
> \`\`\`swift
> var x:any (Sequence\<String\> & Sendable).Type
> \`\`\`
> 
> 
> \### Stack dump
> 
> \`\`\`text
> $ /swift/swift-DEVELOPMENT-SNAPSHOT-2025-01-10-a-ubuntu24.04/usr/bin/swiftc \_crash.swift -g
> error: compile command failed due to signal 6 (use -v to see invocation)
> Failed to reconstruct type for $ss8Sendable\_STpSS7ElementSTRts\_XPXmTD
> Original type:
> (existential\_metatype\_type thick
> (protocol\_composition\_type
> (protocol\_type decl="Swift.(file).Sendable")
> (parameterized\_protocol\_type
> (base=protocol\_type decl="Swift.(file).Sequence")
> (struct\_type decl="Swift.(file).String"))))
> Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
> Pass '-Xfrontend -disable-round-trip-debug-types' to disable this assertion.
> Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
> Stack dump:
> 0. Program arguments: /swift/swift-DEVELOPMENT-SNAPSHOT-2025-01-10-a-ubuntu24.04/usr/bin/swift-frontend -frontend -c -primary-file \_crash.swift -target x86\_64-unknown-linux-gnu -disable-objc-interop -color-diagnostics -g -debug-info-format=dwarf -dwarf-version=4 -empty-abi-descriptor -resource-dir /swift/swift-DEVELOPMENT-SNAPSHOT-2025-01-10-a-ubuntu24.04/usr/lib/swift -enable-anonymous-context-mangled-names -file-compilation-dir /swift/swift-bson -module-name \_crash -in-process-plugin-server-path /swift/swift-DEVELOPMENT-SNAPSHOT-2025-01-10-a-ubuntu24.04/usr/lib/swift/host/libSwiftInProcPluginServer.so -plugin-path /swift/swift-DEVELOPMENT-SNAPSHOT-2025-01-10-a-ubuntu24.04/usr/lib/swift/host/plugins -plugin-path /swift/swift-DEVELOPMENT-SNAPSHOT-2025-01-10-a-ubuntu24.04/usr/local/lib/swift/host/plugins -o /tmp/TemporaryDirectory.cRQLhm/\_crash-2.o
> 1. Swift version 6.2-dev (LLVM 81859ac55f8d09a, Swift 8ec8a1229a7ea14)
> 2. Compiling with effective version 5.10
> 3. While evaluating request IRGenRequest(IR Generation for file "\_crash.swift")
> Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var \`LLVM\_SYMBOLIZER\_PATH\` to point to it):
> 0 swift-frontend 0x000057933084d4d8
> 1 swift-frontend 0x000057933084b07e
> 2 swift-frontend 0x000057933084db78
> 3 libc.so.6 0x00007e7660445320
> 4 libc.so.6 0x00007e766049eb1c pthread\_kill + 284
> 5 libc.so.6 0x00007e766044526e gsignal + 30
> 6 libc.so.6 0x00007e76604288ff abort + 223
> 7 swift-frontend 0x0000579329467ee2
> 8 swift-frontend 0x000057932946141c
> 9 swift-frontend 0x0000579329323b64
> 10 swift-frontend 0x0000579329324810
> 11 swift-frontend 0x00005793293a3e8f
> 12 swift-frontend 0x000057932931a864
> 13 swift-frontend 0x0000579329199675
> 14 swift-frontend 0x000057932920ac2c
> 15 swift-frontend 0x000057932920ab89
> 16 swift-frontend 0x00005793291a3a84
> 17 swift-frontend 0x000057932919bdf8
> 18 swift-frontend 0x0000579328d153d6
> 19 swift-frontend 0x0000579328d10ed5
> 20 swift-frontend 0x0000579328d0f9b8
> 21 swift-frontend 0x0000579328d20cca
> 22 swift-frontend 0x0000579328d1298e
> 23 swift-frontend 0x0000579328d11b3d
> 24 swift-frontend 0x0000579328aaaf1a
> 25 libc.so.6 0x00007e766042a1ca
> 26 libc.so.6 0x00007e766042a28b \_\_libc\_start\_main + 139
> 27 swift-frontend 0x0000579328aa9f15
> \`\`\`
> 
> \### Expected behavior
> 
> this compiled successfully on the 6.0.3 release toolchain
> 
> \### Environment
> 
> $ /swift/swift-DEVELOPMENT-SNAPSHOT-2025-01-10-a-ubuntu24.04/usr/bin/swiftc --version     
> Swift version 6.2-dev (LLVM 81859ac55f8d09a, Swift 8ec8a1229a7ea14)
> Target: x86\_64-unknown-linux-gnu
> 
> \### Additional information
> 
> \_No response\_

> [@j-f1](#):
>
> To mitigate some of the difficulties with types in JavaScriptKit, you could try using [WebAPIKit](https://github.com/swiftwasm/WebAPIKit). I was unfortunately never able to get it to a fully finished state but it should provide “type-safe” access to all the symbols defined by the various web specifications.

nice, i’ll take a look at that

---

<div class="post-metadata">

**Author:** ![sliemeobn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sliemeobn/32/27698_2.png) [@sliemeobn](https://forums.swift.org/u/sliemeobn)\
**Post date:** [January 22, 2025, 10:57am UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/18 "2025-01-22T10:57:04Z")

</div>

@taylorswift not sure if you've seen it, but I was exploring this space as well a while ago and posted about it here:

> [@Web App with Embedded Swift - POC demo](https://forums.swift.org/t/web-app-with-embedded-swift-poc-demo/75486):
>
> Hello lovely community, I just pushed an Embedded Swift proof-of-concept Wasm app out the door that uses [JavaScriptKit](https://github.com/swiftwasm/JavaScriptKit)[elementary-dom](https://github.com/sliemeobn/elementary-dom) (the experimental reactive [Elementary](https://github.com/sliemeobn/elementary) package I am playing with) SwiftPM for building the whole thing (with a few hacks, see below) It is a simplified wordle clone that clocks in at around 71 kB (compressed wasm). Check it out here -\>\> [Swiftle - Embedded Demo App](https://sliemeobn.github.io/elementary-dom/) \<\<- ([source code](https://github.com/sliemeobn/elementary-dom/tree/main/Examples/Swiftle)) Things with this setup are a bit rough but almost good enough, and I wanted t…

I agree that going embedded is a tall order for now, but the [elementary-dom](https://github.com/sliemeobn/elementary-dom) package should also work just fine with carton and "full swift". I think it could be a nicer path to happiness rather than trying to get Tokamak in "lean web" shape.

so, "for your consideration" ; )

---

<div class="post-metadata">

**Author:** ![Max\_Desiatov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/max_desiatov/32/20654_2.png) [@Max\_Desiatov](https://forums.swift.org/u/Max_Desiatov)\
**Post date:** [January 22, 2025, 12:17pm UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/19 "2025-01-22T12:17:09Z")

</div>

> [@taylorswift](#):
>
> while not being restricted completely to the Embedded subset of the language

IMO, it is much more realistic to expect that Embedded Swift gains features that you need (if you highlight those as required for your use cases and file corresponding issues at swiftlang/swift/issues) than to expect non-embedded binaries to get significantly smaller. In fact, at least in the context of Wasm, I suggest reading "Embedded mode" as "small binaries mode" and adopting it as such.

In the non-embedded mode, try using `FoundationEssentials` instead of `Foundation`, or avoid using any Foundation modules altogether if `FoundationEssentials` brings in too much for your use case. Annotating/refining `swift-foundation` and `swift-corelibs-foundation` codebases for compatibility with Embedded Swift also seems to be a goal worth pursuing.

Starting with Swift 6.1, I'd also recommend package authors interested in small binaries to consider providing separate [package traits](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0450-swiftpm-package-traits.md), e.g. a Foundation-less trait, and maybe an embedded trait, or utilize `@_unavailableInEmbedded` API annotation, for users who aren't satisfied with sizes of binaries produced with default traits.

---

<div class="post-metadata">

**Author:** ![sliemeobn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sliemeobn/32/27698_2.png) [@sliemeobn](https://forums.swift.org/u/sliemeobn)\
**Post date:** [January 22, 2025, 2:45pm UTC](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305/20 "2025-01-22T14:45:32Z")

</div>

> [@Max\_Desiatov](#):
>
> Starting with Swift 6.1, I'd also recommend package authors interested in small binaries to consider providing separate [package traits](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0450-swiftpm-package-traits.md), e.g. a Foundation-less trait, and maybe an embedded trait, or utilize `@_unavailableInEmbedded` API annotation, for users who aren't satisfied with sizes of binaries produced with default traits.

I absolutely agree that "embedded swift" should be the focus for small wasm binaries (eg: browser apps) - shipping a heavy runtime in your binary feels so wrong once you realize how little you need of it.

however, IMHO, as it stands, utilizing package traits hardly moves the needle towards this goal. there are still so many rough edges... off the top of my head:

- SwiftPM still cannot really link a binary in embedded (with versioned dependencies)
- linking `@_cdecl` and `@_extern` symbols from dependencies does not work
- string handling intricacies not ideal (unicode support)
- no good solution for `Codable` (web apps without easy handling of JSON? what are we even doing....)

And more generally, I think relying on every package to carefully offer an "embedded" trait is not exactly optimal for adoption/portability either, especially when a lot of code would "just work" anyway.

[Next page](https://forums.swift.org/t/how-far-can-i-get-with-swift-webassembly-in-30-minutes/77305.md?page=2)
