Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions tools/release-bundle/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,5 @@
export * from "@deltic/runtime/embedder";
export { Translator } from "@deltic/runtime/shim";
export * from "@deltic/ct-runner";
export { wasi, wasiShims } from "@deltic/wasi";
export type {
WasiImports,
WasiOptions,
// deprecated aliases, kept through the rename transition
WasiShims,
WasiShimsOptions,
} from "@deltic/wasi";
export { wasi } from "@deltic/wasi";
export type { WasiImports, WasiOptions } from "@deltic/wasi";
53 changes: 18 additions & 35 deletions wasi/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,42 +16,25 @@
// gains `exit-with-code: func(status-code: u8)`, and environment's cwd
// getter is renamed `get-initial-cwd` (0.2 spells it `initial-cwd`).

import { defineBrand, WASI_EXIT } from "@deltic/protocol";
import { Stream } from "@deltic/runtime/embedder";
import { InputStream, OutputStream } from "./io.ts";

/** `wasi:cli/types@0.3`'s `error-code` ENUM: bare kebab-case strings (the
* A10 value table — enums are data strings, not `{kind}` variants; this
* type carried a `{kind}` wrapper until 2026-08-14, a latent bug no err
* path had exercised). */
export type CliErrorCode = "io" | "illegal-byte-sequence" | "pipe";

/** `result<_, error-code>` AS A VALUE (the 0.3 stdio futures). */
export type CliIoResult = { kind: "ok" } | { kind: "err"; value: CliErrorCode };

/** What 0.3 write-via-stream accepts: the lifted handle or any byte producer. */
export type CliByteSource =
| Stream<number>
| AsyncIterable<Uint8Array | number[]>
| Iterable<Uint8Array | number[]>;

/** Raised by `exit()` when `throwOnExit` is set (contract: "option to throw a named ExitError"). */
export class ExitError extends Error {
constructor(readonly ok: boolean, readonly code?: number) {
super(
`wasi:cli/exit#exit(${ok ? "success" : "failure"}${code === undefined ? "" : `, code ${code}`})`,
);
this.name = "ExitError";
}
}
// A9 brand: an exit unwind propagates out through the embedder and any host
// frames in between, so it must be recognizable across runtime copies
// (contracts/embedder-api.md §"Module identity", issue #83).
defineBrand(ExitError.prototype, WASI_EXIT);

/** `terminal-input`/`terminal-output` are opaque resources; never produced (no terminal). */
export class TerminalInput {}
export class TerminalOutput {}
import {
type CliByteSource,
type CliIoResult,
ExitError,
TerminalInput,
TerminalOutput,
} from "./internal/cli_shared.ts";

// The shared `wasi:cli` vocabulary lives in internal/cli_shared.ts (both
// impls consume it); THIS module is its public home.
export {
type CliByteSource,
type CliErrorCode,
type CliIoResult,
ExitError,
TerminalInput,
TerminalOutput,
} from "./internal/cli_shared.ts";

export interface CliOptions {
/** `get-arguments`; default `[]`. */
Expand Down
26 changes: 8 additions & 18 deletions wasi/src/cli_stdio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ import {
ExitError,
TerminalInput,
TerminalOutput,
} from "./cli.ts";
import { type ByteSink, FedInputStream, SinkOutputStream, STREAM_HIGH_WATER } from "./io.ts";
} from "./internal/cli_shared.ts";
import { type ByteSink, FedInputStream, SinkOutputStream } from "./io.ts";

const OK: CliIoResult = { kind: "ok" };

