Add wasip1 support, enabling CLI, API, browser, sync/async - #64174
Draft
Jake Bailey (jakebailey) wants to merge 7 commits into
Draft
Add wasip1 support, enabling CLI, API, browser, sync/async#64174Jake Bailey (jakebailey) wants to merge 7 commits into
Jake Bailey (jakebailey) wants to merge 7 commits into
Conversation
Add an injectable synchronous transport and a browser-conditioned client for the TypeScript API. Provide a Go WebAssembly reactor backed by an in-memory filesystem and exercise it through the compiler and checker APIs. Publish the reactor and its transport separately as @typescript/api-wasm, with release-versioned builds and ordered npm publishing. Keep the main TypeScript package free of the WebAssembly binary and verify its browser module graph with an esbuild regression test.
Reuse the existing async and sync API suites in Playwright with narrow browser shims and explicit host-only exclusions. Add WASI scheduler polling and callback-backed output writes so WasmTransport preserves native filesystem behavior.
Do not clear filesystem callbacks configured directly on a transport when the API is constructed without its own filesystem. Assert that the browser harness accounts for all 669 API tests and cover WASM emit callbacks through the public transport setup.
Keep an active transport's filesystem callback intact when a second transport fails to create a session on the same reactor instance.
Close a newly created reactor session when filesystem callback attachment fails so the instance remains reusable.
Build the compiler, language server, and in-process API from one WASI module. Add the Node fallback, platform-specific runtime behavior, and release packaging for the unified artifact.
Return io.EOF when WASI stdin closes instead of triggering repeated empty reads. Cover the command lifecycle in the unified module test.
Jake Bailey (jakebailey)
force-pushed
the
wasip1
branch
from
September 4, 2026 21:21
f6f443f to
cdbe79f
Compare
Copilot started reviewing on behalf of
Jake Bailey (jakebailey)
September 4, 2026 21:24
View session
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
WASI LSP stdin busy-spins while idle, and process-backed API shutdown can hang during manually batched initialization.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds experimental WASI support for the TypeScript CLI and synchronous/asynchronous APIs across Node.js and browsers.
Changes:
- Adds a dual CLI/reactor
tsc.wasmbuild and minimal WASI host. - Introduces injectable API transports and browser-compatible clients.
- Adds packaging, publishing, CI, and integration-test coverage.
File summaries
| File | Description |
|---|---|
tsc/internal/ipc/timing.go |
Exposes server timing collection. |
tsc/internal/api/wasmreactor/reactor.go |
Implements the in-process API reactor. |
tsc/internal/api/wasmreactor/reactor_test.go |
Tests reactor requests and files. |
tsc/cmd/tsc/wasmapi_wasip1.go |
Defines the WebAssembly reactor ABI. |
tsc/cmd/tsc/sys.go |
Uses platform-aware working-directory lookup. |
tsc/cmd/tsc/notifycontext.go |
Provides native signal handling. |
tsc/cmd/tsc/notifycontext_wasip1.go |
Disables unsupported WASI signals. |
tsc/cmd/tsc/main.go |
Uses platform-specific notification contexts. |
tsc/cmd/tsc/lsp.go |
Makes LSP dependencies WASI-compatible. |
tsc/cmd/tsc/lsp_stdin.go |
Defines native LSP stdin. |
tsc/cmd/tsc/lsp_stdin_wasip1.go |
Adds WASI stdin handling. |
tsc/cmd/tsc/lsp_process.go |
Defines native process integrations. |
tsc/cmd/tsc/lsp_process_wasip1.go |
Disables unavailable WASI process features. |
tsc/cmd/tsc/currentdirectory.go |
Defines native cwd lookup. |
tsc/cmd/tsc/currentdirectory_wasip1.go |
Derives WASI cwd from PWD. |
tsc/cmd/tsc/api.go |
Uses portable cwd and signal helpers. |
tools/pipelines/typescript-publish.yml |
Publishes the WASI npm artifact. |
packages/typescript/test/version.test.ts |
Tests CLI WASI fallback. |
packages/typescript/test/sync/wasm.test.ts |
Tests CLI and API WebAssembly execution. |
packages/typescript/test/sync/transport.test.ts |
Tests synchronous injected transports. |
packages/typescript/test/encoder.test.ts |
Tests portable base64 encoding. |
packages/typescript/test/browser/wasm.test.ts |
Tests WebAssembly APIs in Chromium. |
packages/typescript/test/browser/syncAPI.ts |
Adapts sync API browser tests. |
packages/typescript/test/browser/suite.test.ts |
Runs API suites in Chromium. |
packages/typescript/test/browser/processShim.ts |
Provides browser process/timer shims. |
packages/typescript/test/browser/harness.ts |
Implements the browser test harness. |
packages/typescript/test/browser/bundle.test.ts |
Verifies browser-safe bundles. |
packages/typescript/test/browser/asyncAPI.ts |
Adapts async API browser tests. |
packages/typescript/test/browser/apiWrapper.ts |
Manages browser reactors and filesystem mirroring. |
packages/typescript/test/async/transport.test.ts |
Tests asynchronous transport behavior. |
packages/typescript/src/api/sync/transportClient.ts |
Implements sync protocol-over-transport. |
packages/typescript/src/api/sync/transport.ts |
Defines the sync transport contract. |
packages/typescript/src/api/sync/client.ts |
Supports injected sync transports. |
packages/typescript/src/api/sync/browserClient.ts |
Adds the browser sync client. |
packages/typescript/src/api/sync/api.ts |
Routes generated sync API through browser-aware clients. |
packages/typescript/src/api/options.ts |
Adds transport-based API options. |
packages/typescript/src/api/node/wtf8.ts |
Removes the Node buffer dependency. |
packages/typescript/src/api/node/encoder.ts |
Adds portable base64 encoding. |
packages/typescript/src/api/async/transportClient.ts |
Implements async protocol batching and lifecycle. |
packages/typescript/src/api/async/transport.ts |
Defines the async transport contract. |
packages/typescript/src/api/async/client.ts |
Supports injected async transports. |
packages/typescript/src/api/async/browserClient.ts |
Adds the browser async client. |
packages/typescript/src/api/async/api.ts |
Selects browser-aware clients and adjusts closing. |
packages/typescript/package.json |
Exports transports and browser clients. |
packages/typescript/lib/tsc.js |
Falls back to WASI when native binaries are unavailable. |
packages/typescript/lib/getExePath.js |
Resolves the WASI package artifact. |
packages/typescript/lib/getExePath.d.ts |
Declares WASI path resolution. |
packages/typescript-wasip1-wasm/tsconfig.json |
Configures the WASI helper package. |
packages/typescript-wasip1-wasm/src/wasmURL.ts |
Exposes the packaged module URL. |
packages/typescript-wasip1-wasm/src/wasmURL.source.ts |
Exposes the source-build module URL. |
packages/typescript-wasip1-wasm/src/wasi.ts |
Implements the browser WASI host. |
packages/typescript-wasip1-wasm/src/index.ts |
Implements and exports WasmTransport. |
packages/typescript-wasip1-wasm/README.md |
Documents CLI and API usage. |
packages/typescript-wasip1-wasm/package.json |
Defines the WASI npm package. |
package.json |
Adds Binaryen tooling. |
package-lock.json |
Locks new packages and workspace metadata. |
Herebyfile.mjs |
Builds, patches, tests, and packages WebAssembly. |
.github/workflows/ci.yml |
Runs Chromium API tests in CI. |
Review details
- Files reviewed: 56/58 changed files
- Comments generated: 2
- Review effort level: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+19
to
+22
| if err != syscall.EAGAIN { | ||
| return n, err | ||
| } | ||
| runtime.Gosched() |
Comment on lines
+395
to
+399
| if (this.initializing && !this.initialized) { | ||
| const initializing = this.initializing; | ||
| await this.client.close(); | ||
| await initializing.catch(() => {}); | ||
| this.sourceFileCache.clear(); |
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.
Fixes #63858
Fixes #63862
For #63813
This is still a bit experimental, but this creates a wasip1
tsc.wasmbuild. This build works as a CLI, so one can run it anywhere and get the CLI, LSP server, etc. But, one can also instantiate the module and give it to the new TypeScript IPC-based API (including in the browser!) and get sync/async API access. This works similarly (though not the same) to David Sherret's ts-ast-viewer tsgo prototype. The dual-nature of this is enabled by some Wasm export +binaryentrickery to make one blob that can do both things.In a perfect world, we'd be able to do wasip3 or something, component model, yadda yadda, but the main Go compiler cannot do that yet.
I think for now, this works alright. I think I'd also want to slap a "no warranty" label on this for now until we can get Wasm a bit more settled.
Some interesting tidbits:
node:test, I had copilot write some shims for those APIs to make it work. Smarter would be to use vitest in browser mode, I suspect. But this works and runs all but 20 tests succesfully.TODO: