knitting 0.1.50 → 0.1.52

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 (72) hide show
  1. package/README.md +268 -75
  2. package/knitting.d.ts +1 -0
  3. package/map.md +56 -6
  4. package/package.json +16 -4
  5. package/prebuilds/darwin-arm64-node-127/knitting_buffer_pointer.node +0 -0
  6. package/prebuilds/darwin-arm64-node-127/knitting_shared_memory.node +0 -0
  7. package/prebuilds/darwin-arm64-node-137/knitting_buffer_pointer.node +0 -0
  8. package/prebuilds/darwin-arm64-node-137/knitting_shared_memory.node +0 -0
  9. package/prebuilds/darwin-x64-node-127/knitting_buffer_pointer.node +0 -0
  10. package/prebuilds/darwin-x64-node-127/knitting_shared_memory.node +0 -0
  11. package/prebuilds/darwin-x64-node-137/knitting_buffer_pointer.node +0 -0
  12. package/prebuilds/darwin-x64-node-137/knitting_shared_memory.node +0 -0
  13. package/prebuilds/linux-x64-node-127/knitting_buffer_pointer.node +0 -0
  14. package/prebuilds/linux-x64-node-127/knitting_shared_memory.node +0 -0
  15. package/prebuilds/linux-x64-node-137/knitting_buffer_pointer.node +0 -0
  16. package/prebuilds/linux-x64-node-137/knitting_shared_memory.node +0 -0
  17. package/prebuilds/win32-x64/knitting_windows_shared_memory.dll +0 -0
  18. package/prebuilds/win32-x64-node-127/knitting_buffer_pointer.node +0 -0
  19. package/prebuilds/win32-x64-node-127/knitting_shared_memory.node +0 -0
  20. package/prebuilds/win32-x64-node-127/knitting_shm.node +0 -0
  21. package/prebuilds/win32-x64-node-137/knitting_buffer_pointer.node +0 -0
  22. package/prebuilds/win32-x64-node-137/knitting_shared_memory.node +0 -0
  23. package/prebuilds/win32-x64-node-137/knitting_shm.node +0 -0
  24. package/scripts/build-native-addons.ts +5 -0
  25. package/src/api.d.ts +5 -11
  26. package/src/api.js +103 -22
  27. package/src/common/envelope.d.ts +9 -3
  28. package/src/common/envelope.js +14 -0
  29. package/src/common/task-source.js +4 -0
  30. package/src/common/worker-runtime.d.ts +2 -0
  31. package/src/common/worker-runtime.js +9 -0
  32. package/src/connections/buffer-reference-native.d.ts +56 -0
  33. package/src/connections/buffer-reference-native.js +217 -0
  34. package/src/connections/buffer-reference.d.ts +76 -0
  35. package/src/connections/buffer-reference.js +459 -0
  36. package/src/connections/index.d.ts +1 -0
  37. package/src/connections/index.js +1 -0
  38. package/src/connections/node-addons.d.ts +1 -1
  39. package/src/connections/node-buffer-pointer.d.ts +20 -0
  40. package/src/connections/node-buffer-pointer.js +16 -0
  41. package/src/connections/process-shared-buffer.js +2 -0
  42. package/src/connections/shared-array-buffer-payload.d.ts +36 -0
  43. package/src/connections/shared-array-buffer-payload.js +235 -0
  44. package/src/knitting_buffer_pointer.cc +425 -0
  45. package/src/knitting_shared_memory.cc +9 -2
  46. package/src/memory/lock.d.ts +12 -1
  47. package/src/memory/lock.js +55 -172
  48. package/src/memory/payloadCodec.js +241 -65
  49. package/src/memory/shared-buffer-io.d.ts +2 -0
  50. package/src/memory/shared-buffer-io.js +23 -0
  51. package/src/runtime/inline-executor.d.ts +2 -2
  52. package/src/runtime/inline-executor.js +15 -3
  53. package/src/runtime/pool.d.ts +3 -1
  54. package/src/runtime/pool.js +9 -1
  55. package/src/runtime/process-worker.js +3 -1
  56. package/src/runtime/tx-queue.d.ts +3 -2
  57. package/src/runtime/tx-queue.js +18 -13
  58. package/src/types.d.ts +39 -18
  59. package/src/utils/http.d.ts +21 -0
  60. package/src/utils/http.js +93 -0
  61. package/src/worker/loop.js +26 -4
  62. package/src/worker/process-worker-bootstrap.js +1 -0
  63. package/src/worker/rx-queue.d.ts +4 -1
  64. package/src/worker/rx-queue.js +53 -4
  65. package/src/worker/safety/startup.d.ts +2 -1
  66. package/src/worker/safety/startup.js +5 -2
  67. package/src/worker/task-loader.d.ts +2 -1
  68. package/src/worker/task-loader.js +14 -2
  69. package/unsafe.d.ts +1 -0
  70. package/unsafe.js +1 -0
  71. package/utils.d.ts +1 -0
  72. package/utils.js +1 -0
