knitting 0.1.55 → 0.1.56
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/knitting.d.ts +6 -797
- package/knitting.js +6 -9780
- package/map.md +12 -8
- package/package.json +14 -6
- package/process-shared-buffer.d.ts +1 -0
- package/process-shared-buffer.js +1 -0
- package/shared-memory.d.ts +1 -155
- package/shared-memory.js +1 -1342
- package/src/api.d.ts +69 -0
- package/src/api.js +619 -0
- package/src/common/envelope.d.ts +17 -0
- package/src/common/envelope.js +22 -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 +3 -0
- package/src/common/task-source.js +84 -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 +61 -0
- package/src/connections/buffer-reference-native.d.ts +56 -0
- package/src/connections/buffer-reference-native.js +217 -0
- package/src/connections/buffer-reference.d.ts +78 -0
- package/src/connections/buffer-reference.js +461 -0
- package/src/connections/bun.d.ts +22 -0
- package/src/connections/bun.js +214 -0
- package/src/connections/deno.d.ts +22 -0
- package/src/connections/deno.js +205 -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 +5 -0
- package/src/connections/node-addons.js +44 -0
- package/src/connections/node-buffer-pointer.d.ts +20 -0
- package/src/connections/node-buffer-pointer.js +16 -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 +45 -0
- package/src/connections/posix.d.ts +32 -0
- package/src/connections/posix.js +77 -0
- package/src/connections/process-shared-buffer.d.ts +75 -0
- package/src/connections/process-shared-buffer.js +279 -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 +50 -0
- package/src/connections/types.js +37 -0
- package/src/connections/windows.d.ts +28 -0
- package/src/connections/windows.js +224 -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 +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 +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 +203 -0
- package/src/memory/lock.js +741 -0
- package/src/memory/payload-config.d.ts +31 -0
- package/src/memory/payload-config.js +67 -0
- package/src/memory/payloadCodec.d.ts +46 -0
- package/src/memory/payloadCodec.js +1377 -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/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 +650 -0
- package/src/runtime/balancer.d.ts +19 -0
- package/src/runtime/balancer.js +149 -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 +282 -0
- package/src/runtime/pool.d.ts +39 -0
- package/src/runtime/pool.js +404 -0
- package/src/runtime/process-worker.d.ts +92 -0
- package/src/runtime/process-worker.js +673 -0
- package/src/runtime/tx-queue.d.ts +26 -0
- package/src/runtime/tx-queue.js +155 -0
- package/src/shared/abortSignal.d.ts +23 -0
- package/src/shared/abortSignal.js +134 -0
- package/src/types.d.ts +357 -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 +97 -0
- package/src/worker/loop.d.ts +2 -0
- package/src/worker/loop.js +382 -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 +27 -0
- package/src/worker/task-loader.js +70 -0
- package/src/worker/timers.d.ts +18 -0
- package/src/worker/timers.js +116 -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,22 @@
|
|
|
1
|
+
import { type CreateSharedMemoryOptions, type MapSharedMemoryOptions, type SharedMemoryConnectionPrimitives, type SharedMemoryMapping } from "./types.js";
|
|
2
|
+
type DenoLibc = {
|
|
3
|
+
symbols: {
|
|
4
|
+
memfd_create?: (name: Uint8Array, flags: number) => number;
|
|
5
|
+
shm_open?: (name: Uint8Array, flags: number, mode: number) => number;
|
|
6
|
+
shm_unlink?: (name: Uint8Array) => number;
|
|
7
|
+
ftruncate: (fd: number, length: bigint) => number;
|
|
8
|
+
dup: (fd: number) => number;
|
|
9
|
+
fcntl: (fd: number, cmd: number, arg: number) => number;
|
|
10
|
+
mmap: (address: null, length: number, protection: number, flags: number, fd: number, offset: bigint) => unknown;
|
|
11
|
+
munmap: (address: unknown, length: number) => number;
|
|
12
|
+
close: (fd: number) => number;
|
|
13
|
+
};
|
|
14
|
+
close: () => void;
|
|
15
|
+
};
|
|
16
|
+
export declare const openDenoLibc: () => DenoLibc;
|
|
17
|
+
export declare const mapDenoSharedMemory: (options: MapSharedMemoryOptions, libc?: DenoLibc) => SharedMemoryMapping<ArrayBuffer>;
|
|
18
|
+
export declare const createDenoSharedMemory: (options: number | CreateSharedMemoryOptions, libc?: DenoLibc) => SharedMemoryMapping<ArrayBuffer>;
|
|
19
|
+
export declare const unlinkDenoSharedMemory: (name: string, libc?: DenoLibc) => boolean;
|
|
20
|
+
export declare const createDenoPosixConnectionPrimitives: (libc?: DenoLibc) => SharedMemoryConnectionPrimitives<SharedMemoryMapping<ArrayBuffer>>;
|
|
21
|
+
export declare const createDenoConnectionPrimitives: (libc?: DenoLibc) => SharedMemoryConnectionPrimitives<SharedMemoryMapping<ArrayBuffer>>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { DARWIN_O_CREAT, DARWIN_O_EXCL, DARWIN_SHM_MODE, LINUX_O_CREAT, LINUX_O_EXCL, setCloseOnExec, detectPosixPlatform, encodeCString, getPosixLibcPath, makeDarwinSharedMemoryName, MAP_SHARED, O_RDWR, POSIX_SHM_MODE, PROT_READ, PROT_WRITE, toPosixSharedMemoryName, } from "./posix.js";
|
|
2
|
+
import { expectFd, expectPositiveSize, readCreateName, readCreateMode, readRequiredCreateName, readCreateSize, } from "./types.js";
|
|
3
|
+
import { createDenoWindowsConnectionPrimitives, isWindowsRuntime, } from "./windows.js";
|
|
4
|
+
const getDeno = () => {
|
|
5
|
+
const deno = globalThis.Deno;
|
|
6
|
+
if (deno === undefined) {
|
|
7
|
+
throw new Error("Deno shared memory primitives can only run in Deno");
|
|
8
|
+
}
|
|
9
|
+
return deno;
|
|
10
|
+
};
|
|
11
|
+
export const openDenoLibc = () => getDeno().dlopen(getPosixLibcPath(), {
|
|
12
|
+
...getDenoCreateSymbols(),
|
|
13
|
+
ftruncate: {
|
|
14
|
+
parameters: ["i32", "i64"],
|
|
15
|
+
result: "i32",
|
|
16
|
+
},
|
|
17
|
+
dup: {
|
|
18
|
+
parameters: ["i32"],
|
|
19
|
+
result: "i32",
|
|
20
|
+
},
|
|
21
|
+
fcntl: {
|
|
22
|
+
parameters: ["i32", "i32", "i32"],
|
|
23
|
+
result: "i32",
|
|
24
|
+
},
|
|
25
|
+
mmap: {
|
|
26
|
+
parameters: ["pointer", "usize", "i32", "i32", "i32", "i64"],
|
|
27
|
+
result: "pointer",
|
|
28
|
+
},
|
|
29
|
+
munmap: {
|
|
30
|
+
parameters: ["pointer", "usize"],
|
|
31
|
+
result: "i32",
|
|
32
|
+
},
|
|
33
|
+
close: {
|
|
34
|
+
parameters: ["i32"],
|
|
35
|
+
result: "i32",
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
const getDenoCreateSymbols = (platform = detectPosixPlatform()) => platform === "darwin"
|
|
39
|
+
? {
|
|
40
|
+
shm_open: {
|
|
41
|
+
parameters: ["buffer", "i32", "u32"],
|
|
42
|
+
result: "i32",
|
|
43
|
+
},
|
|
44
|
+
shm_unlink: {
|
|
45
|
+
parameters: ["buffer"],
|
|
46
|
+
result: "i32",
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
: {
|
|
50
|
+
memfd_create: {
|
|
51
|
+
parameters: ["buffer", "u32"],
|
|
52
|
+
result: "i32",
|
|
53
|
+
},
|
|
54
|
+
shm_open: {
|
|
55
|
+
parameters: ["buffer", "i32", "u32"],
|
|
56
|
+
result: "i32",
|
|
57
|
+
},
|
|
58
|
+
shm_unlink: {
|
|
59
|
+
parameters: ["buffer"],
|
|
60
|
+
result: "i32",
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
const checkResult = (result, message) => {
|
|
64
|
+
if (result < 0)
|
|
65
|
+
throw new Error(message);
|
|
66
|
+
return result;
|
|
67
|
+
};
|
|
68
|
+
const isDenoMmapFailed = (pointer) => {
|
|
69
|
+
if (pointer === null)
|
|
70
|
+
return true;
|
|
71
|
+
const value = getDeno().UnsafePointer?.value(pointer);
|
|
72
|
+
return value === -1n || value === BigInt.asUintN(64, -1n);
|
|
73
|
+
};
|
|
74
|
+
const createDenoSharedMemoryFd = (name, platform, libc) => {
|
|
75
|
+
if (platform === "darwin") {
|
|
76
|
+
const shmOpen = libc.symbols.shm_open;
|
|
77
|
+
const shmUnlink = libc.symbols.shm_unlink;
|
|
78
|
+
if (shmOpen === undefined || shmUnlink === undefined) {
|
|
79
|
+
throw new Error("shm_open symbols are not available");
|
|
80
|
+
}
|
|
81
|
+
const shmName = encodeCString(makeDarwinSharedMemoryName(name, "deno"));
|
|
82
|
+
const fd = checkResult(shmOpen(shmName, O_RDWR | DARWIN_O_CREAT | DARWIN_O_EXCL, DARWIN_SHM_MODE), "shm_open failed");
|
|
83
|
+
shmUnlink(shmName);
|
|
84
|
+
try {
|
|
85
|
+
return setCloseOnExec(libc, fd);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
libc.symbols.close(fd);
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const memfdCreate = libc.symbols.memfd_create;
|
|
93
|
+
if (memfdCreate === undefined) {
|
|
94
|
+
throw new Error("memfd_create symbol is not available");
|
|
95
|
+
}
|
|
96
|
+
const fd = checkResult(memfdCreate(encodeCString(name), 0), "memfd_create failed");
|
|
97
|
+
try {
|
|
98
|
+
return setCloseOnExec(libc, fd);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
libc.symbols.close(fd);
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const createNamedDenoSharedMemoryFd = (name, mode, platform, libc) => {
|
|
106
|
+
const shmOpen = libc.symbols.shm_open;
|
|
107
|
+
if (shmOpen === undefined) {
|
|
108
|
+
throw new Error("shm_open symbol is not available");
|
|
109
|
+
}
|
|
110
|
+
const createFlags = platform === "darwin" ? DARWIN_O_CREAT : LINUX_O_CREAT;
|
|
111
|
+
const exclusiveFlags = platform === "darwin" ? DARWIN_O_EXCL : LINUX_O_EXCL;
|
|
112
|
+
const flags = mode === "create"
|
|
113
|
+
? O_RDWR | createFlags | exclusiveFlags
|
|
114
|
+
: O_RDWR;
|
|
115
|
+
const fd = checkResult(shmOpen(encodeCString(toPosixSharedMemoryName(name)), flags, platform === "darwin" ? DARWIN_SHM_MODE : POSIX_SHM_MODE), "shm_open failed");
|
|
116
|
+
try {
|
|
117
|
+
return setCloseOnExec(libc, fd);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
libc.symbols.close(fd);
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
export const mapDenoSharedMemory = (options, libc = openDenoLibc()) => {
|
|
125
|
+
const sourceFd = options.name === undefined ? expectFd(options.fd) : -1;
|
|
126
|
+
const size = expectPositiveSize(options.size);
|
|
127
|
+
let fd = sourceFd;
|
|
128
|
+
if (options.name !== undefined) {
|
|
129
|
+
fd = createNamedDenoSharedMemoryFd(options.name, "open", detectPosixPlatform(), libc);
|
|
130
|
+
}
|
|
131
|
+
else if (options.duplicateFd !== false) {
|
|
132
|
+
fd = checkResult(libc.symbols.dup(sourceFd), "dup(fd) failed");
|
|
133
|
+
try {
|
|
134
|
+
setCloseOnExec(libc, fd);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
libc.symbols.close(fd);
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const pointer = libc.symbols.mmap(null, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0n);
|
|
142
|
+
if (isDenoMmapFailed(pointer)) {
|
|
143
|
+
if (options.duplicateFd !== false)
|
|
144
|
+
libc.symbols.close(fd);
|
|
145
|
+
throw new Error("mmap failed");
|
|
146
|
+
}
|
|
147
|
+
const arrayBuffer = new (getDeno().UnsafePointerView)(pointer)
|
|
148
|
+
.getArrayBuffer(size);
|
|
149
|
+
return {
|
|
150
|
+
runtime: "deno",
|
|
151
|
+
fd,
|
|
152
|
+
name: options.name,
|
|
153
|
+
size,
|
|
154
|
+
byteLength: arrayBuffer.byteLength,
|
|
155
|
+
buffer: arrayBuffer,
|
|
156
|
+
kind: "external-array-buffer",
|
|
157
|
+
arrayBuffer,
|
|
158
|
+
unsafePointer: pointer,
|
|
159
|
+
close: () => {
|
|
160
|
+
libc.symbols.munmap(pointer, size);
|
|
161
|
+
libc.symbols.close(fd);
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
export const createDenoSharedMemory = (options, libc = openDenoLibc()) => {
|
|
166
|
+
const size = expectPositiveSize(readCreateSize(options));
|
|
167
|
+
const mode = readCreateMode(options);
|
|
168
|
+
const name = mode === "anonymous"
|
|
169
|
+
? readCreateName(options, "knitting_shared_memory")
|
|
170
|
+
: readRequiredCreateName(options);
|
|
171
|
+
const platform = detectPosixPlatform();
|
|
172
|
+
const fd = mode === "anonymous"
|
|
173
|
+
? createDenoSharedMemoryFd(name, platform, libc)
|
|
174
|
+
: createNamedDenoSharedMemoryFd(name, mode, platform, libc);
|
|
175
|
+
try {
|
|
176
|
+
if (mode !== "open") {
|
|
177
|
+
checkResult(libc.symbols.ftruncate(fd, BigInt(size)), "ftruncate failed");
|
|
178
|
+
}
|
|
179
|
+
const mapping = mapDenoSharedMemory({ fd, size, duplicateFd: false }, libc);
|
|
180
|
+
if (mode !== "anonymous") {
|
|
181
|
+
return { ...mapping, name };
|
|
182
|
+
}
|
|
183
|
+
return mapping;
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
libc.symbols.close(fd);
|
|
187
|
+
throw error;
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
export const unlinkDenoSharedMemory = (name, libc = openDenoLibc()) => {
|
|
191
|
+
const shmUnlink = libc.symbols.shm_unlink;
|
|
192
|
+
if (shmUnlink === undefined) {
|
|
193
|
+
throw new Error("shm_unlink symbol is not available");
|
|
194
|
+
}
|
|
195
|
+
return shmUnlink(encodeCString(toPosixSharedMemoryName(name))) === 0;
|
|
196
|
+
};
|
|
197
|
+
export const createDenoPosixConnectionPrimitives = (libc = openDenoLibc()) => ({
|
|
198
|
+
runtime: "deno",
|
|
199
|
+
createSharedMemory: (options) => createDenoSharedMemory(options, libc),
|
|
200
|
+
mapSharedMemory: (options) => mapDenoSharedMemory(options, libc),
|
|
201
|
+
unlinkSharedMemory: (name) => unlinkDenoSharedMemory(name, libc),
|
|
202
|
+
});
|
|
203
|
+
export const createDenoConnectionPrimitives = (libc) => isWindowsRuntime()
|
|
204
|
+
? createDenoWindowsConnectionPrimitives()
|
|
205
|
+
: createDenoPosixConnectionPrimitives(libc);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ConnectionRuntime, type SharedMemoryBuffer, type SharedMemoryConnectionPrimitives, type SharedMemoryMapping } from "./types.js";
|
|
2
|
+
export type FileDescriptorMetadata = {
|
|
3
|
+
version: 1;
|
|
4
|
+
fd: number;
|
|
5
|
+
name?: string;
|
|
6
|
+
size: number;
|
|
7
|
+
byteLength: number;
|
|
8
|
+
runtime?: ConnectionRuntime;
|
|
9
|
+
kind?: SharedMemoryMapping["kind"];
|
|
10
|
+
baseAddressMod64?: number;
|
|
11
|
+
};
|
|
12
|
+
type FileDescriptorMapper = Pick<SharedMemoryConnectionPrimitives, "mapSharedMemory">;
|
|
13
|
+
export declare class FileDescriptor {
|
|
14
|
+
#private;
|
|
15
|
+
readonly fd: number;
|
|
16
|
+
readonly name?: string;
|
|
17
|
+
readonly size: number;
|
|
18
|
+
readonly byteLength: number;
|
|
19
|
+
readonly runtime?: ConnectionRuntime;
|
|
20
|
+
readonly kind?: SharedMemoryMapping["kind"];
|
|
21
|
+
readonly baseAddressMod64?: number;
|
|
22
|
+
constructor(metadata: FileDescriptorMetadata, mapping?: SharedMemoryMapping);
|
|
23
|
+
static fromMapping(mapping: SharedMemoryMapping): FileDescriptor;
|
|
24
|
+
static fromMetadata(metadata: unknown): FileDescriptor;
|
|
25
|
+
static parse(serialized: string): FileDescriptor;
|
|
26
|
+
toMetadata(): FileDescriptorMetadata;
|
|
27
|
+
toJSON(): FileDescriptorMetadata;
|
|
28
|
+
stringify(): string;
|
|
29
|
+
stringifyMetadata(): string;
|
|
30
|
+
toString(): string;
|
|
31
|
+
attach(mapping: SharedMemoryMapping): this;
|
|
32
|
+
get mapping(): SharedMemoryMapping | undefined;
|
|
33
|
+
map(mapper: FileDescriptorMapper): SharedMemoryMapping;
|
|
34
|
+
getBuffer(mapper?: FileDescriptorMapper): SharedMemoryBuffer;
|
|
35
|
+
getSharedArrayBuffer(mapper?: FileDescriptorMapper): SharedArrayBuffer;
|
|
36
|
+
getSAB(mapper?: FileDescriptorMapper): SharedArrayBuffer;
|
|
37
|
+
}
|
|
38
|
+
export declare const parseFileDescriptorMetadata: (input: unknown) => FileDescriptorMetadata;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { expectFd, expectPositiveSize, requireSharedArrayBuffer, } from "./types.js";
|
|
2
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
3
|
+
const readOptionalRuntime = (value) => {
|
|
4
|
+
if (value === undefined)
|
|
5
|
+
return undefined;
|
|
6
|
+
if (value === "node" || value === "deno" || value === "bun")
|
|
7
|
+
return value;
|
|
8
|
+
throw new TypeError("file descriptor runtime is invalid");
|
|
9
|
+
};
|
|
10
|
+
const readOptionalKind = (value) => {
|
|
11
|
+
if (value === undefined)
|
|
12
|
+
return undefined;
|
|
13
|
+
if (value === "shared-array-buffer" ||
|
|
14
|
+
value === "external-array-buffer") {
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
throw new TypeError("file descriptor buffer kind is invalid");
|
|
18
|
+
};
|
|
19
|
+
const readOptionalNumber = (value, label) => {
|
|
20
|
+
if (value === undefined)
|
|
21
|
+
return undefined;
|
|
22
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
23
|
+
throw new TypeError(`file descriptor ${label} must be a finite number`);
|
|
24
|
+
}
|
|
25
|
+
return Math.trunc(value);
|
|
26
|
+
};
|
|
27
|
+
const readOptionalName = (value) => {
|
|
28
|
+
if (value === undefined)
|
|
29
|
+
return undefined;
|
|
30
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
31
|
+
throw new TypeError("file descriptor name must be a non-empty string when provided");
|
|
32
|
+
}
|
|
33
|
+
if (value.includes("\0")) {
|
|
34
|
+
throw new TypeError("file descriptor name must not contain NUL bytes");
|
|
35
|
+
}
|
|
36
|
+
return value;
|
|
37
|
+
};
|
|
38
|
+
export class FileDescriptor {
|
|
39
|
+
fd;
|
|
40
|
+
name;
|
|
41
|
+
size;
|
|
42
|
+
byteLength;
|
|
43
|
+
runtime;
|
|
44
|
+
kind;
|
|
45
|
+
baseAddressMod64;
|
|
46
|
+
#mapping;
|
|
47
|
+
constructor(metadata, mapping) {
|
|
48
|
+
this.fd = expectFd(metadata.fd);
|
|
49
|
+
this.name = metadata.name;
|
|
50
|
+
this.size = expectPositiveSize(metadata.size);
|
|
51
|
+
this.byteLength = expectPositiveSize(metadata.byteLength);
|
|
52
|
+
this.runtime = metadata.runtime;
|
|
53
|
+
this.kind = metadata.kind;
|
|
54
|
+
this.baseAddressMod64 = metadata.baseAddressMod64;
|
|
55
|
+
this.#mapping = mapping;
|
|
56
|
+
}
|
|
57
|
+
static fromMapping(mapping) {
|
|
58
|
+
return new FileDescriptor({
|
|
59
|
+
version: 1,
|
|
60
|
+
fd: mapping.fd,
|
|
61
|
+
name: mapping.name,
|
|
62
|
+
size: mapping.size,
|
|
63
|
+
byteLength: mapping.byteLength,
|
|
64
|
+
runtime: mapping.runtime,
|
|
65
|
+
kind: mapping.kind,
|
|
66
|
+
baseAddressMod64: mapping.baseAddressMod64,
|
|
67
|
+
}, mapping);
|
|
68
|
+
}
|
|
69
|
+
static fromMetadata(metadata) {
|
|
70
|
+
return new FileDescriptor(parseFileDescriptorMetadata(metadata));
|
|
71
|
+
}
|
|
72
|
+
static parse(serialized) {
|
|
73
|
+
return FileDescriptor.fromMetadata(serialized);
|
|
74
|
+
}
|
|
75
|
+
toMetadata() {
|
|
76
|
+
const metadata = {
|
|
77
|
+
version: 1,
|
|
78
|
+
fd: this.fd,
|
|
79
|
+
size: this.size,
|
|
80
|
+
byteLength: this.byteLength,
|
|
81
|
+
runtime: this.runtime,
|
|
82
|
+
kind: this.kind,
|
|
83
|
+
baseAddressMod64: this.baseAddressMod64,
|
|
84
|
+
};
|
|
85
|
+
if (this.name !== undefined)
|
|
86
|
+
metadata.name = this.name;
|
|
87
|
+
return metadata;
|
|
88
|
+
}
|
|
89
|
+
toJSON() {
|
|
90
|
+
return this.toMetadata();
|
|
91
|
+
}
|
|
92
|
+
stringify() {
|
|
93
|
+
return JSON.stringify(this.toMetadata());
|
|
94
|
+
}
|
|
95
|
+
stringifyMetadata() {
|
|
96
|
+
// This describes an fd; it does not transfer fd ownership to another process.
|
|
97
|
+
return this.stringify();
|
|
98
|
+
}
|
|
99
|
+
toString() {
|
|
100
|
+
return this.stringify();
|
|
101
|
+
}
|
|
102
|
+
attach(mapping) {
|
|
103
|
+
this.#mapping = mapping;
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
get mapping() {
|
|
107
|
+
return this.#mapping;
|
|
108
|
+
}
|
|
109
|
+
map(mapper) {
|
|
110
|
+
const options = {
|
|
111
|
+
fd: this.fd,
|
|
112
|
+
name: this.name,
|
|
113
|
+
size: this.size,
|
|
114
|
+
};
|
|
115
|
+
this.#mapping = mapper.mapSharedMemory(options);
|
|
116
|
+
return this.#mapping;
|
|
117
|
+
}
|
|
118
|
+
getBuffer(mapper) {
|
|
119
|
+
if (this.#mapping?.buffer !== undefined)
|
|
120
|
+
return this.#mapping.buffer;
|
|
121
|
+
if (mapper === undefined) {
|
|
122
|
+
throw new TypeError("file descriptor is not attached to a shared memory mapping");
|
|
123
|
+
}
|
|
124
|
+
return this.map(mapper).buffer;
|
|
125
|
+
}
|
|
126
|
+
getSharedArrayBuffer(mapper) {
|
|
127
|
+
if (this.#mapping?.sab !== undefined)
|
|
128
|
+
return this.#mapping.sab;
|
|
129
|
+
if (mapper === undefined) {
|
|
130
|
+
throw new TypeError("file descriptor is not attached to a SharedArrayBuffer mapping");
|
|
131
|
+
}
|
|
132
|
+
return requireSharedArrayBuffer(this.map(mapper));
|
|
133
|
+
}
|
|
134
|
+
getSAB(mapper) {
|
|
135
|
+
return this.getSharedArrayBuffer(mapper);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
export const parseFileDescriptorMetadata = (input) => {
|
|
139
|
+
const value = typeof input === "string" ? JSON.parse(input) : input;
|
|
140
|
+
if (!isRecord(value)) {
|
|
141
|
+
throw new TypeError("file descriptor metadata must be an object");
|
|
142
|
+
}
|
|
143
|
+
if (value.version !== 1) {
|
|
144
|
+
throw new TypeError("unsupported file descriptor metadata version");
|
|
145
|
+
}
|
|
146
|
+
const parsed = {
|
|
147
|
+
version: 1,
|
|
148
|
+
fd: expectFd(readOptionalNumber(value.fd, "fd") ?? -1),
|
|
149
|
+
size: expectPositiveSize(readOptionalNumber(value.size, "size") ?? 0),
|
|
150
|
+
byteLength: expectPositiveSize(readOptionalNumber(value.byteLength, "byteLength") ??
|
|
151
|
+
readOptionalNumber(value.size, "size") ??
|
|
152
|
+
0),
|
|
153
|
+
runtime: readOptionalRuntime(value.runtime),
|
|
154
|
+
kind: readOptionalKind(value.kind),
|
|
155
|
+
baseAddressMod64: readOptionalNumber(value.baseAddressMod64, "baseAddressMod64"),
|
|
156
|
+
};
|
|
157
|
+
const name = readOptionalName(value.name);
|
|
158
|
+
if (name !== undefined)
|
|
159
|
+
parsed.name = name;
|
|
160
|
+
return parsed;
|
|
161
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { alignToCacheLine, CACHE_LINE_SIZE, type ConnectionRuntime, type CreateSharedMemoryOptions, expectFd, expectPositiveSize, type MapSharedMemoryOptions, requireSharedArrayBuffer, type SharedMemoryBuffer, type SharedMemoryBufferKind, type SharedMemoryConnectionPrimitives, type SharedMemoryMapping, } from "./types.js";
|
|
2
|
+
export { BufferReference, BUFFER_REFERENCE_KIND, type BufferReferenceMetadata, type BufferReferenceRuntime, isBufferReferenceMetadata, } from "./buffer-reference.js";
|
|
3
|
+
export { FileDescriptor, type FileDescriptorMetadata, parseFileDescriptorMetadata, } from "./file-descriptor.js";
|
|
4
|
+
export { getDefaultProcessSharedBufferPrimitives, parseProcessSharedBufferMetadata, PROCESS_SHARED_BUFFER_BRAND, ProcessSharedBuffer, type ProcessSharedBufferCreator, type ProcessSharedBufferMapper, type ProcessSharedBufferMetadata, type ProcessSharedBufferPrimitives, type ProcessSharedBufferRange, type ProcessSharedBufferView, type ProcessSharedBufferViewConstructor, setDefaultProcessSharedBufferPrimitives, } from "./process-shared-buffer.js";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { alignToCacheLine, CACHE_LINE_SIZE, expectFd, expectPositiveSize, requireSharedArrayBuffer, } from "./types.js";
|
|
2
|
+
export { BufferReference, BUFFER_REFERENCE_KIND, isBufferReferenceMetadata, } from "./buffer-reference.js";
|
|
3
|
+
export { FileDescriptor, parseFileDescriptorMetadata, } from "./file-descriptor.js";
|
|
4
|
+
export { getDefaultProcessSharedBufferPrimitives, parseProcessSharedBufferMetadata, PROCESS_SHARED_BUFFER_BRAND, ProcessSharedBuffer, setDefaultProcessSharedBufferPrimitives, } from "./process-shared-buffer.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
type NodeRequire = (specifier: string) => unknown;
|
|
2
|
+
export type NodeNativeAddonName = "knitting_shared_memory" | "knitting_shm" | "knitting_buffer_pointer";
|
|
3
|
+
export declare const nodeNativeAddonSpecifiers: (name: NodeNativeAddonName) => readonly string[];
|
|
4
|
+
export declare const loadNodeNativeAddon: <T>(require: NodeRequire, name: NodeNativeAddonName, specifier?: string) => T;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { resolveKnittingPackageAsset } from "./package-assets.js";
|
|
2
|
+
const readNodePlatformInfo = () => {
|
|
3
|
+
const processLike = globalThis.process;
|
|
4
|
+
if (typeof processLike?.platform !== "string" ||
|
|
5
|
+
typeof processLike.arch !== "string") {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
return {
|
|
9
|
+
arch: processLike.arch,
|
|
10
|
+
modules: processLike.versions?.modules,
|
|
11
|
+
platform: processLike.platform,
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export const nodeNativeAddonSpecifiers = (name) => {
|
|
15
|
+
const platformInfo = readNodePlatformInfo();
|
|
16
|
+
const fallback = resolveKnittingPackageAsset("build", "Release", `${name}.node`);
|
|
17
|
+
if (platformInfo === undefined)
|
|
18
|
+
return [fallback];
|
|
19
|
+
const nodeModuleAbi = platformInfo.modules;
|
|
20
|
+
if (typeof nodeModuleAbi === "string" && nodeModuleAbi.length > 0) {
|
|
21
|
+
return [
|
|
22
|
+
resolveKnittingPackageAsset("prebuilds", `${platformInfo.platform}-${platformInfo.arch}-node-${nodeModuleAbi}`, `${name}.node`),
|
|
23
|
+
fallback,
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
return [
|
|
27
|
+
resolveKnittingPackageAsset("prebuilds", `${platformInfo.platform}-${platformInfo.arch}`, `${name}.node`),
|
|
28
|
+
fallback,
|
|
29
|
+
];
|
|
30
|
+
};
|
|
31
|
+
export const loadNodeNativeAddon = (require, name, specifier) => {
|
|
32
|
+
if (specifier !== undefined)
|
|
33
|
+
return require(specifier);
|
|
34
|
+
const errors = [];
|
|
35
|
+
for (const candidate of nodeNativeAddonSpecifiers(name)) {
|
|
36
|
+
try {
|
|
37
|
+
return require(candidate);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
errors.push(`${candidate}: ${String(error)}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`Could not load native addon ${name}. Tried:\n${errors.join("\n")}`);
|
|
44
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type NodeBufferPointerAddon = {
|
|
2
|
+
getPointer: (buffer: ArrayBufferView | ArrayBuffer | SharedArrayBuffer) => bigint;
|
|
3
|
+
retainPointer: (buffer: ArrayBufferView | ArrayBuffer | SharedArrayBuffer) => {
|
|
4
|
+
pointer: bigint;
|
|
5
|
+
byteLength: number;
|
|
6
|
+
token: bigint;
|
|
7
|
+
};
|
|
8
|
+
releasePointer: (token: bigint) => boolean;
|
|
9
|
+
wrapPointer: (pointer: bigint, byteLength: number) => ArrayBuffer;
|
|
10
|
+
detachArrayBuffer: (buffer: ArrayBuffer) => boolean;
|
|
11
|
+
retainBackingStore?: (buffer: ArrayBufferView | ArrayBuffer) => {
|
|
12
|
+
pointer: bigint;
|
|
13
|
+
byteOffset: number;
|
|
14
|
+
byteLength: number;
|
|
15
|
+
token: bigint;
|
|
16
|
+
};
|
|
17
|
+
adoptBackingStore?: (token: bigint) => ArrayBuffer;
|
|
18
|
+
releaseBackingStore?: (token: bigint) => boolean;
|
|
19
|
+
};
|
|
20
|
+
export declare const loadNodeBufferPointerAddon: (specifier?: string) => NodeBufferPointerAddon;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getNodeBuiltinModule } from "../common/node-compat.js";
|
|
2
|
+
import { loadNodeNativeAddon } from "./node-addons.js";
|
|
3
|
+
let cached;
|
|
4
|
+
export const loadNodeBufferPointerAddon = (specifier) => {
|
|
5
|
+
if (specifier === undefined && cached !== undefined)
|
|
6
|
+
return cached;
|
|
7
|
+
const nodeModule = getNodeBuiltinModule("node:module");
|
|
8
|
+
if (nodeModule === undefined) {
|
|
9
|
+
throw new Error("Node buffer-pointer addon can only be loaded in Node");
|
|
10
|
+
}
|
|
11
|
+
const require = nodeModule.createRequire(import.meta.url);
|
|
12
|
+
const addon = loadNodeNativeAddon(require, "knitting_buffer_pointer", specifier);
|
|
13
|
+
if (specifier === undefined)
|
|
14
|
+
cached = addon;
|
|
15
|
+
return addon;
|
|
16
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type CreateSharedMemoryOptions, type MapSharedMemoryOptions, type SharedMemoryConnectionPrimitives, type SharedMemoryMapping } from "./types.js";
|
|
2
|
+
export type NodeSharedMemoryNativeMapping = {
|
|
3
|
+
sab: SharedArrayBuffer;
|
|
4
|
+
fd: number;
|
|
5
|
+
name?: string;
|
|
6
|
+
size: number;
|
|
7
|
+
baseAddressMod64?: number;
|
|
8
|
+
};
|
|
9
|
+
export type NodeSharedMemoryAddon = {
|
|
10
|
+
createSharedMemory: (size: number, name?: string, mode?: CreateSharedMemoryOptions["mode"]) => NodeSharedMemoryNativeMapping;
|
|
11
|
+
mapSharedMemory: (fd: number, size: number, name?: string) => NodeSharedMemoryNativeMapping;
|
|
12
|
+
unlinkSharedMemory?: (name: string) => boolean;
|
|
13
|
+
};
|
|
14
|
+
export type NodeFutexWaitResult = "woken" | "changed" | "interrupted" | "timed-out";
|
|
15
|
+
export type NodeFutexAddon = {
|
|
16
|
+
waitU32: (buffer: ArrayBuffer | SharedArrayBuffer, byteOffset: number, expected: number, timeoutMs?: number) => NodeFutexWaitResult;
|
|
17
|
+
wakeU32: (buffer: ArrayBuffer | SharedArrayBuffer, byteOffset: number, count?: number) => number;
|
|
18
|
+
notifyU32?: (buffer: ArrayBuffer | SharedArrayBuffer, byteOffset: number, count?: number) => number;
|
|
19
|
+
sleep?: (milliseconds?: number) => void;
|
|
20
|
+
yield?: () => void;
|
|
21
|
+
};
|
|
22
|
+
export declare const DEFAULT_NODE_SHARED_MEMORY_ADDON = "../../build/Release/knitting_shared_memory.node";
|
|
23
|
+
export declare const DEFAULT_NODE_FUTEX_ADDON = "../../build/Release/knitting_shm.node";
|
|
24
|
+
export declare const loadNodeSharedMemoryAddon: (specifier?: string) => NodeSharedMemoryAddon;
|
|
25
|
+
export declare const loadNodeFutexAddon: (specifier?: string) => NodeFutexAddon;
|
|
26
|
+
export declare const fromNodeNativeMapping: (mapped: NodeSharedMemoryNativeMapping) => SharedMemoryMapping<SharedArrayBuffer>;
|
|
27
|
+
export declare const createNodeSharedMemory: (options: number | CreateSharedMemoryOptions, addon?: NodeSharedMemoryAddon) => SharedMemoryMapping<SharedArrayBuffer>;
|
|
28
|
+
export declare const mapNodeSharedMemory: (options: MapSharedMemoryOptions, addon?: NodeSharedMemoryAddon) => SharedMemoryMapping<SharedArrayBuffer>;
|
|
29
|
+
export declare const createNodeConnectionPrimitives: (addon?: NodeSharedMemoryAddon) => SharedMemoryConnectionPrimitives<SharedMemoryMapping<SharedArrayBuffer>>;
|
|
30
|
+
export declare const unlinkNodeSharedMemory: (name: string, addon?: NodeSharedMemoryAddon) => boolean;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { getNodeBuiltinModule } from "../common/node-compat.js";
|
|
2
|
+
import { loadNodeNativeAddon } from "./node-addons.js";
|
|
3
|
+
import { expectFd, expectPositiveSize, readCreateMode, readCreateName, readRequiredCreateName, readCreateSize, } from "./types.js";
|
|
4
|
+
export const DEFAULT_NODE_SHARED_MEMORY_ADDON = "../../build/Release/knitting_shared_memory.node";
|
|
5
|
+
export const DEFAULT_NODE_FUTEX_ADDON = "../../build/Release/knitting_shm.node";
|
|
6
|
+
export const loadNodeSharedMemoryAddon = (specifier) => {
|
|
7
|
+
const nodeModule = getNodeBuiltinModule("node:module");
|
|
8
|
+
if (nodeModule === undefined) {
|
|
9
|
+
throw new Error("Node shared memory addon can only be loaded in Node");
|
|
10
|
+
}
|
|
11
|
+
const require = nodeModule.createRequire(import.meta.url);
|
|
12
|
+
return loadNodeNativeAddon(require, "knitting_shared_memory", specifier);
|
|
13
|
+
};
|
|
14
|
+
export const loadNodeFutexAddon = (specifier) => {
|
|
15
|
+
const nodeModule = getNodeBuiltinModule("node:module");
|
|
16
|
+
if (nodeModule === undefined) {
|
|
17
|
+
throw new Error("Node futex addon can only be loaded in Node");
|
|
18
|
+
}
|
|
19
|
+
const require = nodeModule.createRequire(import.meta.url);
|
|
20
|
+
return loadNodeNativeAddon(require, "knitting_shm", specifier);
|
|
21
|
+
};
|
|
22
|
+
export const fromNodeNativeMapping = (mapped) => {
|
|
23
|
+
const mapping = {
|
|
24
|
+
runtime: "node",
|
|
25
|
+
fd: mapped.fd,
|
|
26
|
+
size: mapped.size,
|
|
27
|
+
byteLength: mapped.sab.byteLength,
|
|
28
|
+
buffer: mapped.sab,
|
|
29
|
+
kind: "shared-array-buffer",
|
|
30
|
+
sab: mapped.sab,
|
|
31
|
+
baseAddressMod64: mapped.baseAddressMod64,
|
|
32
|
+
};
|
|
33
|
+
if (mapped.name !== undefined && mapped.name.length > 0) {
|
|
34
|
+
mapping.name = mapped.name;
|
|
35
|
+
}
|
|
36
|
+
return mapping;
|
|
37
|
+
};
|
|
38
|
+
export const createNodeSharedMemory = (options, addon = loadNodeSharedMemoryAddon()) => {
|
|
39
|
+
const size = expectPositiveSize(readCreateSize(options));
|
|
40
|
+
const mode = readCreateMode(options);
|
|
41
|
+
const name = mode === "anonymous"
|
|
42
|
+
? readCreateName(options, "knitting_shared_memory")
|
|
43
|
+
: readRequiredCreateName(options);
|
|
44
|
+
return fromNodeNativeMapping(addon.createSharedMemory(size, name, mode));
|
|
45
|
+
};
|
|
46
|
+
export const mapNodeSharedMemory = (options, addon = loadNodeSharedMemoryAddon()) => {
|
|
47
|
+
const fd = expectFd(options.fd);
|
|
48
|
+
const size = expectPositiveSize(options.size);
|
|
49
|
+
return fromNodeNativeMapping(addon.mapSharedMemory(fd, size, options.name));
|
|
50
|
+
};
|
|
51
|
+
export const createNodeConnectionPrimitives = (addon = loadNodeSharedMemoryAddon()) => ({
|
|
52
|
+
runtime: "node",
|
|
53
|
+
createSharedMemory: (options) => createNodeSharedMemory(options, addon),
|
|
54
|
+
mapSharedMemory: (options) => mapNodeSharedMemory(options, addon),
|
|
55
|
+
unlinkSharedMemory: (name) => unlinkNodeSharedMemory(name, addon),
|
|
56
|
+
});
|
|
57
|
+
export const unlinkNodeSharedMemory = (name, addon = loadNodeSharedMemoryAddon()) => {
|
|
58
|
+
if (typeof addon.unlinkSharedMemory !== "function") {
|
|
59
|
+
throw new Error("Node shared memory addon cannot unlink named mappings");
|
|
60
|
+
}
|
|
61
|
+
return addon.unlinkSharedMemory(name);
|
|
62
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const NUMERIC_ARRAY_BRAND: unique symbol;
|
|
2
|
+
export declare class NumericArray extends Array<number> {
|
|
3
|
+
}
|
|
4
|
+
export declare const isNumericArray: (value: object) => value is NumericArray;
|
|
5
|
+
export declare const numericArrayFromFloat64: (view: Float64Array) => NumericArray;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const NUMERIC_ARRAY_BRAND = Symbol.for("knitting.numericArray");
|
|
2
|
+
export class NumericArray extends Array {
|
|
3
|
+
}
|
|
4
|
+
Object.defineProperty(NumericArray.prototype, NUMERIC_ARRAY_BRAND, {
|
|
5
|
+
value: true,
|
|
6
|
+
enumerable: false,
|
|
7
|
+
writable: false,
|
|
8
|
+
configurable: false,
|
|
9
|
+
});
|
|
10
|
+
export const isNumericArray = (value) => value[NUMERIC_ARRAY_BRAND] === true;
|
|
11
|
+
export const numericArrayFromFloat64 = (view) => {
|
|
12
|
+
const length = view.length;
|
|
13
|
+
const out = new NumericArray(length);
|
|
14
|
+
for (let i = 0; i < length; i++)
|
|
15
|
+
out[i] = view[i];
|
|
16
|
+
return out;
|
|
17
|
+
};
|