@threadedstack/wmd-web 0.0.0-stage → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2601 -2
- package/RELEASE.json +123 -0
- package/export-page/coi-sw.js +20 -0
- package/export-page/index.html +17 -0
- package/export-page/run.css +10 -0
- package/export-page/run.js +236 -0
- package/guest/arm64/Image +4 -0
- package/guest/arm64/Image-4k +4 -0
- package/guest/arm64/initramfs.cpio.gz +0 -0
- package/guest/arm64/vm.wasm +0 -0
- package/package.json +36 -4
- package/page/sw.js +381 -0
- package/relay/control.ts +139 -0
- package/relay/engine.ts +787 -0
- package/relay/hosted.ts +660 -0
- package/relay/keys.ts +53 -0
- package/relay/local-tls.ts +121 -0
- package/relay/lock.ts +81 -0
- package/relay/logfile.ts +138 -0
- package/relay/main.ts +642 -0
- package/relay/policy.ts +241 -0
- package/relay/relay.ts +266 -0
- package/relay/token.ts +116 -0
- package/relay/v1.ts +107 -0
- package/relay/wisp.ts +615 -0
- package/src/base.js +325 -0
- package/src/boot.js +2037 -0
- package/src/calib-worker.js +40 -0
- package/src/fs/9p/codec.js +303 -0
- package/src/fs/9p/server.js +521 -0
- package/src/fs/errno.js +43 -0
- package/src/fs/graph.js +380 -0
- package/src/fs/overlay.js +1018 -0
- package/src/fs/pack-write.js +165 -0
- package/src/fs/pack.js +427 -0
- package/src/fs/seed.js +22 -0
- package/src/fs/svc-snapshot.js +65 -0
- package/src/fs/upper-pack.js +112 -0
- package/src/host/base-cache.js +195 -0
- package/src/host/base-file.js +328 -0
- package/src/host/base-io.js +93 -0
- package/src/host/boot-events.js +209 -0
- package/src/host/chan-service.js +300 -0
- package/src/host/chan-services.js +689 -0
- package/src/host/chan.js +655 -0
- package/src/host/ckpt-file.js +395 -0
- package/src/host/ckpt-io.js +207 -0
- package/src/host/ckpt-point.js +160 -0
- package/src/host/ckpt-save.js +64 -0
- package/src/host/ckpt.js +434 -0
- package/src/host/clock.js +111 -0
- package/src/host/ctl.js +778 -0
- package/src/host/errno.js +18 -0
- package/src/host/fs.js +167 -0
- package/src/host/gcnudge.js +83 -0
- package/src/host/i64shim.js +81 -0
- package/src/host/jit-cache.js +341 -0
- package/src/host/jit-hub-core.js +208 -0
- package/src/host/jit-hub.js +93 -0
- package/src/host/jit-snap.js +226 -0
- package/src/host/jit.js +1903 -0
- package/src/host/layout.js +100 -0
- package/src/host/monitor.js +110 -0
- package/src/host/p9mount.js +27 -0
- package/src/host/ram-mem.js +125 -0
- package/src/host/stdio.js +143 -0
- package/src/host/threads.js +109 -0
- package/src/host/wasi.js +335 -0
- package/src/host/wmd-imports.js +71 -0
- package/src/host/yamux.js +387 -0
- package/src/image-files.js +154 -0
- package/src/net/dhcp-dns.js +126 -0
- package/src/net/net-worker.js +172 -0
- package/src/net/packet.js +227 -0
- package/src/net/peer.js +230 -0
- package/src/net/proto.js +189 -0
- package/src/net/relay-client.js +226 -0
- package/src/net/stack.js +867 -0
- package/src/net/switch.js +160 -0
- package/src/net/wisp-client.js +570 -0
- package/src/net/wisp-transport.js +196 -0
- package/src/net/wisp.js +511 -0
- package/src/registry/client.js +176 -0
- package/src/registry/converter.js +68 -0
- package/src/registry/hub.js +221 -0
- package/src/registry/oci.js +76 -0
- package/src/registry/pack-worker.js +70 -0
- package/src/registry/pull.js +258 -0
- package/src/registry/ref.js +110 -0
- package/src/registry/wasi-mem.js +355 -0
- package/src/worker.js +315 -0
- package/wmdpack.wasm +0 -0
package/src/fs/graph.js
ADDED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
// P-B9: a small binary codec for an object graph with shared references and cycles (the
|
|
2
|
+
// 9P service's Overlay tree and its fid table), so the service's state can leave its Worker,
|
|
3
|
+
// go to OPFS and come back after a page reload.
|
|
4
|
+
//
|
|
5
|
+
// It is not a general serializer. It knows what the file server holds: undefined, null,
|
|
6
|
+
// booleans, numbers, BigInts, strings, Uint8Array, Array, Map, Set, plain objects, and
|
|
7
|
+
// instances of the classes a caller registers. Functions are never written.
|
|
8
|
+
//
|
|
9
|
+
// encodeGraph(root, {classes, special}) -> {segments: Uint8Array[], bytes}
|
|
10
|
+
// decodeGraph(bytes, {classes, special}) -> root
|
|
11
|
+
//
|
|
12
|
+
// classes: {Name: {ctor, make?, skip?}}. ctor identifies instances on the way out (an
|
|
13
|
+
// instance's constructor must be the registered one); make() builds the object that
|
|
14
|
+
// decode fills (default: new ctor() with no arguments... classes with private members
|
|
15
|
+
// must be built by their constructor, never by Object.create). skip: field names
|
|
16
|
+
// that are not written (set by the constructor in the new process: a function, a
|
|
17
|
+
// reference to a live Pack, a cap).
|
|
18
|
+
// special: {pack(obj) -> token|undefined, revive(token) -> obj}: values that are not data
|
|
19
|
+
// (a live Pack) are written as a token and revived to the new process's object.
|
|
20
|
+
//
|
|
21
|
+
// Wire format: a tag byte, then the value. Objects (Array, Map, Set, plain, instance) take
|
|
22
|
+
// an id when first written (pre-order); a later reference is tag REF + id. A decoded
|
|
23
|
+
// object is registered before its children are read, so cycles close.
|
|
24
|
+
|
|
25
|
+
const T_UNDEF = 0
|
|
26
|
+
const T_NULL = 1
|
|
27
|
+
const T_FALSE = 2
|
|
28
|
+
const T_TRUE = 3
|
|
29
|
+
const T_INT = 4 // zig-zag varint, |x| <= 2^53
|
|
30
|
+
const T_FLOAT = 5
|
|
31
|
+
const T_BIG = 6 // i64
|
|
32
|
+
const T_BIGSTR = 7 // beyond i64: decimal string
|
|
33
|
+
const T_STR = 8
|
|
34
|
+
const T_BYTES = 9
|
|
35
|
+
const T_ARRAY = 10
|
|
36
|
+
const T_MAP = 11
|
|
37
|
+
const T_SET = 12
|
|
38
|
+
const T_OBJ = 13
|
|
39
|
+
const T_INST = 14
|
|
40
|
+
const T_REF = 15
|
|
41
|
+
const T_SPECIAL = 16
|
|
42
|
+
|
|
43
|
+
const MAGIC = 0x47524631 // "GRF1"
|
|
44
|
+
const BIG_SEGMENT = 1 << 18
|
|
45
|
+
const BUF = 1 << 20
|
|
46
|
+
|
|
47
|
+
class Writer {
|
|
48
|
+
constructor() {
|
|
49
|
+
this.segments = []
|
|
50
|
+
this.buf = new Uint8Array(BUF)
|
|
51
|
+
this.dv = new DataView(this.buf.buffer)
|
|
52
|
+
this.pos = 0
|
|
53
|
+
this.bytes = 0
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#room(n) {
|
|
57
|
+
if (this.pos + n <= this.buf.length) return
|
|
58
|
+
this.#flush()
|
|
59
|
+
if (n > this.buf.length) {
|
|
60
|
+
this.buf = new Uint8Array(n)
|
|
61
|
+
this.dv = new DataView(this.buf.buffer)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
#flush() {
|
|
66
|
+
if (this.pos) {
|
|
67
|
+
this.segments.push(this.buf.slice(0, this.pos))
|
|
68
|
+
this.bytes += this.pos
|
|
69
|
+
this.pos = 0
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
byte(b) {
|
|
74
|
+
this.#room(1)
|
|
75
|
+
this.buf[this.pos++] = b
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
uvarint(n) {
|
|
79
|
+
this.#room(10)
|
|
80
|
+
while (n >= 0x80) {
|
|
81
|
+
this.buf[this.pos++] = (n % 0x80) | 0x80
|
|
82
|
+
n = Math.floor(n / 0x80)
|
|
83
|
+
}
|
|
84
|
+
this.buf[this.pos++] = n
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
svarint(n) {
|
|
88
|
+
this.uvarint(n < 0 ? -2 * n - 1 : 2 * n)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
f64(x) {
|
|
92
|
+
this.#room(8)
|
|
93
|
+
this.dv.setFloat64(this.pos, x)
|
|
94
|
+
this.pos += 8
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
i64(x) {
|
|
98
|
+
this.#room(8)
|
|
99
|
+
this.dv.setBigInt64(this.pos, x)
|
|
100
|
+
this.pos += 8
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
raw(u8) {
|
|
104
|
+
if (u8.length >= BIG_SEGMENT) {
|
|
105
|
+
this.#flush()
|
|
106
|
+
this.segments.push(u8.slice())
|
|
107
|
+
this.bytes += u8.length
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
this.#room(u8.length)
|
|
111
|
+
this.buf.set(u8, this.pos)
|
|
112
|
+
this.pos += u8.length
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
finish() {
|
|
116
|
+
this.#flush()
|
|
117
|
+
return { segments: this.segments, bytes: this.bytes }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const enc = new TextEncoder()
|
|
122
|
+
const dec = new TextDecoder()
|
|
123
|
+
const I64_MIN = -(1n << 63n)
|
|
124
|
+
const I64_MAX = (1n << 63n) - 1n
|
|
125
|
+
|
|
126
|
+
export function encodeGraph(root, { classes = {}, special = null } = {}) {
|
|
127
|
+
const w = new Writer()
|
|
128
|
+
const ids = new Map()
|
|
129
|
+
const names = new Map(Object.entries(classes).map(([n, c]) => [c.ctor, n]))
|
|
130
|
+
const skip = new Map(Object.entries(classes).map(([n, c]) => [n, new Set(c.skip || [])]))
|
|
131
|
+
w.i64(BigInt(MAGIC))
|
|
132
|
+
|
|
133
|
+
function value(v) {
|
|
134
|
+
switch (typeof v) {
|
|
135
|
+
case 'undefined':
|
|
136
|
+
return w.byte(T_UNDEF)
|
|
137
|
+
case 'boolean':
|
|
138
|
+
return w.byte(v ? T_TRUE : T_FALSE)
|
|
139
|
+
case 'number':
|
|
140
|
+
if (Number.isInteger(v) && Math.abs(v) <= Number.MAX_SAFE_INTEGER && !Object.is(v, -0)) {
|
|
141
|
+
w.byte(T_INT)
|
|
142
|
+
return w.svarint(v)
|
|
143
|
+
}
|
|
144
|
+
w.byte(T_FLOAT)
|
|
145
|
+
return w.f64(v)
|
|
146
|
+
case 'bigint':
|
|
147
|
+
if (v >= I64_MIN && v <= I64_MAX) {
|
|
148
|
+
w.byte(T_BIG)
|
|
149
|
+
return w.i64(v)
|
|
150
|
+
}
|
|
151
|
+
w.byte(T_BIGSTR)
|
|
152
|
+
return str(v.toString())
|
|
153
|
+
case 'string':
|
|
154
|
+
w.byte(T_STR)
|
|
155
|
+
return str(v)
|
|
156
|
+
case 'function':
|
|
157
|
+
throw new Error('graph: a function cannot be written')
|
|
158
|
+
case 'symbol':
|
|
159
|
+
throw new Error('graph: a symbol cannot be written')
|
|
160
|
+
}
|
|
161
|
+
if (v === null) return w.byte(T_NULL)
|
|
162
|
+
if (v instanceof Uint8Array) {
|
|
163
|
+
w.byte(T_BYTES)
|
|
164
|
+
w.uvarint(v.length)
|
|
165
|
+
return w.raw(v)
|
|
166
|
+
}
|
|
167
|
+
const had = ids.get(v)
|
|
168
|
+
if (had !== undefined) {
|
|
169
|
+
w.byte(T_REF)
|
|
170
|
+
return w.uvarint(had)
|
|
171
|
+
}
|
|
172
|
+
const tok = special?.pack?.(v)
|
|
173
|
+
if (tok !== undefined) {
|
|
174
|
+
w.byte(T_SPECIAL)
|
|
175
|
+
return value(tok)
|
|
176
|
+
}
|
|
177
|
+
ids.set(v, ids.size)
|
|
178
|
+
if (Array.isArray(v)) {
|
|
179
|
+
w.byte(T_ARRAY)
|
|
180
|
+
w.uvarint(v.length)
|
|
181
|
+
for (const x of v) value(x)
|
|
182
|
+
} else if (v instanceof Map) {
|
|
183
|
+
w.byte(T_MAP)
|
|
184
|
+
w.uvarint(v.size)
|
|
185
|
+
for (const [k, x] of v) {
|
|
186
|
+
value(k)
|
|
187
|
+
value(x)
|
|
188
|
+
}
|
|
189
|
+
} else if (v instanceof Set) {
|
|
190
|
+
w.byte(T_SET)
|
|
191
|
+
w.uvarint(v.size)
|
|
192
|
+
for (const x of v) value(x)
|
|
193
|
+
} else {
|
|
194
|
+
const proto = Object.getPrototypeOf(v)
|
|
195
|
+
const name = names.get(v.constructor)
|
|
196
|
+
if (name !== undefined && proto === v.constructor.prototype) {
|
|
197
|
+
w.byte(T_INST)
|
|
198
|
+
str(name)
|
|
199
|
+
fields(v, skip.get(name))
|
|
200
|
+
} else if (proto === Object.prototype || proto === null) {
|
|
201
|
+
w.byte(T_OBJ)
|
|
202
|
+
fields(v, null)
|
|
203
|
+
} else {
|
|
204
|
+
throw new Error(`graph: an instance of ${v.constructor?.name || 'an unregistered class'} cannot be written`)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function fields(o, skipSet) {
|
|
210
|
+
const keys = Object.keys(o).filter(k => !skipSet?.has(k) && typeof o[k] !== 'function')
|
|
211
|
+
w.uvarint(keys.length)
|
|
212
|
+
for (const k of keys) {
|
|
213
|
+
str(k)
|
|
214
|
+
value(o[k])
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function str(s) {
|
|
219
|
+
const b = enc.encode(s)
|
|
220
|
+
w.uvarint(b.length)
|
|
221
|
+
w.raw(b)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
value(root)
|
|
225
|
+
return w.finish()
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
class Reader {
|
|
229
|
+
constructor(b) {
|
|
230
|
+
this.b = b
|
|
231
|
+
this.p = 0
|
|
232
|
+
this.dv = new DataView(b.buffer, b.byteOffset, b.byteLength)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
need(n) {
|
|
236
|
+
if (this.p + n > this.b.length) throw new Error('graph: truncated')
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
byte() {
|
|
240
|
+
this.need(1)
|
|
241
|
+
return this.b[this.p++]
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
uvarint() {
|
|
245
|
+
let x = 0
|
|
246
|
+
let mul = 1
|
|
247
|
+
for (let i = 0; i < 8; i++) {
|
|
248
|
+
const c = this.byte()
|
|
249
|
+
x += (c & 0x7f) * mul
|
|
250
|
+
if (!(c & 0x80)) return x
|
|
251
|
+
mul *= 0x80
|
|
252
|
+
}
|
|
253
|
+
throw new Error('graph: bad varint')
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
svarint() {
|
|
257
|
+
const u = this.uvarint()
|
|
258
|
+
return u % 2 ? -(u + 1) / 2 : u / 2
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
f64() {
|
|
262
|
+
this.need(8)
|
|
263
|
+
const x = this.dv.getFloat64(this.p)
|
|
264
|
+
this.p += 8
|
|
265
|
+
return x
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
i64() {
|
|
269
|
+
this.need(8)
|
|
270
|
+
const x = this.dv.getBigInt64(this.p)
|
|
271
|
+
this.p += 8
|
|
272
|
+
return x
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
take(n) {
|
|
276
|
+
this.need(n)
|
|
277
|
+
const out = this.b.subarray(this.p, this.p + n)
|
|
278
|
+
this.p += n
|
|
279
|
+
return out
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export function decodeGraph(bytes, { classes = {}, special = null } = {}) {
|
|
284
|
+
const r = new Reader(bytes)
|
|
285
|
+
if (r.i64() !== BigInt(MAGIC)) throw new Error('graph: bad magic')
|
|
286
|
+
const objs = []
|
|
287
|
+
|
|
288
|
+
const str = () => dec.decode(r.take(r.uvarint()))
|
|
289
|
+
|
|
290
|
+
function value() {
|
|
291
|
+
const t = r.byte()
|
|
292
|
+
switch (t) {
|
|
293
|
+
case T_UNDEF:
|
|
294
|
+
return undefined
|
|
295
|
+
case T_NULL:
|
|
296
|
+
return null
|
|
297
|
+
case T_FALSE:
|
|
298
|
+
return false
|
|
299
|
+
case T_TRUE:
|
|
300
|
+
return true
|
|
301
|
+
case T_INT:
|
|
302
|
+
return r.svarint()
|
|
303
|
+
case T_FLOAT:
|
|
304
|
+
return r.f64()
|
|
305
|
+
case T_BIG:
|
|
306
|
+
return r.i64()
|
|
307
|
+
case T_BIGSTR:
|
|
308
|
+
return BigInt(str())
|
|
309
|
+
case T_STR:
|
|
310
|
+
return str()
|
|
311
|
+
case T_BYTES: {
|
|
312
|
+
const n = r.uvarint()
|
|
313
|
+
return r.take(n).slice()
|
|
314
|
+
}
|
|
315
|
+
case T_REF: {
|
|
316
|
+
const id = r.uvarint()
|
|
317
|
+
if (id >= objs.length) throw new Error('graph: bad reference')
|
|
318
|
+
return objs[id]
|
|
319
|
+
}
|
|
320
|
+
case T_SPECIAL: {
|
|
321
|
+
const tok = value()
|
|
322
|
+
if (!special?.revive) throw new Error('graph: a special value and no reviver')
|
|
323
|
+
return special.revive(tok) // the token took its own id if it is an object; the revived value takes none
|
|
324
|
+
}
|
|
325
|
+
case T_ARRAY: {
|
|
326
|
+
const n = r.uvarint()
|
|
327
|
+
const a = []
|
|
328
|
+
objs.push(a)
|
|
329
|
+
for (let i = 0; i < n; i++) a.push(value())
|
|
330
|
+
return a
|
|
331
|
+
}
|
|
332
|
+
case T_MAP: {
|
|
333
|
+
const n = r.uvarint()
|
|
334
|
+
const m = new Map()
|
|
335
|
+
objs.push(m)
|
|
336
|
+
for (let i = 0; i < n; i++) {
|
|
337
|
+
const k = value()
|
|
338
|
+
m.set(k, value())
|
|
339
|
+
}
|
|
340
|
+
return m
|
|
341
|
+
}
|
|
342
|
+
case T_SET: {
|
|
343
|
+
const n = r.uvarint()
|
|
344
|
+
const s = new Set()
|
|
345
|
+
objs.push(s)
|
|
346
|
+
for (let i = 0; i < n; i++) s.add(value())
|
|
347
|
+
return s
|
|
348
|
+
}
|
|
349
|
+
case T_OBJ: {
|
|
350
|
+
const o = {}
|
|
351
|
+
objs.push(o)
|
|
352
|
+
readFields(o)
|
|
353
|
+
return o
|
|
354
|
+
}
|
|
355
|
+
case T_INST: {
|
|
356
|
+
const name = str()
|
|
357
|
+
const c = classes[name]
|
|
358
|
+
if (!c) throw new Error(`graph: unknown class ${name}`)
|
|
359
|
+
const o = c.make ? c.make() : new c.ctor()
|
|
360
|
+
objs.push(o)
|
|
361
|
+
readFields(o)
|
|
362
|
+
return o
|
|
363
|
+
}
|
|
364
|
+
default:
|
|
365
|
+
throw new Error(`graph: bad tag ${t}`)
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function readFields(o) {
|
|
370
|
+
const n = r.uvarint()
|
|
371
|
+
for (let i = 0; i < n; i++) {
|
|
372
|
+
const k = str()
|
|
373
|
+
// a hostile file must not reach Object.prototype (o.__proto__ = {...} would replace the prototype of an instance)
|
|
374
|
+
if (k === '__proto__') throw new Error('graph: field name __proto__')
|
|
375
|
+
o[k] = value()
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return value()
|
|
380
|
+
}
|