diff --git a/README.md b/README.md index 95ad586..c0a501c 100644 --- a/README.md +++ b/README.md @@ -9,14 +9,14 @@ npm install @bjorn3/browser_wasi_shim --save ``` ```javascript -import { WASI, File, OpenFile, PreopenDirectory } from "@bjorn3/browser_wasi_shim"; +import { WASI, File, OpenFile, ConsoleStdout, PreopenDirectory } from "@bjorn3/browser_wasi_shim"; let args = ["bin", "arg1", "arg2"]; let env = ["FOO=bar"]; let fds = [ new OpenFile(new File([])), // stdin - new OpenFile(new File([])), // stdout - new OpenFile(new File([])), // stderr + ConsoleStdout.lineBuffered(msg => console.log(`[WASI stdout] ${msg}`)), + ConsoleStdout.lineBuffered(msg => console.warn(`[WASI stderr] ${msg}`)), new PreopenDirectory(".", { "example.c": new File(new TextEncoder("utf-8").encode(`#include "a"`)), "hello.rs": new File(new TextEncoder("utf-8").encode(`fn main() { println!("Hello World!"); }`)), diff --git a/src/fs_core.ts b/src/fs_core.ts index 50e2758..528fb68 100644 --- a/src/fs_core.ts +++ b/src/fs_core.ts @@ -588,3 +588,55 @@ export class Directory { return entry; } } + +export class ConsoleStdout extends Fd { + write: (buffer: Uint8Array) => void; + + constructor(write: (buffer: Uint8Array) => void) { + super(); + this.write = write; + } + + fd_filestat_get(): { ret: number; filestat: wasi.Filestat } { + const filestat = new wasi.Filestat( + wasi.FILETYPE_CHARACTER_DEVICE, + BigInt(0), + ); + return { ret: 0, filestat }; + } + + fd_fdstat_get(): { ret: number; fdstat: wasi.Fdstat | null } { + const fdstat = new wasi.Fdstat(wasi.FILETYPE_CHARACTER_DEVICE, 0); + fdstat.fs_rights_base = BigInt(wasi.RIGHTS_FD_WRITE); + return { ret: 0, fdstat }; + } + + fd_write( + view8: Uint8Array, + iovs: Array, + ): { ret: number; nwritten: number } { + let nwritten = 0; + for (const iovec of iovs) { + const buffer = view8.slice(iovec.buf, iovec.buf + iovec.buf_len); + this.write(buffer); + nwritten += iovec.buf_len; + } + return { ret: 0, nwritten }; + } + + static lineBuffered(write: (line: string) => void): ConsoleStdout { + const dec = new TextDecoder("utf-8", { fatal: false }); + let line_buf = ""; + return new ConsoleStdout((buffer) => { + line_buf += dec.decode(buffer, { stream: true }); + const lines = line_buf.split("\n"); + for (const [i, line] of lines.entries()) { + if (i < lines.length - 1) { + write(line); + } else { + line_buf = line; + } + } + }); + } +} diff --git a/src/index.ts b/src/index.ts index 76d6837..40f2d24 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,7 @@ export { OpenDirectory, OpenSyncOPFSFile, PreopenDirectory, + ConsoleStdout, } from "./fs_core.js"; export { strace } from "./strace.js"; export * as wasi from "./wasi_defs.js"; diff --git a/test/adapters/browser/run-test.html b/test/adapters/browser/run-test.html index 7efd1ca..1c87557 100644 --- a/test/adapters/browser/run-test.html +++ b/test/adapters/browser/run-test.html @@ -1,36 +1,6 @@