knitting 0.1.55 → 0.1.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +254 -40
- package/knitting.d.ts +7 -797
- package/knitting.js +6 -9780
- package/map.md +31 -15
- package/package.json +20 -6
- package/process-shared-buffer.d.ts +1 -0
- package/process-shared-buffer.js +1 -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/shared-memory.d.ts +1 -155
- package/shared-memory.js +1 -1342
- package/src/api.d.ts +92 -0
- package/src/api.js +798 -0
- package/src/common/envelope.d.ts +17 -0
- package/src/common/envelope.js +22 -0
- package/src/common/module-url.d.ts +2 -0
- package/src/common/module-url.js +52 -0
- package/src/common/node-compat.d.ts +22 -0
- package/src/common/node-compat.js +24 -0
- package/src/common/path-canonical.d.ts +6 -0
- package/src/common/path-canonical.js +55 -0
- package/src/common/runtime.d.ts +16 -0
- package/src/common/runtime.js +105 -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 +5 -0
- package/src/common/task-source.js +100 -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 +42 -0
- package/src/common/worker-runtime.js +70 -0
- package/src/connections/buffer-reference-native.d.ts +56 -0
- package/src/connections/buffer-reference-native.js +241 -0
- package/src/connections/buffer-reference.d.ts +99 -0
- package/src/connections/buffer-reference.js +575 -0
- package/src/connections/bun.d.ts +22 -0
- package/src/connections/bun.js +225 -0
- package/src/connections/deno.d.ts +24 -0
- package/src/connections/deno.js +226 -0
- package/src/connections/external-array-buffer.d.ts +2 -0
- package/src/connections/external-array-buffer.js +33 -0
- package/src/connections/file-descriptor.d.ts +39 -0
- package/src/connections/file-descriptor.js +161 -0
- package/src/connections/index.d.ts +4 -0
- package/src/connections/index.js +4 -0
- package/src/connections/node-addons.d.ts +16 -0
- package/src/connections/node-addons.js +92 -0
- package/src/connections/node-buffer-pointer.d.ts +20 -0
- package/src/connections/node-buffer-pointer.js +16 -0
- 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 +30 -0
- package/src/connections/node.js +62 -0
- package/src/connections/numeric-array.d.ts +5 -0
- package/src/connections/numeric-array.js +17 -0
- package/src/connections/package-assets.d.ts +2 -0
- package/src/connections/package-assets.js +55 -0
- package/src/connections/posix.d.ts +74 -0
- package/src/connections/posix.js +178 -0
- package/src/connections/process-shared-buffer.d.ts +76 -0
- package/src/connections/process-shared-buffer.js +245 -0
- package/src/connections/shared-array-buffer-payload.d.ts +36 -0
- package/src/connections/shared-array-buffer-payload.js +235 -0
- package/src/connections/types.d.ts +54 -0
- package/src/connections/types.js +37 -0
- package/src/connections/windows.d.ts +37 -0
- package/src/connections/windows.js +245 -0
- package/src/debug/env-diff.d.ts +26 -0
- package/src/debug/env-diff.js +49 -0
- package/src/debug/gate.d.ts +18 -0
- package/src/debug/gate.js +69 -0
- package/src/debug/handle.d.ts +23 -0
- package/src/debug/handle.js +48 -0
- package/src/error.d.ts +14 -0
- package/src/error.js +50 -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 +23 -0
- package/src/ipc/transport/shared-memory.js +35 -0
- package/src/memory/byte-carpet.d.ts +73 -0
- package/src/memory/byte-carpet.js +157 -0
- package/src/memory/lock.d.ts +213 -0
- package/src/memory/lock.js +760 -0
- package/src/memory/payload-config.d.ts +31 -0
- package/src/memory/payload-config.js +67 -0
- package/src/memory/payloadCodec.d.ts +55 -0
- package/src/memory/payloadCodec.js +1473 -0
- package/src/memory/regionRegistry.d.ts +17 -0
- package/src/memory/regionRegistry.js +285 -0
- package/src/memory/shared-buffer-io.d.ts +55 -0
- package/src/memory/shared-buffer-io.js +403 -0
- package/src/permission/compatibility.d.ts +28 -0
- package/src/permission/compatibility.js +239 -0
- package/src/permission/index.d.ts +4 -0
- package/src/permission/index.js +3 -0
- package/src/permission/protocol.d.ts +167 -0
- package/src/permission/protocol.js +690 -0
- package/src/runtime/balancer.d.ts +19 -0
- package/src/runtime/balancer.js +149 -0
- 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.d.ts +40 -0
- package/src/runtime/dispatcher.js +142 -0
- package/src/runtime/inline-executor.d.ts +10 -0
- package/src/runtime/inline-executor.js +294 -0
- package/src/runtime/pool.d.ts +44 -0
- package/src/runtime/pool.js +472 -0
- package/src/runtime/process-worker.d.ts +92 -0
- package/src/runtime/process-worker.js +713 -0
- package/src/runtime/tx-queue.d.ts +28 -0
- package/src/runtime/tx-queue.js +158 -0
- package/src/shared/abortSignal.d.ts +23 -0
- package/src/shared/abortSignal.js +134 -0
- package/src/types.d.ts +399 -0
- package/src/types.js +2 -0
- package/src/utils/http.d.ts +29 -0
- package/src/utils/http.js +100 -0
- package/src/worker/bootstrap.d.ts +5 -0
- package/src/worker/bootstrap.js +78 -0
- package/src/worker/composable-runners.d.ts +12 -0
- package/src/worker/composable-runners.js +98 -0
- package/src/worker/loop.d.ts +3 -0
- package/src/worker/loop.js +395 -0
- package/src/worker/process-worker-bootstrap.d.ts +8 -0
- package/src/worker/process-worker-bootstrap.js +160 -0
- package/src/worker/rx-queue.d.ts +25 -0
- package/src/worker/rx-queue.js +173 -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 +28 -0
- package/src/worker/task-loader.js +76 -0
- package/src/worker/timers.d.ts +18 -0
- package/src/worker/timers.js +118 -0
- package/unsafe.d.ts +1 -71
- package/unsafe.js +1 -878
- package/utils.d.ts +1 -31
- package/utils.js +1 -116
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { BufferReference } from "../connections/buffer-reference.js";
|
|
2
|
+
import type { ProcessSharedBuffer } from "../connections/process-shared-buffer.js";
|
|
3
|
+
type EnvelopeHeaderPrimitive = string | number | boolean | null;
|
|
4
|
+
type EnvelopeHeaderValue = EnvelopeHeaderPrimitive | EnvelopeHeaderValue[] | {
|
|
5
|
+
[key: string]: EnvelopeHeaderValue;
|
|
6
|
+
};
|
|
7
|
+
export type EnvelopeHeader = EnvelopeHeaderValue;
|
|
8
|
+
export type EnvelopeBody = ArrayBuffer | SharedArrayBuffer | BufferReference | ProcessSharedBuffer;
|
|
9
|
+
declare const PayloadTransportFinalizer: unique symbol;
|
|
10
|
+
export declare class Envelope<H extends EnvelopeHeader = EnvelopeHeader, B extends EnvelopeBody = ArrayBuffer> {
|
|
11
|
+
readonly header: H;
|
|
12
|
+
readonly payload: B;
|
|
13
|
+
constructor(header: H, payload: B);
|
|
14
|
+
[Symbol.dispose](): void;
|
|
15
|
+
[PayloadTransportFinalizer](): (() => void) | undefined;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const PayloadTransportFinalizer = Symbol.for("knitting.payloadCodec.transportFinalizer");
|
|
2
|
+
export class Envelope {
|
|
3
|
+
header;
|
|
4
|
+
payload;
|
|
5
|
+
constructor(header, payload) {
|
|
6
|
+
this.header = header;
|
|
7
|
+
this.payload = payload;
|
|
8
|
+
}
|
|
9
|
+
[Symbol.dispose]() {
|
|
10
|
+
const body = this.payload;
|
|
11
|
+
if (body !== null && typeof body === "object") {
|
|
12
|
+
body[Symbol.dispose]?.();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
[PayloadTransportFinalizer]() {
|
|
16
|
+
const body = this.payload;
|
|
17
|
+
if (body === null || typeof body !== "object")
|
|
18
|
+
return undefined;
|
|
19
|
+
const finalizer = body[PayloadTransportFinalizer];
|
|
20
|
+
return typeof finalizer === "function" ? finalizer.call(body) : undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { getNodeBuiltinModule } from "./node-compat.js";
|
|
2
|
+
import { IS_ANDROMEDA } from "./runtime.js";
|
|
3
|
+
const WINDOWS_DRIVE_PATH = /^[A-Za-z]:[\\/]/;
|
|
4
|
+
const WINDOWS_UNC_PATH = /^\\\\[^\\/?]+\\[^\\/?]+/;
|
|
5
|
+
const encodeFilePath = (path) => encodeURI(path)
|
|
6
|
+
.replace(/\?/g, "%3F")
|
|
7
|
+
.replace(/#/g, "%23");
|
|
8
|
+
// `node:url` resolved lazily (absent on Andromeda); fall back to a pure
|
|
9
|
+
// path->file-URL conversion when it is missing.
|
|
10
|
+
const nodePathToFileURL = () => getNodeBuiltinModule("node:url")
|
|
11
|
+
?.pathToFileURL;
|
|
12
|
+
const pathToFileUrlFallback = (specifier) => {
|
|
13
|
+
const absolute = specifier.startsWith("/") ? specifier : `/${specifier}`;
|
|
14
|
+
return `file://${encodeFilePath(absolute)}`;
|
|
15
|
+
};
|
|
16
|
+
export const toModuleUrl = (specifier) => {
|
|
17
|
+
if (WINDOWS_DRIVE_PATH.test(specifier)) {
|
|
18
|
+
const normalized = specifier.replace(/\\/g, "/");
|
|
19
|
+
return `file:///${encodeFilePath(normalized)}`;
|
|
20
|
+
}
|
|
21
|
+
if (WINDOWS_UNC_PATH.test(specifier)) {
|
|
22
|
+
const normalized = specifier
|
|
23
|
+
.replace(/^\\\\+/, "")
|
|
24
|
+
.replace(/\\/g, "/");
|
|
25
|
+
return `file://${encodeFilePath(normalized)}`;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
return new URL(specifier).href;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
const pathToFileURL = nodePathToFileURL();
|
|
32
|
+
return pathToFileURL
|
|
33
|
+
? pathToFileURL(specifier).href
|
|
34
|
+
: pathToFileUrlFallback(specifier);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
// Andromeda's loader treats `file://` import specifiers as relative paths;
|
|
38
|
+
// convert back to a plain filesystem path there. No-op elsewhere.
|
|
39
|
+
export const toImportSpecifier = (moduleUrl) => {
|
|
40
|
+
if (!IS_ANDROMEDA || !moduleUrl.startsWith("file://"))
|
|
41
|
+
return moduleUrl;
|
|
42
|
+
const withoutScheme = moduleUrl.slice("file://".length);
|
|
43
|
+
const path = withoutScheme.startsWith("/")
|
|
44
|
+
? withoutScheme
|
|
45
|
+
: `/${withoutScheme}`;
|
|
46
|
+
try {
|
|
47
|
+
return decodeURIComponent(path);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return path;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type NodeProcessLike = {
|
|
2
|
+
getBuiltinModule?: (id: string) => unknown;
|
|
3
|
+
versions?: {
|
|
4
|
+
modules?: string;
|
|
5
|
+
node?: string;
|
|
6
|
+
};
|
|
7
|
+
pid?: number;
|
|
8
|
+
platform?: string;
|
|
9
|
+
allowedNodeEnvironmentFlags?: ReadonlySet<string>;
|
|
10
|
+
execArgv?: string[];
|
|
11
|
+
execPath?: string;
|
|
12
|
+
cwd?: () => string;
|
|
13
|
+
env?: Record<string, string | undefined>;
|
|
14
|
+
on?: (event: string, handler: (...args: unknown[]) => void) => unknown;
|
|
15
|
+
};
|
|
16
|
+
export type NodeCallSiteLike = {
|
|
17
|
+
getFileName?: () => string | null | undefined;
|
|
18
|
+
getFunctionName?: () => string | null | undefined;
|
|
19
|
+
getMethodName?: () => string | null | undefined;
|
|
20
|
+
};
|
|
21
|
+
export declare const getNodeProcess: () => NodeProcessLike | undefined;
|
|
22
|
+
export declare const getNodeBuiltinModule: <T>(specifier: string) => T | undefined;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const nodeProcess = (() => {
|
|
2
|
+
const candidate = globalThis
|
|
3
|
+
.process;
|
|
4
|
+
return typeof candidate?.versions?.node === "string" ? candidate : undefined;
|
|
5
|
+
})();
|
|
6
|
+
export const getNodeProcess = () => nodeProcess;
|
|
7
|
+
export const getNodeBuiltinModule = (specifier) => {
|
|
8
|
+
const getter = nodeProcess?.getBuiltinModule;
|
|
9
|
+
if (typeof getter !== "function")
|
|
10
|
+
return undefined;
|
|
11
|
+
try {
|
|
12
|
+
return getter.call(nodeProcess, specifier);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
}
|
|
16
|
+
if (!specifier.startsWith("node:"))
|
|
17
|
+
return undefined;
|
|
18
|
+
try {
|
|
19
|
+
return getter.call(nodeProcess, specifier.slice(5));
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { getNodeBuiltinModule } from "./node-compat.js";
|
|
2
|
+
const nodeFs = () => getNodeBuiltinModule("node:fs");
|
|
3
|
+
const nodePath = () => {
|
|
4
|
+
const module = getNodeBuiltinModule("node:path");
|
|
5
|
+
if (module === undefined) {
|
|
6
|
+
throw new Error("node:path is not available in this runtime");
|
|
7
|
+
}
|
|
8
|
+
return module;
|
|
9
|
+
};
|
|
10
|
+
const defaultFsApi = () => {
|
|
11
|
+
const fs = nodeFs();
|
|
12
|
+
if (fs === undefined)
|
|
13
|
+
return {};
|
|
14
|
+
return {
|
|
15
|
+
existsSync: fs.existsSync,
|
|
16
|
+
realpathSync: fs.realpathSync.native ?? fs.realpathSync,
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export const toCanonicalPath = (candidate, fsApi = defaultFsApi()) => {
|
|
20
|
+
const { basename: pathBasename, dirname: pathDirname, join: pathJoin, resolve: pathResolve, } = nodePath();
|
|
21
|
+
const absolute = pathResolve(candidate);
|
|
22
|
+
const { existsSync, realpathSync } = fsApi;
|
|
23
|
+
if (typeof realpathSync === "function") {
|
|
24
|
+
try {
|
|
25
|
+
return pathResolve(realpathSync(absolute));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
return absolute;
|
|
32
|
+
}
|
|
33
|
+
if (typeof existsSync !== "function")
|
|
34
|
+
return absolute;
|
|
35
|
+
const missingSegments = [];
|
|
36
|
+
let cursor = absolute;
|
|
37
|
+
while (!existsSync(cursor)) {
|
|
38
|
+
const parent = pathDirname(cursor);
|
|
39
|
+
if (parent === cursor)
|
|
40
|
+
return absolute;
|
|
41
|
+
missingSegments.push(pathBasename(cursor));
|
|
42
|
+
cursor = parent;
|
|
43
|
+
}
|
|
44
|
+
let base = cursor;
|
|
45
|
+
try {
|
|
46
|
+
base = realpathSync(cursor);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
}
|
|
50
|
+
let rebuilt = base;
|
|
51
|
+
for (let i = missingSegments.length - 1; i >= 0; i--) {
|
|
52
|
+
rebuilt = pathJoin(rebuilt, missingSegments[i]);
|
|
53
|
+
}
|
|
54
|
+
return pathResolve(rebuilt);
|
|
55
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type RuntimeName = "deno" | "bun" | "node" | "andromeda" | "unknown";
|
|
2
|
+
export declare const IS_DENO: boolean;
|
|
3
|
+
export declare const IS_BUN: boolean;
|
|
4
|
+
export declare const IS_NODE: boolean;
|
|
5
|
+
export declare const IS_ANDROMEDA: boolean;
|
|
6
|
+
export declare const RUNTIME: RuntimeName;
|
|
7
|
+
export declare const SET_IMMEDIATE: typeof setImmediate & ((cb: () => void) => void);
|
|
8
|
+
export declare const HAS_SHARED_WASM_MEMORY: boolean;
|
|
9
|
+
export declare const createWasmSharedArrayBuffer: (byteLength: number, maxByteLength?: number) => SharedArrayBuffer;
|
|
10
|
+
export declare const HAS_SAB_GROW: boolean;
|
|
11
|
+
export declare const createSharedArrayBuffer: (byteLength: number, maxByteLength?: number) => SharedArrayBuffer;
|
|
12
|
+
export declare const isWasmSharedArrayBuffer: (sab: SharedArrayBuffer) => boolean;
|
|
13
|
+
export declare const isGrowableSharedArrayBuffer: (sab: SharedArrayBuffer) => boolean;
|
|
14
|
+
export declare const sharedArrayBufferMaxByteLength: (sab: SharedArrayBuffer) => number;
|
|
15
|
+
export declare const growSharedArrayBuffer: (sab: SharedArrayBuffer, byteLength: number) => SharedArrayBuffer;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { getNodeProcess } from "./node-compat.js";
|
|
2
|
+
const globals = globalThis;
|
|
3
|
+
const nodeProcess = getNodeProcess();
|
|
4
|
+
export const IS_DENO = typeof globals.Deno?.version?.deno === "string";
|
|
5
|
+
export const IS_BUN = typeof globals.Bun?.version === "string";
|
|
6
|
+
export const IS_NODE = typeof nodeProcess?.versions?.node === "string";
|
|
7
|
+
// Andromeda (Nova engine): no `node:` builtins or `WebAssembly`; detect via
|
|
8
|
+
// its private bootstrap global.
|
|
9
|
+
export const IS_ANDROMEDA = typeof globals.__andromeda__ !== "undefined";
|
|
10
|
+
export const RUNTIME = (IS_DENO
|
|
11
|
+
? "deno"
|
|
12
|
+
: IS_BUN
|
|
13
|
+
? "bun"
|
|
14
|
+
: IS_NODE
|
|
15
|
+
? "node"
|
|
16
|
+
: IS_ANDROMEDA
|
|
17
|
+
? "andromeda"
|
|
18
|
+
: "unknown");
|
|
19
|
+
// `WebAssembly` may be undeclared (not just undefined) on Andromeda, where a
|
|
20
|
+
// bare reference throws; capture it through `globalThis` so access is safe.
|
|
21
|
+
const WebAssemblyRef = globals.WebAssembly;
|
|
22
|
+
export const SET_IMMEDIATE = typeof globals.setImmediate === "function" ? globals.setImmediate : undefined;
|
|
23
|
+
const WASM_MEMORY_PAGE_BYTES = 64 * 1024;
|
|
24
|
+
const wasmSharedBufferMemory = new WeakMap();
|
|
25
|
+
const wasmSharedBufferMaxByteLength = new WeakMap();
|
|
26
|
+
const hasSharedWasmMemory = (() => {
|
|
27
|
+
if (typeof WebAssemblyRef?.Memory !== "function")
|
|
28
|
+
return false;
|
|
29
|
+
try {
|
|
30
|
+
void new WebAssemblyRef.Memory({ initial: 0, maximum: 1, shared: true });
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
})();
|
|
37
|
+
export const HAS_SHARED_WASM_MEMORY = hasSharedWasmMemory;
|
|
38
|
+
const roundupWasmPages = (byteLength) => Math.ceil(Math.max(0, byteLength) / WASM_MEMORY_PAGE_BYTES);
|
|
39
|
+
const createSharedWasmBuffer = (byteLength, maxByteLength) => {
|
|
40
|
+
const memory = new WebAssemblyRef.Memory({
|
|
41
|
+
initial: roundupWasmPages(byteLength),
|
|
42
|
+
maximum: Math.max(roundupWasmPages(byteLength), roundupWasmPages(maxByteLength)),
|
|
43
|
+
shared: true,
|
|
44
|
+
});
|
|
45
|
+
const buffer = memory.buffer;
|
|
46
|
+
wasmSharedBufferMemory.set(buffer, memory);
|
|
47
|
+
wasmSharedBufferMaxByteLength.set(buffer, maxByteLength);
|
|
48
|
+
return buffer;
|
|
49
|
+
};
|
|
50
|
+
export const createWasmSharedArrayBuffer = (byteLength, maxByteLength = byteLength) => {
|
|
51
|
+
if (hasSharedWasmMemory) {
|
|
52
|
+
return createSharedWasmBuffer(byteLength, maxByteLength);
|
|
53
|
+
}
|
|
54
|
+
return new SharedArrayBuffer(byteLength);
|
|
55
|
+
};
|
|
56
|
+
const HAS_NATIVE_SAB_GROW = typeof SharedArrayBuffer === "function" &&
|
|
57
|
+
typeof SharedArrayBuffer.prototype.grow === "function";
|
|
58
|
+
export const HAS_SAB_GROW = HAS_NATIVE_SAB_GROW || hasSharedWasmMemory;
|
|
59
|
+
export const createSharedArrayBuffer = (byteLength, maxByteLength) => {
|
|
60
|
+
if (HAS_NATIVE_SAB_GROW && typeof maxByteLength === "number") {
|
|
61
|
+
return new SharedArrayBuffer(byteLength, { maxByteLength });
|
|
62
|
+
}
|
|
63
|
+
if (hasSharedWasmMemory && typeof maxByteLength === "number") {
|
|
64
|
+
return createSharedWasmBuffer(byteLength, maxByteLength);
|
|
65
|
+
}
|
|
66
|
+
return new SharedArrayBuffer(byteLength);
|
|
67
|
+
};
|
|
68
|
+
export const isWasmSharedArrayBuffer = (sab) => wasmSharedBufferMemory.has(sab);
|
|
69
|
+
export const isGrowableSharedArrayBuffer = (sab) => {
|
|
70
|
+
const value = sab;
|
|
71
|
+
return (HAS_NATIVE_SAB_GROW &&
|
|
72
|
+
typeof value.grow === "function" &&
|
|
73
|
+
value.growable === true) ||
|
|
74
|
+
wasmSharedBufferMemory.has(sab);
|
|
75
|
+
};
|
|
76
|
+
export const sharedArrayBufferMaxByteLength = (sab) => {
|
|
77
|
+
const value = sab;
|
|
78
|
+
if (typeof value.maxByteLength === "number") {
|
|
79
|
+
return value.maxByteLength;
|
|
80
|
+
}
|
|
81
|
+
return wasmSharedBufferMaxByteLength.get(sab) ?? sab.byteLength;
|
|
82
|
+
};
|
|
83
|
+
export const growSharedArrayBuffer = (sab, byteLength) => {
|
|
84
|
+
const native = sab;
|
|
85
|
+
if (typeof native.grow === "function") {
|
|
86
|
+
native.grow(byteLength);
|
|
87
|
+
return sab;
|
|
88
|
+
}
|
|
89
|
+
const memory = wasmSharedBufferMemory.get(sab);
|
|
90
|
+
if (memory == null) {
|
|
91
|
+
throw new TypeError("SharedArrayBuffer is not growable");
|
|
92
|
+
}
|
|
93
|
+
const currentBuffer = memory.buffer;
|
|
94
|
+
if (currentBuffer.byteLength >= byteLength) {
|
|
95
|
+
return currentBuffer;
|
|
96
|
+
}
|
|
97
|
+
const targetPages = roundupWasmPages(byteLength);
|
|
98
|
+
const currentPages = roundupWasmPages(currentBuffer.byteLength);
|
|
99
|
+
memory.grow(targetPages - currentPages);
|
|
100
|
+
const nextBuffer = memory.buffer;
|
|
101
|
+
const maxByteLength = wasmSharedBufferMaxByteLength.get(sab) ?? currentBuffer.byteLength;
|
|
102
|
+
wasmSharedBufferMemory.set(nextBuffer, memory);
|
|
103
|
+
wasmSharedBufferMaxByteLength.set(nextBuffer, maxByteLength);
|
|
104
|
+
return nextBuffer;
|
|
105
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type SharedBuffer = SharedArrayBuffer | ArrayBuffer;
|
|
2
|
+
export type SharedBufferRegion = {
|
|
3
|
+
sab: SharedBuffer;
|
|
4
|
+
byteOffset: number;
|
|
5
|
+
byteLength: number;
|
|
6
|
+
};
|
|
7
|
+
export type SharedBufferSource = SharedBuffer | SharedBufferRegion;
|
|
8
|
+
export declare const isSharedBuffer: (value: unknown) => value is SharedBuffer;
|
|
9
|
+
export declare const isSharedBufferRegion: (value: unknown) => value is SharedBufferRegion;
|
|
10
|
+
export declare const isSharedBufferSource: (value: unknown) => value is SharedBufferSource;
|
|
11
|
+
export declare const toSharedBufferRegion: (value: SharedBufferSource) => SharedBufferRegion;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const isSharedBuffer = (value) => value instanceof SharedArrayBuffer || value instanceof ArrayBuffer;
|
|
2
|
+
export const isSharedBufferRegion = (value) => {
|
|
3
|
+
if (!value || typeof value !== "object")
|
|
4
|
+
return false;
|
|
5
|
+
const candidate = value;
|
|
6
|
+
return isSharedBuffer(candidate.sab) &&
|
|
7
|
+
typeof candidate.byteOffset === "number" &&
|
|
8
|
+
Number.isInteger(candidate.byteOffset) &&
|
|
9
|
+
candidate.byteOffset >= 0 &&
|
|
10
|
+
typeof candidate.byteLength === "number" &&
|
|
11
|
+
Number.isInteger(candidate.byteLength) &&
|
|
12
|
+
candidate.byteLength >= 0;
|
|
13
|
+
};
|
|
14
|
+
export const isSharedBufferSource = (value) => isSharedBuffer(value) || isSharedBufferRegion(value);
|
|
15
|
+
export const toSharedBufferRegion = (value) => isSharedBuffer(value)
|
|
16
|
+
? {
|
|
17
|
+
sab: value,
|
|
18
|
+
byteOffset: 0,
|
|
19
|
+
byteLength: value.byteLength,
|
|
20
|
+
}
|
|
21
|
+
: value;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type SharedBufferSource } from "./shared-buffer-region.js";
|
|
2
|
+
export type SharedBufferTextCompat = {
|
|
3
|
+
encodeInto: boolean;
|
|
4
|
+
decode: boolean;
|
|
5
|
+
};
|
|
6
|
+
export type LockBufferTextCompat = {
|
|
7
|
+
headers: SharedBufferTextCompat;
|
|
8
|
+
payload: SharedBufferTextCompat;
|
|
9
|
+
};
|
|
10
|
+
export declare const isSharedBufferTextCompat: (value: unknown) => value is SharedBufferTextCompat;
|
|
11
|
+
export declare const isLockBufferTextCompat: (value: unknown) => value is LockBufferTextCompat;
|
|
12
|
+
export declare const probeSharedBufferTextCompat: (source: SharedBufferSource) => SharedBufferTextCompat;
|
|
13
|
+
export declare const probeLockBufferTextCompat: ({ headers, payload, }: {
|
|
14
|
+
headers: SharedBufferSource;
|
|
15
|
+
payload: SharedBufferSource;
|
|
16
|
+
}) => LockBufferTextCompat;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { toSharedBufferRegion, } from "./shared-buffer-region.js";
|
|
2
|
+
const textEncode = new TextEncoder();
|
|
3
|
+
const textDecode = new TextDecoder();
|
|
4
|
+
const isSharedBufferTextCompatTypeError = (error) => error instanceof TypeError;
|
|
5
|
+
const makeProbeView = (source) => {
|
|
6
|
+
const region = toSharedBufferRegion(source);
|
|
7
|
+
const probeLength = Math.min(1, region.byteLength);
|
|
8
|
+
return new Uint8Array(region.sab, region.byteOffset, probeLength);
|
|
9
|
+
};
|
|
10
|
+
export const isSharedBufferTextCompat = (value) => {
|
|
11
|
+
if (!value || typeof value !== "object")
|
|
12
|
+
return false;
|
|
13
|
+
const candidate = value;
|
|
14
|
+
return typeof candidate.encodeInto === "boolean" &&
|
|
15
|
+
typeof candidate.decode === "boolean";
|
|
16
|
+
};
|
|
17
|
+
export const isLockBufferTextCompat = (value) => {
|
|
18
|
+
if (!value || typeof value !== "object")
|
|
19
|
+
return false;
|
|
20
|
+
const candidate = value;
|
|
21
|
+
return isSharedBufferTextCompat(candidate.headers) &&
|
|
22
|
+
isSharedBufferTextCompat(candidate.payload);
|
|
23
|
+
};
|
|
24
|
+
export const probeSharedBufferTextCompat = (source) => {
|
|
25
|
+
const view = makeProbeView(source);
|
|
26
|
+
const encodeInto = (() => {
|
|
27
|
+
if (typeof textEncode.encodeInto !== "function")
|
|
28
|
+
return false;
|
|
29
|
+
const probe = view.byteLength > 0 ? view : view.subarray(0, 0);
|
|
30
|
+
const restoredByte = probe.byteLength > 0 ? probe[0] : undefined;
|
|
31
|
+
try {
|
|
32
|
+
textEncode.encodeInto(probe.byteLength > 0 ? "a" : "", probe);
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (!isSharedBufferTextCompatTypeError(error))
|
|
37
|
+
throw error;
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
if (restoredByte !== undefined) {
|
|
42
|
+
probe[0] = restoredByte;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
})();
|
|
46
|
+
const decode = (() => {
|
|
47
|
+
try {
|
|
48
|
+
textDecode.decode(view);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (!isSharedBufferTextCompatTypeError(error))
|
|
53
|
+
throw error;
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
})();
|
|
57
|
+
return {
|
|
58
|
+
encodeInto,
|
|
59
|
+
decode,
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
export const probeLockBufferTextCompat = ({ headers, payload, }) => ({
|
|
63
|
+
headers: probeSharedBufferTextCompat(headers),
|
|
64
|
+
payload: probeSharedBufferTextCompat(payload),
|
|
65
|
+
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const genTaskID: () => number;
|
|
2
|
+
export declare const setModuleUrl: (url: string | undefined) => void;
|
|
3
|
+
export declare const getModuleUrlOverride: () => string | undefined;
|
|
4
|
+
export declare const getCallerHref: (offset?: number) => string;
|
|
5
|
+
export declare const getCallerFilePath: (offset?: number) => [string, number];
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { toModuleUrl } from "./module-url.js";
|
|
2
|
+
export const genTaskID = ((counter) => () => counter++)(0);
|
|
3
|
+
const INTERNAL_CALLER_HINTS = [
|
|
4
|
+
"/src/common/task-source.ts",
|
|
5
|
+
"/src/common/task-source.js",
|
|
6
|
+
"\\src\\common\\task-source.ts",
|
|
7
|
+
"\\src\\common\\task-source.js",
|
|
8
|
+
"/src/api.ts",
|
|
9
|
+
"/src/api.js",
|
|
10
|
+
"\\src\\api.ts",
|
|
11
|
+
"\\src\\api.js",
|
|
12
|
+
];
|
|
13
|
+
const INTERNAL_CALLER_FUNCTIONS = new Set([
|
|
14
|
+
"collectStackFrames",
|
|
15
|
+
"resolveCallerHref",
|
|
16
|
+
"getCallerFilePath",
|
|
17
|
+
"buildTaskDefinition",
|
|
18
|
+
"buildTaskDefinitionFromCaller",
|
|
19
|
+
"task",
|
|
20
|
+
"importTask",
|
|
21
|
+
]);
|
|
22
|
+
const isDefined = (value) => value !== undefined;
|
|
23
|
+
const isInternalCallerFrame = (file) => INTERNAL_CALLER_HINTS.some((hint) => file.includes(hint));
|
|
24
|
+
const isRuntimeInternalFrame = (file) => file.startsWith("node:") ||
|
|
25
|
+
file.startsWith("native:") ||
|
|
26
|
+
file.startsWith("bun:") ||
|
|
27
|
+
file.startsWith("internal/");
|
|
28
|
+
const isInternalCallerFunction = (functionName, methodName) => (functionName !== undefined && INTERNAL_CALLER_FUNCTIONS.has(functionName)) ||
|
|
29
|
+
(methodName !== undefined && INTERNAL_CALLER_FUNCTIONS.has(methodName));
|
|
30
|
+
const collectStackFrames = () => {
|
|
31
|
+
const ErrorCtor = Error;
|
|
32
|
+
const original = ErrorCtor.prepareStackTrace;
|
|
33
|
+
try {
|
|
34
|
+
ErrorCtor.prepareStackTrace = (_error, stack) => stack;
|
|
35
|
+
const stack = new Error().stack;
|
|
36
|
+
if (!Array.isArray(stack))
|
|
37
|
+
return [];
|
|
38
|
+
const frames = stack
|
|
39
|
+
.map((site) => {
|
|
40
|
+
try {
|
|
41
|
+
const file = site?.getFileName?.();
|
|
42
|
+
if (typeof file !== "string" || file.length === 0)
|
|
43
|
+
return undefined;
|
|
44
|
+
return {
|
|
45
|
+
file,
|
|
46
|
+
functionName: site?.getFunctionName?.() ?? undefined,
|
|
47
|
+
methodName: site?.getMethodName?.() ?? undefined,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
.filter(isDefined);
|
|
55
|
+
return frames;
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
ErrorCtor.prepareStackTrace = original;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const isInternalFrame = (frame) => isRuntimeInternalFrame(frame.file) ||
|
|
62
|
+
isInternalCallerFrame(frame.file) ||
|
|
63
|
+
isInternalCallerFunction(frame.functionName, frame.methodName);
|
|
64
|
+
// Module-URL override for runtimes without stack traces (e.g. Andromeda, where
|
|
65
|
+
// `new Error().stack` is undefined). When set, caller discovery skips stack
|
|
66
|
+
// inspection and attributes every task here. Set via
|
|
67
|
+
// `setModuleUrl(import.meta.url)`, which runs in both host and worker copies so
|
|
68
|
+
// both agree on the path.
|
|
69
|
+
let moduleUrlOverride;
|
|
70
|
+
export const setModuleUrl = (url) => {
|
|
71
|
+
moduleUrlOverride = typeof url === "string" && url.length > 0
|
|
72
|
+
? toModuleUrl(url)
|
|
73
|
+
: undefined;
|
|
74
|
+
};
|
|
75
|
+
export const getModuleUrlOverride = () => moduleUrlOverride;
|
|
76
|
+
const resolveCallerHref = (offset) => {
|
|
77
|
+
if (moduleUrlOverride !== undefined)
|
|
78
|
+
return moduleUrlOverride;
|
|
79
|
+
const frames = collectStackFrames();
|
|
80
|
+
const direct = frames[offset];
|
|
81
|
+
const caller = (direct && !isInternalFrame(direct)
|
|
82
|
+
? direct.file
|
|
83
|
+
: undefined) ??
|
|
84
|
+
frames.find((frame) => !isInternalFrame(frame))?.file ??
|
|
85
|
+
frames.find((frame) => !isRuntimeInternalFrame(frame.file))?.file;
|
|
86
|
+
if (!caller) {
|
|
87
|
+
throw new Error("Unable to determine caller file. This runtime exposes no stack traces " +
|
|
88
|
+
"(e.g. Andromeda); call setModuleUrl(import.meta.url) at the top of " +
|
|
89
|
+
"the module that defines your tasks before creating a pool.");
|
|
90
|
+
}
|
|
91
|
+
return toModuleUrl(caller);
|
|
92
|
+
};
|
|
93
|
+
const linkingMap = new Map();
|
|
94
|
+
export const getCallerHref = (offset = 3) => resolveCallerHref(offset);
|
|
95
|
+
export const getCallerFilePath = (offset = 3) => {
|
|
96
|
+
const href = resolveCallerHref(offset);
|
|
97
|
+
const at = linkingMap.get(href) ?? 0;
|
|
98
|
+
linkingMap.set(href, at + 1);
|
|
99
|
+
return [href, at];
|
|
100
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const endpointSymbol: unique symbol;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const endpointSymbol = Symbol.for("task");
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type PromiseWithMaybeReject<T> = Promise<T> & {
|
|
2
|
+
reject: (reason?: unknown) => void;
|
|
3
|
+
};
|
|
4
|
+
export type Deferred<T> = {
|
|
5
|
+
promise: PromiseWithMaybeReject<T>;
|
|
6
|
+
resolve: (value: T | PromiseLike<T>) => void;
|
|
7
|
+
reject: (reason?: unknown) => void;
|
|
8
|
+
};
|
|
9
|
+
export declare const withResolvers: <T = unknown>() => Deferred<T>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const attachReject = (promise, reject) => {
|
|
2
|
+
const deferredPromise = promise;
|
|
3
|
+
deferredPromise.reject = reject;
|
|
4
|
+
return deferredPromise;
|
|
5
|
+
};
|
|
6
|
+
export const withResolvers = () => {
|
|
7
|
+
const native = Promise.withResolvers;
|
|
8
|
+
if (typeof native === "function") {
|
|
9
|
+
const deferred = native.call(Promise);
|
|
10
|
+
return {
|
|
11
|
+
promise: attachReject(deferred.promise, deferred.reject),
|
|
12
|
+
resolve: deferred.resolve,
|
|
13
|
+
reject: deferred.reject,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
let resolve;
|
|
17
|
+
let reject;
|
|
18
|
+
const promise = attachReject(new Promise((res, rej) => {
|
|
19
|
+
resolve = res;
|
|
20
|
+
reject = rej;
|
|
21
|
+
}), reject);
|
|
22
|
+
return { promise, resolve, reject };
|
|
23
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
type RuntimePortMessageHandler = (message: unknown) => void;
|
|
2
|
+
export type RuntimeMessagePortLike = {
|
|
3
|
+
postMessage: (message: unknown) => void;
|
|
4
|
+
close?: () => void;
|
|
5
|
+
start?: () => void;
|
|
6
|
+
on?: (event: string, handler: (...args: unknown[]) => void) => void;
|
|
7
|
+
onmessage?: ((event: {
|
|
8
|
+
data?: unknown;
|
|
9
|
+
}) => void) | null;
|
|
10
|
+
addEventListener?: (type: string, listener: (event: {
|
|
11
|
+
data?: unknown;
|
|
12
|
+
error?: unknown;
|
|
13
|
+
message?: unknown;
|
|
14
|
+
}) => void) => void;
|
|
15
|
+
removeEventListener?: (type: string, listener: (event: {
|
|
16
|
+
data?: unknown;
|
|
17
|
+
error?: unknown;
|
|
18
|
+
message?: unknown;
|
|
19
|
+
}) => void) => void;
|
|
20
|
+
};
|
|
21
|
+
export type RuntimeWorkerLike = RuntimeMessagePortLike & {
|
|
22
|
+
terminate: () => unknown;
|
|
23
|
+
};
|
|
24
|
+
export type RuntimeMessageChannelLike = {
|
|
25
|
+
port1: RuntimeMessagePortLike;
|
|
26
|
+
port2: RuntimeMessagePortLike;
|
|
27
|
+
};
|
|
28
|
+
export declare const RUNTIME_PROCESS_WORKER_ENV = "KNITTING_PROCESS_WORKER";
|
|
29
|
+
export declare const RUNTIME_PROCESS_WORKER_BOOT_ENV = "KNITTING_PROCESS_WORKER_BOOT";
|
|
30
|
+
export declare const RUNTIME_PROCESS_WORKER_BOOT_VERSION = 1;
|
|
31
|
+
export declare const RUNTIME_POOL_DEPTH_ENV = "KNITTING_POOL_DEPTH";
|
|
32
|
+
export declare const RUNTIME_IS_PROCESS_WORKER: boolean;
|
|
33
|
+
export declare const RUNTIME_POOL_DEPTH: number;
|
|
34
|
+
export declare const RUNTIME_WORKER: new (specifier: string | URL, options?: Record<string, unknown>) => RuntimeWorkerLike;
|
|
35
|
+
export declare const RUNTIME_MESSAGE_CHANNEL: new () => RuntimeMessageChannelLike;
|
|
36
|
+
export declare const HAS_NODE_WORKER_THREADS: boolean;
|
|
37
|
+
export declare const RUNTIME_IS_MAIN_THREAD: boolean;
|
|
38
|
+
export declare const RUNTIME_WORKER_DATA: unknown;
|
|
39
|
+
export declare const RUNTIME_PARENT_PORT: RuntimeMessagePortLike;
|
|
40
|
+
export declare const createRuntimeMessageChannel: () => RuntimeMessageChannelLike;
|
|
41
|
+
export declare const addRuntimeDataListener: (target: RuntimeMessagePortLike, handler: RuntimePortMessageHandler) => void;
|
|
42
|
+
export {};
|