From 8c6e1b881dbf35403fd14e2e67c44592226d2401 Mon Sep 17 00:00:00 2001 From: winetree94 Date: Wed, 31 Jul 2024 02:53:12 +0900 Subject: [PATCH] feat: runtime - change directory structure --- packages/browser-runtime/src/main.ts | 4 +- .../src/{ => workers}/stack-worker.ts | 94 ++++++++++--------- .../src/{ => workers}/wasi-util.ts | 60 ++++++------ .../src/{ => workers}/worker-util.ts | 2 +- .../src/{ => workers}/worker.ts | 74 +++++++-------- 5 files changed, 119 insertions(+), 115 deletions(-) rename packages/browser-runtime/src/{ => workers}/stack-worker.ts (73%) rename packages/browser-runtime/src/{ => workers}/wasi-util.ts (63%) rename packages/browser-runtime/src/{ => workers}/worker-util.ts (99%) rename packages/browser-runtime/src/{ => workers}/worker.ts (76%) diff --git a/packages/browser-runtime/src/main.ts b/packages/browser-runtime/src/main.ts index 27215ff..225f5ea 100644 --- a/packages/browser-runtime/src/main.ts +++ b/packages/browser-runtime/src/main.ts @@ -45,7 +45,7 @@ slave.ioctl( xterm.loadAddon(master); -const worker = new Worker(new URL('./worker.ts', import.meta.url), { +const worker = new Worker(new URL('./workers/worker.ts', import.meta.url), { type: 'module', }); @@ -63,7 +63,7 @@ switch (networkMode) { image.wasmName, image.chunkCount, networkMode, - new Worker(new URL('./stack-worker.ts', import.meta.url), { + new Worker(new URL('./workers/stack-worker.ts', import.meta.url), { type: 'module', }), location.origin + '/wasms/c2w-net-proxy.wasm', diff --git a/packages/browser-runtime/src/stack-worker.ts b/packages/browser-runtime/src/workers/stack-worker.ts similarity index 73% rename from packages/browser-runtime/src/stack-worker.ts rename to packages/browser-runtime/src/workers/stack-worker.ts index 7547d17..1854aef 100644 --- a/packages/browser-runtime/src/stack-worker.ts +++ b/packages/browser-runtime/src/workers/stack-worker.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ -import { Fd, WASI, wasi as wasiOrigin } from '@bjorn3/browser_wasi_shim'; +import { Fd, WASI, wasi } from '@bjorn3/browser_wasi_shim'; import { appendData, errStatus, @@ -13,7 +13,7 @@ import { streamStatus, wasiHackSocket, } from './worker-util'; -import { Event, EventType, Subscription } from './wasi-util'; +import { WASIEvent, WASIEventType, WASISubscription } from './wasi-util'; onmessage = async (msg: MessageEvent) => { console.log('init'); @@ -42,22 +42,22 @@ onmessage = async (msg: MessageEvent) => { '--debug', ]; const env: string[] = []; - const wasi = new WASI(args, env, fds); - wasiHack(wasi, certfd, 5); - wasiHackSocket(wasi, listenfd, 5); + const wasiInstance = new WASI(args, env, fds); + wasiHack(wasiInstance, certfd, 5); + wasiHackSocket(wasiInstance, listenfd, 5); const wasm = await fetch(getImagename(), { credentials: 'same-origin' }).then( (res) => res.arrayBuffer(), ); WebAssembly.instantiate(wasm, { - wasi_snapshot_preview1: wasi.wasiImport, - env: envHack(wasi), + wasi_snapshot_preview1: wasiInstance.wasiImport, + env: envHack(wasiInstance), }).then((inst) => { /** * @todo type missmatching */ - wasi.start( + wasiInstance.start( inst.instance as { exports: { memory: WebAssembly.Memory; _start: () => unknown }; }, @@ -68,37 +68,33 @@ onmessage = async (msg: MessageEvent) => { // definition from wasi-libc https://github.com/WebAssembly/wasi-libc/blob/wasi-sdk-19/expected/wasm32-wasi/predefined-macros.txt const ERRNO_INVAL = 28; -function wasiHack(wasi: WASI, certfd: number, connfd: number) { +function wasiHack(wasiInstance: WASI, certfd: number, connfd: number) { let certbuf = new Uint8Array(0); - const _fd_close = wasi.wasiImport.fd_close; - wasi.wasiImport.fd_close = (fd) => { + const _fd_close = wasiInstance.wasiImport.fd_close; + wasiInstance.wasiImport.fd_close = (fd) => { if (fd == certfd) { sendCert(certbuf); return 0; } - return _fd_close.apply(wasi.wasiImport, [fd]); + return _fd_close.apply(wasiInstance.wasiImport, [fd]); }; - const _fd_fdstat_get = wasi.wasiImport.fd_fdstat_get; - wasi.wasiImport.fd_fdstat_get = (fd, fdstat_ptr) => { + const _fd_fdstat_get = wasiInstance.wasiImport.fd_fdstat_get; + wasiInstance.wasiImport.fd_fdstat_get = (fd, fdstat_ptr) => { if (fd == certfd) { return 0; } - return _fd_fdstat_get.apply(wasi.wasiImport, [fd, fdstat_ptr]); + return _fd_fdstat_get.apply(wasiInstance.wasiImport, [fd, fdstat_ptr]); }; - wasi.wasiImport.fd_fdstat_set_flags = () => { + wasiInstance.wasiImport.fd_fdstat_set_flags = () => { // TODO return 0; }; - const _fd_write = wasi.wasiImport.fd_write; - wasi.wasiImport.fd_write = (fd, iovs_ptr, iovs_len, nwritten_ptr) => { + const _fd_write = wasiInstance.wasiImport.fd_write; + wasiInstance.wasiImport.fd_write = (fd, iovs_ptr, iovs_len, nwritten_ptr) => { if (fd == 1 || fd == 2 || fd == certfd) { - const buffer = new DataView(wasi.inst.exports.memory.buffer); - const buffer8 = new Uint8Array(wasi.inst.exports.memory.buffer); - const iovecs = wasiOrigin.Ciovec.read_bytes_array( - buffer, - iovs_ptr, - iovs_len, - ); + const buffer = new DataView(wasiInstance.inst.exports.memory.buffer); + const buffer8 = new Uint8Array(wasiInstance.inst.exports.memory.buffer); + const iovecs = wasi.Ciovec.read_bytes_array(buffer, iovs_ptr, iovs_len); let wtotal = 0; for (let i = 0; i < iovecs.length; i++) { const iovec = iovecs[i]; @@ -116,14 +112,14 @@ function wasiHack(wasi: WASI, certfd: number, connfd: number) { return 0; } console.log('fd_write: unknown fd ' + fd); - return _fd_write.apply(wasi.wasiImport, [ + return _fd_write.apply(wasiInstance.wasiImport, [ fd, iovs_ptr, iovs_len, nwritten_ptr, ]); }; - wasi.wasiImport.poll_oneoff = ( + wasiInstance.wasiImport.poll_oneoff = ( in_ptr, out_ptr, nsubscriptions, @@ -132,8 +128,12 @@ function wasiHack(wasi: WASI, certfd: number, connfd: number) { if (nsubscriptions == 0) { return ERRNO_INVAL; } - const buffer = new DataView(wasi.inst.exports.memory.buffer); - const in_ = Subscription.read_bytes_array(buffer, in_ptr, nsubscriptions); + const buffer = new DataView(wasiInstance.inst.exports.memory.buffer); + const in_ = WASISubscription.read_bytes_array( + buffer, + in_ptr, + nsubscriptions, + ); let isReadPollStdin = false; let isReadPollConn = false; let isClockPoll = false; @@ -176,29 +176,29 @@ function wasiHack(wasi: WASI, certfd: number, connfd: number) { if (sockreadable == errStatus) { return ERRNO_INVAL; } else if (sockreadable == true) { - const event = new Event(); + const event = new WASIEvent(); event.userdata = pollSubConn?.userdata; event.error = 0; - event.type = new EventType('fd_read'); + event.type = new WASIEventType('fd_read'); events.push(event); } } if (isClockPoll) { - const event = new Event(); + const event = new WASIEvent(); event.userdata = clockSub?.userdata; event.error = 0; - event.type = new EventType('clock'); + event.type = new WASIEventType('clock'); events.push(event); } } const len = events.length; - Event.write_bytes_array(buffer, out_ptr, events); + WASIEvent.write_bytes_array(buffer, out_ptr, events); buffer.setUint32(nevents_ptr, len, true); return 0; }; } -function envHack(wasi: WASI) { +function envHack(wasiInstance: WASI) { return { http_send: function ( addressP: number, @@ -207,13 +207,17 @@ function envHack(wasi: WASI) { reqlen: number, idP: number, ) { - const buffer = new DataView(wasi.inst.exports.memory.buffer); + const buffer = new DataView(wasiInstance.inst.exports.memory.buffer); const address = new Uint8Array( - wasi.inst.exports.memory.buffer, + wasiInstance.inst.exports.memory.buffer, addressP, addresslen, ); - const req = new Uint8Array(wasi.inst.exports.memory.buffer, reqP, reqlen); + const req = new Uint8Array( + wasiInstance.inst.exports.memory.buffer, + reqP, + reqlen, + ); streamCtrl[0] = 0; postMessage({ type: 'http_send', @@ -235,9 +239,9 @@ function envHack(wasi: WASI) { nwrittenP: number, isEOF: number, ) { - const buffer = new DataView(wasi.inst.exports.memory.buffer); + const buffer = new DataView(wasiInstance.inst.exports.memory.buffer); const body = new Uint8Array( - wasi.inst.exports.memory.buffer, + wasiInstance.inst.exports.memory.buffer, bodyP, bodylen, ); @@ -256,7 +260,7 @@ function envHack(wasi: WASI) { return 0; }, http_isreadable: function (id: number, isOKP: number) { - const buffer = new DataView(wasi.inst.exports.memory.buffer); + const buffer = new DataView(wasiInstance.inst.exports.memory.buffer); streamCtrl[0] = 0; postMessage({ type: 'http_isreadable', id: id }); Atomics.wait(streamCtrl, 0, 0); @@ -277,8 +281,8 @@ function envHack(wasi: WASI) { respsizeP: number, isEOFP: number, ) { - const buffer = new DataView(wasi.inst.exports.memory.buffer); - const buffer8 = new Uint8Array(wasi.inst.exports.memory.buffer); + const buffer = new DataView(wasiInstance.inst.exports.memory.buffer); + const buffer8 = new Uint8Array(wasiInstance.inst.exports.memory.buffer); streamCtrl[0] = 0; postMessage({ type: 'http_recv', id: id, len: bufsize }); @@ -304,8 +308,8 @@ function envHack(wasi: WASI) { bodysizeP: number, isEOFP: number, ) { - const buffer = new DataView(wasi.inst.exports.memory.buffer); - const buffer8 = new Uint8Array(wasi.inst.exports.memory.buffer); + const buffer = new DataView(wasiInstance.inst.exports.memory.buffer); + const buffer8 = new Uint8Array(wasiInstance.inst.exports.memory.buffer); streamCtrl[0] = 0; postMessage({ type: 'http_readbody', id: id, len: bufsize }); diff --git a/packages/browser-runtime/src/wasi-util.ts b/packages/browser-runtime/src/workers/wasi-util.ts similarity index 63% rename from packages/browser-runtime/src/wasi-util.ts rename to packages/browser-runtime/src/workers/wasi-util.ts index fbd21eb..5f3d5c5 100644 --- a/packages/browser-runtime/src/wasi-util.ts +++ b/packages/browser-runtime/src/workers/wasi-util.ts @@ -7,7 +7,7 @@ import { wasi } from '@bjorn3/browser_wasi_shim'; // //////////////////////////////////////////////////////////// -export class EventType { +export class WASIEventType { /*:: variant: "clock" | "fd_read" | "fd_write"*/ variant: 'clock' | 'fd_read' | 'fd_write'; @@ -18,11 +18,11 @@ export class EventType { static from_u8(data: number) /*: EventType*/ { switch (data) { case wasi.EVENTTYPE_CLOCK: - return new EventType('clock'); + return new WASIEventType('clock'); case wasi.EVENTTYPE_FD_READ: - return new EventType('fd_read'); + return new WASIEventType('fd_read'); case wasi.EVENTTYPE_FD_WRITE: - return new EventType('fd_write'); + return new WASIEventType('fd_write'); default: throw 'Invalid event type ' + String(data); } @@ -42,14 +42,14 @@ export class EventType { } } -export class Event { +export class WASIEvent { /*:: userdata: UserData*/ /*:: error: number*/ /*:: type: EventType*/ /*:: fd_readwrite: EventFdReadWrite | null*/ userdata?: bigint; error?: number; - type?: EventType; + type?: WASIEventType; // fd_readwrite: EventFdReadWrite | null; write_bytes(view: DataView, ptr: number) { @@ -62,48 +62,52 @@ export class Event { // } } - static write_bytes_array(view: DataView, ptr: number, events: Array) { + static write_bytes_array( + view: DataView, + ptr: number, + events: Array, + ) { for (let i = 0; i < events.length; i++) { events[i].write_bytes(view, ptr + 32 * i); } } } -export class SubscriptionClock { +export class WASISubscriptionClock { timeout?: number; - static read_bytes(view: DataView, ptr: number): SubscriptionClock { - const self = new SubscriptionClock(); + static read_bytes(view: DataView, ptr: number): WASISubscriptionClock { + const self = new WASISubscriptionClock(); self.timeout = Number(view.getBigUint64(ptr + 8, true)); return self; } } -export class SubscriptionFdReadWrite { +export class WASISubscriptionFdReadWrite { /*:: fd: number*/ fd?: number; - static read_bytes(view: DataView, ptr: number): SubscriptionFdReadWrite { - const self = new SubscriptionFdReadWrite(); + static read_bytes(view: DataView, ptr: number): WASISubscriptionFdReadWrite { + const self = new WASISubscriptionFdReadWrite(); self.fd = view.getUint32(ptr, true); return self; } } -export class SubscriptionU { - tag?: EventType; - data?: SubscriptionClock | SubscriptionFdReadWrite; +export class WASISubscriptionU { + tag?: WASIEventType; + data?: WASISubscriptionClock | WASISubscriptionFdReadWrite; - static read_bytes(view: DataView, ptr: number): SubscriptionU { - const self = new SubscriptionU(); - self.tag = EventType.from_u8(view.getUint8(ptr)); + static read_bytes(view: DataView, ptr: number): WASISubscriptionU { + const self = new WASISubscriptionU(); + self.tag = WASIEventType.from_u8(view.getUint8(ptr)); switch (self.tag.variant) { case 'clock': - self.data = SubscriptionClock.read_bytes(view, ptr + 8); + self.data = WASISubscriptionClock.read_bytes(view, ptr + 8); break; case 'fd_read': case 'fd_write': - self.data = SubscriptionFdReadWrite.read_bytes(view, ptr + 8); + self.data = WASISubscriptionFdReadWrite.read_bytes(view, ptr + 8); break; default: throw 'unreachable'; @@ -112,14 +116,14 @@ export class SubscriptionU { } } -export class Subscription { +export class WASISubscription { userdata?: bigint; - u?: SubscriptionU; + u?: WASISubscriptionU; - static read_bytes(view: DataView, ptr: number): Subscription { - const subscription = new Subscription(); + static read_bytes(view: DataView, ptr: number): WASISubscription { + const subscription = new WASISubscription(); subscription.userdata = view.getBigUint64(ptr, true); - subscription.u = SubscriptionU.read_bytes(view, ptr + 8); + subscription.u = WASISubscriptionU.read_bytes(view, ptr + 8); return subscription; } @@ -127,10 +131,10 @@ export class Subscription { view: DataView, ptr: number, len: number, - ): Array { + ): Array { const subscriptions = []; for (let i = 0; i < len; i++) { - subscriptions.push(Subscription.read_bytes(view, ptr + 48 * i)); + subscriptions.push(WASISubscription.read_bytes(view, ptr + 48 * i)); } return subscriptions; } diff --git a/packages/browser-runtime/src/worker-util.ts b/packages/browser-runtime/src/workers/worker-util.ts similarity index 99% rename from packages/browser-runtime/src/worker-util.ts rename to packages/browser-runtime/src/workers/worker-util.ts index e4a94ef..64c9daa 100644 --- a/packages/browser-runtime/src/worker-util.ts +++ b/packages/browser-runtime/src/workers/worker-util.ts @@ -5,7 +5,7 @@ import { PreopenDirectory, wasi as wasiOrigin, } from '@bjorn3/browser_wasi_shim'; -import { NetworkMode } from './types'; +import { NetworkMode } from '../types'; export let streamCtrl: Int32Array; export let streamStatus: Int32Array; diff --git a/packages/browser-runtime/src/worker.ts b/packages/browser-runtime/src/workers/worker.ts similarity index 76% rename from packages/browser-runtime/src/worker.ts rename to packages/browser-runtime/src/workers/worker.ts index b2b56e0..131e8aa 100644 --- a/packages/browser-runtime/src/worker.ts +++ b/packages/browser-runtime/src/workers/worker.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ -import { Fd, WASI, wasi as wasiorigin } from '@bjorn3/browser_wasi_shim'; +import { Fd, WASI, wasi } from '@bjorn3/browser_wasi_shim'; import { errStatus, fetchChunks, @@ -11,8 +11,8 @@ import { wasiHackSocket, } from './worker-util'; import { TtyClient } from 'xterm-pty'; -import { Event, EventType, Subscription } from './wasi-util'; -import { NETWORK_MODE } from './types'; +import { WASIEvent, WASIEventType, WASISubscription } from './wasi-util'; +import { NETWORK_MODE } from '../types'; onmessage = async (msg: MessageEvent) => { if (serveIfInitMsg(msg)) { @@ -77,13 +77,13 @@ function startWasi( listenfd: number, connfd: number, ) { - const wasi = new WASI(args, env, fds); - wasiHack(wasi, ttyClient, connfd); - wasiHackSocket(wasi, listenfd, connfd); + const wasiInstance = new WASI(args, env, fds); + wasiHack(wasiInstance, ttyClient, connfd); + wasiHackSocket(wasiInstance, listenfd, connfd); WebAssembly.instantiate(wasm, { - wasi_snapshot_preview1: wasi.wasiImport, + wasi_snapshot_preview1: wasiInstance.wasiImport, }).then((inst) => { - wasi.start( + wasiInstance.start( inst.instance as { // type missmatching exports: { memory: WebAssembly.Memory; _start: () => unknown }; @@ -93,19 +93,15 @@ function startWasi( } // wasiHack patches wasi object for integrating it to xterm-pty. -function wasiHack(wasi: WASI, ttyClient: TtyClient, connfd: number) { +function wasiHack(wasiInstance: WASI, ttyClient: TtyClient, connfd: number) { // definition from wasi-libc https://github.com/WebAssembly/wasi-libc/blob/wasi-sdk-19/expected/wasm32-wasi/predefined-macros.txt const ERRNO_INVAL = 28; - const _fd_read = wasi.wasiImport.fd_read; - wasi.wasiImport.fd_read = (fd, iovs_ptr, iovs_len, nread_ptr) => { + const _fd_read = wasiInstance.wasiImport.fd_read; + wasiInstance.wasiImport.fd_read = (fd, iovs_ptr, iovs_len, nread_ptr) => { if (fd == 0) { - const buffer = new DataView(wasi.inst.exports.memory.buffer); - const buffer8 = new Uint8Array(wasi.inst.exports.memory.buffer); - const iovecs = wasiorigin.Iovec.read_bytes_array( - buffer, - iovs_ptr, - iovs_len, - ); + const buffer = new DataView(wasiInstance.inst.exports.memory.buffer); + const buffer8 = new Uint8Array(wasiInstance.inst.exports.memory.buffer); + const iovecs = wasi.Iovec.read_bytes_array(buffer, iovs_ptr, iovs_len); let nread = 0; for (let i = 0; i < iovecs.length; i++) { const iovec = iovecs[i]; @@ -120,7 +116,7 @@ function wasiHack(wasi: WASI, ttyClient: TtyClient, connfd: number) { return 0; } else { console.log('fd_read: unknown fd ' + fd); - return _fd_read.apply(wasi.wasiImport, [ + return _fd_read.apply(wasiInstance.wasiImport, [ fd, iovs_ptr, iovs_len, @@ -129,16 +125,12 @@ function wasiHack(wasi: WASI, ttyClient: TtyClient, connfd: number) { } return ERRNO_INVAL; }; - const _fd_write = wasi.wasiImport.fd_write; - wasi.wasiImport.fd_write = (fd, iovs_ptr, iovs_len, nwritten_ptr) => { + const _fd_write = wasiInstance.wasiImport.fd_write; + wasiInstance.wasiImport.fd_write = (fd, iovs_ptr, iovs_len, nwritten_ptr) => { if (fd == 1 || fd == 2) { - const buffer = new DataView(wasi.inst.exports.memory.buffer); - const buffer8 = new Uint8Array(wasi.inst.exports.memory.buffer); - const iovecs = wasiorigin.Ciovec.read_bytes_array( - buffer, - iovs_ptr, - iovs_len, - ); + const buffer = new DataView(wasiInstance.inst.exports.memory.buffer); + const buffer8 = new Uint8Array(wasiInstance.inst.exports.memory.buffer); + const iovecs = wasi.Ciovec.read_bytes_array(buffer, iovs_ptr, iovs_len); let wtotal = 0; for (let i = 0; i < iovecs.length; i++) { const iovec = iovecs[i]; @@ -153,7 +145,7 @@ function wasiHack(wasi: WASI, ttyClient: TtyClient, connfd: number) { return 0; } else { console.log('fd_write: unknown fd ' + fd); - return _fd_write.apply(wasi.wasiImport, [ + return _fd_write.apply(wasiInstance.wasiImport, [ fd, iovs_ptr, iovs_len, @@ -162,7 +154,7 @@ function wasiHack(wasi: WASI, ttyClient: TtyClient, connfd: number) { } return ERRNO_INVAL; }; - wasi.wasiImport.poll_oneoff = ( + wasiInstance.wasiImport.poll_oneoff = ( in_ptr, out_ptr, nsubscriptions, @@ -171,8 +163,12 @@ function wasiHack(wasi: WASI, ttyClient: TtyClient, connfd: number) { if (nsubscriptions == 0) { return ERRNO_INVAL; } - const buffer = new DataView(wasi.inst.exports.memory.buffer); - const in_ = Subscription.read_bytes_array(buffer, in_ptr, nsubscriptions); + const buffer = new DataView(wasiInstance.inst.exports.memory.buffer); + const in_ = WASISubscription.read_bytes_array( + buffer, + in_ptr, + nsubscriptions, + ); let isReadPollStdin = false; let isReadPollConn = false; let isClockPoll = false; @@ -218,10 +214,10 @@ function wasiHack(wasi: WASI, ttyClient: TtyClient, connfd: number) { readable = ttyClient.onWaitForReadable(timeout / 1000000000); } if (readable && isReadPollStdin) { - const event = new Event(); + const event = new WASIEvent(); event.userdata = pollSubStdin!.userdata; event.error = 0; - event.type = new EventType('fd_read'); + event.type = new WASIEventType('fd_read'); events.push(event); } if (isReadPollConn) { @@ -229,23 +225,23 @@ function wasiHack(wasi: WASI, ttyClient: TtyClient, connfd: number) { if (sockreadable == errStatus) { return ERRNO_INVAL; } else if (sockreadable == true) { - const event = new Event(); + const event = new WASIEvent(); event.userdata = pollSubConn!.userdata; event.error = 0; - event.type = new EventType('fd_read'); + event.type = new WASIEventType('fd_read'); events.push(event); } } if (isClockPoll) { - const event = new Event(); + const event = new WASIEvent(); event.userdata = clockSub!.userdata; event.error = 0; - event.type = new EventType('clock'); + event.type = new WASIEventType('clock'); events.push(event); } } const len = events.length; - Event.write_bytes_array(buffer, out_ptr, events); + WASIEvent.write_bytes_array(buffer, out_ptr, events); buffer.setUint32(nevents_ptr, len, true); return 0; };