const base = '/srv/proc/', m = {}, qmt = (pid, f) => queueMicrotask(() => { try { f() } catch (e) { req('put', '/srv/cons', pid + ': ' + e + '\n' + (e?.stack ?? '')) } }), dir = pid => base + pid + '/', pf = (pid, f, d) => req('put', dir(pid) + f, d), fail = (pid, e) => { pf(pid, 'err', e + '\n' + (e?.stack ?? '')); pf(pid, 'status', 'err'); throw e }, load = p => { const s = req('put', '/srv/cc', p); try { return (0, eval)('"use strict"; ({ sub, tra }, req, mount) => { ' + s + '\n}\n//# sourceURL=wom:' + p) } catch (e) { err(p + ':' + (req('put', '/srv/parse', s) || e.message)) } }, start = (pid, d, n) => { const old = m[pid]; if (old?.del) return err('busy') const [s = err('bad request'), ...l] = d.split('\n').filter(Boolean), [p, ...args] = s.split(' '), fn = load(p) old && (old.del = 1) const cur = m[pid] = { del: 0, ns: Object.fromEntries([...req('get', '/lib/ns').replaceAll('$pid', pid).split('\n'), ...l].map(x => x.split(' ').slice(1).reverse())), args: args.join(' ') } n('put', dir(pid) + 'record', d) n('put', dir(pid) + 'fs/', '') pf(pid, 'status', 'starting') qmt(pid, () => { old?.c?.dis() if (cur.del) return try { old && (n('del', dir(pid) + 'fs/'), n('put', dir(pid) + 'fs/', '')) cur.c = C(({ sub, der, tra }) => fn({ sub: (f, cb, im) => sub(der(f), cb, im), tra }, (v, p, d) => req(v, p, d, cur.ns), (p, h) => tra(globalThis.mount(p, h, cur.ns))))() pf(pid, 'status', 'started') } catch (e) { fail(pid, e) } }) } req('put', base); mount(base, (v, p, d, n) => { const [, pid, ...l] = p.split('/'), rest = l.join('/') if (v === 'get' && !pid) { const first = id => { try { return ' ' + n('get', dir(id) + 'record').split('\n')[0] } catch { return '' } } return n().split('\n').map(s => s.endsWith('/') ? s + first(s.slice(3, -1)) : s).join('\n') + '\n=> new' } if (v === 'put' && pid === 'new') { const id = 'p' + crypto.randomUUID().slice(0, 8); return start(id, d, n), dir(id) } if (v === 'put' && pid && !l[0] && d) return start(pid, d, n) if (v === 'del' && pid && !l[0]) { if (!m[pid]) return n() if (m[pid].del) return m[pid].del = 1 pf(pid, 'status', 'closing') qmt(pid, () => { m[pid].c?.dis(); delete m[pid]; req('del', dir(pid)) }) return } if (m[pid]) { if (!rest) return v !== 'get' ? n() : n() + '\n=> ns\n=> ctl' if (rest === 'record' && v !== 'get') err('not allowed') if (rest === 'ns') return v !== 'get' ? err('not allowed') : Object.entries(m[pid].ns).map(([k, t]) => '=> ' + t + ' ' + k).join('\n') if (rest === 'ctl') return v !== 'put' ? err('not allowed') : d === 'close' ? req('del', dir(pid)) : err('unknown control message "' + (d ?? '') + '"') return n() } return n() }) req('get', base).split('\n').map(s => s.split(' ')[1]).filter(s => s?.endsWith('/')).forEach(s => { const pid = s.slice(0, -1) try { req('put', dir(pid), req('get', dir(pid) + 'record')) } catch (e) { pf(pid, 'err', e.message); pf(pid, 'status', 'err'); req('put', '/srv/cons', s + ': ' + e.message) } })