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.
- package/LICENSE +202 -0
- package/README.md +632 -0
- package/knitting.d.ts +4 -0
- package/knitting.js +5 -0
- package/map.md +264 -0
- package/package.json +77 -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_shared_memory.node +0 -0
- package/prebuilds/darwin-arm64-node-137/knitting_shm.node +0 -0
- package/prebuilds/darwin-x64-node-127/knitting_shared_memory.node +0 -0
- package/prebuilds/darwin-x64-node-127/knitting_shm.node +0 -0
- package/prebuilds/darwin-x64-node-137/knitting_shared_memory.node +0 -0
- package/prebuilds/darwin-x64-node-137/knitting_shm.node +0 -0
- package/prebuilds/linux-x64-node-127/knitting_shared_memory.node +0 -0
- package/prebuilds/linux-x64-node-127/knitting_shm.node +0 -0
- package/prebuilds/linux-x64-node-137/knitting_shared_memory.node +0 -0
- package/prebuilds/linux-x64-node-137/knitting_shm.node +0 -0
- package/process-shared-buffer.d.ts +1 -0
- package/process-shared-buffer.js +1 -0
- package/scripts/build-native-addons.ts +295 -0
- package/src/api.d.ts +55 -0
- package/src/api.js +384 -0
- package/src/common/envelope.d.ts +11 -0
- package/src/common/envelope.js +8 -0
- package/src/common/module-url.d.ts +1 -0
- package/src/common/module-url.js +24 -0
- package/src/common/node-compat.d.ts +20 -0
- package/src/common/node-compat.js +24 -0
- package/src/common/path-canonical.d.ts +6 -0
- package/src/common/path-canonical.js +41 -0
- package/src/common/runtime.d.ts +15 -0
- package/src/common/runtime.js +91 -0
- package/src/common/shared-buffer-region.d.ts +11 -0
- package/src/common/shared-buffer-region.js +21 -0
- package/src/common/shared-buffer-text.d.ts +16 -0
- package/src/common/shared-buffer-text.js +65 -0
- package/src/common/task-source.d.ts +2 -0
- package/src/common/task-source.js +79 -0
- package/src/common/task-symbol.d.ts +1 -0
- package/src/common/task-symbol.js +1 -0
- package/src/common/with-resolvers.d.ts +9 -0
- package/src/common/with-resolvers.js +23 -0
- package/src/common/worker-runtime.d.ts +40 -0
- package/src/common/worker-runtime.js +52 -0
- package/src/connections/bun.d.ts +20 -0
- package/src/connections/bun.js +159 -0
- package/src/connections/deno.d.ts +20 -0
- package/src/connections/deno.js +150 -0
- package/src/connections/file-descriptor.d.ts +37 -0
- package/src/connections/file-descriptor.js +139 -0
- package/src/connections/index.d.ts +3 -0
- package/src/connections/index.js +3 -0
- package/src/connections/node-addons.d.ts +5 -0
- package/src/connections/node-addons.js +43 -0
- package/src/connections/node.d.ts +29 -0
- package/src/connections/node.js +59 -0
- package/src/connections/posix.d.ts +31 -0
- package/src/connections/posix.js +71 -0
- package/src/connections/process-shared-buffer.d.ts +67 -0
- package/src/connections/process-shared-buffer.js +267 -0
- package/src/connections/types.d.ts +48 -0
- package/src/connections/types.js +37 -0
- package/src/error.d.ts +13 -0
- package/src/error.js +49 -0
- package/src/ipc/tools/ring-queue.d.ts +33 -0
- package/src/ipc/tools/ring-queue.js +159 -0
- package/src/ipc/transport/shared-memory.d.ts +25 -0
- package/src/ipc/transport/shared-memory.js +35 -0
- package/src/knitting_shared_memory.cc +436 -0
- package/src/knitting_shm.cc +476 -0
- package/src/memory/byte-carpet.d.ts +73 -0
- package/src/memory/byte-carpet.js +157 -0
- package/src/memory/lock.d.ts +190 -0
- package/src/memory/lock.js +856 -0
- package/src/memory/payload-config.d.ts +22 -0
- package/src/memory/payload-config.js +67 -0
- package/src/memory/payloadCodec.d.ts +46 -0
- package/src/memory/payloadCodec.js +1157 -0
- package/src/memory/regionRegistry.d.ts +17 -0
- package/src/memory/regionRegistry.js +285 -0
- package/src/memory/shared-buffer-io.d.ts +53 -0
- package/src/memory/shared-buffer-io.js +380 -0
- package/src/permission/index.d.ts +2 -0
- package/src/permission/index.js +2 -0
- package/src/permission/protocol.d.ts +166 -0
- package/src/permission/protocol.js +640 -0
- package/src/runtime/balancer.d.ts +19 -0
- package/src/runtime/balancer.js +149 -0
- package/src/runtime/dispatcher.d.ts +34 -0
- package/src/runtime/dispatcher.js +142 -0
- package/src/runtime/inline-executor.d.ts +10 -0
- package/src/runtime/inline-executor.js +270 -0
- package/src/runtime/pool.d.ts +43 -0
- package/src/runtime/pool.js +922 -0
- package/src/runtime/tx-queue.d.ts +25 -0
- package/src/runtime/tx-queue.js +144 -0
- package/src/shared/abortSignal.d.ts +23 -0
- package/src/shared/abortSignal.js +126 -0
- package/src/types.d.ts +283 -0
- package/src/types.js +2 -0
- package/src/worker/composable-runners.d.ts +12 -0
- package/src/worker/composable-runners.js +105 -0
- package/src/worker/loop.d.ts +2 -0
- package/src/worker/loop.js +453 -0
- package/src/worker/rx-queue.d.ts +22 -0
- package/src/worker/rx-queue.js +124 -0
- package/src/worker/safety/index.d.ts +4 -0
- package/src/worker/safety/index.js +4 -0
- package/src/worker/safety/performance.d.ts +1 -0
- package/src/worker/safety/performance.js +17 -0
- package/src/worker/safety/process.d.ts +2 -0
- package/src/worker/safety/process.js +79 -0
- package/src/worker/safety/startup.d.ts +16 -0
- package/src/worker/safety/startup.js +30 -0
- package/src/worker/safety/worker-data.d.ts +2 -0
- package/src/worker/safety/worker-data.js +36 -0
- package/src/worker/task-loader.d.ts +26 -0
- package/src/worker/task-loader.js +66 -0
- package/src/worker/timers.d.ts +18 -0
- package/src/worker/timers.js +97 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import RingQueue from "../ipc/tools/ring-queue.js";
|
|
2
|
+
import { TaskFlag, TaskIndex, } from "../memory/lock.js";
|
|
3
|
+
import { composeWorkerRunner } from "./composable-runners.js";
|
|
4
|
+
// Create and manage a working queue.
|
|
5
|
+
export const createWorkerRxQueue = ({ listOfFunctions, workerOptions, lock, returnLock, hasAborted, now, }) => {
|
|
6
|
+
const PLACE_HOLDER = (_) => {
|
|
7
|
+
throw ("UNREACHABLE FROM PLACE HOLDER (thread)");
|
|
8
|
+
};
|
|
9
|
+
let hasAnythingFinished = 0;
|
|
10
|
+
let awaiting = 0;
|
|
11
|
+
const jobs = listOfFunctions.reduce((acc, fixed) => (acc.push(fixed.run), acc), []);
|
|
12
|
+
const toWork = new RingQueue();
|
|
13
|
+
const pendingFrames = new RingQueue();
|
|
14
|
+
const toWorkPush = (slot) => toWork.push(slot);
|
|
15
|
+
const toWorkShift = () => toWork.shiftNoClear();
|
|
16
|
+
const pendingShift = () => pendingFrames.shiftNoClear();
|
|
17
|
+
const pendingUnshift = (slot) => pendingFrames.unshift(slot);
|
|
18
|
+
const pendingPush = (slot) => pendingFrames.push(slot);
|
|
19
|
+
const recyclePush = (slot) => lock.recyclecList.push(slot);
|
|
20
|
+
const FUNCTION_ID_MASK = 0xFFFF;
|
|
21
|
+
const IDX_FLAGS = TaskIndex.FlagsToHost;
|
|
22
|
+
const FLAG_REJECT = TaskFlag.Reject;
|
|
23
|
+
const runByIndex = listOfFunctions.reduce((acc, fixed, idx) => {
|
|
24
|
+
const job = jobs[idx];
|
|
25
|
+
acc.push(composeWorkerRunner({
|
|
26
|
+
job,
|
|
27
|
+
timeout: fixed.timeout,
|
|
28
|
+
hasAborted,
|
|
29
|
+
now,
|
|
30
|
+
}));
|
|
31
|
+
return acc;
|
|
32
|
+
}, []);
|
|
33
|
+
const hasCompleted = workerOptions?.resolveAfterFinishingAll === true
|
|
34
|
+
? () => hasAnythingFinished !== 0 && toWork.size === 0
|
|
35
|
+
: () => hasAnythingFinished !== 0;
|
|
36
|
+
const { decode, resolved } = lock;
|
|
37
|
+
const resolvedShift = () => resolved.shiftNoClear();
|
|
38
|
+
const enqueueLock = () => {
|
|
39
|
+
if (!decode())
|
|
40
|
+
return false;
|
|
41
|
+
let task = resolvedShift();
|
|
42
|
+
while (task) {
|
|
43
|
+
task.resolve = PLACE_HOLDER;
|
|
44
|
+
task.reject = PLACE_HOLDER;
|
|
45
|
+
toWorkPush(task);
|
|
46
|
+
task = resolvedShift();
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
};
|
|
50
|
+
const encodeReturnSafe = (slot) => {
|
|
51
|
+
if (!returnLock.encode(slot))
|
|
52
|
+
return false;
|
|
53
|
+
return true;
|
|
54
|
+
};
|
|
55
|
+
const sendReturn = (slot, shouldReject) => {
|
|
56
|
+
slot[IDX_FLAGS] = shouldReject ? FLAG_REJECT : 0;
|
|
57
|
+
if (!encodeReturnSafe(slot))
|
|
58
|
+
return false;
|
|
59
|
+
hasAnythingFinished--;
|
|
60
|
+
recyclePush(slot);
|
|
61
|
+
return true;
|
|
62
|
+
};
|
|
63
|
+
const settleNow = (slot, isError, value, wasAwaited) => {
|
|
64
|
+
slot.value = value;
|
|
65
|
+
hasAnythingFinished++;
|
|
66
|
+
if (wasAwaited && awaiting > 0)
|
|
67
|
+
awaiting--;
|
|
68
|
+
const shouldReject = isError ||
|
|
69
|
+
slot[IDX_FLAGS] === FLAG_REJECT;
|
|
70
|
+
if (!sendReturn(slot, shouldReject))
|
|
71
|
+
pendingPush(slot);
|
|
72
|
+
};
|
|
73
|
+
const writeOne = () => {
|
|
74
|
+
const slot = pendingShift();
|
|
75
|
+
if (!slot)
|
|
76
|
+
return false;
|
|
77
|
+
if (!sendReturn(slot, slot[IDX_FLAGS] === FLAG_REJECT)) {
|
|
78
|
+
pendingUnshift(slot);
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
};
|
|
83
|
+
return {
|
|
84
|
+
hasCompleted,
|
|
85
|
+
hasPending: () => toWork.size !== 0,
|
|
86
|
+
writeBatch: (max) => {
|
|
87
|
+
let wrote = 0;
|
|
88
|
+
while (wrote < max) {
|
|
89
|
+
if (!writeOne())
|
|
90
|
+
break;
|
|
91
|
+
wrote++;
|
|
92
|
+
}
|
|
93
|
+
return wrote;
|
|
94
|
+
},
|
|
95
|
+
serviceBatchImmediate: () => {
|
|
96
|
+
let processed = 0;
|
|
97
|
+
while (processed < 5 && toWork.size !== 0) {
|
|
98
|
+
const slot = toWorkShift();
|
|
99
|
+
try {
|
|
100
|
+
const fnIndex = slot[TaskIndex.FunctionID] & FUNCTION_ID_MASK;
|
|
101
|
+
const result = runByIndex[fnIndex](slot);
|
|
102
|
+
// Slot 0 is reused for response flags; clear request FunctionID value.
|
|
103
|
+
slot[IDX_FLAGS] = 0;
|
|
104
|
+
slot.value = null;
|
|
105
|
+
if (result instanceof Promise) {
|
|
106
|
+
awaiting++;
|
|
107
|
+
result.then((value) => settleNow(slot, false, value, true), (err) => settleNow(slot, true, err, true));
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
settleNow(slot, false, result, false);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
settleNow(slot, true, err, false);
|
|
115
|
+
}
|
|
116
|
+
++processed;
|
|
117
|
+
}
|
|
118
|
+
return processed;
|
|
119
|
+
},
|
|
120
|
+
enqueueLock,
|
|
121
|
+
hasAwaiting: () => awaiting > 0,
|
|
122
|
+
getAwaiting: () => awaiting,
|
|
123
|
+
};
|
|
124
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { installTerminationGuard, installUnhandledRejectionSilencer, } from "./process.js";
|
|
2
|
+
export { installPerformanceNowGuard } from "./performance.js";
|
|
3
|
+
export { scrubWorkerDataSensitiveBuffers } from "./worker-data.js";
|
|
4
|
+
export { assertWorkerSharedMemoryBootData, assertWorkerImportsResolved, } from "./startup.js";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { installTerminationGuard, installUnhandledRejectionSilencer, } from "./process.js";
|
|
2
|
+
export { installPerformanceNowGuard } from "./performance.js";
|
|
3
|
+
export { scrubWorkerDataSensitiveBuffers } from "./worker-data.js";
|
|
4
|
+
export { assertWorkerSharedMemoryBootData, assertWorkerImportsResolved, } from "./startup.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const installPerformanceNowGuard: () => void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const installPerformanceNowGuard = () => {
|
|
2
|
+
const g = globalThis;
|
|
3
|
+
if (g.__knittingPerformanceNowGuardInstalled === true)
|
|
4
|
+
return;
|
|
5
|
+
g.__knittingPerformanceNowGuardInstalled = true;
|
|
6
|
+
const perf = globalThis.performance;
|
|
7
|
+
if (!perf || typeof perf.now !== "function")
|
|
8
|
+
return;
|
|
9
|
+
// Non-intrusive guard: ensure a high-resolution clock exists.
|
|
10
|
+
// Internal timing paths capture a bound `performance.now` reference and
|
|
11
|
+
// do not require freezing global objects.
|
|
12
|
+
try {
|
|
13
|
+
void perf.now();
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { getNodeProcess } from "../../common/node-compat.js";
|
|
2
|
+
const toErrorMessage = (error) => error instanceof Error ? error.message : String(error);
|
|
3
|
+
const failProcessGuardInstall = (target, reason, cause) => {
|
|
4
|
+
const suffix = cause === undefined ? "" : `: ${toErrorMessage(cause)}`;
|
|
5
|
+
throw new Error(`KNT_ERROR_PROCESS_GUARD_INSTALL: ${target} ${reason}${suffix}`);
|
|
6
|
+
};
|
|
7
|
+
export const installTerminationGuard = () => {
|
|
8
|
+
const proc = getNodeProcess();
|
|
9
|
+
if (!proc)
|
|
10
|
+
return;
|
|
11
|
+
if (proc.__knittingTerminationGuard === true)
|
|
12
|
+
return;
|
|
13
|
+
const blocked = (name) => {
|
|
14
|
+
throw new Error(`KNT_ERROR_PROCESS_GUARD: ${name} is disabled in worker tasks`);
|
|
15
|
+
};
|
|
16
|
+
const guardMethod = (name) => {
|
|
17
|
+
try {
|
|
18
|
+
Object.defineProperty(proc, name, {
|
|
19
|
+
configurable: false,
|
|
20
|
+
writable: false,
|
|
21
|
+
value: (..._args) => blocked(`process.${name}`),
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (defineError) {
|
|
25
|
+
try {
|
|
26
|
+
proc[name] = (..._args) => blocked(`process.${name}`);
|
|
27
|
+
}
|
|
28
|
+
catch (assignError) {
|
|
29
|
+
failProcessGuardInstall(`process.${name}`, "install failed", [
|
|
30
|
+
toErrorMessage(defineError),
|
|
31
|
+
toErrorMessage(assignError),
|
|
32
|
+
].join("; "));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (typeof proc[name] !== "function") {
|
|
36
|
+
failProcessGuardInstall(`process.${name}`, "install verification failed");
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
guardMethod("exit");
|
|
40
|
+
guardMethod("kill");
|
|
41
|
+
guardMethod("abort");
|
|
42
|
+
guardMethod("reallyExit");
|
|
43
|
+
const globalScope = globalThis;
|
|
44
|
+
if (globalScope.Deno && typeof globalScope.Deno.exit === "function") {
|
|
45
|
+
try {
|
|
46
|
+
Object.defineProperty(globalScope.Deno, "exit", {
|
|
47
|
+
configurable: false,
|
|
48
|
+
writable: false,
|
|
49
|
+
value: (_code) => blocked("Deno.exit"),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (defineError) {
|
|
53
|
+
try {
|
|
54
|
+
globalScope.Deno.exit = (_code) => blocked("Deno.exit");
|
|
55
|
+
}
|
|
56
|
+
catch (assignError) {
|
|
57
|
+
failProcessGuardInstall("Deno.exit", "install failed", [
|
|
58
|
+
toErrorMessage(defineError),
|
|
59
|
+
toErrorMessage(assignError),
|
|
60
|
+
].join("; "));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (typeof globalScope.Deno.exit !== "function") {
|
|
64
|
+
failProcessGuardInstall("Deno.exit", "install verification failed");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
proc.__knittingTerminationGuard = true;
|
|
68
|
+
};
|
|
69
|
+
export const installUnhandledRejectionSilencer = () => {
|
|
70
|
+
const proc = getNodeProcess();
|
|
71
|
+
if (!proc || typeof proc.on !== "function") {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (proc.__knittingUnhandledRejectionSilencer === true)
|
|
75
|
+
return;
|
|
76
|
+
proc.__knittingUnhandledRejectionSilencer = true;
|
|
77
|
+
// Worker task code may create detached promises; keep workers alive.
|
|
78
|
+
proc.on("unhandledRejection", () => { });
|
|
79
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type SharedBufferSource } from "../../common/shared-buffer-region.js";
|
|
2
|
+
import type { DebugOptions, LockBuffers } from "../../types.js";
|
|
3
|
+
type SharedMemoryBootData = {
|
|
4
|
+
sab: SharedBufferSource | undefined;
|
|
5
|
+
lock: LockBuffers | undefined;
|
|
6
|
+
returnLock: LockBuffers | undefined;
|
|
7
|
+
};
|
|
8
|
+
type ImportedFunctionsState = {
|
|
9
|
+
debug: DebugOptions | undefined;
|
|
10
|
+
list: string[];
|
|
11
|
+
ids: number[];
|
|
12
|
+
listOfFunctions: readonly unknown[];
|
|
13
|
+
};
|
|
14
|
+
export declare const assertWorkerSharedMemoryBootData: ({ sab, lock, returnLock }: SharedMemoryBootData) => void;
|
|
15
|
+
export declare const assertWorkerImportsResolved: ({ debug, list, ids, listOfFunctions }: ImportedFunctionsState) => void;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { isSharedBufferSource, } from "../../common/shared-buffer-region.js";
|
|
2
|
+
import { isLockBufferTextCompat } from "../../common/shared-buffer-text.js";
|
|
3
|
+
const hasLockBuffers = (value) => isSharedBufferSource(value?.headers) &&
|
|
4
|
+
isSharedBufferSource(value?.lockSector) &&
|
|
5
|
+
isSharedBufferSource(value?.payload) &&
|
|
6
|
+
isSharedBufferSource(value?.payloadSector) &&
|
|
7
|
+
(value?.textCompat === undefined ||
|
|
8
|
+
isLockBufferTextCompat(value.textCompat));
|
|
9
|
+
export const assertWorkerSharedMemoryBootData = ({ sab, lock, returnLock }) => {
|
|
10
|
+
if (!isSharedBufferSource(sab)) {
|
|
11
|
+
throw new Error("worker missing transport SAB");
|
|
12
|
+
}
|
|
13
|
+
if (!hasLockBuffers(lock)) {
|
|
14
|
+
throw new Error("worker missing lock SABs");
|
|
15
|
+
}
|
|
16
|
+
if (!hasLockBuffers(returnLock)) {
|
|
17
|
+
throw new Error("worker missing return lock SABs");
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
export const assertWorkerImportsResolved = ({ debug, list, ids, listOfFunctions }) => {
|
|
21
|
+
if (debug?.logImportedUrl === true) {
|
|
22
|
+
console.log(list);
|
|
23
|
+
}
|
|
24
|
+
if (listOfFunctions.length > 0)
|
|
25
|
+
return;
|
|
26
|
+
console.log(list);
|
|
27
|
+
console.log(ids);
|
|
28
|
+
console.log(listOfFunctions);
|
|
29
|
+
throw new Error("No imports were found.");
|
|
30
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const scrubWorkerDataSensitiveBuffers = (value) => {
|
|
2
|
+
const data = value;
|
|
3
|
+
try {
|
|
4
|
+
data.sab = undefined;
|
|
5
|
+
data.lock = undefined;
|
|
6
|
+
data.returnLock = undefined;
|
|
7
|
+
data.permission = undefined;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
delete data.sab;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
delete data.lock;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
delete data.returnLock;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
delete data.permission;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
Object.freeze(data);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
}
|
|
36
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ComposedWithKey } from "../types.js";
|
|
2
|
+
import type { ResolvedPermissionProtocol } from "../permission/protocol.js";
|
|
3
|
+
type GetFunctionParams = {
|
|
4
|
+
list: string[];
|
|
5
|
+
ids: number[];
|
|
6
|
+
at: number[];
|
|
7
|
+
isWorker: boolean;
|
|
8
|
+
permission?: ResolvedPermissionProtocol;
|
|
9
|
+
};
|
|
10
|
+
type WorkerCallable = (args: unknown, abortToolkit?: unknown) => unknown;
|
|
11
|
+
export declare const enum TimeoutKind {
|
|
12
|
+
Reject = 0,
|
|
13
|
+
Resolve = 1
|
|
14
|
+
}
|
|
15
|
+
export type TimeoutSpec = {
|
|
16
|
+
ms: number;
|
|
17
|
+
kind: TimeoutKind;
|
|
18
|
+
value: unknown;
|
|
19
|
+
};
|
|
20
|
+
export type WorkerComposedWithKey = ComposedWithKey & {
|
|
21
|
+
run: WorkerCallable;
|
|
22
|
+
timeout?: TimeoutSpec;
|
|
23
|
+
};
|
|
24
|
+
export declare const getFunctions: ({ list, ids, at, permission }: GetFunctionParams) => Promise<WorkerComposedWithKey[]>;
|
|
25
|
+
export type GetFunctions = ReturnType<typeof getFunctions>;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import { endpointSymbol } from "../common/task-symbol.js";
|
|
10
|
+
import { toModuleUrl } from "../common/module-url.js";
|
|
11
|
+
const normalizeTimeout = (timeout) => {
|
|
12
|
+
if (timeout == null)
|
|
13
|
+
return undefined;
|
|
14
|
+
if (typeof timeout === "number") {
|
|
15
|
+
const ms = Math.floor(timeout);
|
|
16
|
+
return ms >= 0
|
|
17
|
+
? { ms, kind: 0 /* TimeoutKind.Reject */, value: new Error("Task timeout") }
|
|
18
|
+
: undefined;
|
|
19
|
+
}
|
|
20
|
+
const ms = Math.floor(timeout.time);
|
|
21
|
+
if (!(ms >= 0))
|
|
22
|
+
return undefined;
|
|
23
|
+
if ("default" in timeout) {
|
|
24
|
+
return { ms, kind: 1 /* TimeoutKind.Resolve */, value: timeout.default };
|
|
25
|
+
}
|
|
26
|
+
if (timeout.maybe === true) {
|
|
27
|
+
return { ms, kind: 1 /* TimeoutKind.Resolve */, value: undefined };
|
|
28
|
+
}
|
|
29
|
+
if ("error" in timeout) {
|
|
30
|
+
return { ms, kind: 0 /* TimeoutKind.Reject */, value: timeout.error };
|
|
31
|
+
}
|
|
32
|
+
return { ms, kind: 0 /* TimeoutKind.Reject */, value: new Error("Task timeout") };
|
|
33
|
+
};
|
|
34
|
+
const composeWorkerCallable = (fixed, _permission) => {
|
|
35
|
+
return fixed.f;
|
|
36
|
+
};
|
|
37
|
+
export const getFunctions = async ({ list, ids, at, permission }) => {
|
|
38
|
+
const modules = list.map((specifier) => toModuleUrl(specifier));
|
|
39
|
+
const results = await Promise.all(modules.map(async (imports) => {
|
|
40
|
+
const module = (await import(__rewriteRelativeImportExtension(imports)));
|
|
41
|
+
return Object.entries(module)
|
|
42
|
+
.filter(([_, value]) => value != null && typeof value === "object" &&
|
|
43
|
+
//@ts-ignore Reason -> trust me
|
|
44
|
+
value?.[endpointSymbol] === true)
|
|
45
|
+
.map(([name, value]) => ({
|
|
46
|
+
//@ts-ignore Reason -> trust me
|
|
47
|
+
...value,
|
|
48
|
+
name,
|
|
49
|
+
}));
|
|
50
|
+
}));
|
|
51
|
+
// Flatten the results, filter by IDs, and sort
|
|
52
|
+
const flattened = results.flat();
|
|
53
|
+
const useAtFilter = modules.length === 1 && at.length > 0;
|
|
54
|
+
const atSet = useAtFilter ? new Set(at) : null;
|
|
55
|
+
const targetModule = useAtFilter ? modules[0] : null;
|
|
56
|
+
const flattenedResults = flattened
|
|
57
|
+
.filter((obj) => useAtFilter
|
|
58
|
+
? obj.importedFrom === targetModule && atSet.has(obj.at)
|
|
59
|
+
: ids.includes(obj.id))
|
|
60
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
61
|
+
return flattenedResults.map((fixed) => ({
|
|
62
|
+
...fixed,
|
|
63
|
+
run: composeWorkerCallable(fixed, permission),
|
|
64
|
+
timeout: normalizeTimeout(fixed.timeout),
|
|
65
|
+
}));
|
|
66
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type PauseOptions = {
|
|
2
|
+
pauseInNanoseconds?: number;
|
|
3
|
+
};
|
|
4
|
+
export type NativeWaitU32 = (buffer: ArrayBuffer | SharedArrayBuffer, byteOffset: number, expected: number, timeoutMs?: number) => unknown;
|
|
5
|
+
export declare const whilePausing: ({ pauseInNanoseconds }: PauseOptions) => () => void;
|
|
6
|
+
export declare const pauseGeneric: () => void;
|
|
7
|
+
export declare const sleepUntilChanged: ({ at, opView, pauseInNanoseconds, rxStatus, txStatus, enqueueLock, write, nativeWaitU32, useSharedMemoryWait, }: {
|
|
8
|
+
opView: Int32Array;
|
|
9
|
+
rxStatus: Int32Array;
|
|
10
|
+
txStatus: Int32Array;
|
|
11
|
+
pauseInNanoseconds?: number;
|
|
12
|
+
at: number;
|
|
13
|
+
enqueueLock: () => boolean;
|
|
14
|
+
write?: () => number | boolean;
|
|
15
|
+
nativeWaitU32?: NativeWaitU32;
|
|
16
|
+
useSharedMemoryWait?: boolean;
|
|
17
|
+
}) => (value: number, spinMicroseconds: number, parkMs?: number) => void;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
var Comment;
|
|
2
|
+
(function (Comment) {
|
|
3
|
+
Comment[Comment["thisIsAHint"] = 0] = "thisIsAHint";
|
|
4
|
+
})(Comment || (Comment = {}));
|
|
5
|
+
const maybeGc = (() => {
|
|
6
|
+
const host = globalThis;
|
|
7
|
+
const gc = typeof host.gc === "function"
|
|
8
|
+
? (() => host.gc())
|
|
9
|
+
: undefined;
|
|
10
|
+
if (gc) {
|
|
11
|
+
try {
|
|
12
|
+
delete host.gc;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
host.gc = undefined;
|
|
16
|
+
}
|
|
17
|
+
if (host.global) {
|
|
18
|
+
try {
|
|
19
|
+
delete host.global.gc;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
host.global.gc = undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return gc ?? (() => { });
|
|
27
|
+
})();
|
|
28
|
+
const DEFAULT_PAUSE_TIME = 250;
|
|
29
|
+
const a_load = Atomics.load;
|
|
30
|
+
const a_store = Atomics.store;
|
|
31
|
+
const a_wait = typeof Atomics.wait === "function" ? Atomics.wait : undefined;
|
|
32
|
+
const p_now = performance.now.bind(performance);
|
|
33
|
+
const waitFallbackView = a_wait === undefined
|
|
34
|
+
? undefined
|
|
35
|
+
: new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
|
36
|
+
const a_pause = "pause" in Atomics
|
|
37
|
+
? Atomics.pause
|
|
38
|
+
: undefined;
|
|
39
|
+
export const whilePausing = ({ pauseInNanoseconds }) => {
|
|
40
|
+
const forNanoseconds = pauseInNanoseconds ?? DEFAULT_PAUSE_TIME;
|
|
41
|
+
if (!a_pause || forNanoseconds <= 0)
|
|
42
|
+
return () => { };
|
|
43
|
+
return () => a_pause(forNanoseconds);
|
|
44
|
+
};
|
|
45
|
+
export const pauseGeneric = whilePausing({});
|
|
46
|
+
export const sleepUntilChanged = ({ at, opView, pauseInNanoseconds, rxStatus, txStatus, enqueueLock, write, nativeWaitU32, useSharedMemoryWait = true, }) => {
|
|
47
|
+
const pause = pauseInNanoseconds
|
|
48
|
+
!== undefined
|
|
49
|
+
? whilePausing({ pauseInNanoseconds })
|
|
50
|
+
: pauseGeneric;
|
|
51
|
+
const tryProgress = () => {
|
|
52
|
+
let progressed = false;
|
|
53
|
+
if (enqueueLock())
|
|
54
|
+
progressed = true;
|
|
55
|
+
if (write) {
|
|
56
|
+
const wrote = write();
|
|
57
|
+
if (typeof wrote === "number") {
|
|
58
|
+
if (wrote > 0)
|
|
59
|
+
progressed = true;
|
|
60
|
+
}
|
|
61
|
+
else if (wrote === true) {
|
|
62
|
+
progressed = true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return progressed;
|
|
66
|
+
};
|
|
67
|
+
return (value, spinMicroseconds, parkMs) => {
|
|
68
|
+
const until = p_now() + (spinMicroseconds / 1000);
|
|
69
|
+
maybeGc();
|
|
70
|
+
let spinChecks = 0;
|
|
71
|
+
while (true) {
|
|
72
|
+
if (a_load(opView, at) !== value ||
|
|
73
|
+
txStatus[Comment.thisIsAHint] === 1)
|
|
74
|
+
return;
|
|
75
|
+
if (tryProgress())
|
|
76
|
+
return;
|
|
77
|
+
pause();
|
|
78
|
+
if ((spinChecks++ & 63) === 0 && p_now() >= until)
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
if (tryProgress())
|
|
82
|
+
return;
|
|
83
|
+
a_store(rxStatus, 0, 0);
|
|
84
|
+
if (nativeWaitU32 !== undefined) {
|
|
85
|
+
nativeWaitU32(opView.buffer, opView.byteOffset + (at * Int32Array.BYTES_PER_ELEMENT), value >>> 0, parkMs ?? 60);
|
|
86
|
+
}
|
|
87
|
+
else if (useSharedMemoryWait &&
|
|
88
|
+
a_wait &&
|
|
89
|
+
opView.buffer instanceof SharedArrayBuffer) {
|
|
90
|
+
a_wait(opView, at, value, parkMs ?? 60);
|
|
91
|
+
}
|
|
92
|
+
else if (a_wait && waitFallbackView) {
|
|
93
|
+
a_wait(waitFallbackView, 0, 0, parkMs ?? 1);
|
|
94
|
+
}
|
|
95
|
+
a_store(rxStatus, 0, 1);
|
|
96
|
+
};
|
|
97
|
+
};
|