knitting 0.1.46

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 (121) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +632 -0
  3. package/knitting.d.ts +4 -0
  4. package/knitting.js +5 -0
  5. package/map.md +264 -0
  6. package/package.json +77 -0
  7. package/prebuilds/darwin-arm64-node-127/knitting_shared_memory.node +0 -0
  8. package/prebuilds/darwin-arm64-node-127/knitting_shm.node +0 -0
  9. package/prebuilds/darwin-arm64-node-137/knitting_shared_memory.node +0 -0
  10. package/prebuilds/darwin-arm64-node-137/knitting_shm.node +0 -0
  11. package/prebuilds/darwin-x64-node-127/knitting_shared_memory.node +0 -0
  12. package/prebuilds/darwin-x64-node-127/knitting_shm.node +0 -0
  13. package/prebuilds/darwin-x64-node-137/knitting_shared_memory.node +0 -0
  14. package/prebuilds/darwin-x64-node-137/knitting_shm.node +0 -0
  15. package/prebuilds/linux-x64-node-127/knitting_shared_memory.node +0 -0
  16. package/prebuilds/linux-x64-node-127/knitting_shm.node +0 -0
  17. package/prebuilds/linux-x64-node-137/knitting_shared_memory.node +0 -0
  18. package/prebuilds/linux-x64-node-137/knitting_shm.node +0 -0
  19. package/process-shared-buffer.d.ts +1 -0
  20. package/process-shared-buffer.js +1 -0
  21. package/scripts/build-native-addons.ts +295 -0
  22. package/src/api.d.ts +55 -0
  23. package/src/api.js +384 -0
  24. package/src/common/envelope.d.ts +11 -0
  25. package/src/common/envelope.js +8 -0
  26. package/src/common/module-url.d.ts +1 -0
  27. package/src/common/module-url.js +24 -0
  28. package/src/common/node-compat.d.ts +20 -0
  29. package/src/common/node-compat.js +24 -0
  30. package/src/common/path-canonical.d.ts +6 -0
  31. package/src/common/path-canonical.js +41 -0
  32. package/src/common/runtime.d.ts +15 -0
  33. package/src/common/runtime.js +91 -0
  34. package/src/common/shared-buffer-region.d.ts +11 -0
  35. package/src/common/shared-buffer-region.js +21 -0
  36. package/src/common/shared-buffer-text.d.ts +16 -0
  37. package/src/common/shared-buffer-text.js +65 -0
  38. package/src/common/task-source.d.ts +2 -0
  39. package/src/common/task-source.js +79 -0
  40. package/src/common/task-symbol.d.ts +1 -0
  41. package/src/common/task-symbol.js +1 -0
  42. package/src/common/with-resolvers.d.ts +9 -0
  43. package/src/common/with-resolvers.js +23 -0
  44. package/src/common/worker-runtime.d.ts +40 -0
  45. package/src/common/worker-runtime.js +52 -0
  46. package/src/connections/bun.d.ts +20 -0
  47. package/src/connections/bun.js +159 -0
  48. package/src/connections/deno.d.ts +20 -0
  49. package/src/connections/deno.js +150 -0
  50. package/src/connections/file-descriptor.d.ts +37 -0
  51. package/src/connections/file-descriptor.js +139 -0
  52. package/src/connections/index.d.ts +3 -0
  53. package/src/connections/index.js +3 -0
  54. package/src/connections/node-addons.d.ts +5 -0
  55. package/src/connections/node-addons.js +43 -0
  56. package/src/connections/node.d.ts +29 -0
  57. package/src/connections/node.js +59 -0
  58. package/src/connections/posix.d.ts +31 -0
  59. package/src/connections/posix.js +71 -0
  60. package/src/connections/process-shared-buffer.d.ts +67 -0
  61. package/src/connections/process-shared-buffer.js +267 -0
  62. package/src/connections/types.d.ts +48 -0
  63. package/src/connections/types.js +37 -0
  64. package/src/error.d.ts +13 -0
  65. package/src/error.js +49 -0
  66. package/src/ipc/tools/ring-queue.d.ts +33 -0
  67. package/src/ipc/tools/ring-queue.js +159 -0
  68. package/src/ipc/transport/shared-memory.d.ts +25 -0
  69. package/src/ipc/transport/shared-memory.js +35 -0
  70. package/src/knitting_shared_memory.cc +436 -0
  71. package/src/knitting_shm.cc +476 -0
  72. package/src/memory/byte-carpet.d.ts +73 -0
  73. package/src/memory/byte-carpet.js +157 -0
  74. package/src/memory/lock.d.ts +190 -0
  75. package/src/memory/lock.js +856 -0
  76. package/src/memory/payload-config.d.ts +22 -0
  77. package/src/memory/payload-config.js +67 -0
  78. package/src/memory/payloadCodec.d.ts +46 -0
  79. package/src/memory/payloadCodec.js +1157 -0
  80. package/src/memory/regionRegistry.d.ts +17 -0
  81. package/src/memory/regionRegistry.js +285 -0
  82. package/src/memory/shared-buffer-io.d.ts +53 -0
  83. package/src/memory/shared-buffer-io.js +380 -0
  84. package/src/permission/index.d.ts +2 -0
  85. package/src/permission/index.js +2 -0
  86. package/src/permission/protocol.d.ts +166 -0
  87. package/src/permission/protocol.js +640 -0
  88. package/src/runtime/balancer.d.ts +19 -0
  89. package/src/runtime/balancer.js +149 -0
  90. package/src/runtime/dispatcher.d.ts +34 -0
  91. package/src/runtime/dispatcher.js +142 -0
  92. package/src/runtime/inline-executor.d.ts +10 -0
  93. package/src/runtime/inline-executor.js +270 -0
  94. package/src/runtime/pool.d.ts +43 -0
  95. package/src/runtime/pool.js +922 -0
  96. package/src/runtime/tx-queue.d.ts +25 -0
  97. package/src/runtime/tx-queue.js +144 -0
  98. package/src/shared/abortSignal.d.ts +23 -0
  99. package/src/shared/abortSignal.js +126 -0
  100. package/src/types.d.ts +283 -0
  101. package/src/types.js +2 -0
  102. package/src/worker/composable-runners.d.ts +12 -0
  103. package/src/worker/composable-runners.js +105 -0
  104. package/src/worker/loop.d.ts +2 -0
  105. package/src/worker/loop.js +453 -0
  106. package/src/worker/rx-queue.d.ts +22 -0
  107. package/src/worker/rx-queue.js +124 -0
  108. package/src/worker/safety/index.d.ts +4 -0
  109. package/src/worker/safety/index.js +4 -0
  110. package/src/worker/safety/performance.d.ts +1 -0
  111. package/src/worker/safety/performance.js +17 -0
  112. package/src/worker/safety/process.d.ts +2 -0
  113. package/src/worker/safety/process.js +79 -0
  114. package/src/worker/safety/startup.d.ts +16 -0
  115. package/src/worker/safety/startup.js +30 -0
  116. package/src/worker/safety/worker-data.d.ts +2 -0
  117. package/src/worker/safety/worker-data.js +36 -0
  118. package/src/worker/task-loader.d.ts +26 -0
  119. package/src/worker/task-loader.js +66 -0
  120. package/src/worker/timers.d.ts +18 -0
  121. package/src/worker/timers.js +97 -0
