knitting 0.1.63 → 0.1.73

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 (99) hide show
  1. package/README.md +623 -342
  2. package/knitting.browser.d.ts +3 -1
  3. package/knitting.browser.js +1 -1
  4. package/knitting.d.ts +3 -1
  5. package/knitting.js +2 -1
  6. package/map.md +0 -6
  7. package/package.json +10 -5
  8. package/prebuilds/darwin-arm64-node-127/knitting_buffer_pointer.node +0 -0
  9. package/prebuilds/darwin-arm64-node-127/knitting_doorbell.node +0 -0
  10. package/prebuilds/darwin-arm64-node-137/knitting_buffer_pointer.node +0 -0
  11. package/prebuilds/darwin-arm64-node-137/knitting_doorbell.node +0 -0
  12. package/prebuilds/darwin-x64-node-127/knitting_buffer_pointer.node +0 -0
  13. package/prebuilds/darwin-x64-node-127/knitting_doorbell.node +0 -0
  14. package/prebuilds/darwin-x64-node-137/knitting_buffer_pointer.node +0 -0
  15. package/prebuilds/darwin-x64-node-137/knitting_doorbell.node +0 -0
  16. package/prebuilds/linux-x64-node-127/knitting_buffer_pointer.node +0 -0
  17. package/prebuilds/linux-x64-node-127/knitting_doorbell.node +0 -0
  18. package/prebuilds/linux-x64-node-137/knitting_buffer_pointer.node +0 -0
  19. package/prebuilds/linux-x64-node-137/knitting_doorbell.node +0 -0
  20. package/prebuilds/win32-x64/knitting_windows_shared_memory.dll +0 -0
  21. package/prebuilds/win32-x64-node-127/knitting_buffer_pointer.node +0 -0
  22. package/prebuilds/win32-x64-node-127/knitting_doorbell.node +0 -0
  23. package/prebuilds/win32-x64-node-127/knitting_shared_memory.node +0 -0
  24. package/prebuilds/win32-x64-node-127/knitting_shm.node +0 -0
  25. package/prebuilds/win32-x64-node-137/knitting_buffer_pointer.node +0 -0
  26. package/prebuilds/win32-x64-node-137/knitting_doorbell.node +0 -0
  27. package/prebuilds/win32-x64-node-137/knitting_shared_memory.node +0 -0
  28. package/prebuilds/win32-x64-node-137/knitting_shm.node +0 -0
  29. package/scripts/build-native-addons.ts +5 -0
  30. package/shared-memory.d.ts +3 -0
  31. package/shared-memory.js +3 -0
  32. package/src/api.js +158 -71
  33. package/src/common/with-resolvers.js +2 -5
  34. package/src/common/worker-runtime.d.ts +7 -0
  35. package/src/common/worker-runtime.js +7 -0
  36. package/src/connections/buffer-reference.d.ts +10 -36
  37. package/src/connections/buffer-reference.js +15 -170
  38. package/src/connections/node-addons.d.ts +1 -1
  39. package/src/connections/node-addons.js +11 -1
  40. package/src/connections/shared-array-buffer-payload.d.ts +7 -0
  41. package/src/connections/shared-array-buffer-payload.js +27 -11
  42. package/src/debug/gate.js +1 -1
  43. package/src/debug/handle.d.ts +6 -1
  44. package/src/debug/handle.js +14 -6
  45. package/src/error.d.ts +9 -0
  46. package/src/error.js +16 -2
  47. package/src/knitting_buffer_pointer.cc +57 -2
  48. package/src/knitting_doorbell.cc +220 -0
  49. package/src/memory/knitting-body.d.ts +44 -0
  50. package/src/memory/knitting-body.js +51 -0
  51. package/src/memory/knitting-buffer-http.d.ts +116 -0
  52. package/src/memory/knitting-buffer-http.js +255 -0
  53. package/src/memory/knitting-buffer.d.ts +250 -0
  54. package/src/memory/knitting-buffer.js +695 -0
  55. package/src/memory/lazy-region-registry.d.ts +83 -0
  56. package/src/memory/lazy-region-registry.js +355 -0
  57. package/src/memory/lock.d.ts +80 -15
  58. package/src/memory/lock.js +473 -139
  59. package/src/memory/payloadCodec.d.ts +18 -2
  60. package/src/memory/payloadCodec.js +340 -76
  61. package/src/memory/regionRegistry.d.ts +6 -0
  62. package/src/memory/regionRegistry.js +125 -240
  63. package/src/memory/shared-buffer-io.d.ts +7 -0
  64. package/src/memory/shared-buffer-io.js +34 -8
  65. package/src/permission/protocol.d.ts +1 -0
  66. package/src/permission/protocol.js +8 -3
  67. package/src/runtime/deno-doorbell.d.ts +26 -0
  68. package/src/runtime/deno-doorbell.js +117 -0
  69. package/src/runtime/dispatcher.d.ts +13 -6
  70. package/src/runtime/dispatcher.js +101 -63
  71. package/src/runtime/host-arg-arena.d.ts +3 -0
  72. package/src/runtime/host-arg-arena.js +16 -0
  73. package/src/runtime/inline-executor.js +2 -1
  74. package/src/runtime/node-doorbell.d.ts +14 -0
  75. package/src/runtime/node-doorbell.js +84 -0
  76. package/src/runtime/pool.d.ts +30 -15
  77. package/src/runtime/pool.js +199 -151
  78. package/src/runtime/process-worker.d.ts +9 -0
  79. package/src/runtime/process-worker.js +32 -3
  80. package/src/runtime/tx-queue.d.ts +4 -6
  81. package/src/runtime/tx-queue.js +63 -48
  82. package/src/runtime/worker-common.d.ts +7 -0
  83. package/src/runtime/worker-common.js +28 -2
  84. package/src/types.d.ts +66 -78
  85. package/src/worker/loop.js +95 -60
  86. package/src/worker/rx-queue.d.ts +2 -3
  87. package/src/worker/rx-queue.js +34 -40
  88. package/src/worker/safety/index.d.ts +1 -1
  89. package/src/worker/safety/index.js +1 -1
  90. package/src/worker/safety/process.d.ts +2 -0
  91. package/src/worker/safety/process.js +8 -1
  92. package/src/worker/safety/startup.js +11 -6
  93. package/src/worker/shared-return.d.ts +9 -0
  94. package/src/worker/shared-return.js +22 -0
  95. package/src/worker/task-loader.js +1 -2
  96. package/src/worker/timers.d.ts +2 -6
  97. package/src/worker/timers.js +39 -22
  98. package/unsafe.d.ts +2 -1
  99. package/unsafe.js +2 -1
