knitting 0.1.54 → 0.1.55

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.
Files changed (135) hide show
  1. package/README.md +3 -3
  2. package/knitting.d.ts +797 -5
  3. package/knitting.js +9780 -5
  4. package/map.md +9 -12
  5. package/package.json +14 -13
  6. package/shared-memory.d.ts +155 -0
  7. package/shared-memory.js +1342 -0
  8. package/unsafe.d.ts +71 -1
  9. package/unsafe.js +878 -1
  10. package/utils.d.ts +31 -1
  11. package/utils.js +116 -1
  12. package/process-shared-buffer.d.ts +0 -1
  13. package/process-shared-buffer.js +0 -1
  14. package/src/api.d.ts +0 -69
  15. package/src/api.js +0 -627
  16. package/src/common/envelope.d.ts +0 -17
  17. package/src/common/envelope.js +0 -22
  18. package/src/common/module-url.d.ts +0 -1
  19. package/src/common/module-url.js +0 -24
  20. package/src/common/node-compat.d.ts +0 -20
  21. package/src/common/node-compat.js +0 -24
  22. package/src/common/path-canonical.d.ts +0 -6
  23. package/src/common/path-canonical.js +0 -41
  24. package/src/common/runtime.d.ts +0 -15
  25. package/src/common/runtime.js +0 -91
  26. package/src/common/shared-buffer-region.d.ts +0 -11
  27. package/src/common/shared-buffer-region.js +0 -21
  28. package/src/common/shared-buffer-text.d.ts +0 -16
  29. package/src/common/shared-buffer-text.js +0 -65
  30. package/src/common/task-source.d.ts +0 -3
  31. package/src/common/task-source.js +0 -84
  32. package/src/common/task-symbol.d.ts +0 -1
  33. package/src/common/task-symbol.js +0 -1
  34. package/src/common/with-resolvers.d.ts +0 -9
  35. package/src/common/with-resolvers.js +0 -23
  36. package/src/common/worker-runtime.d.ts +0 -42
  37. package/src/common/worker-runtime.js +0 -61
  38. package/src/connections/buffer-reference-native.d.ts +0 -56
  39. package/src/connections/buffer-reference-native.js +0 -217
  40. package/src/connections/buffer-reference.d.ts +0 -78
  41. package/src/connections/buffer-reference.js +0 -461
  42. package/src/connections/bun.d.ts +0 -22
  43. package/src/connections/bun.js +0 -214
  44. package/src/connections/deno.d.ts +0 -22
  45. package/src/connections/deno.js +0 -205
  46. package/src/connections/file-descriptor.d.ts +0 -39
  47. package/src/connections/file-descriptor.js +0 -161
  48. package/src/connections/index.d.ts +0 -4
  49. package/src/connections/index.js +0 -4
  50. package/src/connections/node-addons.d.ts +0 -5
  51. package/src/connections/node-addons.js +0 -43
  52. package/src/connections/node-buffer-pointer.d.ts +0 -20
  53. package/src/connections/node-buffer-pointer.js +0 -16
  54. package/src/connections/node.d.ts +0 -30
  55. package/src/connections/node.js +0 -62
  56. package/src/connections/posix.d.ts +0 -32
  57. package/src/connections/posix.js +0 -77
  58. package/src/connections/process-shared-buffer.d.ts +0 -75
  59. package/src/connections/process-shared-buffer.js +0 -279
  60. package/src/connections/shared-array-buffer-payload.d.ts +0 -36
  61. package/src/connections/shared-array-buffer-payload.js +0 -235
  62. package/src/connections/types.d.ts +0 -50
  63. package/src/connections/types.js +0 -37
  64. package/src/connections/windows.d.ts +0 -28
  65. package/src/connections/windows.js +0 -224
  66. package/src/debug/env-diff.d.ts +0 -26
  67. package/src/debug/env-diff.js +0 -49
  68. package/src/debug/gate.d.ts +0 -18
  69. package/src/debug/gate.js +0 -69
  70. package/src/debug/handle.d.ts +0 -23
  71. package/src/debug/handle.js +0 -48
  72. package/src/error.d.ts +0 -13
  73. package/src/error.js +0 -49
  74. package/src/ipc/tools/ring-queue.d.ts +0 -33
  75. package/src/ipc/tools/ring-queue.js +0 -159
  76. package/src/ipc/transport/shared-memory.d.ts +0 -23
  77. package/src/ipc/transport/shared-memory.js +0 -35
  78. package/src/memory/byte-carpet.d.ts +0 -73
  79. package/src/memory/byte-carpet.js +0 -157
  80. package/src/memory/lock.d.ts +0 -201
  81. package/src/memory/lock.js +0 -739
  82. package/src/memory/payload-config.d.ts +0 -31
  83. package/src/memory/payload-config.js +0 -67
  84. package/src/memory/payloadCodec.d.ts +0 -46
  85. package/src/memory/payloadCodec.js +0 -1334
  86. package/src/memory/regionRegistry.d.ts +0 -17
  87. package/src/memory/regionRegistry.js +0 -285
  88. package/src/memory/shared-buffer-io.d.ts +0 -55
  89. package/src/memory/shared-buffer-io.js +0 -403
  90. package/src/permission/index.d.ts +0 -2
  91. package/src/permission/index.js +0 -2
  92. package/src/permission/protocol.d.ts +0 -166
  93. package/src/permission/protocol.js +0 -650
  94. package/src/runtime/balancer.d.ts +0 -19
  95. package/src/runtime/balancer.js +0 -149
  96. package/src/runtime/dispatcher.d.ts +0 -40
  97. package/src/runtime/dispatcher.js +0 -142
  98. package/src/runtime/inline-executor.d.ts +0 -10
  99. package/src/runtime/inline-executor.js +0 -282
  100. package/src/runtime/pool.d.ts +0 -39
  101. package/src/runtime/pool.js +0 -404
  102. package/src/runtime/process-worker.d.ts +0 -92
  103. package/src/runtime/process-worker.js +0 -673
  104. package/src/runtime/tx-queue.d.ts +0 -26
  105. package/src/runtime/tx-queue.js +0 -155
  106. package/src/shared/abortSignal.d.ts +0 -23
  107. package/src/shared/abortSignal.js +0 -134
  108. package/src/types.d.ts +0 -357
  109. package/src/types.js +0 -2
  110. package/src/utils/http.d.ts +0 -29
  111. package/src/utils/http.js +0 -100
  112. package/src/worker/bootstrap.d.ts +0 -5
  113. package/src/worker/bootstrap.js +0 -78
  114. package/src/worker/composable-runners.d.ts +0 -12
  115. package/src/worker/composable-runners.js +0 -97
  116. package/src/worker/loop.d.ts +0 -2
  117. package/src/worker/loop.js +0 -382
  118. package/src/worker/process-worker-bootstrap.d.ts +0 -8
  119. package/src/worker/process-worker-bootstrap.js +0 -160
  120. package/src/worker/rx-queue.d.ts +0 -25
  121. package/src/worker/rx-queue.js +0 -173
  122. package/src/worker/safety/index.d.ts +0 -4
  123. package/src/worker/safety/index.js +0 -4
  124. package/src/worker/safety/performance.d.ts +0 -1
  125. package/src/worker/safety/performance.js +0 -17
  126. package/src/worker/safety/process.d.ts +0 -2
  127. package/src/worker/safety/process.js +0 -79
  128. package/src/worker/safety/startup.d.ts +0 -16
  129. package/src/worker/safety/startup.js +0 -30
  130. package/src/worker/safety/worker-data.d.ts +0 -2
  131. package/src/worker/safety/worker-data.js +0 -36
  132. package/src/worker/task-loader.d.ts +0 -27
  133. package/src/worker/task-loader.js +0 -78
  134. package/src/worker/timers.d.ts +0 -18
  135. package/src/worker/timers.js +0 -116
