@atolljs/core 0.1.7 → 0.1.8
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 +1 -1
- package/dist/contract/memoryDevtools.d.ts +30 -0
- package/dist/contract/sharedMemory.d.ts +4 -2
- package/dist/contract/types.d.ts +11 -0
- package/dist/devtools.d.ts +127 -4
- package/dist/index.d.ts +8 -4
- package/dist/index.js +19 -17
- package/dist/index10.js +29 -14
- package/dist/index11.js +14 -307
- package/dist/index12.js +29 -50
- package/dist/index13.js +46 -60
- package/dist/index14.js +56 -22
- package/dist/index15.js +332 -55
- package/dist/index16.js +246 -45
- package/dist/index17.js +56 -51
- package/dist/index18.js +9 -39
- package/dist/index19.js +56 -80
- package/dist/index20.js +24 -53
- package/dist/index21.js +56 -52
- package/dist/index22.js +48 -0
- package/dist/index23.js +68 -0
- package/dist/index24.js +41 -0
- package/dist/index25.js +46 -0
- package/dist/index26.js +113 -0
- package/dist/index27.js +60 -0
- package/dist/index28.js +57 -0
- package/dist/index5.js +135 -64
- package/dist/index6.js +160 -35
- package/dist/index7.js +45 -503
- package/dist/index8.js +513 -19
- package/dist/index9.js +19 -33
- package/dist/pool/dedicatedWorker.d.ts +63 -0
- package/dist/pool/devtoolsCommands.d.ts +54 -0
- package/dist/pool/subWorkerClient.d.ts +50 -0
- package/dist/pool/workerChannel.d.ts +44 -0
- package/dist/pool/workerClient.d.ts +36 -8
- package/dist/pool/workerPool.d.ts +10 -1
- package/dist/reactive.d.ts +15 -0
- package/dist/reactiveGraph.d.ts +9 -0
- package/dist/userTiming.d.ts +27 -0
- package/package.json +2 -1
- package/src/contract/memoryDevtools.ts +249 -0
- package/src/contract/sharedMemory.ts +20 -6
- package/src/contract/types.ts +11 -0
- package/src/devtools.ts +251 -6
- package/src/index.ts +13 -1
- package/src/log.ts +22 -0
- package/src/observable.ts +16 -3
- package/src/pool/dedicatedWorker.ts +332 -0
- package/src/pool/devtoolsCommands.ts +165 -0
- package/src/pool/subWorkerClient.ts +70 -0
- package/src/pool/workerChannel.ts +99 -0
- package/src/pool/workerClient.ts +61 -15
- package/src/pool/workerPool.ts +75 -45
- package/src/reactive.ts +87 -12
- package/src/reactiveGraph.ts +91 -0
- package/src/testing/inProcessWorker.ts +4 -3
- package/src/userTiming.ts +71 -0
- package/src/worker/workerBootstrap.ts +27 -4
package/dist/index8.js
CHANGED
|
@@ -1,21 +1,515 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { msgpackrCodec as e } from "./index2.js";
|
|
2
|
+
import { fluent as t, z as n } from "./index3.js";
|
|
3
|
+
import { memberToSpec as r, zodArrayInfo as i, zodObjectShape as a, zodStringBytes as o } from "./index4.js";
|
|
4
|
+
import { devtoolsEnabled as s, emitDevtools as c } from "./index5.js";
|
|
5
|
+
import { checkWatchOnWrite as l, ensureMemoryCommands as u, memoryWatches as d } from "./index6.js";
|
|
6
|
+
import { fmtBytes as f, scoped as p } from "./index7.js";
|
|
7
|
+
//#region src/contract/sharedMemory.ts
|
|
8
|
+
var m = p("memory"), h = 8, g = (e, t) => e + t - 1 & ~(t - 1), _ = (e) => g(e, h), v = (e) => typeof e == "object" && !!e && typeof e.kind == "string" && typeof e.byteLength == "number";
|
|
9
|
+
function y(e) {
|
|
10
|
+
let t = [];
|
|
11
|
+
for (let [n, r] of Object.entries(e)) if (v(r)) t.push({
|
|
12
|
+
path: n,
|
|
13
|
+
descriptor: r
|
|
14
|
+
});
|
|
15
|
+
else for (let [e, i] of Object.entries(r)) {
|
|
16
|
+
if (!v(i)) throw TypeError(`shared memory "${n}.${e}" is not a field descriptor — intent groups nest one level only`);
|
|
17
|
+
t.push({
|
|
18
|
+
path: `${n}.${e}`,
|
|
19
|
+
descriptor: i
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return t;
|
|
23
|
+
}
|
|
24
|
+
var b = new TextEncoder(), x = new TextDecoder(), S = {
|
|
25
|
+
encode: (e) => b.encode(JSON.stringify(e)),
|
|
26
|
+
decode: (e) => JSON.parse(x.decode(e))
|
|
27
|
+
}, C = /* @__PURE__ */ new Map();
|
|
28
|
+
function w(e, t) {
|
|
29
|
+
C.set(e, t);
|
|
30
|
+
}
|
|
31
|
+
var T = {
|
|
32
|
+
i8: 1,
|
|
33
|
+
u8: 1,
|
|
34
|
+
i16: 2,
|
|
35
|
+
u16: 2,
|
|
36
|
+
i32: 4,
|
|
37
|
+
u32: 4,
|
|
38
|
+
f32: 4,
|
|
39
|
+
f64: 8,
|
|
40
|
+
i64: 8,
|
|
41
|
+
u64: 8
|
|
42
|
+
}, E = (e) => typeof e == "string" ? T[e] : "string" in e ? e.string : 1, D = (e) => typeof e == "string" ? T[e] : 1;
|
|
43
|
+
function O(e) {
|
|
44
|
+
let t = {}, n = {}, i = 0;
|
|
45
|
+
for (let a of Object.keys(e)) {
|
|
46
|
+
let o = r(e[a], String(a));
|
|
47
|
+
n[a] = o, i = g(i, D(o)), t[a] = i, i += E(o);
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
layout: n,
|
|
51
|
+
offsets: t,
|
|
52
|
+
recordSize: _(i)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
var k = {
|
|
56
|
+
number: () => ({
|
|
57
|
+
kind: "number",
|
|
58
|
+
byteLength: 8
|
|
59
|
+
}),
|
|
60
|
+
boolean: () => ({
|
|
61
|
+
kind: "boolean",
|
|
62
|
+
byteLength: 8
|
|
63
|
+
}),
|
|
64
|
+
string: (e) => {
|
|
65
|
+
let { schema: t, maxBytes: n } = e;
|
|
66
|
+
if (n !== void 0) return {
|
|
67
|
+
kind: "string",
|
|
68
|
+
byteLength: 4 + n,
|
|
69
|
+
schema: t
|
|
70
|
+
};
|
|
71
|
+
let r = t ? o(t) : null;
|
|
72
|
+
if (r !== null) return {
|
|
73
|
+
kind: "string",
|
|
74
|
+
byteLength: 4 + r,
|
|
75
|
+
schema: t
|
|
76
|
+
};
|
|
77
|
+
throw TypeError("field.string: pass { maxBytes } or a schema carrying a byte budget — reef.string(n) / z.string().meta({ bytes: n })");
|
|
78
|
+
},
|
|
79
|
+
object: (e) => {
|
|
80
|
+
let { schema: t, maxBytes: n } = e;
|
|
81
|
+
if (n === void 0 && t) {
|
|
82
|
+
let e = a(t);
|
|
83
|
+
if (e) {
|
|
84
|
+
let { layout: n, offsets: r, recordSize: i } = O(e);
|
|
85
|
+
return {
|
|
86
|
+
kind: "object",
|
|
87
|
+
byteLength: 8 + i,
|
|
88
|
+
schema: t,
|
|
89
|
+
layout: n,
|
|
90
|
+
offsets: r,
|
|
91
|
+
recordSize: i
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
throw TypeError("field.object: schema can't derive a fixed byte width (not a zod object of fixed-width members) — pass { maxBytes } for codec-encoded storage");
|
|
95
|
+
}
|
|
96
|
+
if (n === void 0) throw TypeError("field.object: pass { schema } for a fixed-layout field or { maxBytes } for a codec-encoded field");
|
|
97
|
+
return {
|
|
98
|
+
kind: "object",
|
|
99
|
+
byteLength: 4 + n,
|
|
100
|
+
schema: t
|
|
101
|
+
};
|
|
102
|
+
},
|
|
103
|
+
array: (e) => {
|
|
104
|
+
let { schema: t, maxBytes: n } = e;
|
|
105
|
+
if (n === void 0 && t) {
|
|
106
|
+
let e = i(t);
|
|
107
|
+
if (e) {
|
|
108
|
+
if (e.capacity === null) throw TypeError("field.array: z.array() needs .max(n) or .length(n) — bounded arrays are fixed-width");
|
|
109
|
+
let n;
|
|
110
|
+
try {
|
|
111
|
+
n = r(e.element, "array element");
|
|
112
|
+
} catch (e) {
|
|
113
|
+
throw TypeError(`field.array: element isn't a fixed-width member — use field.list for arrays of records (${e.message})`);
|
|
114
|
+
}
|
|
115
|
+
let i = g(E(n), D(n));
|
|
116
|
+
return {
|
|
117
|
+
kind: "array",
|
|
118
|
+
byteLength: 8 + e.capacity * i,
|
|
119
|
+
schema: t,
|
|
120
|
+
element: n,
|
|
121
|
+
elementStride: i,
|
|
122
|
+
capacity: e.capacity
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
throw TypeError("field.array: schema can't derive a fixed byte width (not a bounded zod array) — pass { maxBytes } for codec-encoded storage");
|
|
126
|
+
}
|
|
127
|
+
if (n === void 0) throw TypeError("field.array: pass { schema } for a fixed-layout field or { maxBytes } for a codec-encoded field");
|
|
128
|
+
return {
|
|
129
|
+
kind: "array",
|
|
130
|
+
byteLength: 4 + n,
|
|
131
|
+
schema: t
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
int32Array: ({ length: e }) => ({
|
|
135
|
+
kind: "Int32",
|
|
136
|
+
byteLength: e * 4
|
|
137
|
+
}),
|
|
138
|
+
float64Array: ({ length: e }) => ({
|
|
139
|
+
kind: "Float64",
|
|
140
|
+
byteLength: e * 8
|
|
141
|
+
}),
|
|
142
|
+
bigInt64Array: ({ length: e }) => ({
|
|
143
|
+
kind: "BigInt64",
|
|
144
|
+
byteLength: e * 8
|
|
145
|
+
}),
|
|
146
|
+
uint8Array: ({ length: e }) => ({
|
|
147
|
+
kind: "Uint8",
|
|
148
|
+
byteLength: e
|
|
149
|
+
}),
|
|
150
|
+
list: ({ schema: e, count: t }) => {
|
|
151
|
+
let n = a(e);
|
|
152
|
+
if (!n) throw TypeError("field.list: schema must be a reef.object() of fixed-width members");
|
|
153
|
+
let { layout: r, offsets: i, recordSize: o } = O(n);
|
|
154
|
+
return {
|
|
155
|
+
kind: "list",
|
|
156
|
+
byteLength: o * t,
|
|
157
|
+
schema: e,
|
|
158
|
+
layout: r,
|
|
159
|
+
offsets: i,
|
|
160
|
+
recordSize: o,
|
|
161
|
+
count: t
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}, A = {
|
|
165
|
+
Int32: Int32Array,
|
|
166
|
+
Float64: Float64Array,
|
|
167
|
+
BigInt64: BigInt64Array,
|
|
168
|
+
Uint8: Uint8Array
|
|
19
169
|
};
|
|
170
|
+
w("number", (e, t, n) => {
|
|
171
|
+
let r = new Float64Array(t.buffer, n, 1);
|
|
172
|
+
return {
|
|
173
|
+
byteOffset: n,
|
|
174
|
+
byteLength: e.byteLength,
|
|
175
|
+
read: () => r[0],
|
|
176
|
+
write: (e) => {
|
|
177
|
+
r[0] = e;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}), w("boolean", (e, t, n) => {
|
|
181
|
+
let r = new Uint8Array(t.buffer, n, 1);
|
|
182
|
+
return {
|
|
183
|
+
byteOffset: n,
|
|
184
|
+
byteLength: e.byteLength,
|
|
185
|
+
read: () => r[0] === 1,
|
|
186
|
+
write: (e) => {
|
|
187
|
+
r[0] = +!!e;
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
for (let e of Object.keys(A)) w(e, (t, n, r) => {
|
|
192
|
+
let i = A[e], a = new i(n.buffer, r, t.byteLength / i.BYTES_PER_ELEMENT);
|
|
193
|
+
return {
|
|
194
|
+
byteOffset: r,
|
|
195
|
+
byteLength: t.byteLength,
|
|
196
|
+
read: () => a,
|
|
197
|
+
write: (e) => a.set(e)
|
|
198
|
+
};
|
|
199
|
+
});
|
|
200
|
+
w("string", (e, t, n) => {
|
|
201
|
+
let r = new TextEncoder(), i = new TextDecoder(), a = e.byteLength - 4, o = new Uint32Array(t.buffer, n, 1), s = (e) => {
|
|
202
|
+
if (e.byteLength > a) throw Error(`Encoded value of ${e.byteLength} bytes exceeds field capacity of ${a} bytes at offset ${n}`);
|
|
203
|
+
o[0] = e.byteLength, new Uint8Array(t.buffer, n + 4, e.byteLength).set(e);
|
|
204
|
+
}, c = () => new Uint8Array(t.buffer, n + 4, o[0]).slice();
|
|
205
|
+
return {
|
|
206
|
+
byteOffset: n,
|
|
207
|
+
byteLength: e.byteLength,
|
|
208
|
+
read: () => i.decode(c()),
|
|
209
|
+
write: (t) => s(r.encode(e.schema ? e.schema.parse(t) : t))
|
|
210
|
+
};
|
|
211
|
+
});
|
|
212
|
+
function j(e) {
|
|
213
|
+
let t = new DataView(e.buffer), n = new Uint8Array(e.buffer), r = new TextEncoder(), i = new TextDecoder(), a = {
|
|
214
|
+
i8: {
|
|
215
|
+
get: (e) => t.getInt8(e),
|
|
216
|
+
set: (e, n) => t.setInt8(e, n)
|
|
217
|
+
},
|
|
218
|
+
u8: {
|
|
219
|
+
get: (e) => t.getUint8(e),
|
|
220
|
+
set: (e, n) => t.setUint8(e, n)
|
|
221
|
+
},
|
|
222
|
+
i16: {
|
|
223
|
+
get: (e) => t.getInt16(e),
|
|
224
|
+
set: (e, n) => t.setInt16(e, n)
|
|
225
|
+
},
|
|
226
|
+
u16: {
|
|
227
|
+
get: (e) => t.getUint16(e),
|
|
228
|
+
set: (e, n) => t.setUint16(e, n)
|
|
229
|
+
},
|
|
230
|
+
i32: {
|
|
231
|
+
get: (e) => t.getInt32(e),
|
|
232
|
+
set: (e, n) => t.setInt32(e, n)
|
|
233
|
+
},
|
|
234
|
+
u32: {
|
|
235
|
+
get: (e) => t.getUint32(e),
|
|
236
|
+
set: (e, n) => t.setUint32(e, n)
|
|
237
|
+
},
|
|
238
|
+
f32: {
|
|
239
|
+
get: (e) => t.getFloat32(e),
|
|
240
|
+
set: (e, n) => t.setFloat32(e, n)
|
|
241
|
+
},
|
|
242
|
+
f64: {
|
|
243
|
+
get: (e) => t.getFloat64(e),
|
|
244
|
+
set: (e, n) => t.setFloat64(e, n)
|
|
245
|
+
},
|
|
246
|
+
i64: {
|
|
247
|
+
get: (e) => t.getBigInt64(e),
|
|
248
|
+
set: (e, n) => t.setBigInt64(e, n)
|
|
249
|
+
},
|
|
250
|
+
u64: {
|
|
251
|
+
get: (e) => t.getBigUint64(e),
|
|
252
|
+
set: (e, n) => t.setBigUint64(e, n)
|
|
253
|
+
}
|
|
254
|
+
}, o = (e, t) => {
|
|
255
|
+
let r = n.indexOf(0, e), a = r === -1 || r - e >= t ? t : r - e;
|
|
256
|
+
return i.decode(n.slice(e, e + a));
|
|
257
|
+
}, s = /* @__PURE__ */ new Uint8Array(64), c = (e, t, i) => {
|
|
258
|
+
s.length < t && (s = new Uint8Array(t));
|
|
259
|
+
let { read: a, written: o } = r.encodeInto(i, s);
|
|
260
|
+
if (a < i.length || o > t) throw Error(`String exceeds inline field capacity of ${t} bytes`);
|
|
261
|
+
n.set(s.subarray(0, o), e), o < t && n.fill(0, e + o, e + t);
|
|
262
|
+
}, l = (e) => {
|
|
263
|
+
if (typeof e == "string") {
|
|
264
|
+
let t = a[e];
|
|
265
|
+
return {
|
|
266
|
+
get: (e) => t.get(e),
|
|
267
|
+
set: (e, n) => t.set(e, n)
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
return "bool" in e ? {
|
|
271
|
+
get: (e) => !!t.getUint8(e),
|
|
272
|
+
set: (e, n) => t.setUint8(e, +!!n)
|
|
273
|
+
} : {
|
|
274
|
+
get: (t) => o(t, e.string),
|
|
275
|
+
set: (t, n) => c(t, e.string, n)
|
|
276
|
+
};
|
|
277
|
+
};
|
|
278
|
+
return {
|
|
279
|
+
ops: l,
|
|
280
|
+
compile: (e, t) => {
|
|
281
|
+
let n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
|
|
282
|
+
for (let i of Object.keys(e)) {
|
|
283
|
+
let { get: a, set: o } = l(e[i]), s = t[i];
|
|
284
|
+
n.set(i, (e, t) => {
|
|
285
|
+
t[i] = a(e + s);
|
|
286
|
+
}), r.set(i, (e, t) => o(e + s, t[i]));
|
|
287
|
+
}
|
|
288
|
+
let i = [...n.values()], a = [...r.values()];
|
|
289
|
+
return {
|
|
290
|
+
read(e, t = {}, r) {
|
|
291
|
+
if (r) for (let i of r) n.get(i)(e, t);
|
|
292
|
+
else for (let n of i) n(e, t);
|
|
293
|
+
return t;
|
|
294
|
+
},
|
|
295
|
+
write(e, t, n) {
|
|
296
|
+
if (n) for (let i of n) r.get(i)(e, t);
|
|
297
|
+
else for (let n of a) n(e, t);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
var M = (e, t, n) => {
|
|
304
|
+
let { schema: r, byteLength: i, kind: a } = e, o = e;
|
|
305
|
+
if (o.layout && o.offsets && o.recordSize !== void 0) {
|
|
306
|
+
let e = new Uint32Array(t.buffer, n, 2), a = n + 8, s = j(t).compile(o.layout, o.offsets);
|
|
307
|
+
return {
|
|
308
|
+
byteOffset: n,
|
|
309
|
+
byteLength: i,
|
|
310
|
+
read: () => e[0] ? s.read(a, {}) : void 0,
|
|
311
|
+
write: (t) => {
|
|
312
|
+
s.write(a, r ? r.parse(t) : t), e[0] = 1;
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
if (o.element !== void 0 && o.elementStride !== void 0 && o.capacity !== void 0) {
|
|
317
|
+
let e = new Uint32Array(t.buffer, n, 1), a = new Uint32Array(t.buffer, n + 4, 1), s = j(t).ops(o.element), c = o.elementStride, l = o.capacity, u = n + 8;
|
|
318
|
+
return {
|
|
319
|
+
byteOffset: n,
|
|
320
|
+
byteLength: i,
|
|
321
|
+
read: () => {
|
|
322
|
+
if (!e[0]) return;
|
|
323
|
+
let t = a[0];
|
|
324
|
+
return Array.from({ length: t }, (e, t) => s.get(u + t * c));
|
|
325
|
+
},
|
|
326
|
+
write: (t) => {
|
|
327
|
+
let n = r ? r.parse(t) : t;
|
|
328
|
+
if (n.length > l) throw Error(`${n.length} elements exceeds array capacity of ${l}`);
|
|
329
|
+
n.forEach((e, t) => s.set(u + t * c, e)), a[0] = n.length, e[0] = 1;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
let s = i - 4, c = new Uint32Array(t.buffer, n, 1), l = (e) => {
|
|
334
|
+
if (e.byteLength > s) throw Error(`Encoded value of ${e.byteLength} bytes exceeds field capacity of ${s} bytes at offset ${n}`);
|
|
335
|
+
c[0] = e.byteLength, new Uint8Array(t.buffer, n + 4, e.byteLength).set(e);
|
|
336
|
+
}, u = () => new Uint8Array(t.buffer, n + 4, c[0]).slice();
|
|
337
|
+
return {
|
|
338
|
+
byteOffset: n,
|
|
339
|
+
byteLength: i,
|
|
340
|
+
read: () => {
|
|
341
|
+
let e = u();
|
|
342
|
+
if (e.byteLength === 0) return;
|
|
343
|
+
let n = t.codec.decode(e);
|
|
344
|
+
return r ? r.parse(n) : n;
|
|
345
|
+
},
|
|
346
|
+
write: (e) => l(t.codec.encode(r ? r.parse(e) : e))
|
|
347
|
+
};
|
|
348
|
+
};
|
|
349
|
+
w("object", M), w("array", M);
|
|
350
|
+
function N(e, t, n) {
|
|
351
|
+
let r = e, { offsets: i, recordSize: a, count: o } = r, l = j(t).compile(r.layout, i), u = (e) => {
|
|
352
|
+
if (e < 0 || e >= o) throw RangeError(`Record index ${e} out of bounds (0..${o - 1})`);
|
|
353
|
+
}, d = (e, t = {}, r) => (u(e), l.read(n + e * a, t, r)), f = (e, t, r) => {
|
|
354
|
+
u(e), l.write(n + e * a, t, r);
|
|
355
|
+
};
|
|
356
|
+
return {
|
|
357
|
+
byteOffset: n,
|
|
358
|
+
byteLength: e.byteLength,
|
|
359
|
+
recordCount: o,
|
|
360
|
+
recordSize: a,
|
|
361
|
+
readAt: d,
|
|
362
|
+
writeAt: f,
|
|
363
|
+
commit: () => {
|
|
364
|
+
if (t.version) {
|
|
365
|
+
let e = Atomics.add(t.version.view, t.version.index, 1);
|
|
366
|
+
Atomics.notify(t.version.view, t.version.index), t.path && s() && c({
|
|
367
|
+
type: "memory:write",
|
|
368
|
+
path: t.path,
|
|
369
|
+
version: e + 1
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
read: () => Array.from({ length: o }, (e, t) => d(t)),
|
|
374
|
+
write: (e) => {
|
|
375
|
+
if (e.length > o) throw Error(`${e.length} records exceeds list array capacity of ${o}`);
|
|
376
|
+
e.forEach((e, t) => f(t, e));
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
w("list", N);
|
|
381
|
+
var P = [];
|
|
382
|
+
function F(e) {
|
|
383
|
+
let t = {};
|
|
384
|
+
for (let [n, r] of Object.entries(e)) t[n] = v(r) ? I(r) : Object.fromEntries(Object.entries(r).map(([e, t]) => [e, I(t)]));
|
|
385
|
+
return t;
|
|
386
|
+
}
|
|
387
|
+
function I(e) {
|
|
388
|
+
if (e.schema) return e.schema;
|
|
389
|
+
switch (e.kind) {
|
|
390
|
+
case "number": return t(n.number());
|
|
391
|
+
case "boolean": return t(n.boolean());
|
|
392
|
+
case "string": return t(n.string());
|
|
393
|
+
case "Int32": return t(n.instanceof(Int32Array));
|
|
394
|
+
case "Float64": return t(n.instanceof(Float64Array));
|
|
395
|
+
case "BigInt64": return t(n.instanceof(BigInt64Array));
|
|
396
|
+
case "Uint8": return t(n.instanceof(Uint8Array));
|
|
397
|
+
default: return t(n.unknown());
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
var L = class {
|
|
401
|
+
totalBytes;
|
|
402
|
+
spec;
|
|
403
|
+
schemas;
|
|
404
|
+
codec;
|
|
405
|
+
plugins;
|
|
406
|
+
entries;
|
|
407
|
+
offsets = /* @__PURE__ */ new Map();
|
|
408
|
+
versionOffset;
|
|
409
|
+
connectors = /* @__PURE__ */ new Map();
|
|
410
|
+
boundListeners = /* @__PURE__ */ new Set();
|
|
411
|
+
isBound = !1;
|
|
412
|
+
boundBuffer;
|
|
413
|
+
constructor(t, n = {}) {
|
|
414
|
+
this.spec = t, this.codec = n.codec ?? e, this.plugins = n.plugins, this.entries = y(t), this.schemas = F(t);
|
|
415
|
+
let r = 0;
|
|
416
|
+
for (let { path: e, descriptor: t } of this.entries) r = _(r), this.offsets.set(e, r), r += t.byteLength;
|
|
417
|
+
this.versionOffset = _(r), this.totalBytes = this.versionOffset + _(this.entries.length * 4), P.push(this), m.info(`contract defined: ${this.entries.length} field(s), ${f(this.totalBytes)}`, {
|
|
418
|
+
fields: Object.fromEntries(this.entries.map((e) => [e.path, `${e.descriptor.kind}@${this.offsets.get(e.path)?.toLocaleString()}+${f(e.descriptor.byteLength)}`])),
|
|
419
|
+
pluginOverrides: Object.keys(this.plugins ?? {})
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
bind(e) {
|
|
423
|
+
this.connectors.clear();
|
|
424
|
+
let t = new Int32Array(e, this.versionOffset, this.entries.length);
|
|
425
|
+
this.entries.forEach(({ path: n, descriptor: r }, i) => {
|
|
426
|
+
let a = this.plugins?.[r.kind] ?? C.get(r.kind);
|
|
427
|
+
if (!a) throw Error(`Unknown shared memory field kind: ${r.kind}`);
|
|
428
|
+
m.debug(`bind "${n}" (${r.kind}, ${f(r.byteLength)}) via ${this.plugins?.[r.kind] ? "plugin" : "built-in"} factory`);
|
|
429
|
+
let o = a(r, {
|
|
430
|
+
buffer: e,
|
|
431
|
+
codec: this.codec,
|
|
432
|
+
version: {
|
|
433
|
+
view: t,
|
|
434
|
+
index: i
|
|
435
|
+
},
|
|
436
|
+
path: n
|
|
437
|
+
}, this.offsets.get(n)), u = o.commit;
|
|
438
|
+
this.connectors.set(n, {
|
|
439
|
+
...o,
|
|
440
|
+
write: (e) => {
|
|
441
|
+
o.write(e);
|
|
442
|
+
let r = Atomics.add(t, i, 1);
|
|
443
|
+
Atomics.notify(t, i), s() && (c({
|
|
444
|
+
type: "memory:write",
|
|
445
|
+
path: n,
|
|
446
|
+
version: r + 1
|
|
447
|
+
}), d.size && l(this, n, r + 1));
|
|
448
|
+
},
|
|
449
|
+
...u && s() ? { commit: () => {
|
|
450
|
+
u(), d.size && l(this, n, Atomics.load(t, i));
|
|
451
|
+
} } : {},
|
|
452
|
+
_version: {
|
|
453
|
+
view: t,
|
|
454
|
+
index: i
|
|
455
|
+
},
|
|
456
|
+
_path: n
|
|
457
|
+
});
|
|
458
|
+
}), s() && (u(() => P), c({
|
|
459
|
+
type: "memory:bind",
|
|
460
|
+
fields: this.entries.map((e, t) => [t, e.path]),
|
|
461
|
+
totalBytes: this.totalBytes
|
|
462
|
+
})), this.isBound = !0, this.boundBuffer = e;
|
|
463
|
+
for (let e of [...this.boundListeners]) e();
|
|
464
|
+
}
|
|
465
|
+
get bound() {
|
|
466
|
+
return this.isBound;
|
|
467
|
+
}
|
|
468
|
+
get buffer() {
|
|
469
|
+
if (!this.boundBuffer) throw Error("Shared memory contract is not bound to a buffer on this thread.");
|
|
470
|
+
return this.boundBuffer;
|
|
471
|
+
}
|
|
472
|
+
fields() {
|
|
473
|
+
return this.entries.map(({ path: e, descriptor: t }) => ({
|
|
474
|
+
path: e,
|
|
475
|
+
byteOffset: this.offsets.get(e),
|
|
476
|
+
byteLength: t.byteLength
|
|
477
|
+
}));
|
|
478
|
+
}
|
|
479
|
+
onBound(e) {
|
|
480
|
+
return this.boundListeners.add(e), this.isBound && e(), () => this.boundListeners.delete(e);
|
|
481
|
+
}
|
|
482
|
+
connector(e) {
|
|
483
|
+
let t = String(e), n = this.connectors.get(t);
|
|
484
|
+
if (!n) throw Error(`Shared memory field "${t}" was accessed before the buffer was bound on this thread.`);
|
|
485
|
+
return n;
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
function R(e, t = {}) {
|
|
489
|
+
let n = new L(e, t);
|
|
490
|
+
for (let [t, r] of Object.entries(e)) if (v(r)) Object.defineProperty(n, t, {
|
|
491
|
+
enumerable: !0,
|
|
492
|
+
get: () => n.connector(t)
|
|
493
|
+
});
|
|
494
|
+
else {
|
|
495
|
+
let e = {};
|
|
496
|
+
for (let i of Object.keys(r)) Object.defineProperty(e, i, {
|
|
497
|
+
enumerable: !0,
|
|
498
|
+
get: () => n.connector(`${t}.${i}`)
|
|
499
|
+
});
|
|
500
|
+
Object.defineProperty(n, t, {
|
|
501
|
+
enumerable: !0,
|
|
502
|
+
get: () => e
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
return n;
|
|
506
|
+
}
|
|
507
|
+
function z(e) {
|
|
508
|
+
for (let t of P) t.bind(e);
|
|
509
|
+
m.info(`bound ${P.length} contract(s) — ${f(e.byteLength)} buffer`);
|
|
510
|
+
}
|
|
511
|
+
function B() {
|
|
512
|
+
return P.length;
|
|
513
|
+
}
|
|
20
514
|
//#endregion
|
|
21
|
-
export {
|
|
515
|
+
export { L as SharedMemory, z as bindSharedMemories, R as defineSharedMemory, k as field, B as getDefinedSharedMemoryCount, S as jsonCodec, w as registerConnectorFactory };
|
package/dist/index9.js
CHANGED
|
@@ -1,35 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
getView(e, t = 0, n) {
|
|
21
|
-
let r = this.memory.buffer;
|
|
22
|
-
switch (e) {
|
|
23
|
-
case "Int32": return new Int32Array(r, t, n);
|
|
24
|
-
case "Float64": return new Float64Array(r, t, n);
|
|
25
|
-
case "BigInt64": return new BigInt64Array(r, t, n);
|
|
26
|
-
case "Uint8": return new Uint8Array(r, t, n);
|
|
27
|
-
default: throw Error(`Unsupported view type: ${e}`);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
getBuffer() {
|
|
31
|
-
return this.memory.buffer;
|
|
32
|
-
}
|
|
1
|
+
import { fluent as e, z as t } from "./index3.js";
|
|
2
|
+
//#region src/contract/reef.ts
|
|
3
|
+
var n = new TextEncoder(), r = {
|
|
4
|
+
i8: () => e(t.number().check(t.int(), t.gte(-128), t.lte(127))),
|
|
5
|
+
u8: () => e(t.number().check(t.int(), t.gte(0), t.lte(255))),
|
|
6
|
+
i16: () => e(t.number().check(t.int(), t.gte(-32768), t.lte(32767))),
|
|
7
|
+
u16: () => e(t.number().check(t.int(), t.gte(0), t.lte(65535))),
|
|
8
|
+
i32: () => e(t.int32()),
|
|
9
|
+
u32: () => e(t.uint32()),
|
|
10
|
+
f32: () => e(t.float32()),
|
|
11
|
+
f64: () => e(t.float64()),
|
|
12
|
+
i64: () => e(t.int64()),
|
|
13
|
+
u64: () => e(t.uint64()),
|
|
14
|
+
int: (n, r) => e(t.number().check(t.int(), t.gte(n), t.lte(r))),
|
|
15
|
+
boolean: () => e(t.boolean()),
|
|
16
|
+
string: (r) => e(t.string().check(t.refine((e) => n.encode(e).byteLength <= r, `exceeds ${r} UTF-8 bytes`)).register(t.globalRegistry, { bytes: r })),
|
|
17
|
+
object: (n) => e(t.object(n)),
|
|
18
|
+
array: (n) => e(t.array(n))
|
|
33
19
|
};
|
|
34
20
|
//#endregion
|
|
35
|
-
export {
|
|
21
|
+
export { r as reef };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { SharedAccess, SharedMemory, SharedSpec } from '../contract/sharedMemory.js';
|
|
2
|
+
import type { MemoryPersistence, TaskContract, TaskMap, WorkerPoolConfig } from '../contract/types.js';
|
|
3
|
+
import type { PoolStats, RunOptions } from './workerPool.js';
|
|
4
|
+
/**
|
|
5
|
+
* Config for a single dedicated worker: the WorkerPool config minus the
|
|
6
|
+
* pool-only knobs (size, per-worker concurrency cap, queue bound, task
|
|
7
|
+
* methods). Every call posts straight to the worker.
|
|
8
|
+
*/
|
|
9
|
+
export type DedicatedWorkerConfig<S extends SharedSpec = SharedSpec> = Omit<WorkerPoolConfig<S, TaskMap>, 'poolSize' | 'concurrency' | 'maxQueue' | 'tasks'>;
|
|
10
|
+
/**
|
|
11
|
+
* One worker, no pool: what `connectWorker({ workers: 1 })` (the default)
|
|
12
|
+
* builds. Calls are posted to the worker immediately, with no queue and no
|
|
13
|
+
* scheduler; the worker's own message loop runs them in arrival order (a
|
|
14
|
+
* task that awaits lets the next message start, exactly as in a pool slot
|
|
15
|
+
* with a raised concurrency cap). Kept from the pool: per-call
|
|
16
|
+
* timeout/abort, crash respawn, `stats()`, and the same devtools events,
|
|
17
|
+
* with `pool:init` flagged `dedicated: true`.
|
|
18
|
+
*/
|
|
19
|
+
export declare class DedicatedWorker<S extends SharedSpec = SharedSpec> {
|
|
20
|
+
/**
|
|
21
|
+
* Devtools correlation id: '<name>-w' when the config has a `name`, else
|
|
22
|
+
* 'worker-N'. The same role a pool's id plays.
|
|
23
|
+
*/
|
|
24
|
+
readonly poolId: string;
|
|
25
|
+
readonly sharedMemory: (SharedMemory<S> & SharedAccess<S>) | undefined;
|
|
26
|
+
readonly persistence: MemoryPersistence | undefined;
|
|
27
|
+
private readonly mem;
|
|
28
|
+
private readonly spawn;
|
|
29
|
+
private readonly respawn;
|
|
30
|
+
private readonly taskTimeout?;
|
|
31
|
+
private readonly label?;
|
|
32
|
+
private worker;
|
|
33
|
+
private pending;
|
|
34
|
+
private nextMessageId;
|
|
35
|
+
private nextCallId;
|
|
36
|
+
private closed;
|
|
37
|
+
/** Dashboard fault injection (`pool.chaos`); null unless devtools set it. */
|
|
38
|
+
private chaos;
|
|
39
|
+
private devtoolsOff?;
|
|
40
|
+
private drainWaiters;
|
|
41
|
+
private statsAgg;
|
|
42
|
+
constructor(config: DedicatedWorkerConfig<S>);
|
|
43
|
+
private attach;
|
|
44
|
+
private detach;
|
|
45
|
+
private handleReply;
|
|
46
|
+
private handleError;
|
|
47
|
+
private rejectPending;
|
|
48
|
+
/** Abort/timeout: the caller rejects now; the worker's eventual reply is discarded. */
|
|
49
|
+
private cancel;
|
|
50
|
+
private checkDrained;
|
|
51
|
+
/** Post the call straight to the worker — no queue, no scheduler. */
|
|
52
|
+
dispatch<Args extends any[], Result>(contract: TaskContract<Args, Result>, args: Args, options?: RunOptions): Promise<Result>;
|
|
53
|
+
runTask<Args extends any[], Result>(contract: TaskContract<Args, Result>, ...args: Args): Promise<Result>;
|
|
54
|
+
/** The shared buffer handed to the worker via INIT_MEMORY; undefined when message-only. */
|
|
55
|
+
get sharedBuffer(): SharedArrayBuffer | undefined;
|
|
56
|
+
/** The worker, as a one-element snapshot (same shape as `WorkerPool.workers`). */
|
|
57
|
+
get workers(): readonly Worker[];
|
|
58
|
+
/** Same shape as `WorkerPool.stats()`; `queued` and `waitMs` stay zero (there is no queue). */
|
|
59
|
+
stats(): PoolStats;
|
|
60
|
+
/** Resolves once nothing is in flight, then terminates. */
|
|
61
|
+
close(): Promise<void>;
|
|
62
|
+
terminate(): void;
|
|
63
|
+
}
|