@@ -2,10 +2,24 @@
2
2
  const Comment = {
3
3
  thisIsAHint: 0,
4
4
  };
5
+ // A full collection costs milliseconds. Run on every idle entry, it made each
6
+ // sequential call ~1000x slower under --expose-gc; once a second keeps the
7
+ // idle collection without paying it per call.
8
+ const IDLE_GC_INTERVAL_MS = 1000;
5
9
  const maybeGc = (() => {
6
10
  const host = globalThis;
7
- const gc = typeof host.gc === "function"
8
- ? (() => host.gc())
11
+ // Capture the function itself: the global is deleted below, so reading
12
+ // `host.gc` at call time would throw on the first idle pass.
13
+ const exposedGc = host.gc;
14
+ let lastGcAt = -Infinity;
15
+ const gc = typeof exposedGc === "function"
16
+ ? (() => {
17
+ const now = performance.now();
18
+ if (now - lastGcAt < IDLE_GC_INTERVAL_MS)
19
+ return;
20
+ lastGcAt = now;
21
+ exposedGc();
22
+ })
9
23
  : undefined;
10
24
  if (gc) {
11
25
  try {
@@ -30,8 +44,7 @@ const a_load = Atomics.load;
30
44
  const a_store = Atomics.store;
31
45
  const a_wait = typeof Atomics.wait === "function" ? Atomics.wait : undefined;
32
46
  const p_now = performance.now.bind(performance);
33
- // `SharedArrayBuffer` is undeclared on pages that are not cross-origin
34
- // isolated, and this module has to load anyway so the pool can report why.
47
+ // Some pages do not define SharedArrayBuffer; keep this module loadable there.
35
48
  const waitFallbackView = a_wait === undefined || typeof SharedArrayBuffer !== "function"
36
49
  ? undefined
37
50
  : new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
@@ -43,17 +56,16 @@ const isPlainNodeWindows = runtimeGlobals.process?.platform === "win32" &&
43
56
  typeof runtimeGlobals.process?.versions?.node === "string" &&
44
57
  runtimeGlobals.process?.versions?.bun === undefined &&
45
58
  runtimeGlobals.Deno === undefined;
46
- // Windows has no working cross-process wake. The native wake (WakeByAddress)
47
- // is keyed to a virtual address, so a host cannot wake a process worker parked
48
- // on the same physical page mapped at a different address in the child — the
49
- // addon's FutexWake is a no-op there. A parked Windows Node process worker can
50
- // therefore never be signalled and must rediscover work by polling. Cap the
51
- // native wait at 1ms so it re-checks every millisecond instead of sleeping the
52
- // full parkMs (up to seconds); the long park with no wake is what made CI
53
- // runners appear to hang. The native wait already polls internally, so this is
54
- // just bounding each poll slice.
59
+ // Bun on Windows requires special handling for short waits and process rings.
60
+ export const IS_BUN_WINDOWS = runtimeGlobals.process?.platform === "win32" &&
61
+ typeof runtimeGlobals.process?.versions?.bun === "string";
62
+ // Bun on Windows busy-spins for waits of 1ms or less; use a 2ms minimum.
63
+ const BUN_WINDOWS_MIN_WAIT_MS = 2;
64
+ const floorBunWindowsWait = (ms) => IS_BUN_WINDOWS && ms < BUN_WINDOWS_MIN_WAIT_MS ? BUN_WINDOWS_MIN_WAIT_MS : ms;
65
+ // Windows process workers cannot be woken through the native address-based
66
+ // wait, so cap their wait to 1ms and let polling rediscover work.
55
67
  const nativeWaitTimeoutMs = (parkMs) => isPlainNodeWindows ? 1 : Number.isFinite(parkMs) ? parkMs : Infinity;
56
- const pollingWaitTimeoutMs = (parkMs) => Number.isFinite(parkMs) ? Math.min(Math.max(parkMs, 0), 1) : 1;
68
+ const pollingWaitTimeoutMs = (parkMs) => floorBunWindowsWait(Number.isFinite(parkMs) ? Math.min(Math.max(parkMs, 0), 1) : 1);
57
69
  export const whilePausing = ({ pauseInNanoseconds }) => {
58
70
  const forNanoseconds = pauseInNanoseconds ?? DEFAULT_PAUSE_TIME;
59
71
  if (!a_pause || forNanoseconds <= 0)
@@ -84,7 +96,6 @@ export const sleepUntilChanged = ({ at, opView, pauseInNanoseconds, rxStatus, tx
84
96
  };
85
97
  return (value, spinMicroseconds, parkMs) => {
86
98
  const until = p_now() + (spinMicroseconds / 1000);
87
- maybeGc();
88
99
  let spinChecks = 0;
89
100
  while (true) {
90
101
  if (a_load(opView, at) !== value ||
@@ -96,24 +107,30 @@ export const sleepUntilChanged = ({ at, opView, pauseInNanoseconds, rxStatus, tx
96
107
  if ((spinChecks++ & 63) === 0 && p_now() >= until)
97
108
  break;
98
109
  }
110
+ // Collect only once the spin found nothing, then re-check before parking.
111
+ maybeGc();
99
112
  if (tryProgress())
100
113
  return;
101
114
  a_store(rxStatus, 0, 0);
115
+ // The other half of the host's post-publish check: a publication that
116
+ // landed before rxStatus cleared is visible now, and one after it finds
117
+ // rxStatus clear and rings.
118
+ if (a_load(opView, at) !== value || tryProgress()) {
119
+ a_store(rxStatus, 0, 1);
120
+ return;
121
+ }
102
122
  if (nativeWaitU32 !== undefined) {
103
123
  nativeWaitU32(opView.buffer, opView.byteOffset + (at * Int32Array.BYTES_PER_ELEMENT), value >>> 0, nativeWaitTimeoutMs(parkMs));
104
124
  }
105
125
  else if (useSharedMemoryWait &&
106
126
  a_wait &&
107
127
  opView.buffer instanceof SharedArrayBuffer) {
108
- // This is the notify-able path: a host Atomics.notify on opView wakes it.
109
- // An infinite parkMs (debug) is intentional here — the worker blocks until
110
- // a real signal instead of re-polling on a timeout.
111
- a_wait(opView, at, value, parkMs ?? Infinity);
128
+ // This path can be woken with Atomics.notify; an infinite debug wait is
129
+ // intentional.
130
+ a_wait(opView, at, value, floorBunWindowsWait(parkMs ?? Infinity));
112
131
  }
113
132
  else if (a_wait && waitFallbackView) {
114
- // waitFallbackView is never notified — this wait only ever times out and
115
- // re-polls. Keep the slice short and finite so FFI-backed process workers
116
- // stay responsive without a cross-process native wake primitive.
133
+ // This fallback is timeout-driven; keep the slice short for responsiveness.
117
134
  a_wait(waitFallbackView, 0, 0, pollingWaitTimeoutMs(parkMs));
118
135
  }
119
136
  a_store(rxStatus, 0, 1);
package/unsafe.d.ts CHANGED
@@ -1 +1,2 @@
1
- export { BUFFER_REFERENCE_CODEC_ID, BUFFER_REFERENCE_KIND, BufferReference, type BufferReferenceMetadata, BufferReferenceReturn, type BufferReferenceRuntime, isBufferReferenceMetadata, } from "./src/connections/buffer-reference.js";
1
+ export { BUFFER_REFERENCE_CODEC_ID, BUFFER_REFERENCE_KIND, BufferReference, type BufferReferenceMetadata, type BufferReferenceRuntime, isBufferReferenceMetadata, } from "./src/connections/buffer-reference.js";
2
+ export { sharedBytes } from "./src/worker/shared-return.js";
package/unsafe.js CHANGED
@@ -1 +1,2 @@
1
- export { BUFFER_REFERENCE_CODEC_ID, BUFFER_REFERENCE_KIND, BufferReference, BufferReferenceReturn, isBufferReferenceMetadata, } from "./src/connections/buffer-reference.js";
1
+ export { BUFFER_REFERENCE_CODEC_ID, BUFFER_REFERENCE_KIND, BufferReference, isBufferReferenceMetadata, } from "./src/connections/buffer-reference.js";
2
+ export { sharedBytes } from "./src/worker/shared-return.js";