Expand All @@ -67,16 +67,6 @@ function ioErrorCode(e: unknown): CliErrorCode {

export { type ByteSink } from "./io.ts";

/** The p2 stdin stream: `FedInputStream` (io.ts) over the stdin source. */
export const StdinStream = FedInputStream;
export type StdinStream = FedInputStream;
/** The p2 stdout/stderr stream: `SinkOutputStream` (io.ts) over the sink. */
export const StdoutStream = SinkOutputStream;
export type StdoutStream = SinkOutputStream;

/** How many buffered stdin bytes pause the feed (and the p2 write budget). */
export const STDIO_HIGH_WATER = STREAM_HIGH_WATER;

export interface CliStdioOptions {
/** stdin bytes; default: the host process's stdin. */
stdin?: AsyncIterable<Uint8Array>;
Expand Down Expand Up @@ -173,9 +163,9 @@ export function cliStdio(options: CliStdioOptions = {}): CliStdio {

// One p2 stream per stdio channel, shared across get-* calls (the
// process's stdio is one resource, not one per call).
let p2Stdin: StdinStream | undefined;
const p2Stdout = new StdoutStream(stdoutSink);
const p2Stderr = new StdoutStream(stderrSink);
let p2Stdin: FedInputStream | undefined;
const p2Stdout = new SinkOutputStream(stdoutSink);
const p2Stderr = new SinkOutputStream(stderrSink);

// 0.3 write-via-stream: drain the guest's stream to the sink; the
// promise is the future source (A12).
Expand Down Expand Up @@ -224,10 +214,10 @@ export function cliStdio(options: CliStdioOptions = {}): CliStdio {
},
},
"wasi:cli/stdin@0.2": {
getStdin: (): StdinStream => (p2Stdin ??= new StdinStream(stdinSource)),
getStdin: (): FedInputStream => (p2Stdin ??= new FedInputStream(stdinSource)),
},
"wasi:cli/stdout@0.2": { getStdout: (): StdoutStream => p2Stdout },
"wasi:cli/stderr@0.2": { getStderr: (): StdoutStream => p2Stderr },
"wasi:cli/stdout@0.2": { getStdout: (): SinkOutputStream => p2Stdout },
"wasi:cli/stderr@0.2": { getStderr: (): SinkOutputStream => p2Stderr },
"wasi:cli/terminal-input@0.2": { TerminalInput },
"wasi:cli/terminal-output@0.2": { TerminalOutput },
"wasi:cli/terminal-stdin@0.2": {
Expand Down
2 changes: 1 addition & 1 deletion wasi/src/filesystem_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import {
type Opened,
type OpenOptions,
type TimeSpec,
} from "./fs_provider.ts";
} from "./internal/fs_provider.ts";

// --- the node:fs surface we consume (structural, no @types dependency) ------------

Expand Down
2 changes: 1 addition & 1 deletion wasi/src/filesystem_web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {
makeFilesystem,
type Opened,
type OpenOptions,
} from "./fs_provider.ts";
} from "./internal/fs_provider.ts";

// --- the OPFS surface we consume (structural: works with fakes) -------------------

Expand Down
41 changes: 41 additions & 0 deletions wasi/src/internal/cli_shared.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// INTERNAL shared vocabulary of the `wasi:cli` impls (cli.ts capture,
// cli_stdio.ts host-stdio) — not a package export; the public home of
// these names is `@deltic/wasi/cli`. Extracting them here is what keeps
// the two IMPLS independent of each other: an impl imports the
// vocabulary, never its sibling.

import { defineBrand, WASI_EXIT } from "@deltic/protocol";
import { Stream } from "@deltic/runtime/embedder";

/** `wasi:cli/types@0.3`'s `error-code` ENUM: bare kebab-case strings (the
* A10 value table — enums are data strings, not `{kind}` variants; this
* type carried a `{kind}` wrapper until 2026-08-14, a latent bug no err
* path had exercised). */
export type CliErrorCode = "io" | "illegal-byte-sequence" | "pipe";

/** `result<_, error-code>` AS A VALUE (the 0.3 stdio futures). */
export type CliIoResult = { kind: "ok" } | { kind: "err"; value: CliErrorCode };

/** What 0.3 write-via-stream accepts: the lifted handle or any byte producer. */
export type CliByteSource =
| Stream<number>
| AsyncIterable<Uint8Array | number[]>
| Iterable<Uint8Array | number[]>;

/** Raised by `exit()` when `throwOnExit` is set (contract: "option to throw a named ExitError"). */
export class ExitError extends Error {
constructor(readonly ok: boolean, readonly code?: number) {
super(
`wasi:cli/exit#exit(${ok ? "success" : "failure"}${code === undefined ? "" : `, code ${code}`})`,
);
this.name = "ExitError";
}
}
// A9 brand: an exit unwind propagates out through the embedder and any host
// frames in between, so it must be recognizable across runtime copies
// (contracts/embedder-api.md §"Module identity", issue #83).
defineBrand(ExitError.prototype, WASI_EXIT);

/** `terminal-input`/`terminal-output` are opaque resources; never produced (no terminal). */
export class TerminalInput {}
export class TerminalOutput {}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
// has no symlinks, so the web backend is immune.

import { ComponentException, Stream, suspending } from "@deltic/runtime/embedder";
import { FedInputStream, IoError, OutputStream, Pollable, SinkOutputStream } from "./io.ts";
import { FedInputStream, IoError, OutputStream, Pollable, SinkOutputStream } from "../io.ts";

/** `wasi:filesystem/types.error-code` labels. 0.2 (enum): all of these,
* bare. 0.3 (variant): all but `would-block`, as `{kind}` — this package
Expand Down
4 changes: 2 additions & 2 deletions wasi/src/sockets_02.ts → wasi/src/internal/sockets_02.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
// where it has only a setter, `not-supported` where it has neither.

import { ComponentException } from "@deltic/runtime/embedder";
import { FedInputStream, IoError, Pollable, SinkOutputStream } from "./io.ts";
import { FedInputStream, IoError, Pollable, SinkOutputStream } from "../io.ts";
import {
type DatagramConn,
dnsLookup,
Expand All @@ -71,7 +71,7 @@ import {
MAX_UDP_DATAGRAM_SIZE,
parseNetAddr,
sameSocketAddress,
} from "./sockets.ts";
} from "./sockets_shared.ts";

/** `wasi:sockets/network@0.2`'s `error-code` ENUM: bare strings. */
export type SocketErrorCode02 =
Expand Down
Loading
Loading