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
package/src/connections/posix.js
CHANGED
|
@@ -14,6 +14,107 @@ export const F_GETFD = 1;
|
|
|
14
14
|
export const F_SETFD = 2;
|
|
15
15
|
export const FD_CLOEXEC = 1;
|
|
16
16
|
export const encodeCString = (value) => new TextEncoder().encode(`${value}\0`);
|
|
17
|
+
// libc exposes errno through a function returning its address: `__error()` on
|
|
18
|
+
// macOS, `__errno_location()` on Linux. FFI callers read the int behind it to
|
|
19
|
+
// turn a bare -1 into something diagnosable.
|
|
20
|
+
export const getErrnoSymbolName = (platform) => platform === "darwin" ? "__error" : "__errno_location";
|
|
21
|
+
// Only the codes shm_open/mmap/ftruncate/dup realistically return; anything
|
|
22
|
+
// else prints as a bare number.
|
|
23
|
+
const ERRNO_NAMES = {
|
|
24
|
+
1: "EPERM",
|
|
25
|
+
2: "ENOENT",
|
|
26
|
+
9: "EBADF",
|
|
27
|
+
12: "ENOMEM",
|
|
28
|
+
13: "EACCES",
|
|
29
|
+
17: "EEXIST",
|
|
30
|
+
22: "EINVAL",
|
|
31
|
+
24: "EMFILE",
|
|
32
|
+
28: "ENOSPC",
|
|
33
|
+
};
|
|
34
|
+
const PLATFORM_ERRNO_NAMES = {
|
|
35
|
+
darwin: { 45: "ENOTSUP", 63: "ENAMETOOLONG" },
|
|
36
|
+
linux: { 36: "ENAMETOOLONG", 95: "ENOTSUP" },
|
|
37
|
+
};
|
|
38
|
+
const isNullPointer = (pointer) => pointer === null || pointer === undefined || pointer === 0 || pointer === 0n;
|
|
39
|
+
/**
|
|
40
|
+
* Wraps a bound `__error`/`__errno_location` into a reader that never throws.
|
|
41
|
+
* Runtimes differ only in how they turn the returned address into an int.
|
|
42
|
+
*/
|
|
43
|
+
export const makeErrnoReader = (locate, readInt32) => {
|
|
44
|
+
if (locate === undefined)
|
|
45
|
+
return () => undefined;
|
|
46
|
+
return () => {
|
|
47
|
+
try {
|
|
48
|
+
const pointer = locate();
|
|
49
|
+
return isNullPointer(pointer) ? undefined : readInt32(pointer);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
const describeErrno = (errno, platform) => {
|
|
57
|
+
if (errno === undefined)
|
|
58
|
+
return "errno unavailable";
|
|
59
|
+
const name = PLATFORM_ERRNO_NAMES[platform][errno] ?? ERRNO_NAMES[errno];
|
|
60
|
+
return name === undefined ? `errno ${errno}` : `${name} (${errno})`;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Builds `<message>: EACCES (13)`, reading errno as late as possible, or the
|
|
64
|
+
* bare message when the runtime has no errno reader.
|
|
65
|
+
*/
|
|
66
|
+
export const posixError = (message, errno, platform = detectPosixPlatform()) => errno === undefined
|
|
67
|
+
? new Error(message)
|
|
68
|
+
: new Error(`${message}: ${describeErrno(errno(), platform)}`);
|
|
69
|
+
export const checkPosixResult = (result, message, errno, platform) => {
|
|
70
|
+
if (result < 0)
|
|
71
|
+
throw posixError(message, errno, platform);
|
|
72
|
+
return result;
|
|
73
|
+
};
|
|
74
|
+
const detectArch = () => globalThis
|
|
75
|
+
.Deno?.build?.arch ??
|
|
76
|
+
globalThis
|
|
77
|
+
.process?.arch ??
|
|
78
|
+
"";
|
|
79
|
+
/**
|
|
80
|
+
* Whether `shm_open`'s mode argument has to be delivered on the stack.
|
|
81
|
+
*
|
|
82
|
+
* macOS declares `shm_open(const char *, int, ...)` variadic and its libc
|
|
83
|
+
* wrapper reads the mode with `va_arg`. Apple's arm64 ABI passes variadic
|
|
84
|
+
* arguments on the stack, not in registers, so the mode a fixed-arity FFI call
|
|
85
|
+
* leaves in a register is never read: the segment is created with whatever the
|
|
86
|
+
* stack happened to hold. The creator's own descriptor still works, so the
|
|
87
|
+
* damage only surfaces when the name is opened again and fails with EACCES —
|
|
88
|
+
* and because the value comes from uninitialized stack, unrelated changes to
|
|
89
|
+
* the calling code can flip it between working and not.
|
|
90
|
+
*
|
|
91
|
+
* Declaring six extra register arguments moves the mode into the first stack
|
|
92
|
+
* slot, which is exactly where `va_arg` looks. Linux (fixed prototype) and
|
|
93
|
+
* x86-64 macOS (variadic arguments in registers) both want the plain form.
|
|
94
|
+
*/
|
|
95
|
+
export const shmOpenModeIsStackPassed = (platform = detectPosixPlatform()) => platform === "darwin" && /arm64|aarch64/.test(detectArch());
|
|
96
|
+
/** Fills x2–x7 so the mode becomes the first stack argument. */
|
|
97
|
+
export const SHM_OPEN_STACK_PAD = [0, 0, 0, 0, 0, 0];
|
|
98
|
+
/**
|
|
99
|
+
* Proves a freshly created macOS segment can be reopened by name, closing the
|
|
100
|
+
* owner descriptor and throwing if it cannot.
|
|
101
|
+
*
|
|
102
|
+
* Without this, a mode that failed to apply produces a confusing EACCES in
|
|
103
|
+
* whichever process later opens the name, far from the call that caused it.
|
|
104
|
+
* No-ops off macOS, where the mode always applies.
|
|
105
|
+
*/
|
|
106
|
+
export const assertNamedSharedMemoryIsReopenable = (platform, ownerFd, reopen, close, errno) => {
|
|
107
|
+
if (platform !== "darwin")
|
|
108
|
+
return;
|
|
109
|
+
const probe = reopen();
|
|
110
|
+
if (probe >= 0) {
|
|
111
|
+
close(probe);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const error = posixError("created shared memory could not be reopened by name", errno, platform);
|
|
115
|
+
close(ownerFd);
|
|
116
|
+
throw error;
|
|
117
|
+
};
|
|
17
118
|
export const setCloseOnExec = (libc, fd) => {
|
|
18
119
|
const flags = libc.symbols.fcntl(fd, F_GETFD, 0);
|
|
19
120
|
if (flags < 0) {
|
|
@@ -71,5 +71,6 @@ export declare class ProcessSharedBuffer {
|
|
|
71
71
|
stringifyMetadata(): string;
|
|
72
72
|
toString(): string;
|
|
73
73
|
}
|
|
74
|
+
export declare const isProcessSharedBufferValue: (value: unknown) => value is ProcessSharedBuffer;
|
|
74
75
|
export declare const parseProcessSharedBufferMetadata: (input: unknown) => ProcessSharedBufferMetadata;
|
|
75
76
|
export {};
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { getNodeBuiltinModule } from "../common/node-compat.js";
|
|
2
1
|
import { FileDescriptor, } from "./file-descriptor.js";
|
|
3
2
|
import { RUNTIME } from "../common/runtime.js";
|
|
4
3
|
import { createBunConnectionPrimitives } from "./bun.js";
|
|
5
4
|
import { createDenoConnectionPrimitives } from "./deno.js";
|
|
6
|
-
import {
|
|
7
|
-
import { expectFd, expectPositiveSize, readCreateMode, readCreateName, readRequiredCreateName, readCreateSize, } from "./types.js";
|
|
5
|
+
import { createNodeConnectionPrimitives } from "./node.js";
|
|
8
6
|
export const PROCESS_SHARED_BUFFER_BRAND = Symbol.for("knitting.processSharedBuffer");
|
|
9
7
|
export const PROCESS_SHARED_BUFFER_NUMERIC_TRANSFER = Symbol.for("knitting.processSharedBuffer.numericTransfer");
|
|
10
8
|
const EXTERNAL_PAYLOAD_BRAND = Symbol.for("knitting.payloadCodec");
|
|
@@ -39,51 +37,15 @@ const decodeKind = (value) => {
|
|
|
39
37
|
}
|
|
40
38
|
};
|
|
41
39
|
let defaultPrimitives;
|
|
42
|
-
const
|
|
43
|
-
const mapping = {
|
|
44
|
-
runtime: "node",
|
|
45
|
-
fd: mapped.fd,
|
|
46
|
-
size: mapped.size,
|
|
47
|
-
byteLength: mapped.sab.byteLength,
|
|
48
|
-
buffer: mapped.sab,
|
|
49
|
-
kind: "shared-array-buffer",
|
|
50
|
-
sab: mapped.sab,
|
|
51
|
-
baseAddressMod64: mapped.baseAddressMod64,
|
|
52
|
-
};
|
|
53
|
-
if (mapped.name !== undefined && mapped.name.length > 0) {
|
|
54
|
-
mapping.name = mapped.name;
|
|
55
|
-
}
|
|
56
|
-
return mapping;
|
|
57
|
-
};
|
|
58
|
-
const createDefaultNodePrimitives = () => {
|
|
59
|
-
const nodeModule = getNodeBuiltinModule("node:module");
|
|
60
|
-
if (nodeModule === undefined) {
|
|
61
|
-
throw new TypeError("ProcessSharedBuffer needs connection primitives in this runtime");
|
|
62
|
-
}
|
|
63
|
-
const require = nodeModule.createRequire(import.meta.url);
|
|
64
|
-
const addon = loadNodeNativeAddon(require, "knitting_shared_memory");
|
|
65
|
-
return {
|
|
66
|
-
createSharedMemory: (options) => {
|
|
67
|
-
const size = expectPositiveSize(readCreateSize(options));
|
|
68
|
-
const mode = readCreateMode(options);
|
|
69
|
-
const name = mode === "anonymous"
|
|
70
|
-
? readCreateName(options, "knitting_shared_memory")
|
|
71
|
-
: readRequiredCreateName(options);
|
|
72
|
-
return fromDefaultNodeNativeMapping(addon.createSharedMemory(size, name, mode));
|
|
73
|
-
},
|
|
74
|
-
mapSharedMemory: (options) => {
|
|
75
|
-
const fd = expectFd(options.fd);
|
|
76
|
-
const size = expectPositiveSize(options.size);
|
|
77
|
-
return fromDefaultNodeNativeMapping(addon.mapSharedMemory(fd, size, options.name));
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
};
|
|
40
|
+
const processSharedBufferInstances = new WeakSet();
|
|
81
41
|
const createDefaultPrimitives = () => {
|
|
82
42
|
if (RUNTIME === "bun")
|
|
83
43
|
return createBunConnectionPrimitives();
|
|
84
44
|
if (RUNTIME === "deno")
|
|
85
45
|
return createDenoConnectionPrimitives();
|
|
86
|
-
|
|
46
|
+
if (RUNTIME === "node")
|
|
47
|
+
return createNodeConnectionPrimitives();
|
|
48
|
+
throw new TypeError("ProcessSharedBuffer needs connection primitives in this runtime");
|
|
87
49
|
};
|
|
88
50
|
export const setDefaultProcessSharedBufferPrimitives = (primitives) => {
|
|
89
51
|
defaultPrimitives = primitives;
|
|
@@ -136,6 +98,7 @@ export class ProcessSharedBuffer {
|
|
|
136
98
|
this.descriptor = descriptor;
|
|
137
99
|
this.byteOffset = byteOffset;
|
|
138
100
|
this.byteLength = byteLength;
|
|
101
|
+
processSharedBufferInstances.add(this);
|
|
139
102
|
}
|
|
140
103
|
static create(options, creator = getDefaultProcessSharedBufferPrimitives()) {
|
|
141
104
|
return ProcessSharedBuffer.fromMapping(creator.createSharedMemory(options));
|
|
@@ -251,6 +214,9 @@ export class ProcessSharedBuffer {
|
|
|
251
214
|
return this.stringify();
|
|
252
215
|
}
|
|
253
216
|
}
|
|
217
|
+
export const isProcessSharedBufferValue = (value) => value !== null &&
|
|
218
|
+
typeof value === "object" &&
|
|
219
|
+
processSharedBufferInstances.has(value);
|
|
254
220
|
export const parseProcessSharedBufferMetadata = (input) => {
|
|
255
221
|
const value = typeof input === "string" ? JSON.parse(input) : input;
|
|
256
222
|
if (!isRecord(value)) {
|
|
@@ -271,8 +237,8 @@ export const parseProcessSharedBufferMetadata = (input) => {
|
|
|
271
237
|
};
|
|
272
238
|
};
|
|
273
239
|
const processSharedBufferGlobal = globalThis;
|
|
274
|
-
const codecs = processSharedBufferGlobal.__KNITTING_PAYLOAD_CODECS__ ??=
|
|
275
|
-
|
|
240
|
+
const codecs = processSharedBufferGlobal.__KNITTING_PAYLOAD_CODECS__ ??= Object
|
|
241
|
+
.create(null);
|
|
276
242
|
codecs[PROCESS_SHARED_BUFFER_CODEC_ID] = {
|
|
277
243
|
decode: (metadata) => ProcessSharedBuffer.fromMetadata(metadata),
|
|
278
244
|
decodeNumeric: (metadata) => ProcessSharedBuffer[PROCESS_SHARED_BUFFER_NUMERIC_TRANSFER](metadata),
|
|
@@ -31,6 +31,10 @@ export type MapSharedMemoryOptions = {
|
|
|
31
31
|
fd: number;
|
|
32
32
|
name?: string;
|
|
33
33
|
size: number;
|
|
34
|
+
/**
|
|
35
|
+
* When false, map the supplied descriptor directly. Ownership transfers to
|
|
36
|
+
* the returned mapping only after mapping succeeds; failures leave it open.
|
|
37
|
+
*/
|
|
34
38
|
duplicateFd?: boolean;
|
|
35
39
|
};
|
|
36
40
|
export type SharedMemoryConnectionPrimitives<Mapping extends SharedMemoryMapping = SharedMemoryMapping> = {
|
|
@@ -1,28 +1,37 @@
|
|
|
1
|
+
import { type NodeFfiLibrary } from "./node-ffi-api.js";
|
|
1
2
|
import { type CreateSharedMemoryOptions, type MapSharedMemoryOptions, type SharedMemoryConnectionPrimitives, type SharedMemoryMapping } from "./types.js";
|
|
3
|
+
declare const WINDOWS_CREATE_SHARED_MEMORY = "knitting_windows_create_shared_memory";
|
|
4
|
+
declare const WINDOWS_MAP_SHARED_MEMORY = "knitting_windows_map_shared_memory";
|
|
5
|
+
declare const WINDOWS_CLOSE_SHARED_MEMORY = "knitting_windows_close_shared_memory";
|
|
6
|
+
type WindowsSharedMemorySymbols = {
|
|
7
|
+
[WINDOWS_CREATE_SHARED_MEMORY]: (size: bigint, name: Uint16Array, mode: number, out: Uint8Array) => number;
|
|
8
|
+
[WINDOWS_MAP_SHARED_MEMORY]: (handle: bigint, size: bigint, name: Uint16Array, out: Uint8Array) => number;
|
|
9
|
+
[WINDOWS_CLOSE_SHARED_MEMORY]: (mapping: Uint8Array) => number;
|
|
10
|
+
};
|
|
2
11
|
type DenoWindowsLibrary = {
|
|
3
|
-
symbols:
|
|
4
|
-
knitting_windows_create_shared_memory: (size: bigint, name: Uint16Array, mode: number, out: Uint8Array) => number;
|
|
5
|
-
knitting_windows_map_shared_memory: (handle: bigint, size: bigint, name: Uint16Array, out: Uint8Array) => number;
|
|
6
|
-
knitting_windows_close_shared_memory: (mapping: Uint8Array) => number;
|
|
7
|
-
};
|
|
12
|
+
symbols: WindowsSharedMemorySymbols;
|
|
8
13
|
close: () => void;
|
|
9
14
|
};
|
|
10
15
|
type BunWindowsLibrary = {
|
|
11
|
-
symbols:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
symbols: WindowsSharedMemorySymbols;
|
|
17
|
+
};
|
|
18
|
+
type NodeWindowsLibrary = {
|
|
19
|
+
functions: WindowsSharedMemorySymbols;
|
|
20
|
+
lib: NodeFfiLibrary;
|
|
16
21
|
};
|
|
17
22
|
export declare const isWindowsRuntime: () => boolean;
|
|
18
23
|
export declare const windowsSharedMemoryPrebuildPath: () => string;
|
|
19
24
|
export declare const makeWindowsAnonymousSharedMemoryName: (runtime: string) => string;
|
|
20
25
|
export declare const openDenoWindowsSharedMemoryLibrary: () => DenoWindowsLibrary;
|
|
21
26
|
export declare const openBunWindowsSharedMemoryLibrary: () => BunWindowsLibrary;
|
|
27
|
+
export declare const openNodeWindowsSharedMemoryLibrary: () => NodeWindowsLibrary;
|
|
22
28
|
export declare const createDenoWindowsSharedMemory: (options: number | CreateSharedMemoryOptions, lib?: DenoWindowsLibrary) => SharedMemoryMapping<ArrayBuffer>;
|
|
23
29
|
export declare const mapDenoWindowsSharedMemory: (options: MapSharedMemoryOptions, lib?: DenoWindowsLibrary) => SharedMemoryMapping<ArrayBuffer>;
|
|
24
30
|
export declare const createDenoWindowsConnectionPrimitives: (lib?: DenoWindowsLibrary) => SharedMemoryConnectionPrimitives<SharedMemoryMapping<ArrayBuffer>>;
|
|
25
31
|
export declare const createBunWindowsSharedMemory: (options: number | CreateSharedMemoryOptions, lib?: BunWindowsLibrary) => SharedMemoryMapping<ArrayBuffer>;
|
|
26
32
|
export declare const mapBunWindowsSharedMemory: (options: MapSharedMemoryOptions, lib?: BunWindowsLibrary) => SharedMemoryMapping<ArrayBuffer>;
|
|
27
33
|
export declare const createBunWindowsConnectionPrimitives: (lib?: BunWindowsLibrary) => SharedMemoryConnectionPrimitives<SharedMemoryMapping<ArrayBuffer>>;
|
|
34
|
+
export declare const createNodeWindowsSharedMemory: (options: number | CreateSharedMemoryOptions, lib?: NodeWindowsLibrary) => SharedMemoryMapping<ArrayBuffer>;
|
|
35
|
+
export declare const mapNodeWindowsSharedMemory: (options: MapSharedMemoryOptions, lib?: NodeWindowsLibrary) => SharedMemoryMapping<ArrayBuffer>;
|
|
36
|
+
export declare const createNodeWindowsConnectionPrimitives: (lib?: NodeWindowsLibrary) => SharedMemoryConnectionPrimitives<SharedMemoryMapping<ArrayBuffer>>;
|
|
28
37
|
export {};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { resolveKnittingPackageAsset } from "./package-assets.js";
|
|
2
|
+
import { requireDetachedExternalArrayBuffer } from "./external-array-buffer.js";
|
|
3
|
+
import { getNodeFfi, } from "./node-ffi-api.js";
|
|
2
4
|
import { expectFd, expectPositiveSize, readCreateMode, readCreateSize, readRequiredCreateName, } from "./types.js";
|
|
3
5
|
const WINDOWS_CREATE_MODE_CREATE = 1;
|
|
4
6
|
const WINDOWS_CREATE_MODE_OPEN = 2;
|
|
@@ -7,6 +9,9 @@ const POINTER_OFFSET = 0;
|
|
|
7
9
|
const HANDLE_OFFSET = 8;
|
|
8
10
|
const SIZE_OFFSET = 16;
|
|
9
11
|
const BASE_ADDRESS_MOD_64_OFFSET = 24;
|
|
12
|
+
const WINDOWS_CREATE_SHARED_MEMORY = "knitting_windows_create_shared_memory";
|
|
13
|
+
const WINDOWS_MAP_SHARED_MEMORY = "knitting_windows_map_shared_memory";
|
|
14
|
+
const WINDOWS_CLOSE_SHARED_MEMORY = "knitting_windows_close_shared_memory";
|
|
10
15
|
const FFIType = {
|
|
11
16
|
i32: 5,
|
|
12
17
|
u32: 6,
|
|
@@ -105,34 +110,59 @@ const checkWindowsResult = (result, message) => {
|
|
|
105
110
|
}
|
|
106
111
|
};
|
|
107
112
|
const createRecord = () => new Uint8Array(WINDOWS_MAPPING_RECORD_BYTES);
|
|
108
|
-
|
|
109
|
-
|
|
113
|
+
const DENO_WINDOWS_SYMBOLS = {
|
|
114
|
+
[WINDOWS_CREATE_SHARED_MEMORY]: {
|
|
110
115
|
parameters: ["u64", "buffer", "u32", "buffer"],
|
|
111
116
|
result: "i32",
|
|
112
117
|
},
|
|
113
|
-
|
|
118
|
+
[WINDOWS_MAP_SHARED_MEMORY]: {
|
|
114
119
|
parameters: ["u64", "u64", "buffer", "buffer"],
|
|
115
120
|
result: "i32",
|
|
116
121
|
},
|
|
117
|
-
|
|
122
|
+
[WINDOWS_CLOSE_SHARED_MEMORY]: {
|
|
118
123
|
parameters: ["buffer"],
|
|
119
124
|
result: "i32",
|
|
120
125
|
},
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
126
|
+
};
|
|
127
|
+
const BUN_WINDOWS_SYMBOLS = {
|
|
128
|
+
[WINDOWS_CREATE_SHARED_MEMORY]: {
|
|
124
129
|
args: [FFIType.i64, FFIType.ptr, FFIType.u32, FFIType.ptr],
|
|
125
130
|
returns: FFIType.i32,
|
|
126
131
|
},
|
|
127
|
-
|
|
132
|
+
[WINDOWS_MAP_SHARED_MEMORY]: {
|
|
128
133
|
args: [FFIType.i64, FFIType.i64, FFIType.ptr, FFIType.ptr],
|
|
129
134
|
returns: FFIType.i32,
|
|
130
135
|
},
|
|
131
|
-
|
|
136
|
+
[WINDOWS_CLOSE_SHARED_MEMORY]: {
|
|
132
137
|
args: [FFIType.ptr],
|
|
133
138
|
returns: FFIType.i32,
|
|
134
139
|
},
|
|
135
|
-
}
|
|
140
|
+
};
|
|
141
|
+
const NODE_WINDOWS_SYMBOLS = {
|
|
142
|
+
[WINDOWS_CREATE_SHARED_MEMORY]: {
|
|
143
|
+
arguments: ["u64", "pointer", "u32", "pointer"],
|
|
144
|
+
return: "i32",
|
|
145
|
+
},
|
|
146
|
+
[WINDOWS_MAP_SHARED_MEMORY]: {
|
|
147
|
+
arguments: ["u64", "u64", "pointer", "pointer"],
|
|
148
|
+
return: "i32",
|
|
149
|
+
},
|
|
150
|
+
[WINDOWS_CLOSE_SHARED_MEMORY]: {
|
|
151
|
+
arguments: ["pointer"],
|
|
152
|
+
return: "i32",
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
export const openDenoWindowsSharedMemoryLibrary = () => getDeno().dlopen(windowsSharedMemoryPrebuildPath(), DENO_WINDOWS_SYMBOLS);
|
|
156
|
+
export const openBunWindowsSharedMemoryLibrary = () => getBunFFI().dlopen(windowsSharedMemoryPrebuildPath(), BUN_WINDOWS_SYMBOLS);
|
|
157
|
+
let cachedNodeWindowsLibrary;
|
|
158
|
+
export const openNodeWindowsSharedMemoryLibrary = () => {
|
|
159
|
+
if (cachedNodeWindowsLibrary !== undefined) {
|
|
160
|
+
return cachedNodeWindowsLibrary;
|
|
161
|
+
}
|
|
162
|
+
const opened = getNodeFfi().dlopen(windowsSharedMemoryPrebuildPath(), NODE_WINDOWS_SYMBOLS);
|
|
163
|
+
cachedNodeWindowsLibrary = opened;
|
|
164
|
+
return opened;
|
|
165
|
+
};
|
|
136
166
|
const closeWindowsMapping = (record, closeSharedMemory) => {
|
|
137
167
|
let closed = false;
|
|
138
168
|
return () => {
|
|
@@ -142,6 +172,19 @@ const closeWindowsMapping = (record, closeSharedMemory) => {
|
|
|
142
172
|
checkWindowsResult(closeSharedMemory(record), "knitting_windows_close_shared_memory");
|
|
143
173
|
};
|
|
144
174
|
};
|
|
175
|
+
const makeWindowsMapping = (runtime, mapping, name, arrayBuffer, unsafePointer, close) => ({
|
|
176
|
+
runtime,
|
|
177
|
+
fd: fdFromHandle(mapping.handle),
|
|
178
|
+
name,
|
|
179
|
+
size: mapping.size,
|
|
180
|
+
byteLength: arrayBuffer.byteLength,
|
|
181
|
+
buffer: arrayBuffer,
|
|
182
|
+
kind: "external-array-buffer",
|
|
183
|
+
arrayBuffer,
|
|
184
|
+
unsafePointer,
|
|
185
|
+
baseAddressMod64: mapping.baseAddressMod64,
|
|
186
|
+
close,
|
|
187
|
+
});
|
|
145
188
|
const fromDenoWindowsRecord = (record, name, lib) => {
|
|
146
189
|
const mapping = readWindowsNativeMapping(record);
|
|
147
190
|
const pointer = getDeno().UnsafePointer?.create(mapping.address);
|
|
@@ -150,19 +193,7 @@ const fromDenoWindowsRecord = (record, name, lib) => {
|
|
|
150
193
|
}
|
|
151
194
|
const arrayBuffer = new (getDeno().UnsafePointerView)(pointer)
|
|
152
195
|
.getArrayBuffer(mapping.size);
|
|
153
|
-
return
|
|
154
|
-
runtime: "deno",
|
|
155
|
-
fd: fdFromHandle(mapping.handle),
|
|
156
|
-
name,
|
|
157
|
-
size: mapping.size,
|
|
158
|
-
byteLength: arrayBuffer.byteLength,
|
|
159
|
-
buffer: arrayBuffer,
|
|
160
|
-
kind: "external-array-buffer",
|
|
161
|
-
arrayBuffer,
|
|
162
|
-
unsafePointer: pointer,
|
|
163
|
-
baseAddressMod64: mapping.baseAddressMod64,
|
|
164
|
-
close: closeWindowsMapping(record, lib.symbols.knitting_windows_close_shared_memory),
|
|
165
|
-
};
|
|
196
|
+
return makeWindowsMapping("deno", mapping, name, arrayBuffer, pointer, closeWindowsMapping(record, lib.symbols[WINDOWS_CLOSE_SHARED_MEMORY]));
|
|
166
197
|
};
|
|
167
198
|
const fromBunWindowsRecord = (record, name, lib) => {
|
|
168
199
|
const mapping = readWindowsNativeMapping(record);
|
|
@@ -170,55 +201,45 @@ const fromBunWindowsRecord = (record, name, lib) => {
|
|
|
170
201
|
throw new RangeError("Windows mapping pointer is too large for Bun FFI");
|
|
171
202
|
}
|
|
172
203
|
const arrayBuffer = getBunFFI().toArrayBuffer(Number(mapping.address), 0, mapping.size);
|
|
173
|
-
return
|
|
174
|
-
runtime: "bun",
|
|
175
|
-
fd: fdFromHandle(mapping.handle),
|
|
176
|
-
name,
|
|
177
|
-
size: mapping.size,
|
|
178
|
-
byteLength: arrayBuffer.byteLength,
|
|
179
|
-
buffer: arrayBuffer,
|
|
180
|
-
kind: "external-array-buffer",
|
|
181
|
-
arrayBuffer,
|
|
182
|
-
unsafePointer: Number(mapping.address),
|
|
183
|
-
baseAddressMod64: mapping.baseAddressMod64,
|
|
184
|
-
close: closeWindowsMapping(record, lib.symbols.knitting_windows_close_shared_memory),
|
|
185
|
-
};
|
|
186
|
-
};
|
|
187
|
-
export const createDenoWindowsSharedMemory = (options, lib = openDenoWindowsSharedMemoryLibrary()) => {
|
|
188
|
-
const size = expectPositiveSize(readCreateSize(options));
|
|
189
|
-
const { mode, name } = readWindowsCreate(options, "deno");
|
|
190
|
-
const record = createRecord();
|
|
191
|
-
checkWindowsResult(lib.symbols.knitting_windows_create_shared_memory(BigInt(size), encodeWideCString(name), mode, record), "knitting_windows_create_shared_memory");
|
|
192
|
-
return fromDenoWindowsRecord(record, name, lib);
|
|
204
|
+
return makeWindowsMapping("bun", mapping, name, arrayBuffer, Number(mapping.address), closeWindowsMapping(record, lib.symbols[WINDOWS_CLOSE_SHARED_MEMORY]));
|
|
193
205
|
};
|
|
194
|
-
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
206
|
+
const fromNodeWindowsRecord = (record, name, lib) => {
|
|
207
|
+
const mapping = readWindowsNativeMapping(record);
|
|
208
|
+
const arrayBuffer = getNodeFfi().toArrayBuffer(mapping.address, mapping.size, false);
|
|
209
|
+
let closed = false;
|
|
210
|
+
return makeWindowsMapping("node", mapping, name, arrayBuffer, mapping.address, () => {
|
|
211
|
+
if (closed)
|
|
212
|
+
return;
|
|
213
|
+
requireDetachedExternalArrayBuffer(arrayBuffer);
|
|
214
|
+
checkWindowsResult(lib.functions[WINDOWS_CLOSE_SHARED_MEMORY](record), WINDOWS_CLOSE_SHARED_MEMORY);
|
|
215
|
+
closed = true;
|
|
216
|
+
});
|
|
200
217
|
};
|
|
201
|
-
|
|
202
|
-
runtime: "deno",
|
|
203
|
-
createSharedMemory: (options) => createDenoWindowsSharedMemory(options, lib),
|
|
204
|
-
mapSharedMemory: (options) => mapDenoWindowsSharedMemory(options, lib),
|
|
205
|
-
});
|
|
206
|
-
export const createBunWindowsSharedMemory = (options, lib = openBunWindowsSharedMemoryLibrary()) => {
|
|
218
|
+
const createWindowsSharedMemory = (options, runtime, lib, createSharedMemory, fromRecord) => {
|
|
207
219
|
const size = expectPositiveSize(readCreateSize(options));
|
|
208
|
-
const { mode, name } = readWindowsCreate(options,
|
|
220
|
+
const { mode, name } = readWindowsCreate(options, runtime);
|
|
209
221
|
const record = createRecord();
|
|
210
|
-
checkWindowsResult(
|
|
211
|
-
return
|
|
222
|
+
checkWindowsResult(createSharedMemory(BigInt(size), encodeWideCString(name), mode, record), WINDOWS_CREATE_SHARED_MEMORY);
|
|
223
|
+
return fromRecord(record, name, lib);
|
|
212
224
|
};
|
|
213
|
-
|
|
225
|
+
const mapWindowsSharedMemory = (options, lib, mapSharedMemory, fromRecord) => {
|
|
214
226
|
const fd = expectFd(options.fd);
|
|
215
227
|
const size = expectPositiveSize(options.size);
|
|
216
228
|
const record = createRecord();
|
|
217
|
-
checkWindowsResult(
|
|
218
|
-
return
|
|
219
|
-
};
|
|
220
|
-
export const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
229
|
+
checkWindowsResult(mapSharedMemory(BigInt(fd), BigInt(size), encodeWideCString(options.name), record), WINDOWS_MAP_SHARED_MEMORY);
|
|
230
|
+
return fromRecord(record, options.name, lib);
|
|
231
|
+
};
|
|
232
|
+
export const createDenoWindowsSharedMemory = (options, lib = openDenoWindowsSharedMemoryLibrary()) => createWindowsSharedMemory(options, "deno", lib, lib.symbols[WINDOWS_CREATE_SHARED_MEMORY], fromDenoWindowsRecord);
|
|
233
|
+
export const mapDenoWindowsSharedMemory = (options, lib = openDenoWindowsSharedMemoryLibrary()) => mapWindowsSharedMemory(options, lib, lib.symbols[WINDOWS_MAP_SHARED_MEMORY], fromDenoWindowsRecord);
|
|
234
|
+
const createWindowsConnectionPrimitives = (runtime, lib, createSharedMemory, mapSharedMemory) => ({
|
|
235
|
+
runtime,
|
|
236
|
+
createSharedMemory: (options) => createSharedMemory(options, lib),
|
|
237
|
+
mapSharedMemory: (options) => mapSharedMemory(options, lib),
|
|
224
238
|
});
|
|
239
|
+
export const createDenoWindowsConnectionPrimitives = (lib = openDenoWindowsSharedMemoryLibrary()) => createWindowsConnectionPrimitives("deno", lib, createDenoWindowsSharedMemory, mapDenoWindowsSharedMemory);
|
|
240
|
+
export const createBunWindowsSharedMemory = (options, lib = openBunWindowsSharedMemoryLibrary()) => createWindowsSharedMemory(options, "bun", lib, lib.symbols[WINDOWS_CREATE_SHARED_MEMORY], fromBunWindowsRecord);
|
|
241
|
+
export const mapBunWindowsSharedMemory = (options, lib = openBunWindowsSharedMemoryLibrary()) => mapWindowsSharedMemory(options, lib, lib.symbols[WINDOWS_MAP_SHARED_MEMORY], fromBunWindowsRecord);
|
|
242
|
+
export const createBunWindowsConnectionPrimitives = (lib = openBunWindowsSharedMemoryLibrary()) => createWindowsConnectionPrimitives("bun", lib, createBunWindowsSharedMemory, mapBunWindowsSharedMemory);
|
|
243
|
+
export const createNodeWindowsSharedMemory = (options, lib = openNodeWindowsSharedMemoryLibrary()) => createWindowsSharedMemory(options, "node", lib, lib.functions[WINDOWS_CREATE_SHARED_MEMORY], fromNodeWindowsRecord);
|
|
244
|
+
export const mapNodeWindowsSharedMemory = (options, lib = openNodeWindowsSharedMemoryLibrary()) => mapWindowsSharedMemory(options, lib, lib.functions[WINDOWS_MAP_SHARED_MEMORY], fromNodeWindowsRecord);
|
|
245
|
+
export const createNodeWindowsConnectionPrimitives = (lib = openNodeWindowsSharedMemoryLibrary()) => createWindowsConnectionPrimitives("node", lib, createNodeWindowsSharedMemory, mapNodeWindowsSharedMemory);
|
package/src/error.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { type PromisePayloadHandler, type Task } from "./memory/lock.js";
|
|
2
|
-
export declare
|
|
3
|
-
Function
|
|
4
|
-
Symbol
|
|
5
|
-
Json
|
|
6
|
-
Serializable
|
|
7
|
-
}
|
|
2
|
+
export declare const ErrorKnitting: {
|
|
3
|
+
readonly Function: 0;
|
|
4
|
+
readonly Symbol: 1;
|
|
5
|
+
readonly Json: 2;
|
|
6
|
+
readonly Serializable: 3;
|
|
7
|
+
};
|
|
8
|
+
export type ErrorKnitting = typeof ErrorKnitting[keyof typeof ErrorKnitting];
|
|
8
9
|
export declare const encoderError: ({ task, type, onPromise, detail, }: {
|
|
9
10
|
task: Task;
|
|
10
11
|
type: ErrorKnitting;
|
package/src/error.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { beginPromisePayload, finishPromisePayload, TaskFlag, TaskIndex, } from "./memory/lock.js";
|
|
2
2
|
import { RUNTIME_IS_MAIN_THREAD } from "./common/worker-runtime.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
// const object, not `enum`: Andromeda's Nova engine can't parse `enum`. Same
|
|
4
|
+
// value access and emit on Node/Deno/Bun.
|
|
5
|
+
export const ErrorKnitting = {
|
|
6
|
+
Function: 0,
|
|
7
|
+
Symbol: 1,
|
|
8
|
+
Json: 2,
|
|
9
|
+
Serializable: 3,
|
|
10
|
+
};
|
|
10
11
|
const reasonFrom = (task, type, detail) => {
|
|
11
12
|
switch (type) {
|
|
12
13
|
case ErrorKnitting.Function: {
|