Skip to content

Commit 570be9d

Browse files
committed
Adds support for Uint8Array handling to stdin/stdout/stderr.
1. `stdin` now accepts Uint8Arrays directly. 2. Uint8Arrays are sent to `stdout/stderr` handlers, when `outputBuffers: true` is passed to `useStdio({})` options.
1 parent 04f3750 commit 570be9d

File tree

2 files changed

+43
-11
lines changed

2 files changed

+43
-11
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,20 @@ const wasi = new WASI({
9999
});
100100
```
101101

102+
By default, the `stdout` and `stderr` handlers are passed strings. You can pass `outputBuffers: true` to get `Uint8Array` buffers instead. Along with that, you can also pass `Uint8Array` buffers to `stdin`.
103+
104+
```js
105+
import { WASI, useStdio } from "uwasi";
106+
const wasi = new WASI({
107+
features: [useStdio({
108+
outputBuffers: true,
109+
stdin: () => new Uint8Array([1, 2, 3, 4, 5]),
110+
stdout: (buf) => console.log(buf),
111+
stderr: (buf) => console.error(buf),
112+
})],
113+
});
114+
```
115+
102116
## Implementation Status
103117

104118
Some of WASI system calls are not implemented yet. Contributions are welcome!

src/features/fd.ts

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ interface FdEntry {
99

1010
class WritableTextProxy implements FdEntry {
1111
private decoder = new TextDecoder('utf-8');
12-
constructor(private readonly handler: (lines: string) => void) { }
12+
constructor(
13+
private readonly handler: (lines: string | Uint8Array) => void,
14+
private readonly outputBuffers: boolean
15+
) { }
1316

1417
writev(iovs: Uint8Array[]): number {
1518
const totalBufferSize = iovs.reduce((acc, iov) => acc + iov.byteLength, 0);
@@ -20,8 +23,13 @@ class WritableTextProxy implements FdEntry {
2023
offset += buffer.byteLength;
2124
}
2225

23-
const lines = this.decoder.decode(concatBuffer);
24-
this.handler(lines);
26+
if (this.outputBuffers) {
27+
this.handler(concatBuffer);
28+
} else {
29+
const lines = this.decoder.decode(concatBuffer);
30+
this.handler(lines);
31+
}
32+
2533
return concatBuffer.length;
2634
}
2735
readv(_iovs: Uint8Array[]): number {
@@ -33,7 +41,7 @@ class WritableTextProxy implements FdEntry {
3341
export class ReadableTextProxy implements FdEntry {
3442
private encoder = new TextEncoder();
3543
private pending: Uint8Array | null = null;
36-
constructor(private readonly consume: () => string) { }
44+
constructor(private readonly consume: () => string | Uint8Array) { }
3745

3846
writev(_iovs: Uint8Array[]): number {
3947
return 0;
@@ -59,8 +67,15 @@ export class ReadableTextProxy implements FdEntry {
5967
read += consumed.byteLength;
6068
}
6169
while (remaining > 0) {
62-
const newText = this.consume();
63-
const bytes = this.encoder.encode(newText);
70+
const newData = this.consume();
71+
let bytes: Uint8Array;
72+
73+
if (newData instanceof Uint8Array) {
74+
bytes = newData;
75+
} else {
76+
bytes = this.encoder.encode(newData);
77+
}
78+
6479
if (bytes.length == 0) {
6580
return read;
6681
}
@@ -108,16 +123,19 @@ export class ReadableTextProxy implements FdEntry {
108123
*/
109124
export function useStdio(
110125
useOptions: {
111-
stdin?: () => string,
112-
stdout?: (lines: string) => void,
113-
stderr?: (lines: string) => void,
126+
stdin?: () => string | Uint8Array,
127+
stdout?: (lines: string | Uint8Array) => void,
128+
stderr?: (lines: string | Uint8Array) => void,
129+
outputBuffers?: boolean,
114130
} = {}
115131
): WASIFeatureProvider {
116132
return (options, abi, memoryView) => {
133+
const outputBuffers = useOptions.outputBuffers || false;
134+
117135
const fdTable = [
118136
new ReadableTextProxy(useOptions.stdin || (() => { return "" })),
119-
new WritableTextProxy(useOptions.stdout || console.log),
120-
new WritableTextProxy(useOptions.stderr || console.error),
137+
new WritableTextProxy(useOptions.stdout || console.log, outputBuffers),
138+
new WritableTextProxy(useOptions.stderr || console.error, outputBuffers),
121139
]
122140
return {
123141
fd_fdstat_get: (fd: number, buf: number) => {

0 commit comments

Comments
 (0)