WASI support: build SQLiteKit without SwiftNIO or AsyncKit - #4
Draft
scottmarchant wants to merge 3 commits into
Draft
WASI support: build SQLiteKit without SwiftNIO or AsyncKit#4scottmarchant wants to merge 3 commits into
scottmarchant wants to merge 3 commits into
Conversation
scottmarchant
force-pushed
the
feat/wasi-nio-free
branch
from
July 29, 2026 00:21
505c544 to
1927fd4
Compare
Motivation: Neither SwiftNIO nor AsyncKit can be built for `wasm32-unknown-wasip1`: NIOPosix is built on POSIX sockets and threads, neither of which WASI preview 1 provides, and AsyncKit's connection pool is built on NIOPosix in turn. SQLiteKit uses them for the connection pool and for the legacy `EventLoopFuture` half of an API whose `async` half is already the recommended one, so it can build without them, given somewhere to put the differences. Modifications: Gate the affected declarations with `#if canImport(...)`, keyed on the module that actually supplies each API rather than on a platform, so the sources stay in step with whatever the manifest resolves for the target being built and with the gates sqlite-nio and sql-kit apply to the same dependencies. What drops out where the modules are absent: - `SQLiteConnectionSource` — a `ConnectionPoolSource` over AsyncKit and `NIOThreadPool` — drops out entirely, along with the `AsyncKit` re-export. Callers use sqlite-nio's concrete `async` `SQLiteConnection` directly; there is no connection pool on those platforms. - The `SQLDatabase` wrapper's `eventLoop`, its `execute(sql:_:) -> EventLoopFuture<Void>` overload, and `withSession(_:)` (which rides sqlite-nio's protocol-level `withConnection`) drop out. SQLKit removes the first two as protocol requirements on the same platforms and supplies a default for the third. - `SQLiteDataDecoder`'s JSON fallback reads a `[UInt8]` blob rather than a `ByteBuffer`, matching `SQLiteData`'s representation there. The decoder's two blob cases stay forked rather than collapsing to the `[UInt8]` form on both: `Data.init(buffer:byteTransferStrategy:)` is a zero-copy bridge with no `[UInt8]` equivalent, so collapsing them would silently add a copy where SwiftNIO is present. The gate names NIOFoundationCompat, which is the module that declares that initializer. `SQLiteDataEncoder`'s `import NIOCore` is dropped rather than gated: the file references no NIOCore symbol, so the import was already dead. Result: Where SwiftNIO and AsyncKit are available the public API and the symbol graph are unchanged — the same symbols with the same `docComment` line counts — and `diagnose-api-breaking-changes` reports no differences. Where they are absent SQLiteKit compiles down to the pool-free, `async`-only surface.
Motivation: Neither SwiftNIO nor AsyncKit builds for `wasm32-unknown-wasip1`, so SQLiteKit currently fails to configure for that platform at all — the failure is in dependency resolution, before any of the conditional sources in the previous commit get a chance to matter. Modifications: Gate the NIOFoundationCompat and AsyncKit products on `.when(platforms: nonWASIPlatforms)` in both manifests. Target dependency conditions are evaluated per platform, so on WASI the products are simply not linked and the `canImport(...)` gates select the pool-free `async` API. `.when(platforms:)` can only include, never exclude, so excluding one platform means enumerating the others; each list is the set the manifest's own tools version knows about, noted as such so it is not extended without also raising that version. Result: On every other platform the resolved dependency set is byte-identical to before. On WASI the build graph contains no SwiftNIO and no AsyncKit module.
Motivation: `vapor/ci`'s reusable unit-test workflow already knows how to build a package for `wasm32-unknown-wasip1`; sqlite-kit simply had not opted in, so nothing stops the SwiftNIO-free configuration from regressing unnoticed. Modifications: Pass `with_wasm: true` to the reusable workflow, as sql-kit already does. Result: The WASI build is checked on every pull request.
scottmarchant
force-pushed
the
feat/wasi-nio-free
branch
from
July 29, 2026 03:24
1927fd4 to
f0bff69
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on PassiveLogic/sqlite-nio#4 and PassiveLogic/sql-kit#3 being merged and tagged upstream before the WASI CI lane can pass. The released siblings have no WASI support (sqlite-nio's current release, 1.13.0, predates its WASI PR), so the version floors here will need bumping to the first releases that include it once those exist. Stays in draft until then. The native build and tests already pass against the released siblings, so the ordering only matters for the WASI lane.
Builds SQLiteKit on
wasm32-unknown-wasip1without SwiftNIO or AsyncKit. Embedded Swift is stacked separately as #5.Changes:
SQLiteConnectionSourceand theAsyncKitre-export gate oncanImport(AsyncKit), so there is no connection pool on WASI. That is a real functional loss worth being upfront about, and a tolerable one: WASI preview 1 is single-threaded, so a pool buys nothing there, and callers use sqlite-nio's concrete asyncSQLiteConnectiondirectly.SQLDatabasewrapper'seventLoop, itsEventLoopFutureexecuteoverload, andwithSession(_:)gate oncanImport(NIOCore), matching what SQLKit does to the corresponding protocol requirements.SQLiteDataDecoder's JSON fallback reads the blob as[UInt8]where NIOFoundationCompat is absent, matchingSQLiteData's representation there.Package.swiftat tools 5.8 and the existingPackage@swift-5.9.swift) get the same.when(platforms: nonWASIPlatforms)hunk, so 5.9+ toolchains are not silently left behind. Same idiom as Add support for WASILibc apple/swift-nio#2671.with_wasm: truetovapor/ci(sqlite-kit previously had nowith:block at all).On AsyncKit: upstream vapor/async-kit does not compile for WASI, so it is elided rather than ported, which removes vapor/async-kit#111 as a prerequisite entirely. If async-kit gains WASI support later, the condition relaxes and the pool comes back.
Verification:
swift buildandswift test: 9 tests green against the released siblings, which now resolve sqlite-nio at 1.13.0. The CI-flags build is warning-free against 1.13.0; the twoSendablewarnings previously noted here came from the older released sqlite-nio and are gone.swift package diagnose-api-breaking-changesreports no breaking changes.--swift-sdk swift-6.3.1-RELEASE_wasm), with the sibling WASI branches wired in viaswift package edit --path(the committed manifests keep the upstreamvapor/...URLs and floors): green, zero SwiftNIO or AsyncKit object files, no NIO, AsyncKit, EventLoop, or ByteBuffer symbols. The wasm check skips drafts and will stay red until the dependency PRs land and the floors are bumped, which is the sequencing note at the top.Notes for review: no SwiftPM traits, no manifest added, no tools-version bump, no new dependencies.
Base
base/vapor-mainis an exact snapshot of vapor/sqlite-kit@main at 492c46e, excluding the fork's one extra commit (the NIOAsyncRuntime approach from #3, superseded here; apple/swift-nio#3487 was closed unmerged and a pre-1.0 dependency is not acceptable upstream). Rebasing onto the realvapor/mainis a no-op.