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,403 @@
|
|
|
1
|
+
import { HEADER_SLOT_STRIDE_U32, HEADER_STATIC_PAYLOAD_U32, LockBound, } from "./lock.js";
|
|
2
|
+
import { getStridedSlotByteOffset } from "./byte-carpet.js";
|
|
3
|
+
import { IS_BUN, createSharedArrayBuffer, growSharedArrayBuffer, } from "../common/runtime.js";
|
|
4
|
+
import { resolvePayloadBufferOptions, } from "./payload-config.js";
|
|
5
|
+
import { isSharedBuffer, toSharedBufferRegion, } from "../common/shared-buffer-region.js";
|
|
6
|
+
const page = 1024 * 4;
|
|
7
|
+
const textEncode = new TextEncoder();
|
|
8
|
+
const textDecode = new TextDecoder();
|
|
9
|
+
const DYNAMIC_HEADER_BYTES = 64;
|
|
10
|
+
const DYNAMIC_SAFE_PADDING_BYTES = page;
|
|
11
|
+
const alignUpto64 = (n) => (n + (64 - 1)) & ~(64 - 1);
|
|
12
|
+
const isExactUint8Array = (src) => src.constructor === Uint8Array;
|
|
13
|
+
const canonicalDynamicUint8Array = (src) => isExactUint8Array(src)
|
|
14
|
+
? src
|
|
15
|
+
: new Uint8Array(src.buffer, src.byteOffset, src.byteLength);
|
|
16
|
+
const isSharedBufferEncodeIntoError = (error) => error instanceof TypeError;
|
|
17
|
+
const isSharedBufferDecodeError = (error) => error instanceof TypeError;
|
|
18
|
+
const getBufferCtor = () => {
|
|
19
|
+
const bufferCtor = globalThis.Buffer;
|
|
20
|
+
if (typeof bufferCtor?.from !== "function" ||
|
|
21
|
+
typeof bufferCtor?.allocUnsafe !== "function" ||
|
|
22
|
+
typeof bufferCtor?.allocUnsafeSlow !== "function") {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
return bufferCtor;
|
|
26
|
+
};
|
|
27
|
+
const manualEncodeInto = (str, target) => {
|
|
28
|
+
let read = 0;
|
|
29
|
+
let written = 0;
|
|
30
|
+
for (const char of str) {
|
|
31
|
+
const encoded = textEncode.encode(char);
|
|
32
|
+
if (written + encoded.byteLength > target.byteLength)
|
|
33
|
+
break;
|
|
34
|
+
target.set(encoded, written);
|
|
35
|
+
written += encoded.byteLength;
|
|
36
|
+
read += char.length;
|
|
37
|
+
}
|
|
38
|
+
return { read, written };
|
|
39
|
+
};
|
|
40
|
+
const fallbackEncodeInto = (str, target) => {
|
|
41
|
+
const scratch = new Uint8Array(target.byteLength);
|
|
42
|
+
const result = typeof textEncode.encodeInto === "function"
|
|
43
|
+
? textEncode.encodeInto(str, scratch)
|
|
44
|
+
: manualEncodeInto(str, scratch);
|
|
45
|
+
if (result.written > 0) {
|
|
46
|
+
target.set(scratch.subarray(0, result.written), 0);
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
const fallbackDecode = (bytes) => textDecode.decode(bytes.slice());
|
|
51
|
+
const sharedBufferEncodeInto = (str, target, textCompat) => {
|
|
52
|
+
if (typeof textEncode.encodeInto !== "function") {
|
|
53
|
+
return fallbackEncodeInto(str, target);
|
|
54
|
+
}
|
|
55
|
+
if (textCompat?.encodeInto === true) {
|
|
56
|
+
return textEncode.encodeInto(str, target);
|
|
57
|
+
}
|
|
58
|
+
if (textCompat?.encodeInto === false)
|
|
59
|
+
return fallbackEncodeInto(str, target);
|
|
60
|
+
try {
|
|
61
|
+
return textEncode.encodeInto(str, target);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (!isSharedBufferEncodeIntoError(error))
|
|
65
|
+
throw error;
|
|
66
|
+
return fallbackEncodeInto(str, target);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const sharedBufferDecode = (bytes, textCompat) => {
|
|
70
|
+
if (textCompat?.decode === true)
|
|
71
|
+
return textDecode.decode(bytes);
|
|
72
|
+
if (textCompat?.decode === false)
|
|
73
|
+
return fallbackDecode(bytes);
|
|
74
|
+
try {
|
|
75
|
+
return textDecode.decode(bytes);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (!isSharedBufferDecodeError(error))
|
|
79
|
+
throw error;
|
|
80
|
+
return fallbackDecode(bytes);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
export const createSharedDynamicBufferIO = ({ sab, payloadConfig, textCompat, }) => {
|
|
84
|
+
const payloadRegion = sab === undefined
|
|
85
|
+
? undefined
|
|
86
|
+
: toSharedBufferRegion(sab);
|
|
87
|
+
const hasExplicitRegion = sab !== undefined && !isSharedBuffer(sab);
|
|
88
|
+
const hasExternalArrayBuffer = payloadRegion?.sab instanceof ArrayBuffer &&
|
|
89
|
+
!(payloadRegion.sab instanceof SharedArrayBuffer);
|
|
90
|
+
const forceFixedRegion = hasExplicitRegion || hasExternalArrayBuffer;
|
|
91
|
+
const regionByteLength = payloadRegion?.byteLength;
|
|
92
|
+
const bufferCtor = (IS_BUN &&
|
|
93
|
+
payloadRegion?.sab instanceof ArrayBuffer &&
|
|
94
|
+
!(payloadRegion.sab instanceof SharedArrayBuffer))
|
|
95
|
+
? undefined
|
|
96
|
+
: getBufferCtor();
|
|
97
|
+
const resolvedPayload = resolvePayloadBufferOptions({
|
|
98
|
+
sab: payloadRegion?.sab,
|
|
99
|
+
options: !forceFixedRegion || regionByteLength === undefined
|
|
100
|
+
? payloadConfig
|
|
101
|
+
: {
|
|
102
|
+
...payloadConfig,
|
|
103
|
+
mode: "fixed",
|
|
104
|
+
payloadInitialBytes: payloadConfig?.payloadInitialBytes ??
|
|
105
|
+
regionByteLength,
|
|
106
|
+
payloadMaxByteLength: payloadConfig?.payloadMaxByteLength ??
|
|
107
|
+
regionByteLength,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
const canGrow = resolvedPayload.mode === "growable";
|
|
111
|
+
let lockSAB = payloadRegion?.sab ??
|
|
112
|
+
(canGrow
|
|
113
|
+
? createSharedArrayBuffer(resolvedPayload.payloadInitialBytes, resolvedPayload.payloadMaxByteLength)
|
|
114
|
+
: createSharedArrayBuffer(resolvedPayload.payloadInitialBytes));
|
|
115
|
+
let baseByteOffset = payloadRegion?.byteOffset ?? 0;
|
|
116
|
+
let backingByteLength = payloadRegion?.byteLength ?? lockSAB.byteLength;
|
|
117
|
+
let u8 = new Uint8Array(lockSAB, baseByteOffset + DYNAMIC_HEADER_BYTES, Math.max(0, backingByteLength - DYNAMIC_HEADER_BYTES));
|
|
118
|
+
const requireBufferView = bufferCtor
|
|
119
|
+
? (buffer, byteOffset) => {
|
|
120
|
+
const view = bufferCtor.from(buffer, byteOffset + DYNAMIC_HEADER_BYTES);
|
|
121
|
+
if (view.buffer !== buffer) {
|
|
122
|
+
throw new Error("Buffer view does not alias shared buffer");
|
|
123
|
+
}
|
|
124
|
+
return view;
|
|
125
|
+
}
|
|
126
|
+
: undefined;
|
|
127
|
+
let buf = requireBufferView?.(lockSAB, baseByteOffset);
|
|
128
|
+
let f64 = new Float64Array(lockSAB, baseByteOffset + DYNAMIC_HEADER_BYTES, Math.max(0, backingByteLength - DYNAMIC_HEADER_BYTES) >>> 3);
|
|
129
|
+
const capacityBytes = () => backingByteLength - DYNAMIC_HEADER_BYTES;
|
|
130
|
+
const ensureCapacity = (neededBytes) => {
|
|
131
|
+
if (capacityBytes() >= neededBytes)
|
|
132
|
+
return true;
|
|
133
|
+
if (!canGrow)
|
|
134
|
+
return false;
|
|
135
|
+
try {
|
|
136
|
+
if (!(lockSAB instanceof SharedArrayBuffer))
|
|
137
|
+
return false;
|
|
138
|
+
lockSAB = growSharedArrayBuffer(lockSAB, alignUpto64(DYNAMIC_HEADER_BYTES + neededBytes + DYNAMIC_SAFE_PADDING_BYTES));
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
baseByteOffset = 0;
|
|
144
|
+
backingByteLength = lockSAB.byteLength;
|
|
145
|
+
u8 = new Uint8Array(lockSAB, baseByteOffset + DYNAMIC_HEADER_BYTES, backingByteLength - DYNAMIC_HEADER_BYTES);
|
|
146
|
+
buf = requireBufferView?.(lockSAB, baseByteOffset);
|
|
147
|
+
f64 = new Float64Array(lockSAB, baseByteOffset + DYNAMIC_HEADER_BYTES, (backingByteLength - DYNAMIC_HEADER_BYTES) >>> 3);
|
|
148
|
+
return true;
|
|
149
|
+
};
|
|
150
|
+
const readUtf8 = (start, end) => {
|
|
151
|
+
if (!buf) {
|
|
152
|
+
return sharedBufferDecode(u8.subarray(start, end), textCompat);
|
|
153
|
+
}
|
|
154
|
+
return buf.toString("utf8", start, end);
|
|
155
|
+
};
|
|
156
|
+
const writeBinary = (src, start = 0) => {
|
|
157
|
+
const bytes = canonicalDynamicUint8Array(src);
|
|
158
|
+
if (!ensureCapacity(start + bytes.byteLength)) {
|
|
159
|
+
return -1;
|
|
160
|
+
}
|
|
161
|
+
u8.set(bytes, start);
|
|
162
|
+
return bytes.byteLength;
|
|
163
|
+
};
|
|
164
|
+
const writeBuffer = (src, start = 0) => {
|
|
165
|
+
const bytes = src.byteLength;
|
|
166
|
+
if (!ensureCapacity(start + bytes)) {
|
|
167
|
+
return -1;
|
|
168
|
+
}
|
|
169
|
+
u8.set(src, start);
|
|
170
|
+
return bytes;
|
|
171
|
+
};
|
|
172
|
+
const writeArrayBuffer = (src, start = 0) => {
|
|
173
|
+
const bytes = src.byteLength;
|
|
174
|
+
if (!ensureCapacity(start + bytes)) {
|
|
175
|
+
return -1;
|
|
176
|
+
}
|
|
177
|
+
u8.set(new Uint8Array(src), start);
|
|
178
|
+
return bytes;
|
|
179
|
+
};
|
|
180
|
+
const write8Binary = (src, start = 0) => {
|
|
181
|
+
const bytes = src.byteLength;
|
|
182
|
+
if (!ensureCapacity(start + bytes)) {
|
|
183
|
+
return -1;
|
|
184
|
+
}
|
|
185
|
+
f64.set(src, start >>> 3);
|
|
186
|
+
return bytes;
|
|
187
|
+
};
|
|
188
|
+
const readBytesCopy = (start, end) => u8.slice(start, end);
|
|
189
|
+
const readBytesView = (start, end) => u8.subarray(start, end);
|
|
190
|
+
const readBytesBufferCopy = (start, end) => {
|
|
191
|
+
if (!bufferCtor || !buf)
|
|
192
|
+
return readBytesCopy(start, end);
|
|
193
|
+
const length = Math.max(0, (end - start) | 0);
|
|
194
|
+
const out = bufferCtor.allocUnsafe(length);
|
|
195
|
+
if (length === 0)
|
|
196
|
+
return out;
|
|
197
|
+
buf.copy(out, 0, start, end);
|
|
198
|
+
return out;
|
|
199
|
+
};
|
|
200
|
+
const readBytesArrayBufferCopy = (start, end) => {
|
|
201
|
+
if (!bufferCtor || !buf) {
|
|
202
|
+
const out = readBytesCopy(start, end);
|
|
203
|
+
return out.buffer;
|
|
204
|
+
}
|
|
205
|
+
const length = Math.max(0, (end - start) | 0);
|
|
206
|
+
if (length === 0)
|
|
207
|
+
return new ArrayBuffer(0);
|
|
208
|
+
const out = bufferCtor.allocUnsafeSlow(length);
|
|
209
|
+
buf.copy(out, 0, start, end);
|
|
210
|
+
return out.buffer;
|
|
211
|
+
};
|
|
212
|
+
const read8BytesFloatCopy = (start, end) => f64.slice(start >>> 3, end >>> 3);
|
|
213
|
+
const read8BytesFloatView = (start, end) => f64.subarray(start >>> 3, end >>> 3);
|
|
214
|
+
const writeUtf8 = (str, start, reservedBytes = str.length * 3) => {
|
|
215
|
+
if (!ensureCapacity(start + reservedBytes)) {
|
|
216
|
+
return -1;
|
|
217
|
+
}
|
|
218
|
+
const target = u8.subarray(start, start + reservedBytes);
|
|
219
|
+
if (!buf) {
|
|
220
|
+
const { read, written } = sharedBufferEncodeInto(str, target, textCompat);
|
|
221
|
+
if (read !== str.length)
|
|
222
|
+
return -1;
|
|
223
|
+
return written;
|
|
224
|
+
}
|
|
225
|
+
const { read, written } = textEncode.encodeInto(str, target);
|
|
226
|
+
if (read !== str.length)
|
|
227
|
+
return -1;
|
|
228
|
+
return written;
|
|
229
|
+
};
|
|
230
|
+
return {
|
|
231
|
+
readUtf8,
|
|
232
|
+
writeBinary,
|
|
233
|
+
writeBuffer,
|
|
234
|
+
writeArrayBuffer,
|
|
235
|
+
write8Binary,
|
|
236
|
+
readBytesCopy,
|
|
237
|
+
readBytesView,
|
|
238
|
+
readBytesBufferCopy,
|
|
239
|
+
readBufferCopy: readBytesBufferCopy,
|
|
240
|
+
readBytesArrayBufferCopy,
|
|
241
|
+
readArrayBufferCopy: readBytesArrayBufferCopy,
|
|
242
|
+
read8BytesFloatCopy,
|
|
243
|
+
read8BytesFloatView,
|
|
244
|
+
writeUtf8,
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
// it has to be convert it to 8
|
|
248
|
+
export const createSharedStaticBufferIO = ({ headersBuffer, slotStrideU32, textCompat, }) => {
|
|
249
|
+
const bufferCtor = getBufferCtor();
|
|
250
|
+
const buffer = headersBuffer instanceof Uint32Array
|
|
251
|
+
? headersBuffer.buffer
|
|
252
|
+
: headersBuffer;
|
|
253
|
+
const baseByteOffset = headersBuffer instanceof Uint32Array
|
|
254
|
+
? headersBuffer.byteOffset
|
|
255
|
+
: 0;
|
|
256
|
+
const u32Bytes = Uint32Array.BYTES_PER_ELEMENT;
|
|
257
|
+
const slotStride = slotStrideU32 ?? HEADER_SLOT_STRIDE_U32;
|
|
258
|
+
const writableBytes = HEADER_STATIC_PAYLOAD_U32 * u32Bytes;
|
|
259
|
+
const baseU8 = new Uint8Array(buffer, baseByteOffset);
|
|
260
|
+
const baseBuf = bufferCtor?.from(buffer, baseByteOffset);
|
|
261
|
+
const baseF64 = new Float64Array(buffer, baseByteOffset, (buffer.byteLength - baseByteOffset) >>> 3);
|
|
262
|
+
const slotStartBytes = (at) => getStridedSlotByteOffset({
|
|
263
|
+
slotIndex: at,
|
|
264
|
+
slotStrideU32: slotStride,
|
|
265
|
+
baseByteOffset,
|
|
266
|
+
baseU32: LockBound.header,
|
|
267
|
+
});
|
|
268
|
+
const slotByteOffsets = new Uint32Array(LockBound.slots);
|
|
269
|
+
for (let i = 0; i < LockBound.slots; i++) {
|
|
270
|
+
slotByteOffsets[i] = slotStartBytes(i) - baseByteOffset;
|
|
271
|
+
}
|
|
272
|
+
// The static region is itself a Uint32Array, shared in-process with native
|
|
273
|
+
// endianness. Fixed-shape numeric payloads (e.g. ProcessSharedBuffer
|
|
274
|
+
// descriptors) can be written/read as raw words straight into the slot,
|
|
275
|
+
// skipping the byte scratch + DataView + copy that the generic paths require.
|
|
276
|
+
const baseU32 = new Uint32Array(buffer, baseByteOffset, (buffer.byteLength - baseByteOffset) >>> 2);
|
|
277
|
+
const slotU32Offsets = new Uint32Array(LockBound.slots);
|
|
278
|
+
for (let i = 0; i < LockBound.slots; i++) {
|
|
279
|
+
slotU32Offsets[i] = slotByteOffsets[i] >>> 2;
|
|
280
|
+
}
|
|
281
|
+
const writeU32Words = (words, count, at) => {
|
|
282
|
+
const base = slotU32Offsets[at];
|
|
283
|
+
for (let i = 0; i < count; i++)
|
|
284
|
+
baseU32[base + i] = words[i];
|
|
285
|
+
return count * u32Bytes;
|
|
286
|
+
};
|
|
287
|
+
const readU32Words = (out, count, at) => {
|
|
288
|
+
const base = slotU32Offsets[at];
|
|
289
|
+
for (let i = 0; i < count; i++)
|
|
290
|
+
out[i] = baseU32[base + i];
|
|
291
|
+
return out;
|
|
292
|
+
};
|
|
293
|
+
const canWrite = (start, length) => (start | 0) >= 0 && (start + length) <= writableBytes;
|
|
294
|
+
const writeUtf8 = (str, at) => {
|
|
295
|
+
const start = slotByteOffsets[at];
|
|
296
|
+
const target = baseU8.subarray(start, start + writableBytes);
|
|
297
|
+
if (!baseBuf) {
|
|
298
|
+
const { read, written } = sharedBufferEncodeInto(str, target, textCompat);
|
|
299
|
+
if (read !== str.length)
|
|
300
|
+
return -1;
|
|
301
|
+
return written;
|
|
302
|
+
}
|
|
303
|
+
const { read, written } = textEncode.encodeInto(str, target);
|
|
304
|
+
if (read !== str.length)
|
|
305
|
+
return -1;
|
|
306
|
+
return written;
|
|
307
|
+
};
|
|
308
|
+
const readUtf8 = (start, end, at) => {
|
|
309
|
+
const slotStart = slotByteOffsets[at];
|
|
310
|
+
if (!baseBuf) {
|
|
311
|
+
return sharedBufferDecode(baseU8.subarray(slotStart + start, slotStart + end), textCompat);
|
|
312
|
+
}
|
|
313
|
+
return baseBuf.toString("utf8", slotStart + start, slotStart + end);
|
|
314
|
+
};
|
|
315
|
+
const writeBinary = (src, at, start = 0) => {
|
|
316
|
+
baseU8.set(src, slotByteOffsets[at] + start);
|
|
317
|
+
return src.byteLength;
|
|
318
|
+
};
|
|
319
|
+
const writeBuffer = (src, at, start = 0) => {
|
|
320
|
+
baseU8.set(src, slotByteOffsets[at] + start);
|
|
321
|
+
return src.byteLength;
|
|
322
|
+
};
|
|
323
|
+
const writeArrayBuffer = (src, at, start = 0) => {
|
|
324
|
+
const bytes = src.byteLength;
|
|
325
|
+
baseU8.set(new Uint8Array(src), slotByteOffsets[at] + start);
|
|
326
|
+
return bytes;
|
|
327
|
+
};
|
|
328
|
+
const writeExactUint8Array = (src, at, start = 0) => {
|
|
329
|
+
baseU8.set(src, slotByteOffsets[at] + start);
|
|
330
|
+
return src.byteLength;
|
|
331
|
+
};
|
|
332
|
+
const writeUint8Array = (src, at, start = 0) => {
|
|
333
|
+
if (!isExactUint8Array(src))
|
|
334
|
+
return -1;
|
|
335
|
+
return writeExactUint8Array(src, at, start);
|
|
336
|
+
};
|
|
337
|
+
const write8Binary = (src, at, start = 0) => {
|
|
338
|
+
const bytes = src.byteLength;
|
|
339
|
+
if (!canWrite(start, bytes))
|
|
340
|
+
return -1;
|
|
341
|
+
baseF64.set(src, (slotByteOffsets[at] + start) >>> 3);
|
|
342
|
+
return bytes;
|
|
343
|
+
};
|
|
344
|
+
const readBytesCopy = (start, end, at) => baseU8.slice(slotByteOffsets[at] + start, slotByteOffsets[at] + end);
|
|
345
|
+
const readBytesView = (start, end, at) => baseU8.subarray(slotByteOffsets[at] + start, slotByteOffsets[at] + end);
|
|
346
|
+
const readBytesBufferCopy = (start, end, at) => {
|
|
347
|
+
if (!bufferCtor || !baseBuf)
|
|
348
|
+
return readBytesCopy(start, end, at);
|
|
349
|
+
const length = end - start;
|
|
350
|
+
const out = bufferCtor.allocUnsafe(length);
|
|
351
|
+
const slotStart = slotByteOffsets[at];
|
|
352
|
+
baseBuf.copy(out, 0, slotStart + start, slotStart + end);
|
|
353
|
+
return out;
|
|
354
|
+
};
|
|
355
|
+
const readUint8ArrayBufferCopy = (start, end, at) => {
|
|
356
|
+
if (!bufferCtor)
|
|
357
|
+
return readBytesCopy(start, end, at);
|
|
358
|
+
const bytes = readBytesBufferCopy(start, end, at);
|
|
359
|
+
return new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
360
|
+
};
|
|
361
|
+
const readUint8ArraySliceCopy = (start, end, at) => readBytesCopy(start, end, at);
|
|
362
|
+
const readUint8ArrayCopy = IS_BUN
|
|
363
|
+
? readUint8ArraySliceCopy
|
|
364
|
+
: readUint8ArrayBufferCopy;
|
|
365
|
+
const readBytesArrayBufferCopy = (start, end, at) => {
|
|
366
|
+
if (!bufferCtor || !baseBuf) {
|
|
367
|
+
const out = readBytesCopy(start, end, at);
|
|
368
|
+
return out.buffer;
|
|
369
|
+
}
|
|
370
|
+
const length = Math.max(0, (end - start) | 0);
|
|
371
|
+
if (length === 0)
|
|
372
|
+
return new ArrayBuffer(0);
|
|
373
|
+
const out = bufferCtor.allocUnsafeSlow(length);
|
|
374
|
+
const slotStart = slotByteOffsets[at];
|
|
375
|
+
baseBuf.copy(out, 0, slotStart + start, slotStart + end);
|
|
376
|
+
return out.buffer;
|
|
377
|
+
};
|
|
378
|
+
const read8BytesFloatCopy = (start, end, at) => baseF64.slice((slotByteOffsets[at] + start) >>> 3, (slotByteOffsets[at] + end) >>> 3);
|
|
379
|
+
const read8BytesFloatView = (start, end, at) => baseF64.subarray((slotByteOffsets[at] + start) >>> 3, (slotByteOffsets[at] + end) >>> 3);
|
|
380
|
+
return {
|
|
381
|
+
writeUtf8,
|
|
382
|
+
readUtf8,
|
|
383
|
+
writeBinary,
|
|
384
|
+
writeBuffer,
|
|
385
|
+
writeArrayBuffer,
|
|
386
|
+
writeExactUint8Array,
|
|
387
|
+
writeUint8Array,
|
|
388
|
+
writeU32Words,
|
|
389
|
+
readU32Words,
|
|
390
|
+
write8Binary,
|
|
391
|
+
readBytesCopy,
|
|
392
|
+
readBytesView,
|
|
393
|
+
readBytesBufferCopy,
|
|
394
|
+
readBufferCopy: readBytesBufferCopy,
|
|
395
|
+
readUint8ArrayCopy,
|
|
396
|
+
readUint8ArrayBufferCopy,
|
|
397
|
+
readBytesArrayBufferCopy,
|
|
398
|
+
readArrayBufferCopy: readBytesArrayBufferCopy,
|
|
399
|
+
read8BytesFloatCopy,
|
|
400
|
+
read8BytesFloatView,
|
|
401
|
+
maxBytes: writableBytes,
|
|
402
|
+
};
|
|
403
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { PermissionProtocolInput, ResolvedPermissionProtocol } from "./protocol.js";
|
|
2
|
+
type ProcessPermissionRuntime = "bun" | "deno" | "node";
|
|
3
|
+
type PermissionCompatibilityLevel = "exact" | "coarse" | "unsupported";
|
|
4
|
+
type ProcessPermissionTarget = {
|
|
5
|
+
runtime: ProcessPermissionRuntime;
|
|
6
|
+
/**
|
|
7
|
+
* Omitted when a wrapper or another host runtime makes the Node version
|
|
8
|
+
* impossible to prove synchronously.
|
|
9
|
+
*/
|
|
10
|
+
nodeMajor?: number;
|
|
11
|
+
};
|
|
12
|
+
type PermissionCompatibilityCheck = {
|
|
13
|
+
permission: string;
|
|
14
|
+
level: PermissionCompatibilityLevel;
|
|
15
|
+
explicit: boolean;
|
|
16
|
+
reason: string;
|
|
17
|
+
};
|
|
18
|
+
type ProcessPermissionCompatibilityReport = {
|
|
19
|
+
target: ProcessPermissionTarget;
|
|
20
|
+
checks: PermissionCompatibilityCheck[];
|
|
21
|
+
};
|
|
22
|
+
export declare const classifyProcessPermissionCompatibility: ({ permission, resolved, target, }: {
|
|
23
|
+
permission: PermissionProtocolInput | undefined;
|
|
24
|
+
resolved: ResolvedPermissionProtocol | undefined;
|
|
25
|
+
target: ProcessPermissionTarget;
|
|
26
|
+
}) => ProcessPermissionCompatibilityReport;
|
|
27
|
+
export declare const enforceProcessPermissionCompatibility: (report: ProcessPermissionCompatibilityReport) => void;
|
|
28
|
+
export type { PermissionCompatibilityCheck, PermissionCompatibilityLevel, ProcessPermissionCompatibilityReport, ProcessPermissionRuntime, ProcessPermissionTarget, };
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
const hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
2
|
+
const hasExplicit = (value, key) => value !== undefined && hasOwn(value, key);
|
|
3
|
+
const hasNonEmptyArray = (value, key) => Array.isArray(value?.[key]) && value[key].length > 0;
|
|
4
|
+
const explicitProtocolObject = (permission) => permission != null && typeof permission === "object"
|
|
5
|
+
? permission
|
|
6
|
+
: undefined;
|
|
7
|
+
const explicitNestedObject = (input, key) => {
|
|
8
|
+
const value = input?.[key];
|
|
9
|
+
return value != null && typeof value === "object"
|
|
10
|
+
? value
|
|
11
|
+
: undefined;
|
|
12
|
+
};
|
|
13
|
+
const targetLabel = (target) => {
|
|
14
|
+
if (target.runtime !== "node") {
|
|
15
|
+
return `${target.runtime[0].toUpperCase()}${target.runtime.slice(1)}`;
|
|
16
|
+
}
|
|
17
|
+
return target.nodeMajor === undefined
|
|
18
|
+
? "Node (version unknown)"
|
|
19
|
+
: `Node ${target.nodeMajor}`;
|
|
20
|
+
};
|
|
21
|
+
const nodeTargetUsesFfiTransport = (target) => target.runtime === "node" &&
|
|
22
|
+
target.nodeMajor !== undefined &&
|
|
23
|
+
target.nodeMajor >= 26 &&
|
|
24
|
+
target.nodeMajor % 2 === 0;
|
|
25
|
+
const permissionCheck = (permission, level, reason) => ({
|
|
26
|
+
permission,
|
|
27
|
+
level,
|
|
28
|
+
reason,
|
|
29
|
+
});
|
|
30
|
+
const classifyRestriction = ({ target, permission, scoped, processNativeTransport = false, }) => {
|
|
31
|
+
const label = targetLabel(target);
|
|
32
|
+
const exact = (reason) => permissionCheck(permission, "exact", reason);
|
|
33
|
+
const coarse = (reason) => permissionCheck(permission, "coarse", reason);
|
|
34
|
+
const unsupported = (reason) => permissionCheck(permission, "unsupported", reason);
|
|
35
|
+
if (target.runtime === "bun") {
|
|
36
|
+
return unsupported("Bun process workers do not expose a matching runtime permission control.");
|
|
37
|
+
}
|
|
38
|
+
if (target.runtime === "deno") {
|
|
39
|
+
if (permission === "workers") {
|
|
40
|
+
return unsupported("Knitting does not currently configure a Deno worker-spawn restriction.");
|
|
41
|
+
}
|
|
42
|
+
if (permission === "wasi") {
|
|
43
|
+
return unsupported("Deno does not expose a matching Knitting WASI process permission.");
|
|
44
|
+
}
|
|
45
|
+
if (processNativeTransport &&
|
|
46
|
+
(permission === "ffi" || permission === "denyFfi")) {
|
|
47
|
+
return unsupported("Deno process workers require --allow-ffi for Knitting's shared-memory transport.");
|
|
48
|
+
}
|
|
49
|
+
return exact("Deno can represent this restriction with scoped runtime flags.");
|
|
50
|
+
}
|
|
51
|
+
if (permission === "read" || permission === "write") {
|
|
52
|
+
return exact(`${label} supports scoped filesystem allow rules.`);
|
|
53
|
+
}
|
|
54
|
+
if (permission === "run") {
|
|
55
|
+
return scoped
|
|
56
|
+
? coarse(`${label} can only allow or deny all child processes, not an executable allow-list.`)
|
|
57
|
+
: exact(`${label} can deny all child processes.`);
|
|
58
|
+
}
|
|
59
|
+
if (permission === "workers") {
|
|
60
|
+
return exact(`${label} can deny worker creation.`);
|
|
61
|
+
}
|
|
62
|
+
if (permission === "wasi") {
|
|
63
|
+
return exact(`${label} can deny WASI.`);
|
|
64
|
+
}
|
|
65
|
+
if (permission === "net") {
|
|
66
|
+
if (target.nodeMajor === undefined) {
|
|
67
|
+
return unsupported("The Node version is unknown, so Knitting cannot prove that network denial is available.");
|
|
68
|
+
}
|
|
69
|
+
if (target.nodeMajor < 25) {
|
|
70
|
+
return unsupported(`${label} has no network permission control.`);
|
|
71
|
+
}
|
|
72
|
+
return scoped
|
|
73
|
+
? coarse(`${label} --allow-net is all-or-nothing and cannot enforce a host allow-list.`)
|
|
74
|
+
: exact(`${label} denies network access when --allow-net is omitted.`);
|
|
75
|
+
}
|
|
76
|
+
if (permission === "node.allowAddons") {
|
|
77
|
+
if (nodeTargetUsesFfiTransport(target)) {
|
|
78
|
+
return exact(`${label} uses node:ffi rather than addons for Knitting's process transport.`);
|
|
79
|
+
}
|
|
80
|
+
return unsupported(`${label} process workers require addon permission for Knitting's shared-memory transport.`);
|
|
81
|
+
}
|
|
82
|
+
if (permission === "node.allowFfi") {
|
|
83
|
+
if (target.nodeMajor !== undefined &&
|
|
84
|
+
!nodeTargetUsesFfiTransport(target)) {
|
|
85
|
+
return exact(`${label} does not use node:ffi for Knitting's process transport.`);
|
|
86
|
+
}
|
|
87
|
+
return unsupported(`${label} process workers require node:ffi permission for Knitting's shared-memory transport.`);
|
|
88
|
+
}
|
|
89
|
+
if (processNativeTransport &&
|
|
90
|
+
(permission === "ffi" || permission === "denyFfi")) {
|
|
91
|
+
return unsupported(`${label} process workers require native-code permission for Knitting's shared-memory transport.`);
|
|
92
|
+
}
|
|
93
|
+
const unsupportedReasons = {
|
|
94
|
+
denyRead: `${label} has no filesystem deny-list control.`,
|
|
95
|
+
denyWrite: `${label} has no filesystem deny-list control.`,
|
|
96
|
+
denyNet: `${label} has no network deny-list control.`,
|
|
97
|
+
allowImport: `${label} has no import-host allow-list control.`,
|
|
98
|
+
env: `${label} has no environment-variable permission control.`,
|
|
99
|
+
denyEnv: `${label} has no environment-variable deny-list control.`,
|
|
100
|
+
denyRun: `${label} has no child-process deny-list control.`,
|
|
101
|
+
sys: `${label} has no system-information permission control.`,
|
|
102
|
+
denySys: `${label} has no system-information deny-list control.`,
|
|
103
|
+
};
|
|
104
|
+
return unsupported(unsupportedReasons[permission] ??
|
|
105
|
+
`${label} cannot represent this restriction.`);
|
|
106
|
+
};
|
|
107
|
+
export const classifyProcessPermissionCompatibility = ({ permission, resolved, target, }) => {
|
|
108
|
+
if (resolved?.enabled !== true ||
|
|
109
|
+
resolved.unsafe === true ||
|
|
110
|
+
permission === "unsafe" ||
|
|
111
|
+
permission === "off") {
|
|
112
|
+
return { target, checks: [] };
|
|
113
|
+
}
|
|
114
|
+
const input = explicitProtocolObject(permission);
|
|
115
|
+
const envInput = explicitNestedObject(input, "env");
|
|
116
|
+
const nodeInput = explicitNestedObject(input, "node");
|
|
117
|
+
const denoInput = explicitNestedObject(input, "deno");
|
|
118
|
+
const checks = [];
|
|
119
|
+
const add = (permissionName, explicit, options = {}) => {
|
|
120
|
+
checks.push({
|
|
121
|
+
...classifyRestriction({
|
|
122
|
+
target,
|
|
123
|
+
permission: permissionName,
|
|
124
|
+
...options,
|
|
125
|
+
}),
|
|
126
|
+
explicit,
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
if (!resolved.readAll) {
|
|
130
|
+
add("read", hasExplicit(input, "read"), {
|
|
131
|
+
scoped: resolved.read.length > 0,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
if (!resolved.writeAll) {
|
|
135
|
+
add("write", hasExplicit(input, "write"), {
|
|
136
|
+
scoped: resolved.write.length > 0,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
if (resolved.denyRead.length > 0) {
|
|
140
|
+
add("denyRead", hasNonEmptyArray(input, "denyRead"));
|
|
141
|
+
}
|
|
142
|
+
if (resolved.denyWrite.length > 0) {
|
|
143
|
+
add("denyWrite", hasNonEmptyArray(input, "denyWrite"));
|
|
144
|
+
}
|
|
145
|
+
if (!resolved.netAll) {
|
|
146
|
+
add("net", hasExplicit(input, "net"), {
|
|
147
|
+
scoped: resolved.net.length > 0,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
if (resolved.denyNet.length > 0) {
|
|
151
|
+
add("denyNet", hasNonEmptyArray(input, "denyNet"));
|
|
152
|
+
}
|
|
153
|
+
if (!resolved.allowImportAll) {
|
|
154
|
+
add("allowImport", hasExplicit(input, "allowImport"), { scoped: resolved.allowImport.length > 0 });
|
|
155
|
+
}
|
|
156
|
+
if (!resolved.env.allowAll) {
|
|
157
|
+
add("env", hasExplicit(envInput, "allow"), {
|
|
158
|
+
scoped: resolved.env.allow.length > 0,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
if (resolved.env.deny.length > 0) {
|
|
162
|
+
add("denyEnv", hasNonEmptyArray(envInput, "deny"));
|
|
163
|
+
}
|
|
164
|
+
if (!resolved.runAll) {
|
|
165
|
+
const explicitRun = hasExplicit(input, "run") ||
|
|
166
|
+
(target.runtime === "node" &&
|
|
167
|
+
hasExplicit(nodeInput, "allowChildProcess")) ||
|
|
168
|
+
(target.runtime === "deno" &&
|
|
169
|
+
hasExplicit(denoInput, "allowRun"));
|
|
170
|
+
add("run", explicitRun, { scoped: resolved.run.length > 0 });
|
|
171
|
+
}
|
|
172
|
+
if (resolved.denyRun.length > 0) {
|
|
173
|
+
add("denyRun", hasNonEmptyArray(input, "denyRun"));
|
|
174
|
+
}
|
|
175
|
+
if (!resolved.workers) {
|
|
176
|
+
const explicitWorkers = hasExplicit(input, "workers") ||
|
|
177
|
+
(target.runtime === "node" &&
|
|
178
|
+
hasExplicit(nodeInput, "allowWorker"));
|
|
179
|
+
add("workers", explicitWorkers);
|
|
180
|
+
}
|
|
181
|
+
if (!resolved.ffiAll) {
|
|
182
|
+
add("ffi", hasExplicit(input, "ffi"), {
|
|
183
|
+
scoped: resolved.ffi.length > 0,
|
|
184
|
+
processNativeTransport: true,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
if (resolved.denyFfi.length > 0) {
|
|
188
|
+
add("denyFfi", hasNonEmptyArray(input, "denyFfi"), {
|
|
189
|
+
processNativeTransport: !resolved.ffiAll,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
if (!resolved.sysAll) {
|
|
193
|
+
add("sys", hasExplicit(input, "sys"), {
|
|
194
|
+
scoped: resolved.sys.length > 0,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
if (resolved.denySys.length > 0) {
|
|
198
|
+
add("denySys", hasNonEmptyArray(input, "denySys"));
|
|
199
|
+
}
|
|
200
|
+
if (!resolved.wasi) {
|
|
201
|
+
const explicitWasi = hasExplicit(input, "wasi") ||
|
|
202
|
+
(target.runtime === "node" &&
|
|
203
|
+
hasExplicit(nodeInput, "allowWasi"));
|
|
204
|
+
add("wasi", explicitWasi);
|
|
205
|
+
}
|
|
206
|
+
if (target.runtime === "node" && nodeInput !== undefined) {
|
|
207
|
+
if (hasOwn(nodeInput, "allowAddons") && nodeInput.allowAddons === false) {
|
|
208
|
+
add("node.allowAddons", true);
|
|
209
|
+
}
|
|
210
|
+
if (hasOwn(nodeInput, "allowFfi") && nodeInput.allowFfi === false) {
|
|
211
|
+
add("node.allowFfi", true);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return { target, checks };
|
|
215
|
+
};
|
|
216
|
+
const warningKeys = new Set();
|
|
217
|
+
export const enforceProcessPermissionCompatibility = (report) => {
|
|
218
|
+
const incompatible = report.checks.filter((check) => check.level !== "exact");
|
|
219
|
+
const explicit = incompatible.filter((check) => check.explicit);
|
|
220
|
+
const label = targetLabel(report.target);
|
|
221
|
+
if (explicit.length > 0) {
|
|
222
|
+
const details = explicit
|
|
223
|
+
.map((check) => `permission.${check.permission} is ${check.level}: ${check.reason}`)
|
|
224
|
+
.join(" ");
|
|
225
|
+
throw new Error(`knitting: ${label} process workers cannot enforce the requested permission policy. ` +
|
|
226
|
+
`${details} Choose a runtime that can represent the restriction, add an OS sandbox, ` +
|
|
227
|
+
`or remove the restriction only if broader access is acceptable.`);
|
|
228
|
+
}
|
|
229
|
+
if (incompatible.length === 0)
|
|
230
|
+
return;
|
|
231
|
+
const names = [...new Set(incompatible.map((check) => check.permission))];
|
|
232
|
+
const warningKey = label;
|
|
233
|
+
if (warningKeys.has(warningKey))
|
|
234
|
+
return;
|
|
235
|
+
warningKeys.add(warningKey);
|
|
236
|
+
console.warn(`knitting: ${label} process workers cannot enforce every implicit strict ` +
|
|
237
|
+
`permission default (${names.join(", ")}). Explicit unsupported ` +
|
|
238
|
+
`restrictions fail closed; use an OS sandbox for hostile task code.`);
|
|
239
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { classifyProcessPermissionCompatibility, enforceProcessPermissionCompatibility, } from "./compatibility.js";
|
|
2
|
+
export { resolvePermissionProtocol, toRuntimePermissionFlags, } from "./protocol.js";
|
|
3
|
+
export type { PermissionCompatibilityCheck, PermissionCompatibilityLevel, ProcessPermissionCompatibilityReport, ProcessPermissionRuntime, ProcessPermissionTarget, } from "./compatibility.js";
|
|
4
|
+
export type { PermissionPath, PermissionMode, PermissionLegacyMode, SysApiName, NodePermissionSettings, DenoPermissionSettings, PermissionEnvironment, PermissionProtocol, PermissionProtocolInput, ResolvedPermissionProtocol, } from "./protocol.js";
|