knitting 0.1.56 → 0.1.61
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/BROWSER.md +134 -0
- package/README.md +347 -46
- package/knitting.browser.d.ts +6 -0
- package/knitting.browser.js +1 -0
- package/knitting.d.ts +3 -2
- package/knitting.js +3 -3
- package/map.md +21 -9
- package/package.json +17 -2
- package/prebuilds/darwin-arm64-node-127/knitting_buffer_pointer.node +0 -0
- package/prebuilds/darwin-arm64-node-127/knitting_shared_memory.node +0 -0
- package/prebuilds/darwin-arm64-node-127/knitting_shm.node +0 -0
- package/prebuilds/darwin-arm64-node-137/knitting_buffer_pointer.node +0 -0
- package/prebuilds/darwin-arm64-node-137/knitting_shared_memory.node +0 -0
- package/prebuilds/darwin-arm64-node-137/knitting_shm.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-compiled-worker.ts +276 -0
- package/scripts/compiled-worker/porffor.d.ts +5 -0
- package/scripts/compiled-worker/runtime.ts +529 -0
- package/scripts/compiled-worker/task-shim.ts +32 -0
- package/src/api.d.ts +24 -1
- package/src/api.js +311 -27
- package/src/common/module-url.d.ts +1 -0
- package/src/common/module-url.js +30 -2
- package/src/common/node-compat.d.ts +2 -0
- package/src/common/path-canonical.js +20 -6
- package/src/common/runtime.d.ts +3 -1
- package/src/common/runtime.js +25 -4
- package/src/common/task-source.d.ts +2 -0
- package/src/common/task-source.js +17 -1
- package/src/common/worker-runtime.js +16 -7
- package/src/connections/buffer-reference-native.js +25 -1
- package/src/connections/buffer-reference.d.ts +23 -2
- package/src/connections/buffer-reference.js +143 -29
- package/src/connections/bun.d.ts +1 -1
- package/src/connections/bun.js +25 -14
- package/src/connections/deno.d.ts +3 -1
- package/src/connections/deno.js +35 -14
- package/src/connections/external-array-buffer.d.ts +2 -0
- package/src/connections/external-array-buffer.js +33 -0
- package/src/connections/node-addons.d.ts +11 -0
- package/src/connections/node-addons.js +49 -1
- package/src/connections/node-ffi-api.d.ts +19 -0
- package/src/connections/node-ffi-api.js +28 -0
- package/src/connections/node-ffi.d.ts +27 -0
- package/src/connections/node-ffi.js +262 -0
- package/src/connections/node.d.ts +1 -1
- package/src/connections/node.js +20 -20
- package/src/connections/package-assets.js +25 -15
- package/src/connections/posix.d.ts +42 -0
- package/src/connections/posix.js +101 -0
- package/src/connections/process-shared-buffer.d.ts +1 -0
- package/src/connections/process-shared-buffer.js +11 -45
- package/src/connections/types.d.ts +4 -0
- package/src/connections/windows.d.ts +19 -10
- package/src/connections/windows.js +87 -66
- package/src/error.d.ts +7 -6
- package/src/error.js +8 -7
- package/src/memory/lock.d.ts +112 -77
- package/src/memory/lock.js +314 -87
- package/src/memory/payloadCodec.d.ts +11 -2
- package/src/memory/payloadCodec.js +129 -37
- package/src/memory/regionRegistry.d.ts +1 -3
- package/src/memory/regionRegistry.js +16 -14
- package/src/permission/compatibility.d.ts +28 -0
- package/src/permission/compatibility.js +239 -0
- package/src/permission/index.d.ts +2 -0
- package/src/permission/index.js +1 -0
- package/src/permission/protocol.d.ts +1 -0
- package/src/permission/protocol.js +59 -15
- package/src/runtime/compiled-artifact.d.ts +21 -0
- package/src/runtime/compiled-artifact.js +260 -0
- package/src/runtime/compiled-builder.d.ts +8 -0
- package/src/runtime/compiled-builder.js +42 -0
- package/src/runtime/compiled-worker.d.ts +27 -0
- package/src/runtime/compiled-worker.js +562 -0
- package/src/runtime/dispatcher.js +9 -0
- package/src/runtime/inline-executor.js +27 -15
- package/src/runtime/pool.d.ts +121 -5
- package/src/runtime/pool.js +263 -49
- package/src/runtime/process-worker.d.ts +3 -13
- package/src/runtime/process-worker.js +97 -101
- package/src/runtime/tx-queue.d.ts +18 -2
- package/src/runtime/tx-queue.js +56 -16
- package/src/runtime/worker-common.d.ts +13 -0
- package/src/runtime/worker-common.js +102 -0
- package/src/types.d.ts +89 -9
- package/src/worker/composable-runners.js +3 -2
- package/src/worker/loop.d.ts +1 -0
- package/src/worker/loop.js +52 -17
- package/src/worker/rx-queue.d.ts +11 -1
- package/src/worker/rx-queue.js +4 -1
- package/src/worker/task-loader.d.ts +5 -4
- package/src/worker/task-loader.js +13 -7
- package/src/worker/timers.d.ts +8 -1
- package/src/worker/timers.js +28 -23
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { fileURLToPath as fileURLToPathCompat } from "node:url";
|
|
2
1
|
import { HEADER_SLOT_STRIDE_U32, LOCK_SECTOR_BYTE_LENGTH, LockBound, } from "../memory/lock.js";
|
|
3
2
|
import { createByteCarpet, getHeaderBlockByteLength, makeSharedBufferRegion, } from "../memory/byte-carpet.js";
|
|
4
3
|
import { RUNTIME } from "../common/runtime.js";
|
|
5
4
|
import { debugHas } from "../debug/gate.js";
|
|
5
|
+
import { toWorkerCompatExecArgv, } from "./worker-common.js";
|
|
6
6
|
import { RUNTIME_POOL_DEPTH, RUNTIME_POOL_DEPTH_ENV, RUNTIME_PROCESS_WORKER_BOOT_ENV, RUNTIME_PROCESS_WORKER_BOOT_VERSION, RUNTIME_PROCESS_WORKER_ENV, } from "../common/worker-runtime.js";
|
|
7
7
|
import { getNodeBuiltinModule, getNodeProcess } from "../common/node-compat.js";
|
|
8
8
|
import { toSharedBufferRegion, } from "../common/shared-buffer-region.js";
|
|
@@ -12,47 +12,14 @@ import { FileDescriptor, ProcessSharedBuffer, } from "../connections/index.js";
|
|
|
12
12
|
import { createNodeConnectionPrimitives, loadNodeFutexAddon, } from "../connections/node.js";
|
|
13
13
|
import { loadNodeNativeAddon } from "../connections/node-addons.js";
|
|
14
14
|
import { detectPosixPlatform } from "../connections/posix.js";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"--allow-worker",
|
|
22
|
-
"--allow-child-process",
|
|
23
|
-
"--allow-addons",
|
|
24
|
-
"--allow-wasi",
|
|
25
|
-
]);
|
|
26
|
-
const NODE_WORKER_SAFE_EXEC_FLAGS = new Set([
|
|
27
|
-
"--experimental-transform-types",
|
|
28
|
-
"--expose-gc",
|
|
29
|
-
"--no-warnings",
|
|
30
|
-
...NODE_PERMISSION_EXEC_FLAGS,
|
|
31
|
-
]);
|
|
32
|
-
const isNodeWorkerSafeExecFlag = (flag) => NODE_WORKER_SAFE_EXEC_FLAGS.has(execFlagKey(flag));
|
|
33
|
-
const isNodePermissionExecFlag = (flag) => NODE_PERMISSION_EXEC_FLAGS.has(execFlagKey(flag));
|
|
34
|
-
export const toWorkerSafeExecArgv = (flags) => {
|
|
35
|
-
if (!flags || flags.length === 0)
|
|
36
|
-
return undefined;
|
|
37
|
-
const filtered = flags.filter(isNodeWorkerSafeExecFlag);
|
|
38
|
-
if (filtered.length === 0)
|
|
39
|
-
return undefined;
|
|
40
|
-
const seen = new Set();
|
|
41
|
-
const deduped = [];
|
|
42
|
-
for (const flag of filtered) {
|
|
43
|
-
if (seen.has(flag))
|
|
44
|
-
continue;
|
|
45
|
-
seen.add(flag);
|
|
46
|
-
deduped.push(flag);
|
|
15
|
+
// `node:url` resolved lazily so this module evaluates on runtimes without it
|
|
16
|
+
// (e.g. Andromeda); process workers aren't used there, so it never runs.
|
|
17
|
+
const fileURLToPathCompat = (value) => {
|
|
18
|
+
const url = getNodeBuiltinModule("node:url");
|
|
19
|
+
if (url === undefined) {
|
|
20
|
+
throw new Error("node:url is not available in this runtime");
|
|
47
21
|
}
|
|
48
|
-
return
|
|
49
|
-
};
|
|
50
|
-
export const toWorkerCompatExecArgv = (flags) => {
|
|
51
|
-
const safe = toWorkerSafeExecArgv(flags);
|
|
52
|
-
if (!safe || safe.length === 0)
|
|
53
|
-
return undefined;
|
|
54
|
-
const compat = safe.filter((flag) => !isNodePermissionExecFlag(flag));
|
|
55
|
-
return compat.length > 0 ? compat : undefined;
|
|
22
|
+
return url.fileURLToPath(value);
|
|
56
23
|
};
|
|
57
24
|
const toProcessSharedMemorySize = (byteLength) => {
|
|
58
25
|
if (!Number.isFinite(byteLength) || byteLength <= 0) {
|
|
@@ -107,10 +74,22 @@ const DENO_PROCESS_WORKER_INTERNAL_FLAGS = [
|
|
|
107
74
|
`--allow-env=${DENO_PROCESS_WORKER_BOOT_ENV_ALLOW}`,
|
|
108
75
|
"--allow-ffi",
|
|
109
76
|
];
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
77
|
+
const parseNodeMajorVersion = (version) => {
|
|
78
|
+
const match = /^v?(\d+)/.exec(String(version).trim());
|
|
79
|
+
if (match === null)
|
|
80
|
+
return undefined;
|
|
81
|
+
const major = Number.parseInt(match[1], 10);
|
|
82
|
+
return Number.isInteger(major) && major > 0 ? major : undefined;
|
|
83
|
+
};
|
|
84
|
+
const nodeProcessWorkerUsesFfi = (nodeMajor) => nodeMajor !== undefined && nodeMajor >= 26 && nodeMajor % 2 === 0;
|
|
85
|
+
const nodeProcessWorkerInternalExecArgv = (nodeMajor) => {
|
|
86
|
+
return [
|
|
87
|
+
"--no-warnings",
|
|
88
|
+
...(nodeProcessWorkerUsesFfi(nodeMajor)
|
|
89
|
+
? ["--experimental-ffi"]
|
|
90
|
+
: ["--experimental-transform-types"]),
|
|
91
|
+
];
|
|
92
|
+
};
|
|
114
93
|
const getProcessWorkerSharedMemoryPrimitives = () => {
|
|
115
94
|
switch (RUNTIME) {
|
|
116
95
|
case "bun":
|
|
@@ -230,49 +209,6 @@ const toProcessWorkerWireLockBuffers = (lock, descriptor) => ({
|
|
|
230
209
|
payload: toChildProcessSharedBufferMetadata(lock.payload, descriptor),
|
|
231
210
|
payloadSector: toChildProcessSharedBufferMetadata(lock.payloadSector, descriptor),
|
|
232
211
|
});
|
|
233
|
-
const isPlainRecord = (value) => {
|
|
234
|
-
if (value === null || typeof value !== "object")
|
|
235
|
-
return false;
|
|
236
|
-
const prototype = Object.getPrototypeOf(value);
|
|
237
|
-
return prototype === Object.prototype || prototype === null;
|
|
238
|
-
};
|
|
239
|
-
const serializeWorkerBootstrapValue = (value, seen = new WeakMap()) => {
|
|
240
|
-
if (value instanceof ProcessSharedBuffer)
|
|
241
|
-
return value.toMetadata();
|
|
242
|
-
if (value === null || typeof value !== "object")
|
|
243
|
-
return value;
|
|
244
|
-
const existing = seen.get(value);
|
|
245
|
-
if (existing !== undefined)
|
|
246
|
-
return existing;
|
|
247
|
-
if (Array.isArray(value)) {
|
|
248
|
-
const out = [];
|
|
249
|
-
seen.set(value, out);
|
|
250
|
-
for (const item of value) {
|
|
251
|
-
out.push(serializeWorkerBootstrapValue(item, seen));
|
|
252
|
-
}
|
|
253
|
-
return out;
|
|
254
|
-
}
|
|
255
|
-
if (!isPlainRecord(value))
|
|
256
|
-
return value;
|
|
257
|
-
const out = {};
|
|
258
|
-
seen.set(value, out);
|
|
259
|
-
for (const [key, item] of Object.entries(value)) {
|
|
260
|
-
out[key] = serializeWorkerBootstrapValue(item, seen);
|
|
261
|
-
}
|
|
262
|
-
return out;
|
|
263
|
-
};
|
|
264
|
-
export const serializeWorkerBootstrapData = (options) => {
|
|
265
|
-
const bootstrap = options.bootstrap;
|
|
266
|
-
if (bootstrap === undefined || bootstrap.data === undefined)
|
|
267
|
-
return options;
|
|
268
|
-
return {
|
|
269
|
-
...options,
|
|
270
|
-
bootstrap: {
|
|
271
|
-
...bootstrap,
|
|
272
|
-
data: serializeWorkerBootstrapValue(bootstrap.data),
|
|
273
|
-
},
|
|
274
|
-
};
|
|
275
|
-
};
|
|
276
212
|
export const toProcessWorkerBootPayload = (workerData, memory) => ({
|
|
277
213
|
version: RUNTIME_PROCESS_WORKER_BOOT_VERSION,
|
|
278
214
|
workerData: {
|
|
@@ -393,10 +329,62 @@ const processWorkerNodeBinary = (commandPrefix) => {
|
|
|
393
329
|
: undefined) ??
|
|
394
330
|
DEFAULT_NODE_BINARY;
|
|
395
331
|
};
|
|
396
|
-
const
|
|
332
|
+
const processWorkerNodeMajorCache = new Map();
|
|
333
|
+
const resolveProcessWorkerNodeMajor = (commandPrefix) => {
|
|
334
|
+
const nodeProcess = getNodeProcess();
|
|
335
|
+
if (commandPrefix === undefined &&
|
|
336
|
+
nodeProcess !== undefined &&
|
|
337
|
+
nodeProcess?.env?.NODE_BINARY === undefined &&
|
|
338
|
+
RUNTIME === "node") {
|
|
339
|
+
return parseNodeMajorVersion(nodeProcess.versions?.node);
|
|
340
|
+
}
|
|
341
|
+
const nodeBinary = processWorkerNodeBinary(commandPrefix);
|
|
342
|
+
const cacheKey = JSON.stringify([commandPrefix ?? null, nodeBinary]);
|
|
343
|
+
if (processWorkerNodeMajorCache.has(cacheKey)) {
|
|
344
|
+
return processWorkerNodeMajorCache.get(cacheKey);
|
|
345
|
+
}
|
|
346
|
+
let major;
|
|
347
|
+
try {
|
|
348
|
+
const childProcess = getNodeBuiltinModule("node:child_process");
|
|
349
|
+
if (typeof childProcess?.spawnSync === "function") {
|
|
350
|
+
const command = commandPrefix?.[0] ?? nodeBinary;
|
|
351
|
+
const args = commandPrefix === undefined
|
|
352
|
+
? ["--version"]
|
|
353
|
+
: [...commandPrefix.slice(1), nodeBinary, "--version"];
|
|
354
|
+
const probe = childProcess.spawnSync(command, args, {
|
|
355
|
+
encoding: "utf8",
|
|
356
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
357
|
+
timeout: 2_000,
|
|
358
|
+
windowsHide: true,
|
|
359
|
+
});
|
|
360
|
+
if (probe.status === 0) {
|
|
361
|
+
major = parseNodeMajorVersion(probe.stdout);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
// Unknown targets conservatively use the Node 22/24 addon transport.
|
|
367
|
+
}
|
|
368
|
+
processWorkerNodeMajorCache.set(cacheKey, major);
|
|
369
|
+
return major;
|
|
370
|
+
};
|
|
371
|
+
export const readProcessWorkerNodeMajor = (options) => resolveProcessWorkerNodeMajor(readProcessWorkerCommandPrefix(options));
|
|
372
|
+
const nodeProcessWorkerFlagIsSupported = (flag, nodeMajor) => {
|
|
373
|
+
const key = flag.split("=", 1)[0];
|
|
374
|
+
if (key === "--experimental-ffi" || key === "--allow-ffi") {
|
|
375
|
+
return nodeProcessWorkerUsesFfi(nodeMajor);
|
|
376
|
+
}
|
|
377
|
+
if (key === "--allow-net") {
|
|
378
|
+
return nodeMajor !== undefined && nodeMajor >= 25;
|
|
379
|
+
}
|
|
380
|
+
return true;
|
|
381
|
+
};
|
|
382
|
+
const processWorkerNodeExecArgv = (permission, nodeMajor) => {
|
|
397
383
|
const out = [];
|
|
398
384
|
const seen = new Set();
|
|
399
385
|
const add = (flag) => {
|
|
386
|
+
if (!nodeProcessWorkerFlagIsSupported(flag, nodeMajor))
|
|
387
|
+
return;
|
|
400
388
|
if (seen.has(flag))
|
|
401
389
|
return;
|
|
402
390
|
seen.add(flag);
|
|
@@ -405,8 +393,18 @@ const processWorkerNodeExecArgv = () => {
|
|
|
405
393
|
for (const flag of toWorkerCompatExecArgv(getNodeProcess()?.execArgv) ?? []) {
|
|
406
394
|
add(flag);
|
|
407
395
|
}
|
|
408
|
-
for (const flag of
|
|
396
|
+
for (const flag of nodeProcessWorkerInternalExecArgv(nodeMajor))
|
|
409
397
|
add(flag);
|
|
398
|
+
if (permission?.enabled === true && permission.unsafe !== true) {
|
|
399
|
+
for (const flag of permission.node.flags)
|
|
400
|
+
add(flag);
|
|
401
|
+
if (permission.netAll && nodeMajor !== undefined && nodeMajor >= 25) {
|
|
402
|
+
add("--allow-net");
|
|
403
|
+
}
|
|
404
|
+
// Node process workers need one native transport capability regardless of
|
|
405
|
+
// task permissions: addons on Node 22/24, node:ffi on supported Node 26+ LTS.
|
|
406
|
+
add(nodeProcessWorkerUsesFfi(nodeMajor) ? "--allow-ffi" : "--allow-addons");
|
|
407
|
+
}
|
|
410
408
|
return out;
|
|
411
409
|
};
|
|
412
410
|
const processWorkerCommand = ({ processRuntime, workerUrl, bun, deno, commandPrefix, permission, }) => {
|
|
@@ -421,9 +419,10 @@ const processWorkerCommand = ({ processRuntime, workerUrl, bun, deno, commandPre
|
|
|
421
419
|
];
|
|
422
420
|
}
|
|
423
421
|
else if (processRuntime === "node") {
|
|
422
|
+
const nodeMajor = resolveProcessWorkerNodeMajor(commandPrefix);
|
|
424
423
|
command = [
|
|
425
424
|
processWorkerNodeBinary(commandPrefix),
|
|
426
|
-
...processWorkerNodeExecArgv(),
|
|
425
|
+
...processWorkerNodeExecArgv(permission, nodeMajor),
|
|
427
426
|
workerPath,
|
|
428
427
|
];
|
|
429
428
|
}
|
|
@@ -654,20 +653,17 @@ export const spawnProcessWorker = (options) => {
|
|
|
654
653
|
throw new Error("process worker runtime is only available in Node, Deno, or Bun");
|
|
655
654
|
}
|
|
656
655
|
};
|
|
657
|
-
export const terminateWorkerQuietly = (worker) => {
|
|
658
|
-
try {
|
|
659
|
-
// Runaway worker termination can be slow or stuck on some runtimes; once the
|
|
660
|
-
// pool is closing it must not keep the host process alive.
|
|
661
|
-
worker.unref?.();
|
|
662
|
-
void Promise.resolve(worker.terminate()).catch(() => { });
|
|
663
|
-
}
|
|
664
|
-
catch {
|
|
665
|
-
}
|
|
666
|
-
};
|
|
667
656
|
export const cleanupProcessWorkerMemoryQuietly = (memory) => {
|
|
668
657
|
try {
|
|
669
658
|
memory?.cleanup();
|
|
670
659
|
}
|
|
671
660
|
catch {
|
|
672
661
|
}
|
|
662
|
+
finally {
|
|
663
|
+
try {
|
|
664
|
+
memory?.mapping.close?.();
|
|
665
|
+
}
|
|
666
|
+
catch {
|
|
667
|
+
}
|
|
668
|
+
}
|
|
673
669
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import "../memory/payloadCodec.js";
|
|
1
2
|
import { type Lock2, type Task } from "../memory/lock.js";
|
|
2
3
|
import type { AbortSignalOption, TaskTimeout } from "../types.js";
|
|
3
4
|
import { type SignalAbortStore } from "../shared/abortSignal.js";
|
|
5
|
+
import { type BufferReferenceReturnHooks } from "../connections/buffer-reference.js";
|
|
4
6
|
type RawArguments = unknown;
|
|
5
7
|
type FunctionID = number;
|
|
6
8
|
type QueueTask = Task;
|
|
@@ -9,15 +11,29 @@ type CreateHostTxQueueArgs = {
|
|
|
9
11
|
max?: number;
|
|
10
12
|
lock: Lock2;
|
|
11
13
|
returnLock: Lock2;
|
|
12
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Extra return locks to drain into the same pending registry.
|
|
16
|
+
*
|
|
17
|
+
* Under work stealing the host publishes into one shared submit lock and any
|
|
18
|
+
* worker may claim the task, so the response comes back on whichever lane
|
|
19
|
+
* executed it. Task IDs index this queue's `queue` array, which is
|
|
20
|
+
* pool-global, so every lane's `resolveHost` can settle into it — the
|
|
21
|
+
* stealing worker owns the response and the host demultiplexes by ID.
|
|
22
|
+
*
|
|
23
|
+
* When omitted, only `returnLock` is drained (the classic one-lane shape).
|
|
24
|
+
*/
|
|
25
|
+
extraReturnLocks?: readonly Lock2[];
|
|
26
|
+
releaseBufferReferenceReturn?: ((token: bigint) => void) | BufferReferenceReturnHooks;
|
|
13
27
|
abortSignals?: Pick<SignalAbortStore, "getSignal" | "setSignal" | "resetSignal" | "closeNow">;
|
|
14
28
|
now?: () => number;
|
|
15
29
|
};
|
|
16
|
-
|
|
30
|
+
type ReturnHooks = ((token: bigint) => void) | BufferReferenceReturnHooks;
|
|
31
|
+
export declare function createHostTxQueue({ max, lock, returnLock, extraReturnLocks, releaseBufferReferenceReturn, abortSignals, now, }: CreateHostTxQueueArgs): {
|
|
17
32
|
rejectAll: (reason: string) => void;
|
|
18
33
|
hasPendingFrames: () => boolean;
|
|
19
34
|
txIdle: () => boolean;
|
|
20
35
|
completeFrame: () => number;
|
|
36
|
+
setReturnHooks: (lane: number, hooks: ReturnHooks | undefined) => void;
|
|
21
37
|
enqueue: (functionID: FunctionID, timeout?: TaskTimeout, abortSignal?: AbortSignalOption) => (rawArgs: RawArguments) => Promise<never> | import("../common/with-resolvers.js").PromiseWithMaybeReject<unknown>;
|
|
22
38
|
flushToWorker: () => boolean;
|
|
23
39
|
enqueueKnown: (task: QueueTask) => boolean;
|
package/src/runtime/tx-queue.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
// Side-effect import: registers the payload codec (cycle break for Andromeda;
|
|
2
|
+
// see lock.ts), ensuring registration before any lock2() call.
|
|
3
|
+
import "../memory/payloadCodec.js";
|
|
1
4
|
import { makeTask, resetTaskLocalFlags, runTaskFinalizers, TaskIndex, } from "../memory/lock.js";
|
|
2
5
|
import { withResolvers } from "../common/with-resolvers.js";
|
|
3
6
|
import { AbortSignalPoolExhausted, OneShotDeferred, } from "../shared/abortSignal.js";
|
|
4
|
-
import { withBufferReferenceReturnReleaser } from "../connections/buffer-reference.js";
|
|
7
|
+
import { withBufferReferenceReturnReleaser, } from "../connections/buffer-reference.js";
|
|
5
8
|
const SLOT_INDEX_MASK = 31;
|
|
6
9
|
const SLOT_META_MASK = 0x07ffffff;
|
|
7
10
|
const SLOT_META_SHIFT = 5;
|
|
@@ -11,7 +14,7 @@ const FUNCTION_META_SHIFT = 16;
|
|
|
11
14
|
const ABORT_SIGNAL_META_OFFSET = 1;
|
|
12
15
|
const NO_ABORT_SIGNAL = -1;
|
|
13
16
|
const p_now = performance.now.bind(performance);
|
|
14
|
-
export function createHostTxQueue({ max, lock, returnLock, releaseBufferReferenceReturn, abortSignals, now, }) {
|
|
17
|
+
export function createHostTxQueue({ max, lock, returnLock, extraReturnLocks, releaseBufferReferenceReturn, abortSignals, now, }) {
|
|
15
18
|
const PLACE_HOLDER = (_) => {
|
|
16
19
|
throw ("UNREACHABLE FROM PLACE HOLDER (main)");
|
|
17
20
|
};
|
|
@@ -34,22 +37,53 @@ export function createHostTxQueue({ max, lock, returnLock, releaseBufferReferenc
|
|
|
34
37
|
let inUsed = 0 | 0;
|
|
35
38
|
const resetSignal = abortSignals?.resetSignal;
|
|
36
39
|
const nowTime = now ?? p_now;
|
|
37
|
-
const
|
|
40
|
+
const onReturnResolved = (task) => {
|
|
41
|
+
inUsed = (inUsed - 1) | 0;
|
|
42
|
+
resetTaskLocalFlags(task);
|
|
43
|
+
runTaskFinalizers(task);
|
|
44
|
+
task.value = null;
|
|
45
|
+
task.resolve = PLACE_HOLDER;
|
|
46
|
+
task.reject = PLACE_HOLDER;
|
|
47
|
+
freePush(task[TaskIndex.ID]);
|
|
48
|
+
};
|
|
49
|
+
const returnResolvers = [
|
|
50
|
+
returnLock,
|
|
51
|
+
...(extraReturnLocks ?? []),
|
|
52
|
+
].map((each) => each.resolveHost({
|
|
38
53
|
queue,
|
|
39
54
|
activeRejectPlaceholder: PLACE_HOLDER,
|
|
40
|
-
onResolved:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
55
|
+
onResolved: onReturnResolved,
|
|
56
|
+
}));
|
|
57
|
+
// A stealing queue drains one private return lock per worker. Borrowed
|
|
58
|
+
// BufferReferences must therefore be claimed with the hooks belonging to the
|
|
59
|
+
// worker that produced that particular return. The hooks are bound after the
|
|
60
|
+
// worker context exists, while the pool-global queue is built before workers
|
|
61
|
+
// spawn, so keep one mutable hook slot per return lane.
|
|
62
|
+
const returnHooks = new Array(returnResolvers.length);
|
|
63
|
+
if (releaseBufferReferenceReturn !== undefined) {
|
|
64
|
+
returnHooks[0] = releaseBufferReferenceReturn;
|
|
65
|
+
}
|
|
66
|
+
const resolveReturnAt = (index) => {
|
|
67
|
+
const resolve = returnResolvers[index];
|
|
68
|
+
const hooks = returnHooks[index];
|
|
69
|
+
return hooks === undefined
|
|
70
|
+
? resolve()
|
|
71
|
+
: withBufferReferenceReturnReleaser(hooks, resolve);
|
|
72
|
+
};
|
|
73
|
+
// Preserve the original one-lane fast path exactly: no wrapper, array lookup,
|
|
74
|
+
// or hook branch is paid by the default one-worker transport. Mutable
|
|
75
|
+
// per-return-lane hooks are needed only by a multi-worker stealing queue.
|
|
76
|
+
const completeFrame = returnResolvers.length === 1
|
|
77
|
+
? releaseBufferReferenceReturn === undefined
|
|
78
|
+
? returnResolvers[0]
|
|
79
|
+
: () => withBufferReferenceReturnReleaser(releaseBufferReferenceReturn, returnResolvers[0])
|
|
80
|
+
: () => {
|
|
81
|
+
let resolved = 0 | 0;
|
|
82
|
+
for (let i = 0; i < returnResolvers.length; i++) {
|
|
83
|
+
resolved = (resolved + resolveReturnAt(i)) | 0;
|
|
84
|
+
}
|
|
85
|
+
return resolved;
|
|
86
|
+
};
|
|
53
87
|
const hasActiveTasks = () => {
|
|
54
88
|
const count = (inUsed - getPendingPromiseCount()) | 0;
|
|
55
89
|
return count > 0;
|
|
@@ -82,6 +116,12 @@ export function createHostTxQueue({ max, lock, returnLock, releaseBufferReferenc
|
|
|
82
116
|
hasPendingFrames,
|
|
83
117
|
txIdle,
|
|
84
118
|
completeFrame,
|
|
119
|
+
setReturnHooks: (lane, hooks) => {
|
|
120
|
+
if (!Number.isInteger(lane) || lane < 0 || lane >= returnHooks.length) {
|
|
121
|
+
throw new RangeError(`return lane ${lane} out of range`);
|
|
122
|
+
}
|
|
123
|
+
returnHooks[lane] = hooks;
|
|
124
|
+
},
|
|
85
125
|
enqueue: (functionID, timeout, abortSignal) => {
|
|
86
126
|
const HAS_TIMER = timeout !== undefined;
|
|
87
127
|
const functionIDMasked = functionID & FUNCTION_ID_MASK;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { WorkerSettings } from "../types.js";
|
|
2
|
+
export type SpawnedWorker = {
|
|
3
|
+
terminate: () => unknown;
|
|
4
|
+
unref?: () => unknown;
|
|
5
|
+
postMessage?: (message: unknown) => void;
|
|
6
|
+
};
|
|
7
|
+
export type NodeWorkerLike = {
|
|
8
|
+
on?: (event: "error" | "exit" | "message", listener: (...args: unknown[]) => void) => void;
|
|
9
|
+
};
|
|
10
|
+
export declare const toWorkerSafeExecArgv: (flags: string[] | undefined) => string[] | undefined;
|
|
11
|
+
export declare const toWorkerCompatExecArgv: (flags: string[] | undefined) => string[] | undefined;
|
|
12
|
+
export declare const serializeWorkerBootstrapData: (options: WorkerSettings) => WorkerSettings;
|
|
13
|
+
export declare const terminateWorkerQuietly: (worker: SpawnedWorker) => void;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Worker helpers shared by every worker mode. Kept out of `process-worker.ts`
|
|
2
|
+
// so the thread and web-worker paths do not pull the process-worker module —
|
|
3
|
+
// and, through it, the whole native connections tree — into their bundles.
|
|
4
|
+
import { ProcessSharedBuffer } from "../connections/process-shared-buffer.js";
|
|
5
|
+
const execFlagKey = (flag) => flag.split("=", 1)[0];
|
|
6
|
+
const NODE_PERMISSION_EXEC_FLAGS = new Set([
|
|
7
|
+
"--permission",
|
|
8
|
+
"--experimental-permission",
|
|
9
|
+
"--allow-fs-read",
|
|
10
|
+
"--allow-fs-write",
|
|
11
|
+
"--allow-worker",
|
|
12
|
+
"--allow-child-process",
|
|
13
|
+
"--allow-net",
|
|
14
|
+
"--allow-addons",
|
|
15
|
+
"--allow-ffi",
|
|
16
|
+
"--allow-wasi",
|
|
17
|
+
]);
|
|
18
|
+
const NODE_WORKER_SAFE_EXEC_FLAGS = new Set([
|
|
19
|
+
"--experimental-ffi",
|
|
20
|
+
"--experimental-transform-types",
|
|
21
|
+
"--expose-gc",
|
|
22
|
+
"--no-warnings",
|
|
23
|
+
...NODE_PERMISSION_EXEC_FLAGS,
|
|
24
|
+
]);
|
|
25
|
+
const isNodeWorkerSafeExecFlag = (flag) => NODE_WORKER_SAFE_EXEC_FLAGS.has(execFlagKey(flag));
|
|
26
|
+
const isNodePermissionExecFlag = (flag) => NODE_PERMISSION_EXEC_FLAGS.has(execFlagKey(flag));
|
|
27
|
+
export const toWorkerSafeExecArgv = (flags) => {
|
|
28
|
+
if (!flags || flags.length === 0)
|
|
29
|
+
return undefined;
|
|
30
|
+
const filtered = flags.filter(isNodeWorkerSafeExecFlag);
|
|
31
|
+
if (filtered.length === 0)
|
|
32
|
+
return undefined;
|
|
33
|
+
const seen = new Set();
|
|
34
|
+
const deduped = [];
|
|
35
|
+
for (const flag of filtered) {
|
|
36
|
+
if (seen.has(flag))
|
|
37
|
+
continue;
|
|
38
|
+
seen.add(flag);
|
|
39
|
+
deduped.push(flag);
|
|
40
|
+
}
|
|
41
|
+
return deduped;
|
|
42
|
+
};
|
|
43
|
+
export const toWorkerCompatExecArgv = (flags) => {
|
|
44
|
+
const safe = toWorkerSafeExecArgv(flags);
|
|
45
|
+
if (!safe || safe.length === 0)
|
|
46
|
+
return undefined;
|
|
47
|
+
const compat = safe.filter((flag) => !isNodePermissionExecFlag(flag));
|
|
48
|
+
return compat.length > 0 ? compat : undefined;
|
|
49
|
+
};
|
|
50
|
+
const isPlainRecord = (value) => {
|
|
51
|
+
if (value === null || typeof value !== "object")
|
|
52
|
+
return false;
|
|
53
|
+
const prototype = Object.getPrototypeOf(value);
|
|
54
|
+
return prototype === Object.prototype || prototype === null;
|
|
55
|
+
};
|
|
56
|
+
const serializeWorkerBootstrapValue = (value, seen = new WeakMap()) => {
|
|
57
|
+
if (value instanceof ProcessSharedBuffer)
|
|
58
|
+
return value.toMetadata();
|
|
59
|
+
if (value === null || typeof value !== "object")
|
|
60
|
+
return value;
|
|
61
|
+
const existing = seen.get(value);
|
|
62
|
+
if (existing !== undefined)
|
|
63
|
+
return existing;
|
|
64
|
+
if (Array.isArray(value)) {
|
|
65
|
+
const out = [];
|
|
66
|
+
seen.set(value, out);
|
|
67
|
+
for (const item of value) {
|
|
68
|
+
out.push(serializeWorkerBootstrapValue(item, seen));
|
|
69
|
+
}
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
if (!isPlainRecord(value))
|
|
73
|
+
return value;
|
|
74
|
+
const out = {};
|
|
75
|
+
seen.set(value, out);
|
|
76
|
+
for (const [key, item] of Object.entries(value)) {
|
|
77
|
+
out[key] = serializeWorkerBootstrapValue(item, seen);
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
};
|
|
81
|
+
export const serializeWorkerBootstrapData = (options) => {
|
|
82
|
+
const bootstrap = options.bootstrap;
|
|
83
|
+
if (bootstrap === undefined || bootstrap.data === undefined)
|
|
84
|
+
return options;
|
|
85
|
+
return {
|
|
86
|
+
...options,
|
|
87
|
+
bootstrap: {
|
|
88
|
+
...bootstrap,
|
|
89
|
+
data: serializeWorkerBootstrapValue(bootstrap.data),
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
export const terminateWorkerQuietly = (worker) => {
|
|
94
|
+
try {
|
|
95
|
+
// Runaway worker termination can be slow or stuck on some runtimes; once the
|
|
96
|
+
// pool is closing it must not keep the host process alive.
|
|
97
|
+
worker.unref?.();
|
|
98
|
+
void Promise.resolve(worker.terminate()).catch(() => { });
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
}
|
|
102
|
+
};
|
package/src/types.d.ts
CHANGED
|
@@ -34,6 +34,17 @@ type WorkerData = {
|
|
|
34
34
|
payloadConfig?: PayloadBufferOptions;
|
|
35
35
|
bufferReferenceReturn?: "copy" | "borrow";
|
|
36
36
|
permission?: ResolvedPermissionProtocol;
|
|
37
|
+
/**
|
|
38
|
+
* Work stealing. When present, `lock` is a submit region shared by every
|
|
39
|
+
* worker and this worker claims from it as consumer `consumerId` of
|
|
40
|
+
* `consumers`, rather than owning a private request lane. `returnLock` stays
|
|
41
|
+
* private — the endpoint that claims a task owns its response.
|
|
42
|
+
*/
|
|
43
|
+
steal?: {
|
|
44
|
+
consumers: number;
|
|
45
|
+
consumerId: number;
|
|
46
|
+
regionLanes: number;
|
|
47
|
+
};
|
|
37
48
|
};
|
|
38
49
|
type UnsafeOptions = {
|
|
39
50
|
/**
|
|
@@ -83,6 +94,7 @@ type AbortSignalConfig = {
|
|
|
83
94
|
type AbortSignalOption = true | AbortSignalConfig | undefined;
|
|
84
95
|
type AbortSignalMethods<AS extends AbortSignalOption> = AS extends undefined ? never : {
|
|
85
96
|
hasAborted: () => boolean;
|
|
97
|
+
now: () => number;
|
|
86
98
|
};
|
|
87
99
|
type AbortSignalToolkit<AS extends AbortSignalOption> = AbortSignalMethods<AS>;
|
|
88
100
|
type TaskFn<A extends TaskInput, B extends Args, AS extends AbortSignalOption = undefined> = BivariantCallback<AS extends undefined ? [NoBlob<Awaited<A>>] : [NoBlob<Awaited<A>>, AbortSignalToolkit<AS>], MaybePromise<NoBlob<B>>>;
|
|
@@ -220,6 +232,41 @@ type WorkerBootstrapOptions<Data = unknown> = {
|
|
|
220
232
|
*/
|
|
221
233
|
data?: Data;
|
|
222
234
|
};
|
|
235
|
+
/** Native worker artifact and on-demand compiler settings. */
|
|
236
|
+
type CompiledWorkerOptions = {
|
|
237
|
+
/**
|
|
238
|
+
* Native executable path. Relative paths resolve from the createPool caller.
|
|
239
|
+
* Defaults to the task module path with its extension replaced by `.knt`.
|
|
240
|
+
*/
|
|
241
|
+
artifact?: string;
|
|
242
|
+
/**
|
|
243
|
+
* Versioned metadata sidecar. Defaults to `<artifact>.json`.
|
|
244
|
+
*/
|
|
245
|
+
manifest?: string;
|
|
246
|
+
/**
|
|
247
|
+
* Build a missing/incompatible artifact, or use `"always"` to rebuild once
|
|
248
|
+
* whenever a pool is created. Defaults to true.
|
|
249
|
+
*/
|
|
250
|
+
build?: boolean | "always";
|
|
251
|
+
/**
|
|
252
|
+
* Porffor main executable or checkout. Defaults to PORFFOR_MAIN/PORF, then
|
|
253
|
+
* `porf` on PATH; a pinned compiler is cached locally when none is present.
|
|
254
|
+
*/
|
|
255
|
+
compiler?: string;
|
|
256
|
+
};
|
|
257
|
+
type CompiledWorkerSource = string | URL | {
|
|
258
|
+
readonly importedFrom: string;
|
|
259
|
+
};
|
|
260
|
+
type CompiledWorkerCheck = {
|
|
261
|
+
/** True only when the executable and compatible manifest both validate. */
|
|
262
|
+
compiled: boolean;
|
|
263
|
+
artifact: string;
|
|
264
|
+
manifest: string;
|
|
265
|
+
reason?: string;
|
|
266
|
+
compiler?: string;
|
|
267
|
+
protocol?: string;
|
|
268
|
+
tasks?: readonly string[];
|
|
269
|
+
};
|
|
223
270
|
type WorkerSettings = {
|
|
224
271
|
resolveAfterFinishingAll?: true;
|
|
225
272
|
/**
|
|
@@ -230,13 +277,18 @@ type WorkerSettings = {
|
|
|
230
277
|
/**
|
|
231
278
|
* Experimental worker runtime.
|
|
232
279
|
* "thread" uses Worker/worker_threads. "process" spawns another JavaScript
|
|
233
|
-
* runtime, useful for process isolation, bwrap, and containers.
|
|
280
|
+
* runtime, useful for process isolation, bwrap, and containers. "compiled"
|
|
281
|
+
* validates and runs a `.knt` native worker, building it on first use.
|
|
234
282
|
*/
|
|
235
|
-
runtime?: "thread" | "process";
|
|
283
|
+
runtime?: "thread" | "process" | "compiled";
|
|
284
|
+
/** Artifact settings used when runtime is "compiled". */
|
|
285
|
+
compiled?: CompiledWorkerOptions;
|
|
236
286
|
/**
|
|
237
|
-
* Runtime executable
|
|
287
|
+
* Runtime executable for process workers. Standalone `"porffor"` selects the
|
|
288
|
+
* compiled backend and rebuilds once per pool; with `runtime: "compiled"` it
|
|
289
|
+
* reuses the validated artifact.
|
|
238
290
|
*/
|
|
239
|
-
processRuntime?: "bun" | "deno" | "node";
|
|
291
|
+
processRuntime?: "bun" | "deno" | "node" | "porffor";
|
|
240
292
|
/**
|
|
241
293
|
* Command argv to prepend before the process worker runtime command.
|
|
242
294
|
* Useful for wrappers such as systemd-run, cgexec, nice, taskset, or
|
|
@@ -302,11 +354,38 @@ type DispatcherSettings = {
|
|
|
302
354
|
* - `"serial-channel"`: each worker keeps its own dispatcher check state, but
|
|
303
355
|
* one shared channel runs all lane checks from first to last.
|
|
304
356
|
*
|
|
305
|
-
*
|
|
306
|
-
* `"serial-channel"` for multi-worker
|
|
307
|
-
*
|
|
357
|
+
* Used by private-lane pools. Its experimental default is `"per-thread"` on
|
|
358
|
+
* Bun or with one worker, otherwise `"serial-channel"` for multi-worker
|
|
359
|
+
* Node/Deno pools. Selecting it explicitly keeps private lanes unless
|
|
360
|
+
* `steal: true` is also explicit. Can also be forced with the
|
|
361
|
+
* `KNITTING_DISPATCHER` env var (`serial-channel` or `per-thread`).
|
|
308
362
|
*/
|
|
309
363
|
dispatcher?: "per-thread" | "serial-channel";
|
|
364
|
+
/**
|
|
365
|
+
* Work stealing: one shared submit region that any worker may
|
|
366
|
+
* claim from, private return lanes, and a pool-global pending registry. The
|
|
367
|
+
* endpoint that claims a task owns its response.
|
|
368
|
+
*
|
|
369
|
+
* Enabled by default for multi-worker thread pools unless a balancer or
|
|
370
|
+
* private-lane dispatcher was explicitly selected. One-worker pools,
|
|
371
|
+
* inliners, compiled/Porffor workers, process workers, and pools above the
|
|
372
|
+
* current 31-claimant protocol limit retain their existing transport.
|
|
373
|
+
* Explicitly requesting `true` with process workers is rejected because
|
|
374
|
+
* their transport uses separately mapped process-shared memory. Set `false`
|
|
375
|
+
* (or `KNITTING_STEAL=0`) to opt out; `KNITTING_STEAL=1` explicitly opts in
|
|
376
|
+
* and overrides a balancer/dispatcher selection.
|
|
377
|
+
*/
|
|
378
|
+
steal?: boolean;
|
|
379
|
+
/**
|
|
380
|
+
* Lanes claimed per stealing handshake (a power of two, `slots / g >=
|
|
381
|
+
* workers + 1`). Defaults to the widest region the lane budget allows, which
|
|
382
|
+
* amortises arbitration best for cheap tasks.
|
|
383
|
+
*
|
|
384
|
+
* **A region is a batch.** For expensive tasks, a wide region lets one worker
|
|
385
|
+
* claim work the others could have run in parallel; set this to `1` (or a
|
|
386
|
+
* small value) when per-task cost dominates arbitration cost.
|
|
387
|
+
*/
|
|
388
|
+
stealRegionLanes?: number;
|
|
310
389
|
};
|
|
311
390
|
type CreatePool = {
|
|
312
391
|
/** Number of workers. Default: 1. */
|
|
@@ -351,7 +430,8 @@ type CreatePool = {
|
|
|
351
430
|
debug?: DebugOptions;
|
|
352
431
|
source?: string;
|
|
353
432
|
};
|
|
354
|
-
export type { AbortSignalConfig as AbortSignalConfig, AbortSignalMethods as AbortSignalMethods, AbortSignalOption as AbortSignalOption, AbortSignalToolkit as AbortSignalToolkit, Args as Args, Balancer as Balancer, BalancerStrategy as BalancerStrategy, Composed as Composed, ComposedWithKey as ComposedWithKey, CreateContext as CreateContext, CreatePool as CreatePool, DebugNamespace as DebugNamespace, DebugOptions as DebugOptions, DispatcherSettings as DispatcherSettings, Envelope as Envelope, EnvelopeBody as EnvelopeBody, EnvelopeHeader as EnvelopeHeader, External as External, FixPoint as FixPoint, FunctionMapType as FunctionMapType, ImportTaskOptions as ImportTaskOptions, Inliner as Inliner, LockBuffers as LockBuffers, LockBufferTextCompat as LockBufferTextCompat, MaybePromise as MaybePromise, PayloadBufferMode as PayloadBufferMode, PayloadBufferOptions as PayloadBufferOptions, PermissionProtocol as PermissionProtocol, PermissionProtocolInput as PermissionProtocolInput, Pool as Pool, ProcessSharedMemoryMode as ProcessSharedMemoryMode, ProcessSharedMemorySettings as ProcessSharedMemorySettings, ResolvedPermissionProtocol as ResolvedPermissionProtocol, ReturnFixed as ReturnFixed, SecondPart as SecondPart, SharedBufferRegion as SharedBufferRegion, SharedBufferSource as SharedBufferSource, SharedBufferTextCompat as SharedBufferTextCompat, SingleTaskPool as SingleTaskPool, TaskFn as TaskFn, TaskInput as TaskInput, tasks as tasks, TaskTimeout as TaskTimeout, ValidInput as ValidInput, WorkerBootstrapContext as WorkerBootstrapContext, WorkerBootstrapFunction as WorkerBootstrapFunction, WorkerBootstrapOptions as WorkerBootstrapOptions, WorkerCall as WorkerCall, WorkerContext as WorkerContext, WorkerData as WorkerData, WorkerInvoke as WorkerInvoke, WorkerSettings as WorkerSettings, WorkerTimers as WorkerTimers, };
|
|
355
|
-
|
|
433
|
+
export type { AbortSignalConfig as AbortSignalConfig, AbortSignalMethods as AbortSignalMethods, AbortSignalOption as AbortSignalOption, AbortSignalToolkit as AbortSignalToolkit, Args as Args, Balancer as Balancer, BalancerStrategy as BalancerStrategy, CompiledWorkerCheck as CompiledWorkerCheck, CompiledWorkerOptions as CompiledWorkerOptions, CompiledWorkerSource as CompiledWorkerSource, Composed as Composed, ComposedWithKey as ComposedWithKey, CreateContext as CreateContext, CreatePool as CreatePool, DebugNamespace as DebugNamespace, DebugOptions as DebugOptions, DispatcherSettings as DispatcherSettings, Envelope as Envelope, EnvelopeBody as EnvelopeBody, EnvelopeHeader as EnvelopeHeader, External as External, FixPoint as FixPoint, FunctionMapType as FunctionMapType, ImportTaskOptions as ImportTaskOptions, Inliner as Inliner, LockBuffers as LockBuffers, LockBufferTextCompat as LockBufferTextCompat, MaybePromise as MaybePromise, PayloadBufferMode as PayloadBufferMode, PayloadBufferOptions as PayloadBufferOptions, PermissionProtocol as PermissionProtocol, PermissionProtocolInput as PermissionProtocolInput, Pool as Pool, ProcessSharedMemoryMode as ProcessSharedMemoryMode, ProcessSharedMemorySettings as ProcessSharedMemorySettings, ResolvedPermissionProtocol as ResolvedPermissionProtocol, ReturnFixed as ReturnFixed, SecondPart as SecondPart, SharedBufferRegion as SharedBufferRegion, SharedBufferSource as SharedBufferSource, SharedBufferTextCompat as SharedBufferTextCompat, SingleTaskPool as SingleTaskPool, TaskFn as TaskFn, TaskInput as TaskInput, tasks as tasks, TaskTimeout as TaskTimeout, ValidInput as ValidInput, WorkerBootstrapContext as WorkerBootstrapContext, WorkerBootstrapFunction as WorkerBootstrapFunction, WorkerBootstrapOptions as WorkerBootstrapOptions, WorkerCall as WorkerCall, WorkerContext as WorkerContext, WorkerData as WorkerData, WorkerInvoke as WorkerInvoke, WorkerSettings as WorkerSettings, WorkerTimers as WorkerTimers, };
|
|
434
|
+
import type { Task as TaskType } from "./memory/lock.js";
|
|
356
435
|
export { LockBound as LockBound, PayloadBuffer as PayloadBuffer, PayloadSignal as PayloadSignal, TaskIndex as TaskIndex, } from "./memory/lock.js";
|
|
436
|
+
export type Task = TaskType;
|
|
357
437
|
export type { RegisterMalloc as RegisterMalloc } from "./memory/regionRegistry.js";
|