@threadedstack/wmd-web 0.0.0-stage → 0.1.12

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.
Files changed (92) hide show
  1. package/README.md +2601 -2
  2. package/RELEASE.json +123 -0
  3. package/export-page/coi-sw.js +20 -0
  4. package/export-page/index.html +17 -0
  5. package/export-page/run.css +10 -0
  6. package/export-page/run.js +236 -0
  7. package/guest/arm64/Image +4 -0
  8. package/guest/arm64/Image-4k +4 -0
  9. package/guest/arm64/initramfs.cpio.gz +0 -0
  10. package/guest/arm64/vm.wasm +0 -0
  11. package/package.json +36 -4
  12. package/page/sw.js +381 -0
  13. package/relay/control.ts +139 -0
  14. package/relay/engine.ts +787 -0
  15. package/relay/hosted.ts +660 -0
  16. package/relay/keys.ts +53 -0
  17. package/relay/local-tls.ts +121 -0
  18. package/relay/lock.ts +81 -0
  19. package/relay/logfile.ts +138 -0
  20. package/relay/main.ts +642 -0
  21. package/relay/policy.ts +241 -0
  22. package/relay/relay.ts +266 -0
  23. package/relay/token.ts +116 -0
  24. package/relay/v1.ts +107 -0
  25. package/relay/wisp.ts +615 -0
  26. package/src/base.js +325 -0
  27. package/src/boot.js +2037 -0
  28. package/src/calib-worker.js +40 -0
  29. package/src/fs/9p/codec.js +303 -0
  30. package/src/fs/9p/server.js +521 -0
  31. package/src/fs/errno.js +43 -0
  32. package/src/fs/graph.js +380 -0
  33. package/src/fs/overlay.js +1018 -0
  34. package/src/fs/pack-write.js +165 -0
  35. package/src/fs/pack.js +427 -0
  36. package/src/fs/seed.js +22 -0
  37. package/src/fs/svc-snapshot.js +65 -0
  38. package/src/fs/upper-pack.js +112 -0
  39. package/src/host/base-cache.js +195 -0
  40. package/src/host/base-file.js +328 -0
  41. package/src/host/base-io.js +93 -0
  42. package/src/host/boot-events.js +209 -0
  43. package/src/host/chan-service.js +300 -0
  44. package/src/host/chan-services.js +689 -0
  45. package/src/host/chan.js +655 -0
  46. package/src/host/ckpt-file.js +395 -0
  47. package/src/host/ckpt-io.js +207 -0
  48. package/src/host/ckpt-point.js +160 -0
  49. package/src/host/ckpt-save.js +64 -0
  50. package/src/host/ckpt.js +434 -0
  51. package/src/host/clock.js +111 -0
  52. package/src/host/ctl.js +778 -0
  53. package/src/host/errno.js +18 -0
  54. package/src/host/fs.js +167 -0
  55. package/src/host/gcnudge.js +83 -0
  56. package/src/host/i64shim.js +81 -0
  57. package/src/host/jit-cache.js +341 -0
  58. package/src/host/jit-hub-core.js +208 -0
  59. package/src/host/jit-hub.js +93 -0
  60. package/src/host/jit-snap.js +226 -0
  61. package/src/host/jit.js +1903 -0
  62. package/src/host/layout.js +100 -0
  63. package/src/host/monitor.js +110 -0
  64. package/src/host/p9mount.js +27 -0
  65. package/src/host/ram-mem.js +125 -0
  66. package/src/host/stdio.js +143 -0
  67. package/src/host/threads.js +109 -0
  68. package/src/host/wasi.js +335 -0
  69. package/src/host/wmd-imports.js +71 -0
  70. package/src/host/yamux.js +387 -0
  71. package/src/image-files.js +154 -0
  72. package/src/net/dhcp-dns.js +126 -0
  73. package/src/net/net-worker.js +172 -0
  74. package/src/net/packet.js +227 -0
  75. package/src/net/peer.js +230 -0
  76. package/src/net/proto.js +189 -0
  77. package/src/net/relay-client.js +226 -0
  78. package/src/net/stack.js +867 -0
  79. package/src/net/switch.js +160 -0
  80. package/src/net/wisp-client.js +570 -0
  81. package/src/net/wisp-transport.js +196 -0
  82. package/src/net/wisp.js +511 -0
  83. package/src/registry/client.js +176 -0
  84. package/src/registry/converter.js +68 -0
  85. package/src/registry/hub.js +221 -0
  86. package/src/registry/oci.js +76 -0
  87. package/src/registry/pack-worker.js +70 -0
  88. package/src/registry/pull.js +258 -0
  89. package/src/registry/ref.js +110 -0
  90. package/src/registry/wasi-mem.js +355 -0
  91. package/src/worker.js +315 -0
  92. package/wmdpack.wasm +0 -0
@@ -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
+ }