@@ -0,0 +1,105 @@
1
+ import { getTaskFunctionMeta, getTaskSlotMeta, TASK_SLOT_META_VALUE_MASK, } from "../memory/lock.js";
2
+ const ABORT_SIGNAL_META_OFFSET = 1;
3
+ const TIMEOUT_KIND_RESOLVE = 1;
4
+ const p_now = performance.now.bind(performance);
5
+ const raceTimeout = (promise, ms, resolveOnTimeout, timeoutValue) => new Promise((resolve, reject) => {
6
+ let done = false;
7
+ const timer = setTimeout(() => {
8
+ if (done)
9
+ return;
10
+ done = true;
11
+ if (resolveOnTimeout)
12
+ resolve(timeoutValue);
13
+ else
14
+ reject(timeoutValue);
15
+ }, ms);
16
+ promise.then((value) => {
17
+ if (done)
18
+ return;
19
+ done = true;
20
+ clearTimeout(timer);
21
+ resolve(value);
22
+ }, (err) => {
23
+ if (done)
24
+ return;
25
+ done = true;
26
+ clearTimeout(timer);
27
+ reject(err);
28
+ });
29
+ });
30
+ const nowStamp = (now) => (Math.floor(now()) & TASK_SLOT_META_VALUE_MASK) >>> 0;
31
+ const applyTimeoutBudget = (promise, slot, spec, now) => {
32
+ const elapsed = (nowStamp(now) - getTaskSlotMeta(slot)) & TASK_SLOT_META_VALUE_MASK;
33
+ const remaining = spec.ms - elapsed;
34
+ if (!(remaining > 0)) {
35
+ // Prevent late unhandled rejections from the original promise.
36
+ promise.then(() => { }, () => { });
37
+ return spec.kind === TIMEOUT_KIND_RESOLVE
38
+ ? Promise.resolve(spec.value)
39
+ : Promise.reject(spec.value);
40
+ }
41
+ const timeoutMs = Math.max(1, Math.floor(remaining));
42
+ return raceTimeout(promise, timeoutMs, spec.kind === TIMEOUT_KIND_RESOLVE, spec.value);
43
+ };
44
+ const NO_ABORT_SIGNAL = -1;
45
+ const readSignal = (slot) => {
46
+ const encodedSignal = getTaskFunctionMeta(slot);
47
+ if (encodedSignal === 0)
48
+ return NO_ABORT_SIGNAL;
49
+ const signal = (encodedSignal - ABORT_SIGNAL_META_OFFSET) | 0;
50
+ return signal >= 0 ? signal : NO_ABORT_SIGNAL;
51
+ };
52
+ const throwIfAborted = (signal, hasAborted) => {
53
+ if (signal === NO_ABORT_SIGNAL)
54
+ return;
55
+ if (hasAborted(signal))
56
+ throw new Error("Task aborted");
57
+ };
58
+ const makeToolkitCache = (hasAborted) => {
59
+ const bySignal = [];
60
+ return (signal) => {
61
+ let toolkit = bySignal[signal];
62
+ if (toolkit)
63
+ return toolkit;
64
+ const hasAbortedMethod = () => hasAborted(signal);
65
+ toolkit = {
66
+ hasAborted: hasAbortedMethod,
67
+ };
68
+ bySignal[signal] = toolkit;
69
+ return toolkit;
70
+ };
71
+ };
72
+ export const composeWorkerRunner = ({ job, timeout, hasAborted, now, }) => {
73
+ const nowTime = now ?? p_now;
74
+ if (!hasAborted) {
75
+ if (!timeout) {
76
+ return (slot) => job(slot.value);
77
+ }
78
+ return (slot) => {
79
+ const result = job(slot.value);
80
+ if (!(result instanceof Promise))
81
+ return result;
82
+ return applyTimeoutBudget(result, slot, timeout, nowTime);
83
+ };
84
+ }
85
+ const getToolkit = makeToolkitCache(hasAborted);
86
+ if (!timeout) {
87
+ return (slot) => {
88
+ const signal = readSignal(slot);
89
+ throwIfAborted(signal, hasAborted);
90
+ if (signal === NO_ABORT_SIGNAL)
91
+ return job(slot.value);
92
+ return job(slot.value, getToolkit(signal));
93
+ };
94
+ }
95
+ return (slot) => {
96
+ const signal = readSignal(slot);
97
+ throwIfAborted(signal, hasAborted);
98
+ const result = signal === NO_ABORT_SIGNAL
99
+ ? job(slot.value)
100
+ : job(slot.value, getToolkit(signal));
101
+ if (!(result instanceof Promise))
102
+ return result;
103
+ return applyTimeoutBudget(result, slot, timeout, nowTime);
104
+ };
105
+ };
@@ -0,0 +1,2 @@
1
+ import type { WorkerData } from "../types.js";
2
+ export declare const workerMainLoop: (startupData: WorkerData) => Promise<void>;
@@ -0,0 +1,453 @@
1
+ import { RUNTIME_IS_MAIN_THREAD, RUNTIME_IS_PROCESS_WORKER, RUNTIME_PARENT_PORT, RUNTIME_PROCESS_WORKER_BOOT_ENV, RUNTIME_PROCESS_WORKER_BOOT_VERSION, RUNTIME_WORKER_DATA, createRuntimeMessageChannel, } from "../common/worker-runtime.js";
2
+ import { isSharedBufferSource, } from "../common/shared-buffer-region.js";
3
+ import { isLockBufferTextCompat } from "../common/shared-buffer-text.js";
4
+ import { createWorkerRxQueue } from "./rx-queue.js";
5
+ import { createSharedMemoryTransport, } from "../ipc/transport/shared-memory.js";
6
+ import { lock2 } from "../memory/lock.js";
7
+ import { getFunctions } from "./task-loader.js";
8
+ import { pauseGeneric, sleepUntilChanged, whilePausing, } from "./timers.js";
9
+ import { RUNTIME, SET_IMMEDIATE } from "../common/runtime.js";
10
+ import { getNodeProcess } from "../common/node-compat.js";
11
+ import { getDefaultProcessSharedBufferPrimitives, ProcessSharedBuffer, setDefaultProcessSharedBufferPrimitives, } from "../connections/process-shared-buffer.js";
12
+ import { createBunConnectionPrimitives } from "../connections/bun.js";
13
+ import { createDenoConnectionPrimitives } from "../connections/deno.js";
14
+ import { loadNodeFutexAddon } from "../connections/node.js";
15
+ import { installTerminationGuard, installUnhandledRejectionSilencer, installPerformanceNowGuard, scrubWorkerDataSensitiveBuffers, assertWorkerSharedMemoryBootData, assertWorkerImportsResolved, } from "./safety/index.js";
16
+ import { signalAbortFactory } from "../shared/abortSignal.js";
17
+ const WORKER_FATAL_MESSAGE_KEY = "__knittingWorkerFatal";
18
+ const getProcessWorkerNativeWaitU32 = () => {
19
+ if (!RUNTIME_IS_PROCESS_WORKER || RUNTIME !== "node")
20
+ return undefined;
21
+ try {
22
+ return loadNodeFutexAddon().waitU32;
23
+ }
24
+ catch {
25
+ return undefined;
26
+ }
27
+ };
28
+ const reportWorkerStartupFatal = (error) => {
29
+ const message = String(error?.message ?? error);
30
+ const payload = {
31
+ [WORKER_FATAL_MESSAGE_KEY]: message,
32
+ };
33
+ let reported = false;
34
+ try {
35
+ RUNTIME_PARENT_PORT?.postMessage?.(payload);
36
+ reported = RUNTIME_PARENT_PORT !== undefined;
37
+ }
38
+ catch {
39
+ }
40
+ if (!reported) {
41
+ try {
42
+ globalThis.postMessage(payload);
43
+ reported = true;
44
+ }
45
+ catch {
46
+ }
47
+ }
48
+ if (!reported) {
49
+ try {
50
+ console.error(`Worker startup failed: ${message}`);
51
+ }
52
+ catch {
53
+ }
54
+ if (RUNTIME_IS_PROCESS_WORKER) {
55
+ try {
56
+ getNodeProcess()?.exit?.(1);
57
+ }
58
+ catch {
59
+ }
60
+ }
61
+ }
62
+ };
63
+ export const workerMainLoop = async (startupData) => {
64
+ // Startup-only safety layer: no per-iteration checks in the hot loop.
65
+ installTerminationGuard();
66
+ installUnhandledRejectionSilencer();
67
+ installPerformanceNowGuard();
68
+ const { debug, sab, thread, startAt, workerOptions, lock, returnLock, abortSignalSAB, abortSignalMax, payloadConfig, permission, totalNumberOfThread, list, ids, at, } = startupData;
69
+ scrubWorkerDataSensitiveBuffers(startupData);
70
+ assertWorkerSharedMemoryBootData({ sab, lock, returnLock });
71
+ let Comment;
72
+ (function (Comment) {
73
+ Comment[Comment["thisIsAHint"] = 0] = "thisIsAHint";
74
+ })(Comment || (Comment = {}));
75
+ const signals = createSharedMemoryTransport({
76
+ sabObject: {
77
+ sharedSab: sab,
78
+ },
79
+ isMain: false,
80
+ thread,
81
+ debug,
82
+ startTime: startAt,
83
+ });
84
+ const lockState = lock2({
85
+ headers: lock.headers,
86
+ headerSlotStrideU32: lock.headerSlotStrideU32,
87
+ LockBoundSector: lock.lockSector,
88
+ payload: lock.payload,
89
+ payloadSector: lock.payloadSector,
90
+ payloadConfig,
91
+ textCompat: lock.textCompat,
92
+ });
93
+ const returnLockState = lock2({
94
+ headers: returnLock.headers,
95
+ headerSlotStrideU32: returnLock.headerSlotStrideU32,
96
+ LockBoundSector: returnLock.lockSector,
97
+ payload: returnLock.payload,
98
+ payloadSector: returnLock.payloadSector,
99
+ payloadConfig,
100
+ textCompat: returnLock.textCompat,
101
+ });
102
+ const timers = workerOptions?.timers;
103
+ const spinMicroseconds = timers?.spinMicroseconds ??
104
+ Math.max(1, totalNumberOfThread) * 50;
105
+ const parkMs = timers?.parkMs ??
106
+ Math.max(1, totalNumberOfThread) * 50;
107
+ const pauseSpin = (() => {
108
+ const fn = typeof timers?.pauseNanoseconds === "number"
109
+ ? whilePausing({ pauseInNanoseconds: timers.pauseNanoseconds })
110
+ : pauseGeneric;
111
+ return () => fn(); // always a closure wrapper
112
+ })();
113
+ const { opView, rxStatus, txStatus } = signals;
114
+ const a_store = Atomics.store;
115
+ const a_load = Atomics.load;
116
+ const nativeWaitU32 = getProcessWorkerNativeWaitU32();
117
+ const listOfFunctions = await getFunctions({
118
+ list,
119
+ isWorker: true,
120
+ ids,
121
+ at,
122
+ permission,
123
+ });
124
+ assertWorkerImportsResolved({ debug, list, ids, listOfFunctions });
125
+ const abortSignals = abortSignalSAB
126
+ ? signalAbortFactory({
127
+ sab: abortSignalSAB,
128
+ maxSignals: abortSignalMax,
129
+ })
130
+ : undefined;
131
+ const { enqueueLock, serviceBatchImmediate, hasCompleted, writeBatch, hasPending, getAwaiting, } = createWorkerRxQueue({
132
+ listOfFunctions,
133
+ workerOptions,
134
+ lock: lockState,
135
+ returnLock: returnLockState,
136
+ hasAborted: abortSignals?.hasAborted,
137
+ });
138
+ a_store(rxStatus, 0, 1);
139
+ const WRITE_MAX = 64;
140
+ const pauseUntil = sleepUntilChanged({
141
+ opView,
142
+ at: 0,
143
+ rxStatus,
144
+ txStatus,
145
+ pauseInNanoseconds: timers?.pauseNanoseconds,
146
+ enqueueLock,
147
+ write: () => hasCompleted() ? writeBatch(WRITE_MAX) : 0,
148
+ nativeWaitU32,
149
+ useSharedMemoryWait: !(RUNTIME_IS_PROCESS_WORKER &&
150
+ RUNTIME === "node" &&
151
+ nativeWaitU32 === undefined),
152
+ });
153
+ const channel = createRuntimeMessageChannel();
154
+ const port1 = channel.port1;
155
+ const port2 = channel.port2;
156
+ const post2 = (message) => port2.postMessage(message);
157
+ let isInMacro = false;
158
+ let awaitingSpins = 0;
159
+ let lastAwaiting = 0;
160
+ const MAX_AWAITING_MS = 10;
161
+ let wakeSeq = a_load(opView, 0);
162
+ const scheduleMacro = () => {
163
+ if (isInMacro)
164
+ return;
165
+ isInMacro = true;
166
+ post2(null);
167
+ };
168
+ const scheduleTimer = (delayMs) => {
169
+ if (isInMacro)
170
+ return;
171
+ isInMacro = true;
172
+ if (delayMs <= 0 && typeof SET_IMMEDIATE === "function") {
173
+ SET_IMMEDIATE(loop);
174
+ return;
175
+ }
176
+ if (delayMs <= 0) {
177
+ post2(null);
178
+ return;
179
+ }
180
+ if (typeof setTimeout === "function") {
181
+ setTimeout(loop, delayMs);
182
+ return;
183
+ }
184
+ post2(null);
185
+ };
186
+ const _enqueueLock = enqueueLock;
187
+ const _hasCompleted = hasCompleted;
188
+ const _writeBatch = writeBatch;
189
+ const _hasPending = hasPending;
190
+ const _serviceBatchImmediate = serviceBatchImmediate;
191
+ const _getAwaiting = getAwaiting;
192
+ const _pauseSpin = pauseSpin;
193
+ const _pauseUntil = pauseUntil;
194
+ const loop = () => {
195
+ isInMacro = false;
196
+ let progressed = true;
197
+ let awaiting = 0;
198
+ while (true) {
199
+ progressed = _enqueueLock();
200
+ if (_hasCompleted()) {
201
+ if (_writeBatch(WRITE_MAX) > 0)
202
+ progressed = true;
203
+ }
204
+ if (_hasPending()) {
205
+ if (_serviceBatchImmediate() > 0)
206
+ progressed = true;
207
+ }
208
+ if ((awaiting = _getAwaiting()) > 0) {
209
+ if (awaiting !== lastAwaiting)
210
+ awaitingSpins = 0;
211
+ lastAwaiting = awaiting;
212
+ awaitingSpins++;
213
+ const delay = Math.min(MAX_AWAITING_MS, Math.max(0, awaitingSpins - 1));
214
+ scheduleTimer(delay);
215
+ return;
216
+ }
217
+ awaitingSpins = lastAwaiting = 0;
218
+ if (!progressed) {
219
+ if (txStatus[Comment.thisIsAHint] === 1) {
220
+ _pauseSpin();
221
+ continue;
222
+ }
223
+ _pauseUntil(wakeSeq, spinMicroseconds, parkMs);
224
+ wakeSeq = a_load(opView, 0);
225
+ }
226
+ }
227
+ };
228
+ const port1Any = port1;
229
+ if (typeof port1Any.on === "function") {
230
+ port1Any.on("message", loop);
231
+ }
232
+ else {
233
+ // @ts-ignore
234
+ port1Any.onmessage = loop;
235
+ }
236
+ port1Any.start?.();
237
+ port2.start?.();
238
+ scheduleMacro();
239
+ };
240
+ const isWorkerGlobalScope = () => {
241
+ const scopeCtor = globalThis.WorkerGlobalScope;
242
+ if (typeof scopeCtor !== "function")
243
+ return false;
244
+ try {
245
+ return globalThis instanceof
246
+ scopeCtor;
247
+ }
248
+ catch {
249
+ return false;
250
+ }
251
+ };
252
+ const isLockBuffers = (value) => {
253
+ if (!value || typeof value !== "object")
254
+ return false;
255
+ const candidate = value;
256
+ return isSharedBufferSource(candidate.headers) &&
257
+ isSharedBufferSource(candidate.lockSector) &&
258
+ isSharedBufferSource(candidate.payload) &&
259
+ isSharedBufferSource(candidate.payloadSector) &&
260
+ (candidate.textCompat === undefined ||
261
+ isLockBufferTextCompat(candidate.textCompat));
262
+ };
263
+ const isWorkerBootPayload = (value) => {
264
+ if (!value || typeof value !== "object")
265
+ return false;
266
+ const candidate = value;
267
+ return isSharedBufferSource(candidate.sab) &&
268
+ Array.isArray(candidate.list) &&
269
+ Array.isArray(candidate.ids) &&
270
+ Array.isArray(candidate.at) &&
271
+ typeof candidate.thread === "number" &&
272
+ typeof candidate.totalNumberOfThread === "number" &&
273
+ typeof candidate.startAt === "number" &&
274
+ (candidate.abortSignalSAB === undefined ||
275
+ isSharedBufferSource(candidate.abortSignalSAB)) &&
276
+ isLockBuffers(candidate.lock) &&
277
+ isLockBuffers(candidate.returnLock);
278
+ };
279
+ const installWorkerGlobalBootstrap = () => {
280
+ const g = globalThis;
281
+ const start = (data) => {
282
+ if (!isWorkerBootPayload(data))
283
+ return;
284
+ void workerMainLoop(data).catch(reportWorkerStartupFatal);
285
+ };
286
+ if (typeof g.addEventListener === "function" &&
287
+ typeof g.removeEventListener === "function") {
288
+ const onMessage = (event) => {
289
+ const data = event?.data;
290
+ if (!isWorkerBootPayload(data))
291
+ return;
292
+ try {
293
+ g.removeEventListener?.("message", onMessage);
294
+ }
295
+ catch {
296
+ }
297
+ start(data);
298
+ };
299
+ g.addEventListener("message", onMessage);
300
+ return;
301
+ }
302
+ g.onmessage = (event) => {
303
+ const data = event?.data;
304
+ if (!isWorkerBootPayload(data))
305
+ return;
306
+ g.onmessage = null;
307
+ start(data);
308
+ };
309
+ };
310
+ const isProcessSharedBufferMetadata = (value) => {
311
+ try {
312
+ ProcessSharedBuffer.fromMetadata(value);
313
+ return true;
314
+ }
315
+ catch {
316
+ return false;
317
+ }
318
+ };
319
+ const isProcessWorkerWireLockBuffers = (value) => {
320
+ if (!value || typeof value !== "object")
321
+ return false;
322
+ const candidate = value;
323
+ return isProcessSharedBufferMetadata(candidate.headers) &&
324
+ isProcessSharedBufferMetadata(candidate.lockSector) &&
325
+ isProcessSharedBufferMetadata(candidate.payload) &&
326
+ isProcessSharedBufferMetadata(candidate.payloadSector) &&
327
+ (candidate.textCompat === undefined ||
328
+ isLockBufferTextCompat(candidate.textCompat));
329
+ };
330
+ const isProcessWorkerBootPayload = (value) => {
331
+ if (!value || typeof value !== "object")
332
+ return false;
333
+ const candidate = value;
334
+ const workerData = candidate.workerData;
335
+ return candidate.version === RUNTIME_PROCESS_WORKER_BOOT_VERSION &&
336
+ !!workerData &&
337
+ isProcessSharedBufferMetadata(workerData.sab) &&
338
+ Array.isArray(workerData.list) &&
339
+ Array.isArray(workerData.ids) &&
340
+ Array.isArray(workerData.at) &&
341
+ typeof workerData.thread === "number" &&
342
+ typeof workerData.totalNumberOfThread === "number" &&
343
+ typeof workerData.startAt === "number" &&
344
+ (workerData.abortSignalSAB === undefined ||
345
+ isProcessSharedBufferMetadata(workerData.abortSignalSAB)) &&
346
+ isProcessWorkerWireLockBuffers(workerData.lock) &&
347
+ isProcessWorkerWireLockBuffers(workerData.returnLock);
348
+ };
349
+ const getProcessWorkerPrimitives = () => {
350
+ const primitives = RUNTIME === "bun"
351
+ ? createBunConnectionPrimitives()
352
+ : RUNTIME === "deno"
353
+ ? createDenoConnectionPrimitives()
354
+ : getDefaultProcessSharedBufferPrimitives();
355
+ setDefaultProcessSharedBufferPrimitives(primitives);
356
+ return primitives;
357
+ };
358
+ const reviveProcessWorkerData = (wire) => {
359
+ const primitives = getProcessWorkerPrimitives();
360
+ const mappings = new Map();
361
+ const reviveRegion = (metadata) => {
362
+ const processBuffer = ProcessSharedBuffer.fromMetadata(metadata);
363
+ const descriptor = processBuffer.descriptor;
364
+ const key = `${descriptor.fd}:${descriptor.size}:${descriptor.runtime ?? ""}`;
365
+ let mapping = mappings.get(key);
366
+ if (mapping === undefined) {
367
+ mapping = descriptor.map(primitives);
368
+ mappings.set(key, mapping);
369
+ }
370
+ else {
371
+ descriptor.attach(mapping);
372
+ }
373
+ return {
374
+ sab: mapping.buffer,
375
+ byteOffset: processBuffer.byteOffset,
376
+ byteLength: processBuffer.byteLength,
377
+ };
378
+ };
379
+ const reviveLockBuffers = (lock) => ({
380
+ ...lock,
381
+ headers: reviveRegion(lock.headers),
382
+ lockSector: reviveRegion(lock.lockSector),
383
+ payload: reviveRegion(lock.payload),
384
+ payloadSector: reviveRegion(lock.payloadSector),
385
+ });
386
+ return {
387
+ ...wire,
388
+ sab: reviveRegion(wire.sab),
389
+ abortSignalSAB: wire.abortSignalSAB === undefined
390
+ ? undefined
391
+ : reviveRegion(wire.abortSignalSAB),
392
+ lock: reviveLockBuffers(wire.lock),
393
+ returnLock: reviveLockBuffers(wire.returnLock),
394
+ };
395
+ };
396
+ const installProcessWorkerBootstrap = () => {
397
+ const processLike = getNodeProcess();
398
+ const start = (payload) => {
399
+ const data = reviveProcessWorkerData(payload.workerData);
400
+ if (!isWorkerBootPayload(data)) {
401
+ throw new TypeError("invalid process worker boot payload");
402
+ }
403
+ void workerMainLoop(data).catch(reportWorkerStartupFatal);
404
+ };
405
+ const envBoot = processLike?.env?.[RUNTIME_PROCESS_WORKER_BOOT_ENV];
406
+ if (typeof envBoot === "string" && envBoot.length > 0) {
407
+ try {
408
+ const payload = JSON.parse(envBoot);
409
+ if (!isProcessWorkerBootPayload(payload)) {
410
+ throw new TypeError("invalid process worker boot payload");
411
+ }
412
+ try {
413
+ delete processLike?.env?.[RUNTIME_PROCESS_WORKER_BOOT_ENV];
414
+ }
415
+ catch {
416
+ }
417
+ start(payload);
418
+ }
419
+ catch (error) {
420
+ reportWorkerStartupFatal(error);
421
+ }
422
+ return;
423
+ }
424
+ if (typeof processLike?.on !== "function")
425
+ return;
426
+ const onMessage = (message) => {
427
+ if (!isProcessWorkerBootPayload(message))
428
+ return;
429
+ try {
430
+ processLike.off?.("message", onMessage);
431
+ processLike.removeListener?.("message", onMessage);
432
+ }
433
+ catch {
434
+ }
435
+ try {
436
+ start(message);
437
+ }
438
+ catch (error) {
439
+ reportWorkerStartupFatal(error);
440
+ }
441
+ };
442
+ processLike.on("message", onMessage);
443
+ };
444
+ if (RUNTIME_IS_MAIN_THREAD === false &&
445
+ isWorkerBootPayload(RUNTIME_WORKER_DATA)) {
446
+ void workerMainLoop(RUNTIME_WORKER_DATA).catch(reportWorkerStartupFatal);
447
+ }
448
+ else if (RUNTIME_IS_PROCESS_WORKER) {
449
+ installProcessWorkerBootstrap();
450
+ }
451
+ else if (isWorkerGlobalScope()) {
452
+ installWorkerGlobalBootstrap();
453
+ }
@@ -0,0 +1,22 @@
1
+ import { type Lock2 } from "../memory/lock.js";
2
+ import type { WorkerComposedWithKey } from "./task-loader.js";
3
+ import type { WorkerSettings } from "../types.js";
4
+ type ArgumentsForCreateWorkerQueue = {
5
+ listOfFunctions: WorkerComposedWithKey[];
6
+ workerOptions?: WorkerSettings;
7
+ lock: Lock2;
8
+ returnLock: Lock2;
9
+ hasAborted?: (signal: number) => boolean;
10
+ now?: () => number;
11
+ };
12
+ export type CreateWorkerRxQueue = ReturnType<typeof createWorkerRxQueue>;
13
+ export declare const createWorkerRxQueue: ({ listOfFunctions, workerOptions, lock, returnLock, hasAborted, now, }: ArgumentsForCreateWorkerQueue) => {
14
+ hasCompleted: () => boolean;
15
+ hasPending: () => boolean;
16
+ writeBatch: (max: number) => number;
17
+ serviceBatchImmediate: () => number;
18
+ enqueueLock: () => boolean;
19
+ hasAwaiting: () => boolean;
20
+ getAwaiting: () => number;
21
+ };
22
+ export {};