knitting 0.1.51 → 0.1.53
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 +213 -54
- package/knitting.d.ts +1 -0
- package/map.md +15 -3
- package/package.json +14 -2
- package/prebuilds/darwin-arm64-node-127/knitting_buffer_pointer.node +0 -0
- package/prebuilds/darwin-arm64-node-137/knitting_buffer_pointer.node +0 -0
- package/prebuilds/darwin-x64-node-127/knitting_buffer_pointer.node +0 -0
- package/prebuilds/darwin-x64-node-137/knitting_buffer_pointer.node +0 -0
- package/prebuilds/linux-x64-node-127/knitting_buffer_pointer.node +0 -0
- package/prebuilds/linux-x64-node-137/knitting_buffer_pointer.node +0 -0
- package/prebuilds/win32-x64/knitting_windows_shared_memory.dll +0 -0
- package/prebuilds/win32-x64-node-127/knitting_buffer_pointer.node +0 -0
- package/prebuilds/win32-x64-node-127/knitting_shared_memory.node +0 -0
- package/prebuilds/win32-x64-node-127/knitting_shm.node +0 -0
- package/prebuilds/win32-x64-node-137/knitting_buffer_pointer.node +0 -0
- package/prebuilds/win32-x64-node-137/knitting_shared_memory.node +0 -0
- package/prebuilds/win32-x64-node-137/knitting_shm.node +0 -0
- package/scripts/build-native-addons.ts +5 -0
- package/src/api.d.ts +29 -16
- package/src/api.js +98 -28
- package/src/common/envelope.d.ts +9 -3
- package/src/common/envelope.js +14 -0
- package/src/common/worker-runtime.d.ts +2 -0
- package/src/common/worker-runtime.js +9 -0
- package/src/connections/buffer-reference-native.d.ts +56 -0
- package/src/connections/buffer-reference-native.js +217 -0
- package/src/connections/buffer-reference.d.ts +78 -0
- package/src/connections/buffer-reference.js +461 -0
- package/src/connections/index.d.ts +1 -0
- package/src/connections/index.js +1 -0
- package/src/connections/node-addons.d.ts +1 -1
- package/src/connections/node-buffer-pointer.d.ts +20 -0
- package/src/connections/node-buffer-pointer.js +16 -0
- package/src/connections/process-shared-buffer.d.ts +6 -0
- package/src/connections/process-shared-buffer.js +6 -0
- package/src/connections/shared-array-buffer-payload.d.ts +36 -0
- package/src/connections/shared-array-buffer-payload.js +235 -0
- package/src/debug/env-diff.d.ts +26 -0
- package/src/debug/env-diff.js +49 -0
- package/src/debug/gate.d.ts +18 -0
- package/src/debug/gate.js +69 -0
- package/src/debug/handle.d.ts +23 -0
- package/src/debug/handle.js +48 -0
- package/src/ipc/transport/shared-memory.d.ts +1 -3
- package/src/knitting_buffer_pointer.cc +425 -0
- package/src/memory/lock.d.ts +12 -1
- package/src/memory/lock.js +47 -4
- package/src/memory/payload-config.d.ts +9 -0
- package/src/memory/payloadCodec.js +220 -37
- package/src/permission/protocol.d.ts +1 -1
- package/src/permission/protocol.js +30 -20
- package/src/runtime/pool.d.ts +3 -5
- package/src/runtime/pool.js +18 -18
- package/src/runtime/process-worker.js +5 -2
- package/src/runtime/tx-queue.d.ts +3 -2
- package/src/runtime/tx-queue.js +18 -13
- package/src/types.d.ts +54 -50
- package/src/utils/http.d.ts +29 -0
- package/src/utils/http.js +100 -0
- package/src/worker/loop.js +76 -14
- package/src/worker/rx-queue.d.ts +4 -1
- package/src/worker/rx-queue.js +53 -4
- package/src/worker/safety/startup.d.ts +2 -3
- package/src/worker/safety/startup.js +1 -4
- package/src/worker/timers.js +7 -2
- package/unsafe.d.ts +1 -0
- package/unsafe.js +1 -0
- package/utils.d.ts +1 -0
- package/utils.js +1 -0
package/src/worker/loop.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createRuntimeMessageChannel, RUNTIME_IS_MAIN_THREAD, RUNTIME_IS_PROCESS_WORKER, RUNTIME_PARENT_PORT, RUNTIME_WORKER_DATA, } from "../common/worker-runtime.js";
|
|
1
|
+
import { addRuntimeDataListener, createRuntimeMessageChannel, RUNTIME_IS_MAIN_THREAD, RUNTIME_IS_PROCESS_WORKER, RUNTIME_PARENT_PORT, RUNTIME_WORKER_DATA, } from "../common/worker-runtime.js";
|
|
2
2
|
import { isSharedBufferSource } from "../common/shared-buffer-region.js";
|
|
3
3
|
import { isLockBufferTextCompat } from "../common/shared-buffer-text.js";
|
|
4
4
|
import { createWorkerRxQueue } from "./rx-queue.js";
|
|
@@ -12,6 +12,8 @@ import { assertWorkerImportsResolved, assertWorkerSharedMemoryBootData, installP
|
|
|
12
12
|
import { signalAbortFactory } from "../shared/abortSignal.js";
|
|
13
13
|
import { runWorkerBootstrap } from "./bootstrap.js";
|
|
14
14
|
import { getProcessWorkerNativeWaitU32, installProcessWorkerBootstrap, } from "./process-worker-bootstrap.js";
|
|
15
|
+
import { readBufferReferenceReturnReleaseMessage, } from "../connections/buffer-reference.js";
|
|
16
|
+
import { resolveDebugNamespaces } from "../debug/gate.js";
|
|
15
17
|
const WORKER_FATAL_MESSAGE_KEY = "__knittingWorkerFatal";
|
|
16
18
|
const reportWorkerStartupFatal = (error) => {
|
|
17
19
|
const message = String(error?.message ?? error);
|
|
@@ -48,14 +50,37 @@ const reportWorkerStartupFatal = (error) => {
|
|
|
48
50
|
}
|
|
49
51
|
}
|
|
50
52
|
};
|
|
53
|
+
const installBufferReferenceReleaseListener = (releaseReturnedBufferReference) => {
|
|
54
|
+
const handleMessage = (message) => {
|
|
55
|
+
const token = readBufferReferenceReturnReleaseMessage(message);
|
|
56
|
+
if (token !== undefined)
|
|
57
|
+
releaseReturnedBufferReference(token);
|
|
58
|
+
};
|
|
59
|
+
if (RUNTIME_PARENT_PORT !== undefined) {
|
|
60
|
+
addRuntimeDataListener(RUNTIME_PARENT_PORT, handleMessage);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const scope = globalThis;
|
|
64
|
+
scope.addEventListener?.("message", (event) => {
|
|
65
|
+
handleMessage(event?.data);
|
|
66
|
+
});
|
|
67
|
+
};
|
|
51
68
|
export const workerMainLoop = async (startupData) => {
|
|
52
69
|
// Startup-only safety layer: no per-iteration checks in the hot loop.
|
|
53
70
|
installTerminationGuard();
|
|
54
71
|
installUnhandledRejectionSilencer();
|
|
55
72
|
installPerformanceNowGuard();
|
|
56
|
-
const { debug, sab, thread, startAt, workerOptions, lock, returnLock, abortSignalSAB, abortSignalMax, payloadConfig, permission, totalNumberOfThread, list, ids, names, at, } = startupData;
|
|
73
|
+
const { debug, sab, thread, startAt, workerOptions, lock, returnLock, abortSignalSAB, abortSignalMax, payloadConfig, bufferReferenceReturn, permission, totalNumberOfThread, list, ids, names, at, } = startupData;
|
|
57
74
|
scrubWorkerDataSensitiveBuffers(startupData);
|
|
58
75
|
assertWorkerSharedMemoryBootData({ sab, lock, returnLock });
|
|
76
|
+
const debugNamespaces = resolveDebugNamespaces(debug);
|
|
77
|
+
const dbg = debugNamespaces.size > 0
|
|
78
|
+
? await import("../debug/handle.js").then((module) => module.initDebug({
|
|
79
|
+
name: `w${thread}`,
|
|
80
|
+
runtime: RUNTIME,
|
|
81
|
+
namespaces: debugNamespaces,
|
|
82
|
+
}))
|
|
83
|
+
: undefined;
|
|
59
84
|
let Comment;
|
|
60
85
|
(function (Comment) {
|
|
61
86
|
Comment[Comment["thisIsAHint"] = 0] = "thisIsAHint";
|
|
@@ -66,7 +91,6 @@ export const workerMainLoop = async (startupData) => {
|
|
|
66
91
|
},
|
|
67
92
|
isMain: false,
|
|
68
93
|
thread,
|
|
69
|
-
debug,
|
|
70
94
|
startTime: startAt,
|
|
71
95
|
});
|
|
72
96
|
const lockState = lock2({
|
|
@@ -90,8 +114,10 @@ export const workerMainLoop = async (startupData) => {
|
|
|
90
114
|
const timers = workerOptions?.timers;
|
|
91
115
|
const spinMicroseconds = timers?.spinMicroseconds ??
|
|
92
116
|
Math.max(1, totalNumberOfThread) * 50;
|
|
93
|
-
const parkMs =
|
|
94
|
-
|
|
117
|
+
const parkMs = dbg !== undefined
|
|
118
|
+
? Number.POSITIVE_INFINITY
|
|
119
|
+
: (timers?.parkMs ??
|
|
120
|
+
Math.max(1, totalNumberOfThread) * 50);
|
|
95
121
|
const pauseSpin = (() => {
|
|
96
122
|
const fn = typeof timers?.pauseNanoseconds === "number"
|
|
97
123
|
? whilePausing({ pauseInNanoseconds: timers.pauseNanoseconds })
|
|
@@ -107,6 +133,7 @@ export const workerMainLoop = async (startupData) => {
|
|
|
107
133
|
thread,
|
|
108
134
|
totalNumberOfThread,
|
|
109
135
|
});
|
|
136
|
+
dbg?.envPhase("bootstrap");
|
|
110
137
|
const listOfFunctions = await getFunctions({
|
|
111
138
|
list,
|
|
112
139
|
isWorker: true,
|
|
@@ -115,20 +142,24 @@ export const workerMainLoop = async (startupData) => {
|
|
|
115
142
|
at,
|
|
116
143
|
permission,
|
|
117
144
|
});
|
|
118
|
-
|
|
145
|
+
dbg?.envPhase("tasks");
|
|
146
|
+
dbg?.log("imports", `${listOfFunctions.length} task(s) from ${list.map((spec) => spec.split(/[\\/]/).pop() || spec).join(", ")}`);
|
|
147
|
+
assertWorkerImportsResolved({ list, ids, names, listOfFunctions });
|
|
119
148
|
const abortSignals = abortSignalSAB
|
|
120
149
|
? signalAbortFactory({
|
|
121
150
|
sab: abortSignalSAB,
|
|
122
151
|
maxSignals: abortSignalMax,
|
|
123
152
|
})
|
|
124
153
|
: undefined;
|
|
125
|
-
const { enqueueLock, serviceBatchImmediate, hasCompleted, writeBatch, hasPending, getAwaiting, } = createWorkerRxQueue({
|
|
154
|
+
const { enqueueLock, serviceBatchImmediate, hasCompleted, writeBatch, hasPending, getAwaiting, drainReturnReleases, releaseReturnedBufferReference, } = createWorkerRxQueue({
|
|
126
155
|
listOfFunctions,
|
|
127
156
|
workerOptions,
|
|
128
157
|
lock: lockState,
|
|
129
158
|
returnLock: returnLockState,
|
|
159
|
+
borrowReturnedBufferReferences: bufferReferenceReturn === "borrow",
|
|
130
160
|
hasAborted: abortSignals?.hasAborted,
|
|
131
161
|
});
|
|
162
|
+
installBufferReferenceReleaseListener(releaseReturnedBufferReference);
|
|
132
163
|
a_store(rxStatus, 0, 1);
|
|
133
164
|
const WRITE_MAX = 64;
|
|
134
165
|
const pauseUntil = sleepUntilChanged({
|
|
@@ -152,7 +183,7 @@ export const workerMainLoop = async (startupData) => {
|
|
|
152
183
|
let awaitingSpins = 0;
|
|
153
184
|
let lastAwaiting = 0;
|
|
154
185
|
const MAX_AWAITING_MS = 10;
|
|
155
|
-
let
|
|
186
|
+
let wakeToken = a_load(opView, 0);
|
|
156
187
|
const scheduleMacro = () => {
|
|
157
188
|
if (isInMacro)
|
|
158
189
|
return;
|
|
@@ -177,14 +208,43 @@ export const workerMainLoop = async (startupData) => {
|
|
|
177
208
|
}
|
|
178
209
|
post2(null);
|
|
179
210
|
};
|
|
180
|
-
const
|
|
211
|
+
const traceSignals = dbg?.enabled("signals") === true;
|
|
181
212
|
const _hasCompleted = hasCompleted;
|
|
182
|
-
const _writeBatch = writeBatch;
|
|
183
213
|
const _hasPending = hasPending;
|
|
184
|
-
const _serviceBatchImmediate = serviceBatchImmediate;
|
|
185
214
|
const _getAwaiting = getAwaiting;
|
|
215
|
+
const _drainReturnReleases = drainReturnReleases;
|
|
186
216
|
const _pauseSpin = pauseSpin;
|
|
187
|
-
const
|
|
217
|
+
const _enqueueLock = traceSignals
|
|
218
|
+
? () => {
|
|
219
|
+
const progressed = enqueueLock();
|
|
220
|
+
if (progressed) {
|
|
221
|
+
dbg.log("signals", "work from=host");
|
|
222
|
+
}
|
|
223
|
+
return progressed;
|
|
224
|
+
}
|
|
225
|
+
: enqueueLock;
|
|
226
|
+
const _writeBatch = traceSignals
|
|
227
|
+
? (max) => {
|
|
228
|
+
const wrote = writeBatch(max);
|
|
229
|
+
if (wrote > 0)
|
|
230
|
+
dbg.log("signals", `result count=${wrote}`);
|
|
231
|
+
return wrote;
|
|
232
|
+
}
|
|
233
|
+
: writeBatch;
|
|
234
|
+
const _serviceBatchImmediate = traceSignals
|
|
235
|
+
? () => {
|
|
236
|
+
const ran = serviceBatchImmediate();
|
|
237
|
+
if (ran > 0)
|
|
238
|
+
dbg.log("signals", `run count=${ran}`);
|
|
239
|
+
return ran;
|
|
240
|
+
}
|
|
241
|
+
: serviceBatchImmediate;
|
|
242
|
+
const _pauseUntil = traceSignals
|
|
243
|
+
? (value, spinMicroseconds, parkMs) => {
|
|
244
|
+
dbg.log("signals", `idle token=${value}`);
|
|
245
|
+
pauseUntil(value, spinMicroseconds, parkMs);
|
|
246
|
+
}
|
|
247
|
+
: pauseUntil;
|
|
188
248
|
const loop = () => {
|
|
189
249
|
isInMacro = false;
|
|
190
250
|
let progressed = true;
|
|
@@ -195,6 +255,7 @@ export const workerMainLoop = async (startupData) => {
|
|
|
195
255
|
if (_writeBatch(WRITE_MAX) > 0)
|
|
196
256
|
progressed = true;
|
|
197
257
|
}
|
|
258
|
+
_drainReturnReleases();
|
|
198
259
|
if (_hasPending()) {
|
|
199
260
|
if (_serviceBatchImmediate() > 0)
|
|
200
261
|
progressed = true;
|
|
@@ -214,8 +275,8 @@ export const workerMainLoop = async (startupData) => {
|
|
|
214
275
|
_pauseSpin();
|
|
215
276
|
continue;
|
|
216
277
|
}
|
|
217
|
-
_pauseUntil(
|
|
218
|
-
|
|
278
|
+
_pauseUntil(wakeToken, spinMicroseconds, parkMs);
|
|
279
|
+
wakeToken = a_load(opView, 0);
|
|
219
280
|
}
|
|
220
281
|
}
|
|
221
282
|
};
|
|
@@ -229,6 +290,7 @@ export const workerMainLoop = async (startupData) => {
|
|
|
229
290
|
}
|
|
230
291
|
port1Any.start?.();
|
|
231
292
|
port2.start?.();
|
|
293
|
+
dbg?.log("lifecycle", `ready: ${listOfFunctions.length} task(s) on thread ${thread}/${totalNumberOfThread}, entering dispatch loop`);
|
|
232
294
|
scheduleMacro();
|
|
233
295
|
};
|
|
234
296
|
const isWorkerGlobalScope = () => {
|
package/src/worker/rx-queue.d.ts
CHANGED
|
@@ -6,16 +6,19 @@ type ArgumentsForCreateWorkerQueue = {
|
|
|
6
6
|
workerOptions?: WorkerSettings;
|
|
7
7
|
lock: Lock2;
|
|
8
8
|
returnLock: Lock2;
|
|
9
|
+
borrowReturnedBufferReferences?: boolean;
|
|
9
10
|
hasAborted?: (signal: number) => boolean;
|
|
10
11
|
now?: () => number;
|
|
11
12
|
};
|
|
12
13
|
export type CreateWorkerRxQueue = ReturnType<typeof createWorkerRxQueue>;
|
|
13
|
-
export declare const createWorkerRxQueue: ({ listOfFunctions, workerOptions, lock, returnLock, hasAborted, now, }: ArgumentsForCreateWorkerQueue) => {
|
|
14
|
+
export declare const createWorkerRxQueue: ({ listOfFunctions, workerOptions, lock, returnLock, borrowReturnedBufferReferences, hasAborted, now, }: ArgumentsForCreateWorkerQueue) => {
|
|
14
15
|
hasCompleted: () => boolean;
|
|
15
16
|
hasPending: () => boolean;
|
|
16
17
|
writeBatch: (max: number) => number;
|
|
17
18
|
serviceBatchImmediate: () => number;
|
|
18
19
|
enqueueLock: () => boolean;
|
|
20
|
+
drainReturnReleases: () => void;
|
|
21
|
+
releaseReturnedBufferReference: (token: bigint) => void;
|
|
19
22
|
hasAwaiting: () => boolean;
|
|
20
23
|
getAwaiting: () => number;
|
|
21
24
|
};
|
package/src/worker/rx-queue.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import RingQueue from "../ipc/tools/ring-queue.js";
|
|
2
|
-
import { TaskFlag, TaskIndex, } from "../memory/lock.js";
|
|
2
|
+
import { attachPayloadTransportFinalizer, runTaskFinalizers, TaskFlag, TaskIndex, } from "../memory/lock.js";
|
|
3
3
|
import { composeWorkerRunner } from "./composable-runners.js";
|
|
4
|
-
|
|
5
|
-
export const createWorkerRxQueue = ({ listOfFunctions, workerOptions, lock, returnLock, hasAborted, now, }) => {
|
|
4
|
+
import { BUFFER_REFERENCE_RETURN_RELEASE_TOKEN } from "../connections/buffer-reference.js";
|
|
5
|
+
export const createWorkerRxQueue = ({ listOfFunctions, workerOptions, lock, returnLock, borrowReturnedBufferReferences, hasAborted, now, }) => {
|
|
6
6
|
const PLACE_HOLDER = (_) => {
|
|
7
7
|
throw ("UNREACHABLE FROM PLACE HOLDER (thread)");
|
|
8
8
|
};
|
|
@@ -20,6 +20,41 @@ export const createWorkerRxQueue = ({ listOfFunctions, workerOptions, lock, retu
|
|
|
20
20
|
const FUNCTION_ID_MASK = 0xFFFF;
|
|
21
21
|
const IDX_FLAGS = TaskIndex.FlagsToHost;
|
|
22
22
|
const FLAG_REJECT = TaskFlag.Reject;
|
|
23
|
+
// Return-payload finalizers wait until the host consumes the return.
|
|
24
|
+
// Quiescence (hostBits XOR workerBits == 0) lets us release them in batch.
|
|
25
|
+
const a_load = Atomics.load;
|
|
26
|
+
const returnHostBits = returnLock.hostBits;
|
|
27
|
+
const returnWorkerBits = returnLock.workerBits;
|
|
28
|
+
const deferredReleases = [];
|
|
29
|
+
const explicitReturnReleases = new Map();
|
|
30
|
+
const drainReturnReleases = () => {
|
|
31
|
+
if (deferredReleases.length === 0)
|
|
32
|
+
return;
|
|
33
|
+
if ((a_load(returnHostBits, 0) ^ a_load(returnWorkerBits, 0)) !== 0)
|
|
34
|
+
return;
|
|
35
|
+
for (let i = 0; i < deferredReleases.length; i++) {
|
|
36
|
+
try {
|
|
37
|
+
deferredReleases[i]();
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// best effort
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
deferredReleases.length = 0;
|
|
44
|
+
};
|
|
45
|
+
const releaseReturnedBufferReference = (token) => {
|
|
46
|
+
const key = token.toString();
|
|
47
|
+
const release = explicitReturnReleases.get(key);
|
|
48
|
+
if (release === undefined)
|
|
49
|
+
return;
|
|
50
|
+
explicitReturnReleases.delete(key);
|
|
51
|
+
try {
|
|
52
|
+
release();
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// best effort
|
|
56
|
+
}
|
|
57
|
+
};
|
|
23
58
|
const runByIndex = listOfFunctions.reduce((acc, fixed, idx) => {
|
|
24
59
|
const job = jobs[idx];
|
|
25
60
|
acc.push(composeWorkerRunner({
|
|
@@ -42,6 +77,7 @@ export const createWorkerRxQueue = ({ listOfFunctions, workerOptions, lock, retu
|
|
|
42
77
|
while (task) {
|
|
43
78
|
task.resolve = PLACE_HOLDER;
|
|
44
79
|
task.reject = PLACE_HOLDER;
|
|
80
|
+
attachPayloadTransportFinalizer(task, task.value);
|
|
45
81
|
toWorkPush(task);
|
|
46
82
|
task = resolvedShift();
|
|
47
83
|
}
|
|
@@ -56,11 +92,23 @@ export const createWorkerRxQueue = ({ listOfFunctions, workerOptions, lock, retu
|
|
|
56
92
|
slot[IDX_FLAGS] = shouldReject ? FLAG_REJECT : 0;
|
|
57
93
|
if (!encodeReturnSafe(slot))
|
|
58
94
|
return false;
|
|
95
|
+
// Preserve return finalizers past slot recycle; release after drain.
|
|
96
|
+
if (slot.finalize !== undefined) {
|
|
97
|
+
const token = slot.finalize[BUFFER_REFERENCE_RETURN_RELEASE_TOKEN];
|
|
98
|
+
if (token === undefined || borrowReturnedBufferReferences !== true) {
|
|
99
|
+
deferredReleases.push(slot.finalize);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
explicitReturnReleases.set(token.toString(), slot.finalize);
|
|
103
|
+
}
|
|
104
|
+
slot.finalize = undefined;
|
|
105
|
+
}
|
|
59
106
|
hasAnythingFinished--;
|
|
60
107
|
recyclePush(slot);
|
|
61
108
|
return true;
|
|
62
109
|
};
|
|
63
110
|
const settleNow = (slot, isError, value, wasAwaited) => {
|
|
111
|
+
runTaskFinalizers(slot);
|
|
64
112
|
slot.value = value;
|
|
65
113
|
hasAnythingFinished++;
|
|
66
114
|
if (wasAwaited && awaiting > 0)
|
|
@@ -99,7 +147,6 @@ export const createWorkerRxQueue = ({ listOfFunctions, workerOptions, lock, retu
|
|
|
99
147
|
try {
|
|
100
148
|
const fnIndex = slot[TaskIndex.FunctionID] & FUNCTION_ID_MASK;
|
|
101
149
|
const result = runByIndex[fnIndex](slot);
|
|
102
|
-
// Slot 0 is reused for response flags; clear request FunctionID value.
|
|
103
150
|
slot[IDX_FLAGS] = 0;
|
|
104
151
|
slot.value = null;
|
|
105
152
|
if (result instanceof Promise) {
|
|
@@ -118,6 +165,8 @@ export const createWorkerRxQueue = ({ listOfFunctions, workerOptions, lock, retu
|
|
|
118
165
|
return processed;
|
|
119
166
|
},
|
|
120
167
|
enqueueLock,
|
|
168
|
+
drainReturnReleases,
|
|
169
|
+
releaseReturnedBufferReference,
|
|
121
170
|
hasAwaiting: () => awaiting > 0,
|
|
122
171
|
getAwaiting: () => awaiting,
|
|
123
172
|
};
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { type SharedBufferSource } from "../../common/shared-buffer-region.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { LockBuffers } from "../../types.js";
|
|
3
3
|
type SharedMemoryBootData = {
|
|
4
4
|
sab: SharedBufferSource | undefined;
|
|
5
5
|
lock: LockBuffers | undefined;
|
|
6
6
|
returnLock: LockBuffers | undefined;
|
|
7
7
|
};
|
|
8
8
|
type ImportedFunctionsState = {
|
|
9
|
-
debug: DebugOptions | undefined;
|
|
10
9
|
list: string[];
|
|
11
10
|
ids: number[];
|
|
12
11
|
names?: string[];
|
|
13
12
|
listOfFunctions: readonly unknown[];
|
|
14
13
|
};
|
|
15
14
|
export declare const assertWorkerSharedMemoryBootData: ({ sab, lock, returnLock }: SharedMemoryBootData) => void;
|
|
16
|
-
export declare const assertWorkerImportsResolved: ({
|
|
15
|
+
export declare const assertWorkerImportsResolved: ({ list, ids, names, listOfFunctions }: ImportedFunctionsState) => void;
|
|
17
16
|
export {};
|
|
@@ -17,10 +17,7 @@ export const assertWorkerSharedMemoryBootData = ({ sab, lock, returnLock }) => {
|
|
|
17
17
|
throw new Error("worker missing return lock SABs");
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
|
-
export const assertWorkerImportsResolved = ({
|
|
21
|
-
if (debug?.logImportedUrl === true) {
|
|
22
|
-
console.log(list);
|
|
23
|
-
}
|
|
20
|
+
export const assertWorkerImportsResolved = ({ list, ids, names, listOfFunctions }) => {
|
|
24
21
|
if (listOfFunctions.length > 0 &&
|
|
25
22
|
(names === undefined || listOfFunctions.length === names.length))
|
|
26
23
|
return;
|
package/src/worker/timers.js
CHANGED
|
@@ -50,7 +50,7 @@ const isPlainNodeWindows = runtimeGlobals.process?.platform === "win32" &&
|
|
|
50
50
|
// full parkMs (up to seconds); the long park with no wake is what made CI
|
|
51
51
|
// runners appear to hang. The native wait already polls internally, so this is
|
|
52
52
|
// just bounding each poll slice.
|
|
53
|
-
const nativeWaitTimeoutMs = (parkMs) => isPlainNodeWindows ? 1 : parkMs
|
|
53
|
+
const nativeWaitTimeoutMs = (parkMs) => isPlainNodeWindows ? 1 : Number.isFinite(parkMs) ? parkMs : 60;
|
|
54
54
|
export const whilePausing = ({ pauseInNanoseconds }) => {
|
|
55
55
|
const forNanoseconds = pauseInNanoseconds ?? DEFAULT_PAUSE_TIME;
|
|
56
56
|
if (!a_pause || forNanoseconds <= 0)
|
|
@@ -101,10 +101,15 @@ export const sleepUntilChanged = ({ at, opView, pauseInNanoseconds, rxStatus, tx
|
|
|
101
101
|
else if (useSharedMemoryWait &&
|
|
102
102
|
a_wait &&
|
|
103
103
|
opView.buffer instanceof SharedArrayBuffer) {
|
|
104
|
+
// This is the notify-able path: a host Atomics.notify on opView wakes it.
|
|
105
|
+
// An infinite parkMs (debug) is intentional here — the worker blocks until
|
|
106
|
+
// a real signal instead of re-polling on a timeout.
|
|
104
107
|
a_wait(opView, at, value, parkMs ?? 60);
|
|
105
108
|
}
|
|
106
109
|
else if (a_wait && waitFallbackView) {
|
|
107
|
-
|
|
110
|
+
// waitFallbackView is never notified — this wait only ever times out and
|
|
111
|
+
// re-polls, so it must stay finite or the worker would hang forever.
|
|
112
|
+
a_wait(waitFallbackView, 0, 0, Number.isFinite(parkMs) ? parkMs : 1);
|
|
108
113
|
}
|
|
109
114
|
a_store(rxStatus, 0, 1);
|
|
110
115
|
};
|
package/unsafe.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BUFFER_REFERENCE_CODEC_ID, BUFFER_REFERENCE_KIND, BufferReference, type BufferReferenceMetadata, BufferReferenceReturn, type BufferReferenceRuntime, isBufferReferenceMetadata, } from "./src/connections/buffer-reference.js";
|
package/unsafe.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BUFFER_REFERENCE_CODEC_ID, BUFFER_REFERENCE_KIND, BufferReference, BufferReferenceReturn, isBufferReferenceMetadata, } from "./src/connections/buffer-reference.js";
|
package/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { type BufferLike, bufferToBytes, bufferToJson, bufferToNumbers, bufferToString, bytesToBuffer, jsonToBuffer, type NumberBufferOptions, type NumberFormat, numbersToBuffer, stringToBuffer, } from "./src/utils/http.js";
|
package/utils.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { bufferToBytes, bufferToJson, bufferToNumbers, bufferToString, bytesToBuffer, jsonToBuffer, numbersToBuffer, stringToBuffer, } from "./src/utils/http.js";
|