@@ -1,1334 +0,0 @@
1
- import { attachPayloadTransportFinalizer, beginPromisePayload, finishPromisePayload, getTaskSlotIndex, HEADER_BYTE_LENGTH, HEADER_SLOT_STRIDE_U32, HEADER_STATIC_PAYLOAD_U32, LockBound, PayloadBuffer, PayloadSignal, TaskIndex, } from "./lock.js";
2
- import { register } from "./regionRegistry.js";
3
- import { createSharedDynamicBufferIO, createSharedStaticBufferIO, } from "./shared-buffer-io.js";
4
- import { getStridedRegionSpanBytes } from "./byte-carpet.js";
5
- import { encoderError, ErrorKnitting } from "../error.js";
6
- import { Envelope } from "../common/envelope.js";
7
- import { resolvePayloadBufferOptions, } from "./payload-config.js";
8
- import { getSharedArrayBufferPayload, SHARED_ARRAY_BUFFER_CODEC_ID, SHARED_ARRAY_BUFFER_NUMERIC_TRANSFER, SHARED_ARRAY_BUFFER_NUMERIC_WORDS, } from "../connections/shared-array-buffer-payload.js";
9
- const BUFFER_REFERENCE_NUMERIC_TRANSFER = Symbol.for("knitting.bufferReference.numericTransfer");
10
- const memory = new ArrayBuffer(8);
11
- const Float64View = new Float64Array(memory);
12
- const BigInt64View = new BigInt64Array(memory);
13
- const Uint32View = new Uint32Array(memory);
14
- const textEncode = new TextEncoder();
15
- const runtimeBufferClass = globalThis.Buffer;
16
- const runtimeBufferByteLength = typeof runtimeBufferClass?.byteLength ===
17
- "function"
18
- ? ((value, encoding) => runtimeBufferClass.byteLength(value, encoding))
19
- : undefined;
20
- const isRuntimeBuffer = (value) => typeof runtimeBufferClass?.isBuffer === "function" &&
21
- runtimeBufferClass.isBuffer(value);
22
- const isRuntimeUint8Array = (value) => value != null &&
23
- typeof value === "object" &&
24
- Object.getPrototypeOf(value) === Uint8Array.prototype;
25
- const utf8ByteLength = !runtimeBufferByteLength
26
- ? (text) => textEncode.encode(text).byteLength
27
- : (text) => runtimeBufferByteLength(text, "utf8");
28
- const BIGINT64_MIN = -(1n << 63n);
29
- const BIGINT64_MAX = (1n << 63n) - 1n;
30
- const { parse: parseJSON, stringify: stringifyJSON } = JSON;
31
- const { for: symbolFor, keyFor: symbolKeyFor } = Symbol;
32
- const EXTERNAL_PAYLOAD_BRAND = symbolFor("knitting.payloadCodec");
33
- const BUFFER_REFERENCE_CODEC_ID = "knitting.bufferReference";
34
- const PROCESS_SHARED_BUFFER_CODEC_ID = "knitting.processSharedBuffer";
35
- const externalPayloadGlobal = globalThis;
36
- const objectGetPrototypeOf = Object.getPrototypeOf;
37
- const objectHasOwn = Object.prototype.hasOwnProperty;
38
- const arrayIsArray = Array.isArray;
39
- const objectPrototype = Object.prototype;
40
- const UNSUPPORTED_OBJECT_DETAIL = "Unsupported object type. Allowed: plain object, array, Error, Date, Envelope, Buffer, ArrayBuffer, DataView, typed arrays, and registered external payloads. Serialize it yourself.";
41
- const ENVELOPE_PAYLOAD_DETAIL = "Envelope payload must be an ArrayBuffer, SharedArrayBuffer, " +
42
- "ProcessSharedBuffer, or BufferReference.";
43
- const ENVELOPE_HEADER_DETAIL = "Envelope header must be a JSON-like value or string.";
44
- const ENVELOPE_PROMISE_DETAIL = "Envelope header cannot contain Promise values.";
45
- const DYNAMIC_PAYLOAD_LIMIT_DETAIL = "Dynamic payload exceeds maxPayloadBytes.";
46
- const DYNAMIC_PAYLOAD_CAPACITY_DETAIL = "Dynamic payload buffer capacity exceeded.";
47
- const isPlainJsonObject = (value) => {
48
- const proto = objectGetPrototypeOf(value);
49
- return proto === objectPrototype || proto === null;
50
- };
51
- const readExternalPayloadCodecId = (value) => {
52
- const codecId = value[EXTERNAL_PAYLOAD_BRAND];
53
- return typeof codecId === "string" ? codecId : undefined;
54
- };
55
- const runtimeCode = (value) => {
56
- switch (value) {
57
- case "node":
58
- return 1;
59
- case "deno":
60
- return 2;
61
- case "bun":
62
- return 3;
63
- default:
64
- return 0;
65
- }
66
- };
67
- const kindCode = (value) => {
68
- switch (value) {
69
- case "shared-array-buffer":
70
- return 1;
71
- case "external-array-buffer":
72
- return 2;
73
- default:
74
- return 0;
75
- }
76
- };
77
- const isU32 = (value) => typeof value === "number" &&
78
- Number.isInteger(value) &&
79
- value >= 0 &&
80
- value <= 0xffffffff;
81
- const isExternalPayloadLike = (value) => typeof value.toMetadata === "function" &&
82
- typeof value[EXTERNAL_PAYLOAD_BRAND] ===
83
- "string";
84
- const decodeExternalPayload = (raw) => {
85
- const payload = parseJSON(raw);
86
- if (!arrayIsArray(payload) || payload.length !== 2)
87
- return payload;
88
- const codecId = payload[0];
89
- const metadata = payload[1];
90
- if (typeof codecId !== "string") {
91
- return { codec: codecId, metadata };
92
- }
93
- const codec = externalPayloadGlobal.__KNITTING_PAYLOAD_CODECS__?.[codecId];
94
- return typeof codec?.decode === "function"
95
- ? codec.decode(metadata)
96
- : { codec: codecId, metadata };
97
- };
98
- const PROCESS_SHARED_BUFFER_NUMERIC_WORDS = 8;
99
- const BUFFER_REFERENCE_NUMERIC_WORDS = 8;
100
- const NUMERIC_SENTINEL = 0xffffffff;
101
- const decodeNumericExternalPayload = (codecId, words) => {
102
- const codec = externalPayloadGlobal.__KNITTING_PAYLOAD_CODECS__?.[codecId];
103
- if (typeof codec?.decodeNumeric === "function") {
104
- return codec.decodeNumeric(words);
105
- }
106
- return { codec: codecId, metadata: Array.from(words) };
107
- };
108
- const decodeProcessSharedBufferNumericWords = (words) => decodeNumericExternalPayload(PROCESS_SHARED_BUFFER_CODEC_ID, words);
109
- const decodeBufferReferenceNumericWords = (words) => decodeNumericExternalPayload(BUFFER_REFERENCE_CODEC_ID, words);
110
- const decodeSharedArrayBufferNumericWords = (words) => decodeNumericExternalPayload(SHARED_ARRAY_BUFFER_CODEC_ID, words);
111
- const tryEncodePrimitiveTask = (task) => {
112
- const value = task.value;
113
- switch (typeof value) {
114
- case "number":
115
- if (value !== value) {
116
- task[TaskIndex.Type] = PayloadSignal.NaN;
117
- return true;
118
- }
119
- Float64View[0] = value;
120
- task[TaskIndex.Type] = PayloadSignal.Float64;
121
- task[TaskIndex.Start] = Uint32View[0];
122
- task[TaskIndex.End] = Uint32View[1];
123
- return true;
124
- case "boolean":
125
- task[TaskIndex.Type] = value ? PayloadSignal.True : PayloadSignal.False;
126
- return true;
127
- case "undefined":
128
- task[TaskIndex.Type] = PayloadSignal.Undefined;
129
- return true;
130
- case "bigint":
131
- if (value < BIGINT64_MIN || value > BIGINT64_MAX)
132
- return false;
133
- BigInt64View[0] = value;
134
- task[TaskIndex.Type] = PayloadSignal.BigInt;
135
- task[TaskIndex.Start] = Uint32View[0];
136
- task[TaskIndex.End] = Uint32View[1];
137
- return true;
138
- case "object":
139
- if (value === null) {
140
- task[TaskIndex.Type] = PayloadSignal.Null;
141
- return true;
142
- }
143
- return false;
144
- default:
145
- return false;
146
- }
147
- };
148
- const hasPromiseInEnvelopeHeader = (value, seen) => {
149
- if (value instanceof Promise)
150
- return true;
151
- if (value === null || typeof value !== "object")
152
- return false;
153
- const objectValue = value;
154
- const visited = seen ?? new Set();
155
- if (visited.has(objectValue))
156
- return false;
157
- visited.add(objectValue);
158
- if (arrayIsArray(objectValue)) {
159
- const list = objectValue;
160
- for (let i = 0; i < list.length; i++) {
161
- if (hasPromiseInEnvelopeHeader(list[i], visited))
162
- return true;
163
- }
164
- return false;
165
- }
166
- if (!isPlainJsonObject(objectValue))
167
- return false;
168
- const record = objectValue;
169
- for (const key in record) {
170
- if (!objectHasOwn.call(record, key))
171
- continue;
172
- if (hasPromiseInEnvelopeHeader(record[key], visited))
173
- return true;
174
- }
175
- return false;
176
- };
177
- const toErrorCause = (cause) => {
178
- if (cause === null || cause === undefined)
179
- return cause;
180
- switch (typeof cause) {
181
- case "string":
182
- case "number":
183
- case "boolean":
184
- return cause;
185
- case "bigint":
186
- return cause.toString();
187
- case "symbol":
188
- case "function":
189
- return String(cause);
190
- }
191
- if (cause instanceof Error) {
192
- const nested = {
193
- name: cause.name,
194
- message: cause.message,
195
- };
196
- if (typeof cause.stack === "string")
197
- nested.stack = cause.stack;
198
- if (objectHasOwn.call(cause, "cause")) {
199
- nested.cause = toErrorCause(cause.cause);
200
- }
201
- return nested;
202
- }
203
- try {
204
- return parseJSON(stringifyJSON(cause));
205
- }
206
- catch {
207
- return String(cause);
208
- }
209
- };
210
- const toErrorPayload = (error) => {
211
- const payload = {
212
- name: error.name,
213
- message: error.message,
214
- };
215
- if (typeof error.stack === "string")
216
- payload.stack = error.stack;
217
- if (objectHasOwn.call(error, "cause")) {
218
- payload.cause = toErrorCause(error.cause);
219
- }
220
- return payload;
221
- };
222
- const parseErrorPayload = (raw) => {
223
- let parsed;
224
- try {
225
- parsed = parseJSON(raw);
226
- }
227
- catch {
228
- return new Error(raw);
229
- }
230
- if (parsed == null || typeof parsed !== "object") {
231
- return new Error(String(parsed));
232
- }
233
- const payload = parsed;
234
- const err = new Error(typeof payload.message === "string" ? payload.message : "");
235
- if (typeof payload.name === "string" && payload.name.length > 0) {
236
- err.name = payload.name;
237
- }
238
- if (typeof payload.stack === "string") {
239
- try {
240
- err.stack = payload.stack;
241
- }
242
- catch {
243
- }
244
- }
245
- if (objectHasOwn.call(payload, "cause")) {
246
- err.cause = payload.cause;
247
- }
248
- return err;
249
- };
250
- const decodeBigIntBinary = (bytes) => {
251
- const sign = bytes[0];
252
- let value = 0n;
253
- for (let i = bytes.length - 1; i >= 1; i--) {
254
- value = (value << 8n) | BigInt(bytes[i]);
255
- }
256
- return sign === 1 ? -value : value;
257
- };
258
- const initStaticIO = (headersBuffer, headerSlotStrideU32, textCompat) => {
259
- const slotStride = headerSlotStrideU32 ?? HEADER_SLOT_STRIDE_U32;
260
- const requiredBytes = getStridedRegionSpanBytes({
261
- slotCount: LockBound.slots,
262
- slotStrideU32: slotStride,
263
- slotLengthU32: HEADER_STATIC_PAYLOAD_U32,
264
- baseU32: LockBound.header,
265
- });
266
- if (headersBuffer.byteLength < Math.max(requiredBytes, HEADER_BYTE_LENGTH)) {
267
- return null;
268
- }
269
- return createSharedStaticBufferIO({
270
- headersBuffer,
271
- slotStrideU32: slotStride,
272
- textCompat,
273
- });
274
- };
275
- const requireStaticIO = (headersBuffer, headerSlotStrideU32, textCompat) => {
276
- const staticIO = initStaticIO(headersBuffer, headerSlotStrideU32, textCompat);
277
- if (staticIO === null) {
278
- throw new RangeError("headersBuffer is too small for static payload IO");
279
- }
280
- return staticIO;
281
- };
282
- /**
283
- * Returns `true` when the payload is encoded successfully.
284
- * Returns `false` when dynamic payload space could not be reserved.
285
- */
286
- export const encodePayload = ({ lockSector, payload, sab, payloadConfig, headersBuffer, headerSlotStrideU32, textCompat, onPromise, }) => {
287
- const payloadSab = payload?.sab ?? sab;
288
- const resolvedPayloadConfig = resolvePayloadBufferOptions({
289
- sab: payloadSab,
290
- options: payload?.config ?? payloadConfig,
291
- });
292
- const maxPayloadBytes = resolvedPayloadConfig.maxPayloadBytes;
293
- const { allocTask, setSlotLength, free } = register({
294
- lockSector,
295
- });
296
- const { writeBinary: writeDynamicBinary, writeBuffer: writeDynamicBuffer, writeArrayBuffer: writeDynamicArrayBuffer, write8Binary: writeDynamic8Binary, writeUtf8: writeDynamicUtf8, } = createSharedDynamicBufferIO({
297
- sab: payloadSab,
298
- payloadConfig: resolvedPayloadConfig,
299
- textCompat: textCompat?.payload,
300
- });
301
- const { maxBytes: staticMaxBytes, writeBinary: writeStaticBinary, writeBuffer: writeStaticBuffer, writeArrayBuffer: writeStaticArrayBuffer, writeExactUint8Array: writeStaticExactUint8Array, writeU32Words: writeStaticU32Words, write8Binary: writeStatic8Binary, writeUtf8: writeStaticUtf8, } = requireStaticIO(headersBuffer, headerSlotStrideU32, textCompat?.headers);
302
- const dynamicLimitError = (task, actualBytes, label) => encoderError({
303
- task,
304
- type: ErrorKnitting.Serializable,
305
- onPromise,
306
- detail: `${DYNAMIC_PAYLOAD_LIMIT_DETAIL} limit=${maxPayloadBytes}; ` +
307
- `actual=${actualBytes}; type=${label}.`,
308
- });
309
- const dynamicCapacityError = (task) => encoderError({
310
- task,
311
- type: ErrorKnitting.Serializable,
312
- onPromise,
313
- detail: DYNAMIC_PAYLOAD_CAPACITY_DETAIL,
314
- });
315
- const ensureWithinDynamicLimit = (task, bytes, label) => {
316
- if (bytes <= maxPayloadBytes)
317
- return true;
318
- return dynamicLimitError(task, bytes, label);
319
- };
320
- const dynamicUtf8ReserveBytesWithExtra = (task, text, extraBytes, label) => {
321
- const estimatedBytes = text.length * 3;
322
- const estimatedTotal = estimatedBytes + extraBytes;
323
- if (estimatedTotal <= maxPayloadBytes)
324
- return estimatedBytes;
325
- const exactBytes = utf8ByteLength(text);
326
- const exactTotal = exactBytes + extraBytes;
327
- if (exactTotal > maxPayloadBytes) {
328
- dynamicLimitError(task, exactTotal, label);
329
- return -1;
330
- }
331
- return exactBytes;
332
- };
333
- const dynamicUtf8ReserveBytes = (task, text, label) => dynamicUtf8ReserveBytesWithExtra(task, text, 0, label);
334
- const reserveDynamic = (task, bytes) => {
335
- task[TaskIndex.PayloadLen] = bytes;
336
- // PayloadCodec only reserves after the lock has guaranteed capacity.
337
- return allocTask(task);
338
- };
339
- let objectDynamicSlot = -1;
340
- const reserveDynamicObject = (task, bytes) => {
341
- task[TaskIndex.PayloadLen] = bytes;
342
- const reservedSlot = allocTask(task);
343
- objectDynamicSlot = reservedSlot;
344
- return reservedSlot;
345
- };
346
- const rollbackObjectDynamic = () => {
347
- if (objectDynamicSlot !== -1) {
348
- free(objectDynamicSlot);
349
- objectDynamicSlot = -1;
350
- }
351
- };
352
- const failDynamicWriteAfterReserve = (task, reservedSlot) => {
353
- free(reservedSlot);
354
- if (objectDynamicSlot === reservedSlot)
355
- objectDynamicSlot = -1;
356
- return dynamicCapacityError(task);
357
- };
358
- let bigintScratch = new Uint8Array(16);
359
- const encodeBigIntIntoScratch = (value) => {
360
- let sign = 0;
361
- let abs = value;
362
- if (value < 0n) {
363
- sign = 1;
364
- abs = -value;
365
- }
366
- let at = 1;
367
- while (abs > 0n) {
368
- if (at >= bigintScratch.byteLength) {
369
- const next = new Uint8Array(bigintScratch.byteLength << 1);
370
- next.set(bigintScratch, 0);
371
- bigintScratch = next;
372
- }
373
- bigintScratch[at++] = Number(abs & 0xffn);
374
- abs >>= 8n;
375
- }
376
- bigintScratch[0] = sign;
377
- return at;
378
- };
379
- const clearBigIntScratch = (used) => {
380
- bigintScratch.fill(0, 0, used);
381
- };
382
- const encodeErrorObject = (task, error) => {
383
- let text;
384
- try {
385
- text = stringifyJSON(toErrorPayload(error));
386
- }
387
- catch (encodeErrorReason) {
388
- const detail = encodeErrorReason instanceof Error
389
- ? encodeErrorReason.message
390
- : String(encodeErrorReason);
391
- return encoderError({
392
- task,
393
- type: ErrorKnitting.Serializable,
394
- onPromise,
395
- detail,
396
- });
397
- }
398
- const reserveBytes = dynamicUtf8ReserveBytes(task, text, "Error");
399
- if (reserveBytes < 0)
400
- return false;
401
- task[TaskIndex.Type] = PayloadBuffer.Error;
402
- const reservedSlot = reserveDynamicObject(task, reserveBytes);
403
- const written = writeDynamicUtf8(text, task[TaskIndex.Start], reserveBytes);
404
- if (written < 0)
405
- return failDynamicWriteAfterReserve(task, reservedSlot);
406
- task[TaskIndex.PayloadLen] = written;
407
- setSlotLength(reservedSlot, written);
408
- task.value = null;
409
- return true;
410
- };
411
- const encodeObjectBinary = (task, slotIndex, bytesView, dynamicType, staticType) => {
412
- const bytes = bytesView.byteLength;
413
- if (bytes <= staticMaxBytes) {
414
- const written = writeStaticBinary(bytesView, slotIndex);
415
- if (written !== -1) {
416
- task[TaskIndex.Type] = staticType;
417
- task[TaskIndex.PayloadLen] = written;
418
- task.value = null;
419
- return true;
420
- }
421
- }
422
- task[TaskIndex.Type] = dynamicType;
423
- if (!ensureWithinDynamicLimit(task, bytes, PayloadBuffer[dynamicType])) {
424
- return false;
425
- }
426
- const reservedSlot = reserveDynamicObject(task, bytes);
427
- const written = writeDynamicBinary(bytesView, task[TaskIndex.Start]);
428
- if (written < 0)
429
- return failDynamicWriteAfterReserve(task, reservedSlot);
430
- task[TaskIndex.PayloadLen] = written;
431
- setSlotLength(reservedSlot, written);
432
- task.value = null;
433
- return true;
434
- };
435
- const encodeObjectUint8Array = (task, slotIndex, bytesView) => {
436
- const bytes = bytesView.byteLength;
437
- if (bytes <= staticMaxBytes) {
438
- writeStaticExactUint8Array(bytesView, slotIndex);
439
- task[TaskIndex.Type] = PayloadBuffer.StaticBinary;
440
- task[TaskIndex.PayloadLen] = bytes;
441
- task.value = null;
442
- return true;
443
- }
444
- task[TaskIndex.Type] = PayloadBuffer.Binary;
445
- if (!ensureWithinDynamicLimit(task, bytes, "Binary"))
446
- return false;
447
- const reservedSlot = reserveDynamicObject(task, bytes);
448
- const written = writeDynamicBinary(bytesView, task[TaskIndex.Start]);
449
- if (written < 0)
450
- return failDynamicWriteAfterReserve(task, reservedSlot);
451
- task[TaskIndex.PayloadLen] = written;
452
- setSlotLength(reservedSlot, written);
453
- task.value = null;
454
- return true;
455
- };
456
- const encodeObjectBuffer = (task, slotIndex, buffer) => {
457
- const bytes = buffer.byteLength;
458
- if (bytes <= staticMaxBytes) {
459
- const written = writeStaticBuffer(buffer, slotIndex);
460
- if (written !== -1) {
461
- task[TaskIndex.Type] = PayloadBuffer.StaticBuffer;
462
- task[TaskIndex.PayloadLen] = written;
463
- task.value = null;
464
- return true;
465
- }
466
- }
467
- task[TaskIndex.Type] = PayloadBuffer.Buffer;
468
- if (!ensureWithinDynamicLimit(task, bytes, "Buffer"))
469
- return false;
470
- const reservedSlot = reserveDynamicObject(task, bytes);
471
- const written = writeDynamicBuffer(buffer, task[TaskIndex.Start]);
472
- if (written < 0)
473
- return failDynamicWriteAfterReserve(task, reservedSlot);
474
- task[TaskIndex.PayloadLen] = written;
475
- setSlotLength(reservedSlot, written);
476
- task.value = null;
477
- return true;
478
- };
479
- const encodeObjectFloat64Array = (task, slotIndex, float64) => {
480
- const bytes = float64.byteLength;
481
- if (bytes <= staticMaxBytes) {
482
- const written = writeStatic8Binary(float64, slotIndex);
483
- if (written !== -1) {
484
- task[TaskIndex.Type] = PayloadBuffer.StaticFloat64Array;
485
- task[TaskIndex.PayloadLen] = written;
486
- task.value = null;
487
- return true;
488
- }
489
- }
490
- task[TaskIndex.Type] = PayloadBuffer.Float64Array;
491
- if (!ensureWithinDynamicLimit(task, bytes, "Float64Array"))
492
- return false;
493
- const reservedSlot = reserveDynamicObject(task, bytes);
494
- const written = writeDynamic8Binary(float64, task[TaskIndex.Start]);
495
- if (written < 0)
496
- return failDynamicWriteAfterReserve(task, reservedSlot);
497
- task[TaskIndex.PayloadLen] = written;
498
- setSlotLength(reservedSlot, written);
499
- task.value = null;
500
- return true;
501
- };
502
- const encodeObjectArrayBuffer = (task, slotIndex, arrayBuffer) => {
503
- const bytes = arrayBuffer.byteLength;
504
- if (bytes <= staticMaxBytes) {
505
- const written = writeStaticArrayBuffer(arrayBuffer, slotIndex);
506
- if (written !== -1) {
507
- task[TaskIndex.Type] = PayloadBuffer.StaticArrayBuffer;
508
- task[TaskIndex.PayloadLen] = written;
509
- task.value = null;
510
- return true;
511
- }
512
- }
513
- task[TaskIndex.Type] = PayloadBuffer.ArrayBuffer;
514
- if (!ensureWithinDynamicLimit(task, bytes, "ArrayBuffer"))
515
- return false;
516
- const reservedSlot = reserveDynamicObject(task, bytes);
517
- const written = writeDynamicArrayBuffer(arrayBuffer, task[TaskIndex.Start]);
518
- if (written < 0)
519
- return failDynamicWriteAfterReserve(task, reservedSlot);
520
- task[TaskIndex.PayloadLen] = written;
521
- setSlotLength(reservedSlot, written);
522
- task.value = null;
523
- return true;
524
- };
525
- const processSharedBufferWords = new Uint32Array(PROCESS_SHARED_BUFFER_NUMERIC_WORDS);
526
- const sharedArrayBufferWords = new Uint32Array(SHARED_ARRAY_BUFFER_NUMERIC_WORDS);
527
- const tryEncodeProcessSharedBufferNumeric = (task, slotIndex, value) => {
528
- const descriptor = value.descriptor;
529
- if (descriptor === undefined ||
530
- descriptor.name !== undefined ||
531
- !isU32(descriptor.fd) ||
532
- !isU32(descriptor.size) ||
533
- !isU32(descriptor.byteLength) ||
534
- !isU32(value.byteOffset) ||
535
- !isU32(value.byteLength)) {
536
- return false;
537
- }
538
- const baseAddressMod64 = descriptor.baseAddressMod64;
539
- if (baseAddressMod64 !== undefined &&
540
- !isU32(baseAddressMod64)) {
541
- return false;
542
- }
543
- processSharedBufferWords[0] = descriptor.fd;
544
- processSharedBufferWords[1] = descriptor.size;
545
- processSharedBufferWords[2] = descriptor.byteLength;
546
- processSharedBufferWords[3] = value.byteOffset;
547
- processSharedBufferWords[4] = value.byteLength;
548
- processSharedBufferWords[5] = runtimeCode(descriptor.runtime);
549
- processSharedBufferWords[6] = kindCode(descriptor.kind);
550
- processSharedBufferWords[7] = baseAddressMod64 === undefined
551
- ? NUMERIC_SENTINEL
552
- : baseAddressMod64;
553
- task[TaskIndex.Type] = PayloadBuffer.ProcessSharedBuffer;
554
- // Static region is a Uint32Array shared in-process; write the descriptor
555
- // words straight in instead of staging bytes through a DataView + copy.
556
- task[TaskIndex.PayloadLen] = writeStaticU32Words(processSharedBufferWords, PROCESS_SHARED_BUFFER_NUMERIC_WORDS, slotIndex);
557
- task.value = null;
558
- return true;
559
- };
560
- const tryEncodeBufferReferenceNumeric = (task, slotIndex, value) => {
561
- const words = value[BUFFER_REFERENCE_NUMERIC_TRANSFER]?.();
562
- if (words === undefined)
563
- return false;
564
- task[TaskIndex.Type] = PayloadBuffer.BufferReference;
565
- task[TaskIndex.PayloadLen] = writeStaticU32Words(words, BUFFER_REFERENCE_NUMERIC_WORDS, slotIndex);
566
- attachPayloadTransportFinalizer(task, value);
567
- task.value = null;
568
- return true;
569
- };
570
- const tryEncodeSharedArrayBufferNumeric = (task, slotIndex, value) => {
571
- const words = value[SHARED_ARRAY_BUFFER_NUMERIC_TRANSFER]?.(lockSector);
572
- if (words === undefined)
573
- return false;
574
- sharedArrayBufferWords[0] = words[0] ?? 0;
575
- sharedArrayBufferWords[1] = words[1] ?? 0;
576
- sharedArrayBufferWords[2] = words[2] ?? 0;
577
- sharedArrayBufferWords[3] = words[3] ?? 0;
578
- sharedArrayBufferWords[4] = words[4] ?? 0;
579
- sharedArrayBufferWords[5] = words[5] ?? 0;
580
- sharedArrayBufferWords[6] = words[6] ?? 0;
581
- sharedArrayBufferWords[7] = words[7] ?? 0;
582
- task[TaskIndex.Type] = PayloadBuffer.SharedArrayBuffer;
583
- task[TaskIndex.PayloadLen] = writeStaticU32Words(sharedArrayBufferWords, words.length, slotIndex);
584
- task.value = null;
585
- return true;
586
- };
587
- const encodeObjectExternalPayload = (task, slotIndex, externalPayload) => {
588
- const codecId = readExternalPayloadCodecId(externalPayload);
589
- if (codecId === undefined) {
590
- return encoderError({
591
- task,
592
- type: ErrorKnitting.Serializable,
593
- onPromise,
594
- detail: UNSUPPORTED_OBJECT_DETAIL,
595
- });
596
- }
597
- if (codecId === SHARED_ARRAY_BUFFER_CODEC_ID &&
598
- tryEncodeSharedArrayBufferNumeric(task, slotIndex, externalPayload)) {
599
- return true;
600
- }
601
- if (codecId === BUFFER_REFERENCE_CODEC_ID &&
602
- tryEncodeBufferReferenceNumeric(task, slotIndex, externalPayload)) {
603
- return true;
604
- }
605
- if (codecId === PROCESS_SHARED_BUFFER_CODEC_ID &&
606
- tryEncodeProcessSharedBufferNumeric(task, slotIndex, externalPayload)) {
607
- return true;
608
- }
609
- let text;
610
- try {
611
- text = stringifyJSON([codecId, externalPayload.toMetadata()]);
612
- }
613
- catch (error) {
614
- const detail = error instanceof Error ? error.message : String(error);
615
- return encoderError({
616
- task,
617
- type: ErrorKnitting.Serializable,
618
- onPromise,
619
- detail,
620
- });
621
- }
622
- if (typeof text !== "string") {
623
- return encoderError({
624
- task,
625
- type: ErrorKnitting.Serializable,
626
- onPromise,
627
- detail: "External payload metadata must be JSON serializable.",
628
- });
629
- }
630
- if (text.length <= staticMaxBytes) {
631
- const written = writeStaticUtf8(text, slotIndex);
632
- if (written !== -1) {
633
- task[TaskIndex.Type] = PayloadBuffer.StaticExternalPayload;
634
- task[TaskIndex.PayloadLen] = written;
635
- attachPayloadTransportFinalizer(task, externalPayload);
636
- task.value = null;
637
- return true;
638
- }
639
- }
640
- task[TaskIndex.Type] = PayloadBuffer.ExternalPayload;
641
- const reserveBytes = dynamicUtf8ReserveBytes(task, text, "ExternalPayload");
642
- if (reserveBytes < 0)
643
- return false;
644
- const reservedSlot = reserveDynamicObject(task, reserveBytes);
645
- const written = writeDynamicUtf8(text, task[TaskIndex.Start], reserveBytes);
646
- if (written < 0)
647
- return failDynamicWriteAfterReserve(task, reservedSlot);
648
- task[TaskIndex.PayloadLen] = written;
649
- setSlotLength(reservedSlot, written);
650
- attachPayloadTransportFinalizer(task, externalPayload);
651
- task.value = null;
652
- return true;
653
- };
654
- const encodeObjectDate = (task, date) => {
655
- Float64View[0] = date.getTime();
656
- task[TaskIndex.Type] = PayloadBuffer.Date;
657
- task[TaskIndex.Start] = Uint32View[0];
658
- task[TaskIndex.End] = Uint32View[1];
659
- task.value = null;
660
- return true;
661
- };
662
- const encodeEnvelopeHeaderText = (task, header, headerIsString) => {
663
- if (hasPromiseInEnvelopeHeader(header)) {
664
- encoderError({
665
- task,
666
- type: ErrorKnitting.Serializable,
667
- onPromise,
668
- detail: ENVELOPE_PROMISE_DETAIL,
669
- });
670
- return undefined;
671
- }
672
- if (headerIsString)
673
- return header;
674
- let headerText;
675
- try {
676
- headerText = stringifyJSON(header);
677
- }
678
- catch (error) {
679
- const detail = error instanceof Error ? error.message : String(error);
680
- encoderError({ task, type: ErrorKnitting.Json, onPromise, detail });
681
- return undefined;
682
- }
683
- if (typeof headerText !== "string") {
684
- encoderError({
685
- task,
686
- type: ErrorKnitting.Serializable,
687
- onPromise,
688
- detail: ENVELOPE_HEADER_DETAIL,
689
- });
690
- return undefined;
691
- }
692
- return headerText;
693
- };
694
- const resolveEnvelopeExternalBody = (body) => {
695
- if (body === null || typeof body !== "object")
696
- return undefined;
697
- const sharedArrayBuffer = getSharedArrayBufferPayload(body);
698
- if (sharedArrayBuffer !== undefined)
699
- return sharedArrayBuffer;
700
- if (isExternalPayloadLike(body)) {
701
- return body;
702
- }
703
- return undefined;
704
- };
705
- const encodeEnvelopeArrayBufferBody = (task, slotIndex, headerText, headerIsString, payload) => {
706
- const payloadBytes = new Uint8Array(payload);
707
- const payloadLength = payloadBytes.byteLength;
708
- const payloadReserveBytes = payloadLength > 0 ? payloadLength : 1;
709
- const staticHeaderWritten = writeStaticUtf8(headerText, slotIndex);
710
- if (staticHeaderWritten !== -1) {
711
- if (!ensureWithinDynamicLimit(task, payloadReserveBytes, "EnvelopeStaticHeaderPayload"))
712
- return false;
713
- const reservedSlot = reserveDynamicObject(task, payloadReserveBytes);
714
- task[TaskIndex.Type] = headerIsString
715
- ? PayloadBuffer.EnvelopeStaticHeaderString
716
- : PayloadBuffer.EnvelopeStaticHeader;
717
- task[TaskIndex.PayloadLen] = staticHeaderWritten;
718
- task[TaskIndex.End] = payloadLength;
719
- if (payloadLength > 0) {
720
- const payloadWritten = writeDynamicBinary(payloadBytes, task[TaskIndex.Start]);
721
- if (payloadWritten < 0) {
722
- return failDynamicWriteAfterReserve(task, reservedSlot);
723
- }
724
- setSlotLength(reservedSlot, payloadWritten);
725
- }
726
- task.value = null;
727
- return true;
728
- }
729
- const headerReserveBytes = dynamicUtf8ReserveBytesWithExtra(task, headerText, payloadLength, headerIsString ? "EnvelopeDynamicHeaderString" : "EnvelopeDynamicHeader");
730
- if (headerReserveBytes < 0)
731
- return false;
732
- task[TaskIndex.Type] = headerIsString
733
- ? PayloadBuffer.EnvelopeDynamicHeaderString
734
- : PayloadBuffer.EnvelopeDynamicHeader;
735
- const reservedSlot = reserveDynamicObject(task, headerReserveBytes + payloadLength);
736
- const baseStart = task[TaskIndex.Start];
737
- const writtenHeaderBytes = writeDynamicUtf8(headerText, baseStart, headerReserveBytes);
738
- if (writtenHeaderBytes < 0) {
739
- return failDynamicWriteAfterReserve(task, reservedSlot);
740
- }
741
- if (payloadLength > 0) {
742
- const payloadWritten = writeDynamicBinary(payloadBytes, baseStart + writtenHeaderBytes);
743
- if (payloadWritten < 0) {
744
- return failDynamicWriteAfterReserve(task, reservedSlot);
745
- }
746
- }
747
- task[TaskIndex.PayloadLen] = writtenHeaderBytes;
748
- task[TaskIndex.End] = payloadLength;
749
- setSlotLength(reservedSlot, writtenHeaderBytes + payloadLength);
750
- task.value = null;
751
- return true;
752
- };
753
- const encodeEnvelopeExternalBody = (task, slotIndex, headerText, headerIsString, externalBody) => {
754
- const codecId = readExternalPayloadCodecId(externalBody);
755
- if (codecId === undefined) {
756
- return encoderError({
757
- task,
758
- type: ErrorKnitting.Serializable,
759
- onPromise,
760
- detail: ENVELOPE_PAYLOAD_DETAIL,
761
- });
762
- }
763
- let bodyText;
764
- try {
765
- bodyText = stringifyJSON([codecId, externalBody.toMetadata()]);
766
- }
767
- catch (error) {
768
- const detail = error instanceof Error ? error.message : String(error);
769
- return encoderError({
770
- task,
771
- type: ErrorKnitting.Serializable,
772
- onPromise,
773
- detail,
774
- });
775
- }
776
- if (typeof bodyText !== "string") {
777
- return encoderError({
778
- task,
779
- type: ErrorKnitting.Serializable,
780
- onPromise,
781
- detail: "Envelope body metadata must be JSON serializable.",
782
- });
783
- }
784
- const bodyBytes = textEncode.encode(bodyText);
785
- const bodyLength = bodyBytes.byteLength;
786
- const staticHeaderWritten = writeStaticUtf8(headerText, slotIndex);
787
- if (staticHeaderWritten !== -1) {
788
- if (!ensureWithinDynamicLimit(task, bodyLength, "EnvelopeStaticHeaderExternal"))
789
- return false;
790
- const reservedSlot = reserveDynamicObject(task, bodyLength);
791
- task[TaskIndex.Type] = headerIsString
792
- ? PayloadBuffer.EnvelopeStaticHeaderStringExternal
793
- : PayloadBuffer.EnvelopeStaticHeaderExternal;
794
- task[TaskIndex.PayloadLen] = staticHeaderWritten;
795
- task[TaskIndex.End] = bodyLength;
796
- const bodyWritten = writeDynamicBinary(bodyBytes, task[TaskIndex.Start]);
797
- if (bodyWritten < 0) {
798
- return failDynamicWriteAfterReserve(task, reservedSlot);
799
- }
800
- setSlotLength(reservedSlot, bodyWritten);
801
- attachPayloadTransportFinalizer(task, externalBody);
802
- task.value = null;
803
- return true;
804
- }
805
- const headerReserveBytes = dynamicUtf8ReserveBytesWithExtra(task, headerText, bodyLength, headerIsString
806
- ? "EnvelopeDynamicHeaderStringExternal"
807
- : "EnvelopeDynamicHeaderExternal");
808
- if (headerReserveBytes < 0)
809
- return false;
810
- task[TaskIndex.Type] = headerIsString
811
- ? PayloadBuffer.EnvelopeDynamicHeaderStringExternal
812
- : PayloadBuffer.EnvelopeDynamicHeaderExternal;
813
- const reservedSlot = reserveDynamicObject(task, headerReserveBytes + bodyLength);
814
- const baseStart = task[TaskIndex.Start];
815
- const writtenHeaderBytes = writeDynamicUtf8(headerText, baseStart, headerReserveBytes);
816
- if (writtenHeaderBytes < 0) {
817
- return failDynamicWriteAfterReserve(task, reservedSlot);
818
- }
819
- const bodyWritten = writeDynamicBinary(bodyBytes, baseStart + writtenHeaderBytes);
820
- if (bodyWritten < 0) {
821
- return failDynamicWriteAfterReserve(task, reservedSlot);
822
- }
823
- task[TaskIndex.PayloadLen] = writtenHeaderBytes;
824
- task[TaskIndex.End] = bodyLength;
825
- setSlotLength(reservedSlot, writtenHeaderBytes + bodyLength);
826
- attachPayloadTransportFinalizer(task, externalBody);
827
- task.value = null;
828
- return true;
829
- };
830
- const encodeObjectEnvelope = (task, slotIndex, envelope) => {
831
- const header = envelope.header;
832
- const payload = envelope.payload;
833
- const headerIsString = typeof header === "string";
834
- if (payload instanceof ArrayBuffer) {
835
- const headerText = encodeEnvelopeHeaderText(task, header, headerIsString);
836
- if (headerText === undefined)
837
- return false;
838
- return encodeEnvelopeArrayBufferBody(task, slotIndex, headerText, headerIsString, payload);
839
- }
840
- const externalBody = resolveEnvelopeExternalBody(payload);
841
- if (externalBody !== undefined) {
842
- const headerText = encodeEnvelopeHeaderText(task, header, headerIsString);
843
- if (headerText === undefined)
844
- return false;
845
- return encodeEnvelopeExternalBody(task, slotIndex, headerText, headerIsString, externalBody);
846
- }
847
- return encoderError({
848
- task,
849
- type: ErrorKnitting.Serializable,
850
- onPromise,
851
- detail: ENVELOPE_PAYLOAD_DETAIL,
852
- });
853
- };
854
- const encodeObjectPromise = (task, promise) => {
855
- if (beginPromisePayload(task)) {
856
- promise.then((value) => {
857
- finishPromisePayload(task);
858
- task.value = value;
859
- onPromise(task, false, value);
860
- }, (reason) => {
861
- finishPromisePayload(task);
862
- task.value = reason;
863
- onPromise(task, true, reason);
864
- });
865
- }
866
- return false;
867
- };
868
- // Named function so V8/TurboFan can compile it independently from the
869
- // encodePayload factory closure. Anonymous returns prevent full optimization
870
- // because the outer factory is too large for TurboFan's bytecode limit.
871
- const encodeDispatch = (task, slotIndex) => {
872
- const args = task.value;
873
- if (tryEncodePrimitiveTask(task))
874
- return true;
875
- switch (typeof args) {
876
- case "bigint": {
877
- const binaryBytes = encodeBigIntIntoScratch(args);
878
- const binary = bigintScratch.subarray(0, binaryBytes);
879
- if (binaryBytes <= staticMaxBytes) {
880
- const written = writeStaticBinary(binary, slotIndex);
881
- if (written !== -1) {
882
- task[TaskIndex.Type] = PayloadBuffer.StaticBigInt;
883
- task[TaskIndex.PayloadLen] = written;
884
- clearBigIntScratch(binaryBytes);
885
- task.value = null;
886
- return true;
887
- }
888
- }
889
- task[TaskIndex.Type] = PayloadBuffer.BigInt;
890
- if (!ensureWithinDynamicLimit(task, binaryBytes, "BigInt")) {
891
- clearBigIntScratch(binaryBytes);
892
- return false;
893
- }
894
- const reservedSlot = reserveDynamic(task, binaryBytes);
895
- const written = writeDynamicBinary(binary, task[TaskIndex.Start]);
896
- if (written < 0) {
897
- clearBigIntScratch(binaryBytes);
898
- return failDynamicWriteAfterReserve(task, reservedSlot);
899
- }
900
- task[TaskIndex.PayloadLen] = written;
901
- setSlotLength(reservedSlot, written);
902
- clearBigIntScratch(binaryBytes);
903
- task.value = null;
904
- return true;
905
- }
906
- case "function":
907
- return encoderError({
908
- task,
909
- type: ErrorKnitting.Function,
910
- onPromise,
911
- });
912
- case "object":
913
- objectDynamicSlot = -1;
914
- try {
915
- const objectValue = args;
916
- const sharedArrayBufferPayload = getSharedArrayBufferPayload(objectValue);
917
- if (sharedArrayBufferPayload !== undefined) {
918
- return encodeObjectExternalPayload(task, slotIndex, sharedArrayBufferPayload);
919
- }
920
- const objectProto = objectGetPrototypeOf(objectValue);
921
- if (isRuntimeUint8Array(objectValue)) {
922
- return encodeObjectUint8Array(task, slotIndex, objectValue);
923
- }
924
- if (arrayIsArray(objectValue) ||
925
- objectProto === objectPrototype ||
926
- objectProto === null) {
927
- let text;
928
- try {
929
- text = stringifyJSON(objectValue);
930
- }
931
- catch (error) {
932
- const detail = error instanceof Error
933
- ? error.message
934
- : String(error);
935
- return encoderError({
936
- task,
937
- type: ErrorKnitting.Json,
938
- onPromise,
939
- detail,
940
- });
941
- }
942
- if (text.length <= staticMaxBytes) {
943
- const written = writeStaticUtf8(text, slotIndex);
944
- if (written !== -1) {
945
- task[TaskIndex.Type] = PayloadBuffer.StaticJson;
946
- task[TaskIndex.PayloadLen] = written;
947
- task.value = null;
948
- return true;
949
- }
950
- }
951
- task[TaskIndex.Type] = PayloadBuffer.Json;
952
- const reserveBytes = dynamicUtf8ReserveBytes(task, text, "Json");
953
- if (reserveBytes < 0)
954
- return false;
955
- const reservedSlot = reserveDynamicObject(task, reserveBytes);
956
- const written = writeDynamicUtf8(text, task[TaskIndex.Start], reserveBytes);
957
- if (written < 0) {
958
- return failDynamicWriteAfterReserve(task, reservedSlot);
959
- }
960
- task[TaskIndex.PayloadLen] = written;
961
- setSlotLength(reservedSlot, written);
962
- task.value = null;
963
- return true;
964
- }
965
- const objectCtor = objectValue
966
- .constructor;
967
- if (isRuntimeBuffer(objectValue)) {
968
- return encodeObjectBuffer(task, slotIndex, objectValue);
969
- }
970
- switch (objectCtor) {
971
- case ArrayBuffer:
972
- return encodeObjectArrayBuffer(task, slotIndex, objectValue);
973
- case Int32Array: {
974
- const int32 = objectValue;
975
- return encodeObjectBinary(task, slotIndex, new Uint8Array(int32.buffer, int32.byteOffset, int32.byteLength), PayloadBuffer.Int32Array, PayloadBuffer.StaticInt32Array);
976
- }
977
- case Float64Array:
978
- return encodeObjectFloat64Array(task, slotIndex, objectValue);
979
- case BigInt64Array: {
980
- const bigInt64 = objectValue;
981
- return encodeObjectBinary(task, slotIndex, new Uint8Array(bigInt64.buffer, bigInt64.byteOffset, bigInt64.byteLength), PayloadBuffer.BigInt64Array, PayloadBuffer.StaticBigInt64Array);
982
- }
983
- case BigUint64Array: {
984
- const bigUint64 = objectValue;
985
- return encodeObjectBinary(task, slotIndex, new Uint8Array(bigUint64.buffer, bigUint64.byteOffset, bigUint64.byteLength), PayloadBuffer.BigUint64Array, PayloadBuffer.StaticBigUint64Array);
986
- }
987
- case DataView: {
988
- const dataView = objectValue;
989
- return encodeObjectBinary(task, slotIndex, new Uint8Array(dataView.buffer, dataView.byteOffset, dataView.byteLength), PayloadBuffer.DataView, PayloadBuffer.StaticDataView);
990
- }
991
- case Date:
992
- return encodeObjectDate(task, objectValue);
993
- case Envelope:
994
- return encodeObjectEnvelope(task, slotIndex, objectValue);
995
- case Promise:
996
- return encodeObjectPromise(task, objectValue);
997
- case Error:
998
- return encodeErrorObject(task, objectValue);
999
- }
1000
- if (objectValue instanceof Date) {
1001
- return encodeObjectDate(task, objectValue);
1002
- }
1003
- if (objectValue instanceof Envelope) {
1004
- return encodeObjectEnvelope(task, slotIndex, objectValue);
1005
- }
1006
- if (objectValue instanceof Promise) {
1007
- return encodeObjectPromise(task, objectValue);
1008
- }
1009
- if (objectValue instanceof Error) {
1010
- return encodeErrorObject(task, objectValue);
1011
- }
1012
- if (isExternalPayloadLike(objectValue)) {
1013
- return encodeObjectExternalPayload(task, slotIndex, objectValue);
1014
- }
1015
- return encoderError({
1016
- task,
1017
- type: ErrorKnitting.Serializable,
1018
- onPromise,
1019
- detail: UNSUPPORTED_OBJECT_DETAIL,
1020
- });
1021
- }
1022
- catch (error) {
1023
- rollbackObjectDynamic();
1024
- const detail = error instanceof Error ? error.message : String(error);
1025
- return encoderError({
1026
- task,
1027
- type: ErrorKnitting.Serializable,
1028
- onPromise,
1029
- detail,
1030
- });
1031
- }
1032
- case "string": {
1033
- const text = args;
1034
- if (text.length <= staticMaxBytes) {
1035
- const written = writeStaticUtf8(text, slotIndex);
1036
- if (written !== -1) {
1037
- task[TaskIndex.Type] = PayloadBuffer.StaticString;
1038
- task[TaskIndex.PayloadLen] = written;
1039
- task.value = null;
1040
- return true;
1041
- }
1042
- }
1043
- task[TaskIndex.Type] = PayloadBuffer.String;
1044
- const reserveBytes = dynamicUtf8ReserveBytes(task, text, "String");
1045
- if (reserveBytes < 0)
1046
- return false;
1047
- const reservedSlot = reserveDynamic(task, reserveBytes);
1048
- const written = writeDynamicUtf8(text, task[TaskIndex.Start], reserveBytes);
1049
- if (written < 0) {
1050
- return failDynamicWriteAfterReserve(task, reservedSlot);
1051
- }
1052
- task[TaskIndex.PayloadLen] = written;
1053
- setSlotLength(reservedSlot, written);
1054
- task.value = null;
1055
- return true;
1056
- }
1057
- case "symbol": {
1058
- const key = symbolKeyFor(args);
1059
- if (key === undefined) {
1060
- return encoderError({
1061
- task,
1062
- type: ErrorKnitting.Symbol,
1063
- onPromise,
1064
- });
1065
- }
1066
- if (key.length * 3 <= staticMaxBytes) {
1067
- const written = writeStaticUtf8(key, slotIndex);
1068
- if (written !== -1) {
1069
- task[TaskIndex.Type] = PayloadBuffer.StaticSymbol;
1070
- task[TaskIndex.PayloadLen] = written;
1071
- task.value = null;
1072
- return true;
1073
- }
1074
- }
1075
- task[TaskIndex.Type] = PayloadBuffer.Symbol;
1076
- const reserveBytes = dynamicUtf8ReserveBytes(task, key, "Symbol");
1077
- if (reserveBytes < 0)
1078
- return false;
1079
- const reservedSlot = reserveDynamic(task, reserveBytes);
1080
- const written = writeDynamicUtf8(key, task[TaskIndex.Start], reserveBytes);
1081
- if (written < 0) {
1082
- return failDynamicWriteAfterReserve(task, reservedSlot);
1083
- }
1084
- task[TaskIndex.PayloadLen] = written;
1085
- setSlotLength(reservedSlot, written);
1086
- task.value = null;
1087
- return true;
1088
- }
1089
- }
1090
- return false;
1091
- };
1092
- return encodeDispatch;
1093
- };
1094
- export const decodePayload = ({ lockSector, payload, sab, payloadConfig, headersBuffer, headerSlotStrideU32, textCompat, host, }) => {
1095
- const payloadSab = payload?.sab ?? sab;
1096
- const resolvedPayloadConfig = resolvePayloadBufferOptions({
1097
- sab: payloadSab,
1098
- options: payload?.config ?? payloadConfig,
1099
- });
1100
- const { free } = register({
1101
- lockSector,
1102
- });
1103
- const freeTaskSlot = (task) => free(getTaskSlotIndex(task));
1104
- const { readUtf8: readDynamicUtf8, readBytesCopy: readDynamicBytesCopy, readBytesBufferCopy: readDynamicBufferCopy, readBufferCopy: readDynamicBuffer, readBytesArrayBufferCopy: readDynamicArrayBufferCopy, readArrayBufferCopy: readDynamicArrayBuffer, read8BytesFloatCopy: readDynamic8BytesFloatCopy, read8BytesFloatView: readDynamic8BytesFloatView, } = createSharedDynamicBufferIO({
1105
- sab: payloadSab,
1106
- payloadConfig: resolvedPayloadConfig,
1107
- textCompat: textCompat?.payload,
1108
- });
1109
- const { readUtf8: readStaticUtf8, readBytesBufferCopy: readStaticBufferCopy, readBufferCopy: readStaticBuffer, readUint8ArrayCopy: readStaticUint8ArrayCopy, readBytesArrayBufferCopy: readStaticArrayBufferCopy, readArrayBufferCopy: readStaticArrayBuffer, read8BytesFloatCopy: readStatic8BytesFloatCopy, readU32Words: readStaticU32Words, } = requireStaticIO(headersBuffer, headerSlotStrideU32, textCompat?.headers);
1110
- // Reusable scratch for the ProcessSharedBuffer raw-word decode. Safe to share:
1111
- // decode is single-consumer and not re-entrant, and the words are consumed
1112
- // synchronously when building the ProcessSharedBuffer.
1113
- const processSharedBufferWords = new Uint32Array(PROCESS_SHARED_BUFFER_NUMERIC_WORDS);
1114
- const sharedArrayBufferWords = new Uint32Array(SHARED_ARRAY_BUFFER_NUMERIC_WORDS);
1115
- const bufferReferenceWords = new Uint32Array(BUFFER_REFERENCE_NUMERIC_WORDS);
1116
- // TODO: remove slotIndex and make that all their callers
1117
- // store the slot in their Task, to just get it when it comes
1118
- // to the static versions of decoding
1119
- return (task, slotIndex, specialFlags) => {
1120
- switch (task[TaskIndex.Type]) {
1121
- case PayloadSignal.BigInt:
1122
- Uint32View[0] = task[TaskIndex.Start];
1123
- Uint32View[1] = task[TaskIndex.End];
1124
- task.value = BigInt64View[0];
1125
- return;
1126
- case PayloadSignal.True:
1127
- task.value = true;
1128
- return;
1129
- case PayloadSignal.False:
1130
- task.value = false;
1131
- return;
1132
- case PayloadSignal.Float64:
1133
- Uint32View[0] = task[TaskIndex.Start];
1134
- Uint32View[1] = task[TaskIndex.End];
1135
- task.value = Float64View[0];
1136
- return;
1137
- case PayloadSignal.NaN:
1138
- task.value = NaN;
1139
- return;
1140
- case PayloadSignal.Null:
1141
- task.value = null;
1142
- return;
1143
- case PayloadSignal.Undefined:
1144
- task.value = undefined;
1145
- return;
1146
- case PayloadBuffer.String:
1147
- task.value = readDynamicUtf8(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]);
1148
- freeTaskSlot(task);
1149
- return;
1150
- case PayloadBuffer.StaticString:
1151
- task.value = readStaticUtf8(0, task[TaskIndex.PayloadLen], slotIndex);
1152
- return;
1153
- case PayloadBuffer.Json:
1154
- task.value = parseJSON(readDynamicUtf8(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]));
1155
- freeTaskSlot(task);
1156
- return;
1157
- case PayloadBuffer.StaticJson:
1158
- task.value = parseJSON(readStaticUtf8(0, task[TaskIndex.PayloadLen], slotIndex));
1159
- return;
1160
- case PayloadBuffer.EnvelopeStaticHeader:
1161
- case PayloadBuffer.EnvelopeStaticHeaderString: {
1162
- const rawHeader = readStaticUtf8(0, task[TaskIndex.PayloadLen], slotIndex);
1163
- const header = task[TaskIndex.Type] === PayloadBuffer.EnvelopeStaticHeaderString
1164
- ? rawHeader
1165
- : parseJSON(rawHeader);
1166
- const payloadLength = task[TaskIndex.End];
1167
- const payload = payloadLength > 0
1168
- ? readDynamicArrayBufferCopy(task[TaskIndex.Start], task[TaskIndex.Start] + payloadLength)
1169
- : new ArrayBuffer(0);
1170
- task.value = new Envelope(header, payload);
1171
- freeTaskSlot(task);
1172
- return;
1173
- }
1174
- case PayloadBuffer.EnvelopeDynamicHeader:
1175
- case PayloadBuffer.EnvelopeDynamicHeaderString: {
1176
- const headerStart = task[TaskIndex.Start];
1177
- const payloadStart = headerStart + task[TaskIndex.PayloadLen];
1178
- const payloadLength = task[TaskIndex.End];
1179
- const rawHeader = readDynamicUtf8(headerStart, payloadStart);
1180
- const header = task[TaskIndex.Type] === PayloadBuffer.EnvelopeDynamicHeaderString
1181
- ? rawHeader
1182
- : parseJSON(rawHeader);
1183
- const payload = payloadLength > 0
1184
- ? readDynamicArrayBufferCopy(payloadStart, payloadStart + payloadLength)
1185
- : new ArrayBuffer(0);
1186
- task.value = new Envelope(header, payload);
1187
- freeTaskSlot(task);
1188
- return;
1189
- }
1190
- case PayloadBuffer.EnvelopeStaticHeaderExternal:
1191
- case PayloadBuffer.EnvelopeStaticHeaderStringExternal: {
1192
- const rawHeader = readStaticUtf8(0, task[TaskIndex.PayloadLen], slotIndex);
1193
- const header = task[TaskIndex.Type] ===
1194
- PayloadBuffer.EnvelopeStaticHeaderStringExternal
1195
- ? rawHeader
1196
- : parseJSON(rawHeader);
1197
- const bodyStart = task[TaskIndex.Start];
1198
- const body = decodeExternalPayload(readDynamicUtf8(bodyStart, bodyStart + task[TaskIndex.End]));
1199
- task.value = new Envelope(header, body);
1200
- freeTaskSlot(task);
1201
- return;
1202
- }
1203
- case PayloadBuffer.EnvelopeDynamicHeaderExternal:
1204
- case PayloadBuffer.EnvelopeDynamicHeaderStringExternal: {
1205
- const headerStart = task[TaskIndex.Start];
1206
- const bodyStart = headerStart + task[TaskIndex.PayloadLen];
1207
- const rawHeader = readDynamicUtf8(headerStart, bodyStart);
1208
- const header = task[TaskIndex.Type] ===
1209
- PayloadBuffer.EnvelopeDynamicHeaderStringExternal
1210
- ? rawHeader
1211
- : parseJSON(rawHeader);
1212
- const body = decodeExternalPayload(readDynamicUtf8(bodyStart, bodyStart + task[TaskIndex.End]));
1213
- task.value = new Envelope(header, body);
1214
- freeTaskSlot(task);
1215
- return;
1216
- }
1217
- case PayloadBuffer.BigInt:
1218
- task.value = decodeBigIntBinary(readDynamicBufferCopy(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]));
1219
- freeTaskSlot(task);
1220
- return;
1221
- case PayloadBuffer.StaticBigInt:
1222
- task.value = decodeBigIntBinary(readStaticBufferCopy(0, task[TaskIndex.PayloadLen], slotIndex));
1223
- return;
1224
- case PayloadBuffer.Symbol:
1225
- task.value = symbolFor(readDynamicUtf8(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]));
1226
- freeTaskSlot(task);
1227
- return;
1228
- case PayloadBuffer.StaticSymbol:
1229
- task.value = symbolFor(readStaticUtf8(0, task[TaskIndex.PayloadLen], slotIndex));
1230
- return;
1231
- case PayloadBuffer.Int32Array: {
1232
- const bytes = readDynamicBufferCopy(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]);
1233
- task.value = new Int32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >>> 2);
1234
- freeTaskSlot(task);
1235
- return;
1236
- }
1237
- case PayloadBuffer.StaticInt32Array: {
1238
- const bytes = readStaticBufferCopy(0, task[TaskIndex.PayloadLen], slotIndex);
1239
- task.value = new Int32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >>> 2);
1240
- return;
1241
- }
1242
- case PayloadBuffer.Float64Array: {
1243
- task.value = readDynamic8BytesFloatCopy(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]);
1244
- freeTaskSlot(task);
1245
- return;
1246
- }
1247
- case PayloadBuffer.StaticFloat64Array:
1248
- task.value = readStatic8BytesFloatCopy(0, task[TaskIndex.PayloadLen], slotIndex);
1249
- return;
1250
- case PayloadBuffer.BigInt64Array: {
1251
- const bytes = readDynamicBufferCopy(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]);
1252
- task.value = new BigInt64Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >>> 3);
1253
- freeTaskSlot(task);
1254
- return;
1255
- }
1256
- case PayloadBuffer.StaticBigInt64Array: {
1257
- const bytes = readStaticBufferCopy(0, task[TaskIndex.PayloadLen], slotIndex);
1258
- task.value = new BigInt64Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >>> 3);
1259
- return;
1260
- }
1261
- case PayloadBuffer.BigUint64Array: {
1262
- const bytes = readDynamicBufferCopy(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]);
1263
- task.value = new BigUint64Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >>> 3);
1264
- freeTaskSlot(task);
1265
- return;
1266
- }
1267
- case PayloadBuffer.StaticBigUint64Array: {
1268
- const bytes = readStaticBufferCopy(0, task[TaskIndex.PayloadLen], slotIndex);
1269
- task.value = new BigUint64Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >>> 3);
1270
- return;
1271
- }
1272
- case PayloadBuffer.DataView: {
1273
- const bytes = readDynamicBufferCopy(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]);
1274
- task.value = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
1275
- freeTaskSlot(task);
1276
- return;
1277
- }
1278
- case PayloadBuffer.StaticDataView: {
1279
- const bytes = readStaticBufferCopy(0, task[TaskIndex.PayloadLen], slotIndex);
1280
- task.value = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
1281
- return;
1282
- }
1283
- case PayloadBuffer.ExternalPayload:
1284
- task.value = decodeExternalPayload(readDynamicUtf8(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]));
1285
- freeTaskSlot(task);
1286
- return;
1287
- case PayloadBuffer.StaticExternalPayload:
1288
- task.value = decodeExternalPayload(readStaticUtf8(0, task[TaskIndex.PayloadLen], slotIndex));
1289
- return;
1290
- case PayloadBuffer.ProcessSharedBuffer:
1291
- task.value = decodeProcessSharedBufferNumericWords(readStaticU32Words(processSharedBufferWords, PROCESS_SHARED_BUFFER_NUMERIC_WORDS, slotIndex));
1292
- return;
1293
- case PayloadBuffer.SharedArrayBuffer:
1294
- task.value = decodeSharedArrayBufferNumericWords(readStaticU32Words(sharedArrayBufferWords, task[TaskIndex.PayloadLen] >>> 2, slotIndex));
1295
- return;
1296
- case PayloadBuffer.BufferReference:
1297
- task.value = decodeBufferReferenceNumericWords(readStaticU32Words(bufferReferenceWords, BUFFER_REFERENCE_NUMERIC_WORDS, slotIndex));
1298
- return;
1299
- case PayloadBuffer.Date:
1300
- Uint32View[0] = task[TaskIndex.Start];
1301
- Uint32View[1] = task[TaskIndex.End];
1302
- task.value = new Date(Float64View[0]);
1303
- return;
1304
- case PayloadBuffer.Error:
1305
- task.value = parseErrorPayload(readDynamicUtf8(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]));
1306
- freeTaskSlot(task);
1307
- return;
1308
- case PayloadBuffer.Binary:
1309
- {
1310
- const buffer = readDynamicBufferCopy(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]);
1311
- task.value = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
1312
- }
1313
- freeTaskSlot(task);
1314
- return;
1315
- case PayloadBuffer.StaticBinary:
1316
- task.value = readStaticUint8ArrayCopy(0, task[TaskIndex.PayloadLen], slotIndex);
1317
- return;
1318
- case PayloadBuffer.ArrayBuffer:
1319
- task.value = readDynamicArrayBuffer(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]);
1320
- freeTaskSlot(task);
1321
- return;
1322
- case PayloadBuffer.StaticArrayBuffer:
1323
- task.value = readStaticArrayBuffer(0, task[TaskIndex.PayloadLen], slotIndex);
1324
- return;
1325
- case PayloadBuffer.Buffer:
1326
- task.value = readDynamicBuffer(task[TaskIndex.Start], task[TaskIndex.Start] + task[TaskIndex.PayloadLen]);
1327
- freeTaskSlot(task);
1328
- return;
1329
- case PayloadBuffer.StaticBuffer:
1330
- task.value = readStaticBuffer(0, task[TaskIndex.PayloadLen], slotIndex);
1331
- return;
1332
- }
1333
- };
1334
- };