### Wasmtime Output Example Source: https://github.com/microsoft/vscode-wasm/blob/main/testbeds/static-linking-wasi/readme.md This is an example of the expected output when the 'main.wasm' module is executed successfully. ```text The result is 3 ``` -------------------------------- ### Python C Extension Module Setup Source: https://github.com/microsoft/vscode-wasm/blob/main/docs/nativeModule.md Use this script to build Python extension modules in C. It configures the compiler and linker toolchain for C extensions. ```python from distutils.core import setup, Extension def main(): setup(name="fputs", version="1.0.0", description="Python interface for the fputs C library function", author="Dirk Baeumer", author_email="dirk.baeumer@gmail.com", ext_modules=[Extension("fputs", ["fputsmodule.c"])] ) if __name__ == "__main__": main() ``` -------------------------------- ### Worker Side Sync API Client Setup Source: https://github.com/microsoft/vscode-wasm/blob/main/sync-api-client/README.md Set up the worker side to establish a client connection and interact with the VS Code API. This includes connecting to the service, initializing the API client, and performing operations like reading workspace folders or files. ```typescript import { ClientConnection } from '@vscode/sync-api-common/browser'; import { ApiClient, APIRequests } from '@vscode/sync-api-client'; const connection = new ClientConnection(parentPort); await connection.serviceReady(); const apiClient = new ApiClient(connection); // Get the current workspace folders. const workspaceFolders = apiClient.vscode.workspace.workspaceFolders; // Read a file for a given uri const content = apiClient.vscode.workspace.filesystem.readFile(uri); ``` -------------------------------- ### Setup Extension Host Worker with Sync API Source: https://github.com/microsoft/vscode-wasm/blob/main/sync-api-client/README.md Configure the extension host worker to offer access to the VS Code API using the sync API service. Ensure the correct imports and service connection are established. ```typescript import { ServiceConnection } from '@vscode/sync-api-common/browser'; import { APIRequests, ApiService } from '@vscode/sync-api-service'; const worker = new Worker(...); const connection = new ServiceConnection(worker); const apiService = new ApiService('Worker Name', connection); // A terminal in case the worker write to one. const terminal = window.createTerminal({ name: 'Worker name', pty: apiService.getPty() }); terminal.show(); connection.signalReady(); ``` -------------------------------- ### Execute Python WASM Process in Web Shell Source: https://github.com/microsoft/vscode-wasm/blob/main/webshell/README.md Implement a command handler to execute a Python WASM binary. This example demonstrates setting up process options, including environment variables and arguments, and compiling and running the WASM module. ```typescript commands.registerCommand('testbed-python.webshell.python', async (_command: string, args: string[], _cwd: string, stdio: Stdio, mountPoints?: MountPointDescriptor[] | undefined): Promise => { const options: ProcessOptions = { stdio, mountPoints: (mountPoints ?? []).concat([ { kind: 'workspaceFolder' }, { kind: 'extensionLocation', extension: context, path: 'wasm/lib', mountPoint: '/usr/local/lib/python3.11' } ]), env: { PYTHONPATH: '/workspace' }, args: ['-B', '-X', 'utf8', ...args] }; const filename = Uri.joinPath(context.extensionUri, 'wasm', 'bin', 'python.wasm'); const bits = await workspace.fs.readFile(filename); const module = await WebAssembly.compile(bits); const process = await wasm.createProcess('python', module, options); const result = await process.run(); return result; }); ``` -------------------------------- ### Generate TypeScript Bindings with wit2ts CLI Source: https://context7.com/microsoft/vscode-wasm/llms.txt Generates TypeScript bindings from WIT files using the `wit2ts` CLI. Requires `wasm-tools >= 1.226.0` on PATH. Install the package using npm. ```bash # Install the package that ships the CLI npm install @vscode/wasm-component-model # Generate TypeScript from a .wit file or directory npx wit2ts --outDir ./src/generated ./my-interface.wit # Generate from a pre-parsed JSON document (piped from wasm-tools) wasm-tools component wit --json ./wit | npx wit2ts --stdin --outDir ./src/generated # Generate with a package filter (e.g. only the "wasi" namespace) wasm-tools component wit --json ../dependencies/wasmtime/crates/wasi/wit \ | npx wit2ts --outDir ./src --filter wasi --stdin # The output directory will contain .ts files ready to import: # import * as MyInterface from './src/generated/my-package/my-interface'; ``` -------------------------------- ### Create and run a WASI process with wasm.createProcess() Source: https://context7.com/microsoft/vscode-wasm/llms.txt Instantiates a WASM module as a WASI process within VS Code's extension host. The `name` argument is used as `argv[0]`. The returned `WasmProcess` has a `run()` method that resolves to the process exit code. This example demonstrates setting up stdio, loading WASM bytes, and configuring mount points. ```typescript import { Wasm } from '@vscode/wasm-wasi/v1'; import { commands, ExtensionContext, Uri, window, workspace } from 'vscode'; export async function activate(context: ExtensionContext) { const wasm: Wasm = await Wasm.load(); commands.registerCommand('myExt.runWasm', async () => { // 1. Create a terminal for stdio const pty = wasm.createPseudoterminal(); const terminal = window.createTerminal({ name: 'My WASM Process', pty, isTransient: true }); terminal.show(true); try { // 2. Load .wasm bytes from the extension bundle (works on desktop + web) const bits = await workspace.fs.readFile( Uri.joinPath(context.extensionUri, 'hello.wasm') ); const module = await WebAssembly.compile(bits); // 3. Create the process with stdio wired to the terminal const process = await wasm.createProcess('hello', module, { stdio: pty.stdio, args: ['--verbose'], env: { MY_VAR: 'value' }, mountPoints: [{ kind: 'workspaceFolder' }], // /workspace → workspace root }); // 4. Run and await exit code const exitCode = await process.run(); if (exitCode !== 0) { void window.showWarningMessage(`Process exited with code ${exitCode}`); } } catch (err: any) { void window.showErrorMessage(err.message); } }); } ``` -------------------------------- ### JavaScript Singleton for Variants Without Values Source: https://github.com/microsoft/vscode-wasm/blob/main/wasm-component-model/js-typings.md This JavaScript example demonstrates using a singleton object literal for variant cases that do not carry a value, simplifying direct comparison. Note the potential inconsistency when comparing with variants that do have values. ```javascript export const AccessType = { // as above Exists: Object.freeze({ tag: AccessType.exists }) } ``` -------------------------------- ### Generated TypeScript Declaration File (.d.ts) Source: https://github.com/microsoft/vscode-wasm/blob/main/wasm-component-model/js-typings.md This is an example of a generated TypeScript declaration file (.d.ts) for component model variants, showcasing how types are exported for external use. ```typescript export declare namespace AccessType { type Access = { readonly tag: typeof AccessType.access; readonly value: Modes; }; type Exists = { readonly tag: typeof AccessType.exists; }; } export declare const AccessType: { /** * Test for readability, writeability, or executability. */ access: "access"; /** * Test whether the path exists. */ exists: "exists"; Access: (mode: Modes) => AccessType.Access; Exists: () => AccessType.Exists; }; export type AccessType = AccessType.Access | AccessType.Exists; ``` -------------------------------- ### Initialize and Run Mocha Tests Source: https://github.com/microsoft/vscode-wasm/blob/main/sync-api-common/src/browser/test/index.html Sets up the Mocha testing environment with a specific UI and timeout, then registers a custom reporter and runs the tests. This is the entry point for executing the browser tests. ```javascript mocha.setup({ ui: 'tdd', timeout: 5000 }); mocha.reporter(PlaywrightReporter); mocha.run(); ``` -------------------------------- ### wasm.createRootFileSystem() Source: https://context7.com/microsoft/vscode-wasm/llms.txt Creates a `RootFileSystem` from an array of `MountPointDescriptor` objects, providing path translation utilities between WASM paths and VS Code URIs. ```APIDOC ## `wasm.createRootFileSystem()` — Composable root filesystem Creates a `RootFileSystem` from an array of `MountPointDescriptor` objects. Provides `toVSCode()` and `toWasm()` path translation utilities, allowing extension code to convert between WASM paths and VS Code URIs. ### Example Usage: ```typescript import { Wasm } from '@vscode/wasm-wasi/v1'; import { ExtensionContext, Uri, window, workspace } from 'vscode'; export async function activate(context: ExtensionContext) { const wasm: Wasm = await Wasm.load(); const memFs = await wasm.createMemoryFileSystem(); memFs.createFile('/readme.txt', new TextEncoder().encode('hi')); const rootFs = await wasm.createRootFileSystem([ { kind: 'workspaceFolder' }, // /workspace { kind: 'memoryFileSystem', fileSystem: memFs, mountPoint: '/mem' }, { kind: 'extensionLocation', extension: context, path: 'assets', mountPoint: '/assets', // /assets → /assets }, { kind: 'vscodeFileSystem', uri: Uri.parse('vscode-userdata:/settings.json'), mountPoint: '/config', }, ]); // Translate a WASM path back to a VS Code URI const vsUri = await rootFs.toVSCode('/workspace/src/main.ts'); console.log(vsUri?.toString()); // vscode-vfs://... or file:///... // Translate a VS Code URI to a WASM path const wasmPath = await rootFs.toWasm(Uri.file('/home/user/project/src/main.ts')); console.log(wasmPath); // /workspace/src/main.ts // Stat a path in the WASM FS const stat = await rootFs.stat('/workspace'); console.log(stat.filetype); // Filetype.directory const bits = await workspace.fs.readFile(Uri.joinPath(context.extensionUri, 'app.wasm')); const module = await WebAssembly.compile(bits); const pty = wasm.createPseudoterminal(); window.createTerminal({ name: 'App', pty, isTransient: true }).show(true); const process = await wasm.createProcess('app', module, { stdio: pty.stdio, rootFileSystem: rootFs, }); await process.run(); } ``` ``` -------------------------------- ### Build .NET WASI App Source: https://github.com/microsoft/vscode-wasm/blob/main/testbeds/lsp-dotnet/README.md Build the .NET WASI application from the command line. The output will be located in the `bin/$(Configuration)/net8.0/wasi-wasm/AppBundle` directory. ```bash dotnet build -c Debug/Release ``` -------------------------------- ### wasm.createMemoryFileSystem() Source: https://context7.com/microsoft/vscode-wasm/llms.txt Creates an in-memory virtual file system that can be mounted into a WASM process. ```APIDOC ## wasm.createMemoryFileSystem() ### Description Creates a `MemoryFileSystem` that can be pre-populated with files and directories and then mounted into a WASM process under a chosen mount point. ### Method `wasm.createMemoryFileSystem()` ### Parameters None ### Request Example ```typescript import { Wasm } from '@vscode/wasm-wasi/v1'; import { ExtensionContext, Uri, window, workspace } from 'vscode'; export async function activate(context: ExtensionContext) { const wasm: Wasm = await Wasm.load(); // Build an in-memory FS with input data const memFs = await wasm.createMemoryFileSystem(); memFs.createDirectory('/input'); memFs.createFile('/input/data.txt', new TextEncoder().encode('Hello from memory FS!\n')); // Lazy-loaded large file (loaded on demand by the WASM process) memFs.createFile('/input/large.bin', { size: 1024n * 1024n, // 1 MB reported size reader: async () => new Uint8Array(1024 * 1024).fill(0x42), }); const bits = await workspace.fs.readFile(Uri.joinPath(context.extensionUri, 'processor.wasm')); const module = await WebAssembly.compile(bits); const pty = wasm.createPseudoterminal(); window.createTerminal({ name: 'Processor', pty, isTransient: true }).show(true); const process = await wasm.createProcess('processor', module, { stdio: pty.stdio, mountPoints: [ { kind: 'memoryFileSystem', fileSystem: memFs, mountPoint: '/data' }, { kind: 'workspaceFolder' }, // /workspace ], }); await process.run(); } ``` ### Response #### Success Response (200) - **memFs** (MemoryFileSystem) - The created in-memory file system object. #### Response Example None provided. ``` -------------------------------- ### Headless Environment Simulation Source: https://github.com/microsoft/vscode-wasm/blob/main/docs/emscripten.md Enables a partial shim to simulate a browser environment for running browser-specific code (like SDL) in a headless environment, useful for benchmarking and debugging. Setting to 1 enables this simulation. ```javascript var HEADLESS = 0; ``` -------------------------------- ### Custom Mocha Reporter for Browser Tests Source: https://github.com/microsoft/vscode-wasm/blob/main/sync-api-common/src/browser/test/index.html A custom Mocha reporter that sends test events (start, end, suite, test, pass, fail, etc.) to the `window.mocha_report` function. This allows for reporting test results from the browser environment. ```javascript function PlaywrightReporter(runner) { runner.on('start', () => window.mocha_report('start')); runner.on('end', () => window.mocha_report('end')); runner.on('suite', suite => window.mocha_report('suite', serializeSuite(suite))); runner.on('suite end', suite => window.mocha_report('suite end', serializeSuite(suite))); runner.on('test', test => window.mocha_report('test', serializeRunnable(test))); runner.on('test end', test => window.mocha_report('test end', serializeRunnable(test))); runner.on('hook', hook => window.mocha_report('hook', serializeRunnable(hook))); runner.on('hook end', hook => window.mocha_report('hook end', serializeRunnable(hook))); runner.on('pass', test => window.mocha_report('pass', serializeRunnable(test))); runner.on('fail', (test, err) => window.mocha_report('fail', serializeRunnable(test), serializeError(err))); runner.on('pending', test => window.mocha_report('pending', serializeRunnable(test))); } ``` -------------------------------- ### Compile and Link C Modules with WASI SDK Source: https://github.com/microsoft/vscode-wasm/blob/main/testbeds/static-linking-wasi/readme.md Use clang from WASI SDK to compile C source files into object files and then link them into a single WASM module. Ensure the WASI SDK is in your PATH. ```sh ~/bin/wasi-sdk/bin/clang module1.c -c -o out/module1.o ``` ```sh ~/bin/wasi-sdk/bin/clang main.c -c -o out/main.o ``` ```sh ~/bin/wasi-sdk/bin/clang -o main.wasm out/module1.o out/main.o ``` -------------------------------- ### Mount File System in Web Shell Source: https://github.com/microsoft/vscode-wasm/blob/main/webshell/README.md Configure a directory from the extension's location to be mounted into the web shell's file system. This allows files within the extension to be accessible as if they were part of the web shell's environment. ```json "contributes": { "webShellMountPoints": [ { "mountPoint": "/usr/local/lib/python3.11", "path": "wasm/lib" } ] } ``` -------------------------------- ### Compile C module to object file and shared library (Linux) Source: https://github.com/microsoft/vscode-wasm/blob/main/testbeds/dynamic-linking/readme.md Standard compilation steps for creating a shared library on a Linux system. ```bash clang module1.c -c -o module1.o ``` ```bash clang --shared module1.o -o module1.so ``` ```bash clang main.c module1.so -o main ``` -------------------------------- ### Compile C module to object file and WASM side module (Emscripten) Source: https://github.com/microsoft/vscode-wasm/blob/main/testbeds/dynamic-linking/readme.md Compilation steps using Emscripten to create a side module and a main module. This approach simulates dynamic linking. ```bash emcc -c func1.c -o out/func1.o ``` ```bash emcc -sSIDE_MODULE out/func1.o -o func1.wasm ``` ```bash emcc -sMAIN_MODULE main.c func1.wasm -o main.js ``` ```bash node main.js ``` -------------------------------- ### Create In-Memory Virtual File System for WASM Source: https://context7.com/microsoft/vscode-wasm/llms.txt Use `wasm.createMemoryFileSystem()` to create a `MemoryFileSystem`. This allows you to pre-populate an in-memory filesystem with files and directories, which can then be mounted into a WASM process at a specified mount point. It supports both direct file content and lazy-loaded large files. ```typescript import { Wasm } from '@vscode/wasm-wasi/v1'; import { ExtensionContext, Uri, window, workspace } from 'vscode'; export async function activate(context: ExtensionContext) { const wasm: Wasm = await Wasm.load(); // Build an in-memory FS with input data const memFs = await wasm.createMemoryFileSystem(); memFs.createDirectory('/input'); memFs.createFile('/input/data.txt', new TextEncoder().encode('Hello from memory FS!\n')); // Lazy-loaded large file (loaded on demand by the WASM process) memFs.createFile('/input/large.bin', { size: 1024n * 1024n, // 1 MB reported size reader: async () => new Uint8Array(1024 * 1024).fill(0x42), }); const bits = await workspace.fs.readFile(Uri.joinPath(context.extensionUri, 'processor.wasm')); const module = await WebAssembly.compile(bits); const pty = wasm.createPseudoterminal(); window.createTerminal({ name: 'Processor', pty, isTransient: true }).show(true); const process = await wasm.createProcess('processor', module, { stdio: pty.stdio, mountPoints: [ { kind: 'memoryFileSystem', fileSystem: memFs, mountPoint: '/data' }, { kind: 'workspaceFolder' }, // /workspace ], }); await process.run(); } ``` -------------------------------- ### Compile C module to object file and WASM shared module (WASI-SDK) Source: https://github.com/microsoft/vscode-wasm/blob/main/testbeds/dynamic-linking/readme.md Compilation using WASI-SDK to create a WebAssembly shared module. Note the use of specific flags for WASI compilation and shared library creation. ```bash ~/bin/wasi-sdk/bin/clang module1.c -c -o module1.o ``` ```bash ~/bin/wasi-sdk/bin/clang -nostdlib -Wl,--shared -Wl,--export-all module1.o -o module1.wasm ``` ```bash ~/bin/wasi-sdk/bin/clang -Wl,--allow-undefined main.c out/func1.wasm -o main.wasm ``` -------------------------------- ### Create Root File System with VSCode WASM API Source: https://context7.com/microsoft/vscode-wasm/llms.txt Creates a `RootFileSystem` from various mount point descriptors. Use `toVSCode()` and `toWasm()` for path translations. Requires importing `Wasm` from '@vscode/wasm-wasi/v1'. ```typescript import { Wasm } from '@vscode/wasm-wasi/v1'; import { ExtensionContext, Uri, window, workspace } from 'vscode'; export async function activate(context: ExtensionContext) { const wasm: Wasm = await Wasm.load(); const memFs = await wasm.createMemoryFileSystem(); memFs.createFile('/readme.txt', new TextEncoder().encode('hi')); const rootFs = await wasm.createRootFileSystem([ { kind: 'workspaceFolder' }, // /workspace { kind: 'memoryFileSystem', fileSystem: memFs, mountPoint: '/mem' }, { kind: 'extensionLocation', extension: context, path: 'assets', mountPoint: '/assets', // /assets → /assets }, { kind: 'vscodeFileSystem', uri: Uri.parse('vscode-userdata:/settings.json'), mountPoint: '/config', }, ]); // Translate a WASM path back to a VS Code URI const vsUri = await rootFs.toVSCode('/workspace/src/main.ts'); console.log(vsUri?.toString()); // vscode-vfs://... or file:///... // Translate a VS Code URI to a WASM path const wasmPath = await rootFs.toWasm(Uri.file('/home/user/project/src/main.ts')); console.log(wasmPath); // /workspace/src/main.ts // Stat a path in the WASM FS const stat = await rootFs.stat('/workspace'); console.log(stat.filetype); // Filetype.directory const bits = await workspace.fs.readFile(Uri.joinPath(context.extensionUri, 'app.wasm')); const module = await WebAssembly.compile(bits); const pty = wasm.createPseudoterminal(); window.createTerminal({ name: 'App', pty, isTransient: true }).show(true); const process = await wasm.createProcess('app', module, { stdio: pty.stdio, rootFileSystem: rootFs, }); await process.run(); } ``` -------------------------------- ### Run .NET WASI App Source: https://github.com/microsoft/vscode-wasm/blob/main/testbeds/lsp-dotnet/README.md Run the .NET WASI application using `dotnet run` or directly execute the WASM binary with `wasmtime`. ```bash dotnet run -c Debug/Release ``` ```bash wasmtime bin/$(Configuration)/net8.0/browser-wasm/AppBundle/wasi-lsp.wasm ``` -------------------------------- ### Synchronous RPC with @vscode/sync-api-common Source: https://context7.com/microsoft/vscode-wasm/llms.txt Illustrates setting up a synchronous request/response channel between workers using SharedArrayBuffer and Atomics.wait. This allows client workers to call service handlers synchronously without using await. ```APIDOC ## `@vscode/sync-api-common` — Synchronous RPC over SharedArrayBuffer Implements a synchronous request/response channel between two workers using `SharedArrayBuffer` + `Atomics.wait`. The service worker (main thread) registers async handlers; the client worker calls them synchronously without `await`. ### Shared type definition (`requests.ts`) ```typescript import { VariableResult } from '@vscode/sync-api-common'; export type Requests = { method: 'readFile'; params: { uri: string }; result: VariableResult; } | { method: 'writeFile'; params: { uri: string; content: Uint8Array }; result: void; }; ``` ### Service implementation (`service.ts` - main/extension-host thread) ```typescript import { ServiceConnection } from '@vscode/sync-api-common/node'; // or /browser import { Requests } from './requests'; import * as fs from 'fs/promises'; import { Worker } from 'worker_threads'; const worker = new Worker('./client-worker.js'); const connection = new ServiceConnection(worker); connection.onRequest('readFile', async ({ uri }) => { const data = await fs.readFile(uri); return { errno: 0, data }; }); connection.onRequest('writeFile', async ({ uri, content }) => { await fs.writeFile(uri, content); return { errno: 0 }; }); connection.signalReady(); // unblocks the client worker ``` ### Client implementation (`client-worker.ts` - worker thread) ```typescript import { ClientConnection, RequestResult, VariableResult } from '@vscode/sync-api-common/node'; import { Requests } from './requests'; import { parentPort } from 'worker_threads'; const connection = new ClientConnection(parentPort!); await connection.serviceReady(); // waits for signalReady() // Synchronous call — no await, blocks until response arrives const result = connection.sendRequest('readFile', { uri: '/tmp/data.bin' }, new VariableResult('binary')); if (RequestResult.hasData(result)) { console.log('Read bytes:', result.data.length); } else { console.error('RPC error:', result.errno); } ``` ``` -------------------------------- ### wasm.compile() Source: https://context7.com/microsoft/vscode-wasm/llms.txt Compiles a WebAssembly module from a VS Code Uri, abstracting platform differences for streaming compilation. ```APIDOC ## wasm.compile() ### Description Compiles a `WebAssembly.Module` from a VS Code `Uri`. Uses streaming compilation in the browser and buffered loading on the desktop, abstracting the platform difference. ### Method `wasm.compile(uri: Uri)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **uri** (Uri) - Required - The VS Code Uri pointing to the WASM file. ### Request Example ```typescript import { Wasm } from '@vscode/wasm-wasi/v1'; import { ExtensionContext, Uri, window } from 'vscode'; export async function activate(context: ExtensionContext) { const wasm: Wasm = await Wasm.load(); // Compiles using streaming (browser) or readFile+compile (desktop) transparently const module = await wasm.compile(Uri.joinPath(context.extensionUri, 'app.wasm')); const pty = wasm.createPseudoterminal(); window.createTerminal({ name: 'App', pty, isTransient: true }).show(true); const proc = await wasm.createProcess('app', module, { stdio: pty.stdio }); await proc.run(); } ``` ### Response #### Success Response (200) - **module** (WebAssembly.Module) - The compiled WebAssembly module. #### Response Example None provided. ``` -------------------------------- ### Execute a WASM Process with WASM WASI Core Source: https://github.com/microsoft/vscode-wasm/blob/main/wasm-wasi-core/README.md Load the WASM API, create a pseudoterminal and VS Code terminal, compile the WASM module, and then create and run a WASM process using the provided API. Ensure the WASM file is loaded correctly. ```typescript // Load the WASM API const wasm: Wasm = await Wasm.load(); const pty = wasm.createPseudoterminal(); const terminal = window.createTerminal({ name: 'My Example', pty, isTransient: true }); terminal.show(true); const module = await WebAssembly.compile(await fs.readFile(...)); const process = await wasm.createProcess('hello', module, { stdio: pty.stdio }); await process.run(); ``` -------------------------------- ### Execute a WASM process with WASM WASI Core API Source: https://github.com/microsoft/vscode-wasm/blob/main/wasm-wasi/README.md Load the WASM API, create a pseudoterminal for stdio, and then load and execute a WASM module using the WASM WASI Core API. Handles potential errors during execution. ```typescript // Load the WASM API const wasm: Wasm = await Wasm.load(); // Create a pseudoterminal to provide stdio to the WASM process. const pty = wasm.createPseudoterminal(); const terminal = window.createTerminal({ name: 'Run C Example', pty, isTransient: true }); terminal.show(true); // Load the WASM module. It is stored alongside the extension JS code. // So we can use VS Code's file system API to load it. Makes it // independent of whether the code runs in the desktop or the web. try { const bits = await workspace.fs.readFile(Uri.joinPath(context.extensionUri, 'hello.wasm')); const module = await WebAssembly.compile(bits); // Create a WASM process. const process = await wasm.createProcess('hello', module, { stdio: pty.stdio }); // Run the process and wait for its result. const result = await process.run(); } catch (error) { // Show an error message if something goes wrong. void window.showErrorMessage(error.message); } ``` -------------------------------- ### Compile Native Module to WASM Object File Source: https://github.com/microsoft/vscode-wasm/blob/main/docs/nativeModule.md Compile a C source file for a native Python extension into a WASM object file. This is the first step before linking it into the main Python WASM binary. ```bash clang -c fputsmodule.c -o fputsmodule.o ``` -------------------------------- ### Build as Worker Source: https://github.com/microsoft/vscode-wasm/blob/main/docs/emscripten.md Configures the Emscripten library to run as a worker. Setting to 1 enables this mode. ```javascript var BUILD_AS_WORKER = 0; ``` -------------------------------- ### Worker-Side Sync API Client Source: https://github.com/microsoft/vscode-wasm/blob/main/sync-api-common/README.md Sets up a client connection in a worker to send synchronous requests to a service. Ensure the service is ready before sending requests. ```typescript import { ClientConnection } from '@vscode/sync-api-common/browser'; import { Requests } from './requests'; const connection = new ClientConnection(parentPort); await connection.serviceReady(); // Note that this is a sync call with no await needed. const requestResult = connection.sendRequest('getValue', { arg: 10 }, new VariableResult('json')); // An error has occurred. if (requestResult.errno !== 0) { } // Get the actual data const value = requestResult.data.value; ``` -------------------------------- ### Link Native Module into Python WASM Binary Source: https://github.com/microsoft/vscode-wasm/blob/main/docs/nativeModule.md Create a new python.wasm binary by linking existing Python object files, libraries, and the compiled native module object file. This command also exports the initialization function for the native module. ```bash clang -z stack-size=524288 -Wl,--stack-first -Wl,--initial-memory=10485760 -lwasi-emulated-signal -lwasi-emulated-getpid -lwasi-emulated-process-clocks -o python.wasm Programs/python.o libpython3.12.a Modules/_decimal/libmpdec/libmpdec.a Modules/expat/libexpat.a fputsmodule.o -Wl,--export=PyInit_fputs ``` -------------------------------- ### Component Model ABI in TypeScript with Connection Class Source: https://context7.com/microsoft/vscode-wasm/llms.txt Demonstrates using the `Connection` class from `@vscode/wasm-component-model` to bridge main-thread and worker threads via `SharedArrayBuffer`. Generated bindings from `wit2ts` utilize these primitives. ```typescript import { Connection, WorldType, WorkerConnection, MainConnection } from '@vscode/wasm-component-model'; // ---------- In the main thread (extension host) ---------- import type { MyWorld } from './generated/my-world'; // WorldType is the generated descriptor for the WIT world async function startWorker(world: WorldType): Promise { // Creates a WorkerConnection on the worker side (called inside the worker) const workerConn: WorkerConnection = await Connection.createWorker(world); // MainConnection is obtained in the main thread via RAL().Connection.createMain(...) } // ---------- Lower-level memory primitives ---------- import { MemoryRange, ReadonlyMemoryRange, Alignment, u32, ptr, size } from '@vscode/wasm-component-model'; // Alignment utilities const aligned = Alignment.align(13, Alignment.word); // → 16 const alignment = Alignment.getAlignment(16); // → Alignment.word (4) // Reading typed values from a MemoryRange (wraps a SharedArrayBuffer region) function readU32FromRange(range: ReadonlyMemoryRange, byteOffset: number): number { // range.getUint32 reads little-endian u32 with alignment check const value: u32 = range.getUint32(byteOffset); return value; } // Supported scalar readers: getUint8, getInt8, getUint16, getInt16, // getUint32, getInt32, getUint64, getInt64, getFloat32, getFloat64, // getPtr, getUint8Array, getUint16Array, getUint32Array, getFloat32Array, ... ``` -------------------------------- ### wasm.createPseudoterminal() Source: https://context7.com/microsoft/vscode-wasm/llms.txt Creates a pseudoterminal for WASM processes, acting as both a VS Code terminal and a stdio interface. ```APIDOC ## wasm.createPseudoterminal() ### Description Creates a `WasmPseudoterminal` that acts as both a VS Code terminal (`Pseudoterminal`) and a stdio source/sink for WASM processes. Supports interactive input, Ctrl+C handling, and state lifecycle events. ### Method `wasm.createPseudoterminal(options?: PseudoterminalOptions)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **options** (PseudoterminalOptions) - Optional - Configuration options for the pseudoterminal, such as encoding and history. - **encoding** (string) - Optional - The character encoding to use (e.g., 'utf-8'). - **history** (boolean) - Optional - Whether to enable command history. ### Request Example ```typescript import { Wasm, PseudoterminalState } from '@vscode/wasm-wasi/v1'; import { window } from 'vscode'; const wasm: Wasm = await Wasm.load(); // Create a terminal with UTF-8 encoding and command history const pty = wasm.createPseudoterminal({ encoding: 'utf-8', history: true }); const terminal = window.createTerminal({ name: 'Interactive Shell', pty, isTransient: true }); terminal.show(true); // Listen for Ctrl+C pty.onDidCtrlC(() => { console.log('User pressed Ctrl+C'); }); // Listen for state changes (free → idle → busy → idle) pty.onDidChangeState((event) => { console.log(`Terminal state: ${PseudoterminalState[event.old]} → ${PseudoterminalState[event.new]}`); }); // Write a prompt and read a line (interactive) await pty.prompt('Enter your name: '); const name = await pty.readline(); await pty.write(`Hello, ${name}! `); // Direct byte I/O const bytes = await pty.read(256, 'utf-8'); await pty.write(new Uint8Array([72, 101, 108, 108, 111, 10])); // "Hello\n" ``` ### Response #### Success Response (200) - **pty** (WasmPseudoterminal) - The created pseudoterminal object. #### Response Example None provided. ``` -------------------------------- ### Define Runtime Environment Source: https://github.com/microsoft/vscode-wasm/blob/main/docs/emscripten.md Specifies the environments where the Emscripten application will run. Use 'web', 'webview', 'worker', or 'node'. ```javascript var ENVIRONMENT = 'web,webview,worker,node'; ``` -------------------------------- ### Configure Extension Dependencies for WASM WASI Core Source: https://github.com/microsoft/vscode-wasm/blob/main/wasm-wasi-core/README.md Define 'extensionDependencies' to include 'ms-vscode.wasm-wasi-core' and 'dependencies' for '@vscode/wasm-wasi' in your extension's package.json to enable WASM execution. ```json { "name": "...", ... // depend on the wasm-wasi-core extension "extensionDependencies": [ "ms-vscode.wasm-wasi-core" ], // Depend on the wasm-wasi facade npm module to get easier API access to the // core extension. "dependencies": { "@vscode/wasm-wasi": "..." }, } ``` -------------------------------- ### Run WASM Module with Wasmtime Source: https://github.com/microsoft/vscode-wasm/blob/main/testbeds/static-linking-wasi/readme.md Execute the compiled WASM module using the Wasmtime runtime. This command assumes 'main.wasm' is the output of the linking step. ```sh wasmtime main.wasm ``` -------------------------------- ### wasm.createProcess() Source: https://context7.com/microsoft/vscode-wasm/llms.txt Instantiates a WASM module as a WASI process within VS Code's extension host. The `name` argument is used as `argv[0]`. The returned `WasmProcess` has a `run()` method that resolves to the process exit code. ```APIDOC ## wasm.createProcess() ### Description Instantiates a WASM module as a WASI process inside VS Code's extension host. The `name` argument becomes `argv[0]`. Returns a `WasmProcess` whose `run()` method resolves to the process exit code. ### Method ```typescript createProcess(name: string, module: WebAssembly.Module, options?: ProcessOptions): Promise ``` ### Parameters - **name** (string) - The name of the process, used as `argv[0]`. - **module** (WebAssembly.Module) - The compiled WebAssembly module. - **options** (ProcessOptions, optional) - Configuration options for the process. - **stdio** (Pseudoterminal.Stdio) - Standard input, output, and error streams. - **args** (string[]) - Command-line arguments for the process. - **env** (Record) - Environment variables for the process. - **mountPoints** (MountPoint[]) - File system mount points. - **kind** ('workspaceFolder' | 'extfs') - The type of mount point. ### Response - **WasmProcess** (object) - An object representing the running WASI process. - **run()**: Promise - Executes the process and resolves with the exit code. ### Request Example ```typescript import { Wasm } from '@vscode/wasm-wasi/v1'; import { commands, ExtensionContext, Uri, window, workspace } from 'vscode'; export async function activate(context: ExtensionContext) { const wasm: Wasm = await Wasm.load(); commands.registerCommand('myExt.runWasm', async () => { // 1. Create a terminal for stdio const pty = wasm.createPseudoterminal(); const terminal = window.createTerminal({ name: 'My WASM Process', pty, isTransient: true }); terminal.show(true); try { // 2. Load .wasm bytes from the extension bundle (works on desktop + web) const bits = await workspace.fs.readFile( Uri.joinPath(context.extensionUri, 'hello.wasm') ); const module = await WebAssembly.compile(bits); // 3. Create the process with stdio wired to the terminal const process = await wasm.createProcess('hello', module, { stdio: pty.stdio, args: ['--verbose'], env: { MY_VAR: 'value' }, mountPoints: [{ kind: 'workspaceFolder' }], // /workspace → workspace root }); // 4. Run and await exit code const exitCode = await process.run(); if (exitCode !== 0) { void window.showWarningMessage(`Process exited with code ${exitCode}`); } } catch (err: any) { void window.showErrorMessage(err.message); } }); } ``` ``` -------------------------------- ### Load WASM API facade with Wasm.load() Source: https://context7.com/microsoft/vscode-wasm/llms.txt Activates the `ms-vscode.wasm-wasi-core` VS Code extension and returns the `Wasm` API object. This must be called once before any other API is used. It automatically checks for version compatibility. ```typescript // extension.ts import { Wasm } from '@vscode/wasm-wasi/v1'; import { ExtensionContext } from 'vscode'; export async function activate (_context: ExtensionContext) { // Activates ms-vscode.wasm-wasi-core and returns the versioned API. // Throws if the extension is missing or incompatible. const wasm: Wasm = await Wasm.load(); console.log('Extension version:', wasm.versions.extension); // => e.g. "1.0.2" } ``` -------------------------------- ### Mount Command in Web Shell Source: https://github.com/microsoft/vscode-wasm/blob/main/webshell/README.md Register a VS Code command to be executable from within the web shell. When the specified command is invoked in the shell, the associated VS Code command will be triggered. ```json "contributes": { "webShellMountPoints": [ { "mountPoint": "/usr/bin/python", "command": "testbed-python.webshell.python" } ] } ``` -------------------------------- ### Wasm.load() Source: https://context7.com/microsoft/vscode-wasm/llms.txt Activates the `ms-vscode.wasm-wasi-core` VS Code extension and returns the `Wasm` API object. This must be called once before any other API is used. It checks for version compatibility automatically. ```APIDOC ## Wasm.load() ### Description Activates the `ms-vscode.wasm-wasi-core` VS Code extension and returns the `Wasm` API object. Must be called once before any other API is used. Version compatibility between the facade and the core extension is checked automatically (requires extension `^0.13.3` or `^1.0.0`). ### Method ```typescript async load(): Promise ``` ### Parameters None ### Response - **Wasm** (object) - The Wasm API object. ### Request Example ```typescript // extension.ts import { Wasm } from '@vscode/wasm-wasi/v1'; import { ExtensionContext } from 'vscode'; export async function activate (_context: ExtensionContext) { // Activates ms-vscode.wasm-wasi-core and returns the versioned API. // Throws if the extension is missing or incompatible. const wasm: Wasm = await Wasm.load(); console.log('Extension version:', wasm.versions.extension); // => e.g. "1.0.2" } ``` ``` -------------------------------- ### Activate WASM LSP Server in VSCode Source: https://context7.com/microsoft/vscode-wasm/llms.txt Activates a WASM Language Server Protocol server using stdio pipes. Ensure 'server.wasm' is in the extension's root and 'myLang' is in your document selector. ```typescript import { Wasm } from '@vscode/wasm-wasi/v1'; import { createStdioOptions, startServer, createUriConverters } from '@vscode/wasm-wasi-lsp'; import { LanguageClient, LanguageClientOptions, ServerOptions } from 'vscode-languageclient/browser'; import { ExtensionContext, Uri, workspace } from 'vscode'; export async function activate(context: ExtensionContext) { const wasm: Wasm = await Wasm.load(); // Pipe-based stdio for LSP JSON-RPC communication const stdio = createStdioOptions(); const bits = await workspace.fs.readFile(Uri.joinPath(context.extensionUri, 'server.wasm')); const module = await WebAssembly.compile(bits); const process = await wasm.createProcess('lsp-server', module, { stdio, mountPoints: [{ kind: 'workspaceFolder' }], }); // Bridge WASM streams → vscode-languageclient MessageTransports const transport = await startServer(process); const serverOptions: ServerOptions = () => Promise.resolve(transport); const clientOptions: LanguageClientOptions = { documentSelector: [{ scheme: 'file', language: 'myLang' }], uriConverters: createUriConverters(), // maps /workspace ↔ VS Code URIs }; const client = new LanguageClient('myLsp', 'My LSP', serverOptions, clientOptions); context.subscriptions.push(client.start()); } ``` -------------------------------- ### Main-Side Sync API Service Source: https://github.com/microsoft/vscode-wasm/blob/main/sync-api-common/README.md Establishes a service connection on the main thread to handle incoming synchronous requests from workers. Signal readiness after setting up request handlers. ```typescript import { ServiceConnection } from '@vscode/sync-api-common'; import { Requests } from './requests'; // The worker to access API in sync from. const worker = new Worker('...'); const connection = new ServiceConnection(worker); // The request handler for getValue connection.onRequest('getValue', async (params) => { const str = await getValue(params.arg); return { errno: 0, data: { value: str } }; }); // Signal connection ready so that the worker can call // sync API. connection.signalReady(); ``` -------------------------------- ### Enable Pure WASI Support in Emscripten Source: https://github.com/microsoft/vscode-wasm/blob/main/docs/emscripten.md Set PURE_WASI to 0 to build binaries that maximize WASI API usage and include additional JS support libraries. This setting is experimental. ```javascript var PURE_WASI = 0; ``` -------------------------------- ### wasm.createReadable() / wasm.createWritable() Source: https://context7.com/microsoft/vscode-wasm/llms.txt Creates `Readable` and `Writable` stream objects for piping stdin/stdout/stderr to a WASM process, enabling programmatic data exchange. ```APIDOC ## `wasm.createReadable()` / `wasm.createWritable()` — Pipe streams Creates `Readable` and `Writable` stream objects that can be wired as stdin/stdout/stderr pipes to a WASM process, allowing the extension host to feed data to or consume data from the process programmatically. ### Example Usage: ```typescript import { Wasm } from '@vscode/wasm-wasi/v1'; import { ExtensionContext, Uri, workspace } from 'vscode'; export async function activate(context: ExtensionContext) { const wasm: Wasm = await Wasm.load(); // stdin pipe: extension writes into it, WASM reads from it const stdinWrite = wasm.createWritable('utf-8'); // stdout pipe: WASM writes into it, extension reads from it const stdoutRead = wasm.createReadable(); // stderr pipe with EOT support (closes stream on EOT char) const stderrRead = wasm.createReadable(); const bits = await workspace.fs.readFile(Uri.joinPath(context.extensionUri, 'filter.wasm')); const module = await WebAssembly.compile(bits); const process = await wasm.createProcess('filter', module, { stdio: { in: { kind: 'pipeIn', pipe: stdinWrite }, out: { kind: 'pipeOut', pipe: stdoutRead }, err: { kind: 'pipeOut', pipe: stderrRead }, }, }); // Collect stdout chunks const chunks: Uint8Array[] = []; stdoutRead.onData((chunk) => chunks.push(chunk)); // Feed stdin and run await stdinWrite.write('hello world\n', 'utf-8'); const exitCode = await process.run(); const output = new TextDecoder().decode( chunks.reduce((a, b) => { const r = new Uint8Array(a.length + b.length); r.set(a); r.set(b, a.length); return r; }, new Uint8Array()) ); console.log('Output:', output, 'Exit:', exitCode); } ``` ```