wasmrs-js
Version:
A JavaScript implementation of the RSocket protocol over WebAssembly.
105 lines • 3.43 kB
JavaScript
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import { PreopenDirectory, WASI as WasiShim, SyncOPFSFile, Fd, } from '@candlecorp/browser_wasi_shim';
class CallbackFd extends Fd {
fn;
constructor(fn) {
super();
this.fn = fn;
}
fd_write(view8, iovs) {
let nwritten = 0;
for (const iovec of iovs) {
const buffer = view8.slice(iovec.buf, iovec.buf + iovec.buf_len);
this.fn(new TextDecoder().decode(buffer));
nwritten += iovec.buf_len;
}
return { ret: 0, nwritten };
}
}
class NullFd extends Fd {
constructor() {
super();
}
}
async function openOpfsDirectory(root, to) {
const files = {};
for await (const [name, item] of root.entries()) {
if (item.kind === 'file') {
const file = item;
files[name] = new SyncOPFSFile(await file.createSyncAccessHandle());
}
else if (item.kind === 'directory') {
files[name] = await openOpfsDirectory(item, to + '/' + name);
}
else {
throw new Error('Unknown item kind: ' + item.kind);
}
}
return new PreopenDirectory(to, files);
}
export class WASI {
wasi;
constructor(wasi) {
this.wasi = wasi;
}
static async create(options) {
const opfsRoot = await navigator.storage.getDirectory();
const files = [];
if (options.stdin === 0) {
files.push(new NullFd());
}
else if (options.stdin === undefined) {
files.push(new NullFd());
}
else {
throw new Error('Unsupported stdin mode');
}
if (options.stdout === 1) {
files.push(new CallbackFd(console.log.bind(console, 'stdout: ')));
}
else if (options.stdin === undefined) {
files.push(new NullFd());
}
else {
throw new Error('Unsupported stdout mode');
}
if (options.stderr === 2) {
files.push(new CallbackFd(console.error.bind(console, 'stderr: ')));
}
else if (options.stdin === undefined) {
files.push(new NullFd());
}
else {
throw new Error('Unsupported stderr mode');
}
for (const [to, from] of Object.entries(options.preopens || {})) {
if (from.startsWith('opfs:')) {
const opfsPath = from.slice(5);
if (opfsPath === '/') {
files.push(await openOpfsDirectory(opfsRoot, to));
}
else {
const root = await opfsRoot.getDirectoryHandle(opfsPath, {
create: true,
});
files.push(await openOpfsDirectory(root, to));
}
}
}
const env = Object.entries(options.env || {}).map(([key, value]) => `${key}=${value}`);
return new WASI(new WasiShim(options.args || [], env, files, { debug: true }));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
start(instance) {
this.wasi.start(instance);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
initialize(instance) {
this.wasi.initialize(instance);
}
getImports() {
return this.wasi.wasiImport;
}
}
//# sourceMappingURL=wasi.js.map