@@ -49,7 +49,13 @@ export declare enum PayloadBuffer {
49
49
  EnvelopeDynamicHeaderString = 43,
50
50
  ExternalPayload = 44,
51
51
  StaticExternalPayload = 45,
52
- ProcessSharedBuffer = 46
52
+ ProcessSharedBuffer = 46,
53
+ BufferReference = 47,
54
+ SharedArrayBuffer = 48,
55
+ EnvelopeStaticHeaderExternal = 49,
56
+ EnvelopeDynamicHeaderExternal = 50,
57
+ EnvelopeStaticHeaderStringExternal = 51,
58
+ EnvelopeDynamicHeaderStringExternal = 52
53
59
  }
54
60
  export declare enum LockBound {
55
61
  paddingLock = 0,
@@ -70,15 +76,20 @@ export type Task = [
70
76
  number
71
77
  ] & {
72
78
  value: unknown;
79
+ finalize?: (() => void) | undefined;
73
80
  resolve: (value?: unknown) => void;
74
81
  reject: (reason?: unknown) => void;
75
82
  };
83
+ export declare const PayloadTransportFinalizer: unique symbol;
76
84
  export declare const PromisePayloadMarker: unique symbol;
77
85
  export type PromisePayloadHandler = (task: Task, isRejected: boolean, value: unknown) => void;
78
86
  export declare const beginPromisePayload: (task: Task) => boolean;
79
87
  export declare const finishPromisePayload: (task: Task) => void;
80
88
  export declare const isPromisePayloadPending: (task: Task) => boolean;
81
89
  export declare const resetTaskLocalFlags: (task: Task) => void;
90
+ export declare const addTaskFinalizer: (task: Task, finalizer: () => void) => void;
91
+ export declare const attachPayloadTransportFinalizer: (task: Task, value: unknown) => void;
92
+ export declare const runTaskFinalizers: (task: Task) => void;
82
93
  export declare enum TaskIndex {
83
94
  /**
84
95
  * Worker -> host response flags word.
@@ -54,6 +54,12 @@ export var PayloadBuffer;
54
54
  PayloadBuffer[PayloadBuffer["ExternalPayload"] = 44] = "ExternalPayload";
55
55
  PayloadBuffer[PayloadBuffer["StaticExternalPayload"] = 45] = "StaticExternalPayload";
56
56
  PayloadBuffer[PayloadBuffer["ProcessSharedBuffer"] = 46] = "ProcessSharedBuffer";
57
+ PayloadBuffer[PayloadBuffer["BufferReference"] = 47] = "BufferReference";
58
+ PayloadBuffer[PayloadBuffer["SharedArrayBuffer"] = 48] = "SharedArrayBuffer";
59
+ PayloadBuffer[PayloadBuffer["EnvelopeStaticHeaderExternal"] = 49] = "EnvelopeStaticHeaderExternal";
60
+ PayloadBuffer[PayloadBuffer["EnvelopeDynamicHeaderExternal"] = 50] = "EnvelopeDynamicHeaderExternal";
61
+ PayloadBuffer[PayloadBuffer["EnvelopeStaticHeaderStringExternal"] = 51] = "EnvelopeStaticHeaderStringExternal";
62
+ PayloadBuffer[PayloadBuffer["EnvelopeDynamicHeaderStringExternal"] = 52] = "EnvelopeDynamicHeaderStringExternal";
57
63
  })(PayloadBuffer || (PayloadBuffer = {}));
58
64
  export var LockBound;
59
65
  (function (LockBound) {
@@ -64,6 +70,7 @@ export var LockBound;
64
70
  })(LockBound || (LockBound = {}));
65
71
  export const LOCK_CACHE_LINE_BYTES = 64;
66
72
  export const LOCK_SECTOR_BYTES = 256;
73
+ export const PayloadTransportFinalizer = Symbol.for("knitting.payloadCodec.transportFinalizer");
67
74
  export const PromisePayloadMarker = Symbol.for("knitting.promise.payload");
68
75
  const TASK_LOCAL_FLAGS_INDEX = 7;
69
76
  const TASK_LOCAL_PROMISE_PENDING_FLAG = 1 << 0;
@@ -72,7 +79,8 @@ export const beginPromisePayload = (task) => {
72
79
  const flags = task[TASK_LOCAL_FLAGS_INDEX];
73
80
  if ((flags & TASK_LOCAL_PROMISE_PENDING_FLAG) !== 0)
74
81
  return false;
75
- task[TASK_LOCAL_FLAGS_INDEX] = (flags | TASK_LOCAL_PROMISE_PENDING_FLAG) >>> 0;
82
+ task[TASK_LOCAL_FLAGS_INDEX] = (flags | TASK_LOCAL_PROMISE_PENDING_FLAG) >>>
83
+ 0;
76
84
  return true;
77
85
  };
78
86
  export const finishPromisePayload = (task) => {
@@ -83,6 +91,36 @@ export const isPromisePayloadPending = (task) => (task[TASK_LOCAL_FLAGS_INDEX] &
83
91
  export const resetTaskLocalFlags = (task) => {
84
92
  task[TASK_LOCAL_FLAGS_INDEX] = 0;
85
93
  };
94
+ export const addTaskFinalizer = (task, finalizer) => {
95
+ const previous = task.finalize;
96
+ task.finalize = previous === undefined ? finalizer : () => {
97
+ try {
98
+ previous();
99
+ }
100
+ finally {
101
+ finalizer();
102
+ }
103
+ };
104
+ };
105
+ export const attachPayloadTransportFinalizer = (task, value) => {
106
+ if (task.finalize !== undefined || value === null || typeof value !== "object") {
107
+ return;
108
+ }
109
+ const finalizer = value[PayloadTransportFinalizer]?.();
110
+ if (typeof finalizer === "function")
111
+ addTaskFinalizer(task, finalizer);
112
+ };
113
+ export const runTaskFinalizers = (task) => {
114
+ const finalizer = task.finalize;
115
+ task.finalize = undefined;
116
+ if (finalizer !== undefined) {
117
+ try {
118
+ finalizer();
119
+ }
120
+ catch {
121
+ }
122
+ }
123
+ };
86
124
  export var TaskIndex;
87
125
  (function (TaskIndex) {
88
126
  /**
@@ -186,6 +224,7 @@ const def = (_) => { };
186
224
  const createTaskShell = () => {
187
225
  const task = new Uint32Array(TaskIndex.Size);
188
226
  task.value = null;
227
+ task.finalize = undefined;
189
228
  task.resolve = def;
190
229
  task.reject = def;
191
230
  task[TASK_LOCAL_FLAGS_INDEX] = 0;
@@ -266,10 +305,12 @@ export const lock2 = ({ headers, headerSlotStrideU32, LockBoundSector, payload,
266
305
  lockSector: payloadLockRegion,
267
306
  textCompat: resolvedTextCompat,
268
307
  onPromise: (task, isRejected, value) => {
269
- if ((task[TASK_LOCAL_FLAGS_INDEX] & TASK_LOCAL_PROMISE_TRACKED_FLAG) !== 0 &&
308
+ if ((task[TASK_LOCAL_FLAGS_INDEX] & TASK_LOCAL_PROMISE_TRACKED_FLAG) !==
309
+ 0 &&
270
310
  pendingPromiseCount > 0) {
271
311
  task[TASK_LOCAL_FLAGS_INDEX] =
272
- (task[TASK_LOCAL_FLAGS_INDEX] & ~TASK_LOCAL_PROMISE_TRACKED_FLAG) >>> 0;
312
+ (task[TASK_LOCAL_FLAGS_INDEX] & ~TASK_LOCAL_PROMISE_TRACKED_FLAG) >>>
313
+ 0;
273
314
  pendingPromiseCount = (pendingPromiseCount - 1) | 0;
274
315
  }
275
316
  promiseHandler(task, isRejected, value);
@@ -322,7 +363,8 @@ export const lock2 = ({ headers, headerSlotStrideU32, LockBoundSector, payload,
322
363
  const flags = task[TASK_LOCAL_FLAGS_INDEX];
323
364
  if ((flags & TASK_LOCAL_PROMISE_TRACKED_FLAG) !== 0)
324
365
  return;
325
- task[TASK_LOCAL_FLAGS_INDEX] = (flags | TASK_LOCAL_PROMISE_TRACKED_FLAG) >>> 0;
366
+ task[TASK_LOCAL_FLAGS_INDEX] = (flags | TASK_LOCAL_PROMISE_TRACKED_FLAG) >>>
367
+ 0;
326
368
  pendingPromiseCount = (pendingPromiseCount + 1) | 0;
327
369
  };
328
370
  const encodeTaskValue = (task, slotIndex) => encodeTask(task, slotIndex);
@@ -564,171 +606,9 @@ export const lock2 = ({ headers, headerSlotStrideU32, LockBoundSector, payload,
564
606
  return modified;
565
607
  };
566
608
  }
567
- if (!shouldSettle) {
568
- if (!onResolved) {
569
- return () => {
570
- let diff = (a_load(hostBits, 0) ^ LastWorker) | 0;
571
- if (diff === 0)
572
- return 0;
573
- let modified = 0;
574
- let consumedBits = 0 | 0;
575
- let last = lastResolved;
576
- if (last === 32) {
577
- const idx = 31 - clz32(diff);
578
- const selectedBit = 1 << idx;
579
- const task = getTask(idx);
580
- decodeTask(task, idx);
581
- consumedBits = (consumedBits ^ selectedBit) | 0;
582
- settleTask(task);
583
- diff ^= selectedBit;
584
- modified++;
585
- if ((modified & 7) === 0 && consumedBits !== 0) {
586
- LastWorker = (LastWorker ^ consumedBits) | 0;
587
- a_store(workerBits, 0, LastWorker);
588
- consumedBits = 0 | 0;
589
- }
590
- last = idx;
591
- }
592
- while (diff !== 0) {
593
- const lowerMask = last === 31 ? 0x7fffffff : ((1 << last) - 1);
594
- let pick = diff & lowerMask;
595
- if (pick === 0)
596
- pick = diff;
597
- const idx = 31 - clz32(pick);
598
- const selectedBit = 1 << idx;
599
- const task = getTask(idx);
600
- decodeTask(task, idx);
601
- consumedBits = (consumedBits ^ selectedBit) | 0;
602
- settleTask(task);
603
- diff ^= selectedBit;
604
- modified++;
605
- if ((modified & 7) === 0 && consumedBits !== 0) {
606
- LastWorker = (LastWorker ^ consumedBits) | 0;
607
- a_store(workerBits, 0, LastWorker);
608
- consumedBits = 0 | 0;
609
- }
610
- last = idx;
611
- }
612
- if (consumedBits !== 0) {
613
- LastWorker = (LastWorker ^ consumedBits) | 0;
614
- a_store(workerBits, 0, LastWorker);
615
- }
616
- lastResolved = last;
617
- return modified;
618
- };
619
- }
620
- const onResolvedTask = onResolved;
621
- return () => {
622
- let diff = (a_load(hostBits, 0) ^ LastWorker) | 0;
623
- if (diff === 0)
624
- return 0;
625
- let modified = 0;
626
- let consumedBits = 0 | 0;
627
- let last = lastResolved;
628
- if (last === 32) {
629
- const idx = 31 - clz32(diff);
630
- const selectedBit = 1 << idx;
631
- const task = getTask(idx);
632
- decodeTask(task, idx);
633
- consumedBits = (consumedBits ^ selectedBit) | 0;
634
- settleTask(task);
635
- onResolvedTask(task);
636
- diff ^= selectedBit;
637
- modified++;
638
- if ((modified & 7) === 0 && consumedBits !== 0) {
639
- LastWorker = (LastWorker ^ consumedBits) | 0;
640
- a_store(workerBits, 0, LastWorker);
641
- consumedBits = 0 | 0;
642
- }
643
- last = idx;
644
- }
645
- while (diff !== 0) {
646
- const lowerMask = last === 31 ? 0x7fffffff : ((1 << last) - 1);
647
- let pick = diff & lowerMask;
648
- if (pick === 0)
649
- pick = diff;
650
- const idx = 31 - clz32(pick);
651
- const selectedBit = 1 << idx;
652
- const task = getTask(idx);
653
- decodeTask(task, idx);
654
- consumedBits = (consumedBits ^ selectedBit) | 0;
655
- settleTask(task);
656
- onResolvedTask(task);
657
- diff ^= selectedBit;
658
- modified++;
659
- if ((modified & 7) === 0 && consumedBits !== 0) {
660
- LastWorker = (LastWorker ^ consumedBits) | 0;
661
- a_store(workerBits, 0, LastWorker);
662
- consumedBits = 0 | 0;
663
- }
664
- last = idx;
665
- }
666
- if (consumedBits !== 0) {
667
- LastWorker = (LastWorker ^ consumedBits) | 0;
668
- a_store(workerBits, 0, LastWorker);
669
- }
670
- lastResolved = last;
671
- return modified;
672
- };
673
- }
609
+ const hasOnResolved = onResolved !== undefined;
610
+ const onResolvedTask = onResolved ?? def;
674
611
  const shouldSettleTask = shouldSettle;
675
- if (!onResolved) {
676
- return () => {
677
- let diff = (a_load(hostBits, 0) ^ LastWorker) | 0;
678
- if (diff === 0)
679
- return 0;
680
- let modified = 0;
681
- let consumedBits = 0 | 0;
682
- let last = lastResolved;
683
- if (last === 32) {
684
- const idx = 31 - clz32(diff);
685
- const selectedBit = 1 << idx;
686
- const task = getTask(idx);
687
- decodeTask(task, idx);
688
- consumedBits = (consumedBits ^ selectedBit) | 0;
689
- if (shouldSettleTask(task)) {
690
- settleTask(task);
691
- }
692
- diff ^= selectedBit;
693
- modified++;
694
- if ((modified & 7) === 0 && consumedBits !== 0) {
695
- LastWorker = (LastWorker ^ consumedBits) | 0;
696
- a_store(workerBits, 0, LastWorker);
697
- consumedBits = 0 | 0;
698
- }
699
- last = idx;
700
- }
701
- while (diff !== 0) {
702
- const lowerMask = last === 31 ? 0x7fffffff : ((1 << last) - 1);
703
- let pick = diff & lowerMask;
704
- if (pick === 0)
705
- pick = diff;
706
- const idx = 31 - clz32(pick);
707
- const selectedBit = 1 << idx;
708
- const task = getTask(idx);
709
- decodeTask(task, idx);
710
- consumedBits = (consumedBits ^ selectedBit) | 0;
711
- if (shouldSettleTask(task)) {
712
- settleTask(task);
713
- }
714
- diff ^= selectedBit;
715
- modified++;
716
- if ((modified & 7) === 0 && consumedBits !== 0) {
717
- LastWorker = (LastWorker ^ consumedBits) | 0;
718
- a_store(workerBits, 0, LastWorker);
719
- consumedBits = 0 | 0;
720
- }
721
- last = idx;
722
- }
723
- if (consumedBits !== 0) {
724
- LastWorker = (LastWorker ^ consumedBits) | 0;
725
- a_store(workerBits, 0, LastWorker);
726
- }
727
- lastResolved = last;
728
- return modified;
729
- };
730
- }
731
- const onResolvedTask = onResolved;
732
612
  return () => {
733
613
  let diff = (a_load(hostBits, 0) ^ LastWorker) | 0;
734
614
  if (diff === 0)
@@ -742,9 +622,10 @@ export const lock2 = ({ headers, headerSlotStrideU32, LockBoundSector, payload,
742
622
  const task = getTask(idx);
743
623
  decodeTask(task, idx);
744
624
  consumedBits = (consumedBits ^ selectedBit) | 0;
745
- if (shouldSettleTask(task)) {
625
+ if (shouldSettleTask === undefined || shouldSettleTask(task)) {
746
626
  settleTask(task);
747
- onResolvedTask(task);
627
+ if (hasOnResolved)
628
+ onResolvedTask(task);
748
629
  }
749
630
  diff ^= selectedBit;
750
631
  modified++;
@@ -765,9 +646,10 @@ export const lock2 = ({ headers, headerSlotStrideU32, LockBoundSector, payload,
765
646
  const task = getTask(idx);
766
647
  decodeTask(task, idx);
767
648
  consumedBits = (consumedBits ^ selectedBit) | 0;
768
- if (shouldSettleTask(task)) {
649
+ if (shouldSettleTask === undefined || shouldSettleTask(task)) {
769
650
  settleTask(task);
770
- onResolvedTask(task);
651
+ if (hasOnResolved)
652
+ onResolvedTask(task);
771
653
  }
772
654
  diff ^= selectedBit;
773
655
  modified++;
@@ -793,6 +675,7 @@ export const lock2 = ({ headers, headerSlotStrideU32, LockBoundSector, payload,
793
675
  if (recycled) {
794
676
  fillTaskFrom(recycled, headersBuffer, off);
795
677
  recycled.value = null;
678
+ recycled.finalize = undefined;
796
679
  recycled.resolve = def;
797
680
  recycled.reject = def;
798
681
  task = recycled;