@atolljs/core 0.1.6 → 0.1.8

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 (59) hide show
  1. package/README.md +1 -1
  2. package/dist/contract/memoryDevtools.d.ts +30 -0
  3. package/dist/contract/sharedMemory.d.ts +6 -2
  4. package/dist/contract/types.d.ts +13 -0
  5. package/dist/devtools.d.ts +346 -0
  6. package/dist/index.d.ts +8 -2
  7. package/dist/index.js +19 -16
  8. package/dist/index10.js +28 -184
  9. package/dist/index11.js +18 -48
  10. package/dist/index12.js +29 -63
  11. package/dist/index13.js +49 -24
  12. package/dist/index14.js +57 -59
  13. package/dist/index15.js +335 -45
  14. package/dist/index16.js +242 -47
  15. package/dist/index17.js +57 -38
  16. package/dist/index18.js +9 -86
  17. package/dist/index19.js +58 -48
  18. package/dist/index20.js +24 -56
  19. package/dist/index21.js +61 -0
  20. package/dist/index22.js +48 -0
  21. package/dist/index23.js +68 -0
  22. package/dist/index24.js +41 -0
  23. package/dist/index25.js +46 -0
  24. package/dist/index26.js +113 -0
  25. package/dist/index27.js +60 -0
  26. package/dist/index28.js +57 -0
  27. package/dist/index5.js +227 -35
  28. package/dist/index6.js +143 -471
  29. package/dist/index7.js +51 -20
  30. package/dist/index8.js +507 -27
  31. package/dist/index9.js +19 -18
  32. package/dist/pool/dedicatedWorker.d.ts +63 -0
  33. package/dist/pool/devtoolsCommands.d.ts +54 -0
  34. package/dist/pool/subWorkerClient.d.ts +50 -0
  35. package/dist/pool/workerChannel.d.ts +44 -0
  36. package/dist/pool/workerClient.d.ts +38 -8
  37. package/dist/pool/workerPool.d.ts +13 -0
  38. package/dist/reactive.d.ts +15 -0
  39. package/dist/reactiveGraph.d.ts +9 -0
  40. package/dist/userTiming.d.ts +27 -0
  41. package/package.json +2 -1
  42. package/src/contract/memoryDevtools.ts +249 -0
  43. package/src/contract/sharedMemory.ts +39 -9
  44. package/src/contract/types.ts +13 -0
  45. package/src/devtools.ts +735 -0
  46. package/src/index.ts +27 -1
  47. package/src/log.ts +22 -0
  48. package/src/observable.ts +16 -3
  49. package/src/pool/dedicatedWorker.ts +332 -0
  50. package/src/pool/devtoolsCommands.ts +165 -0
  51. package/src/pool/subWorkerClient.ts +70 -0
  52. package/src/pool/workerChannel.ts +99 -0
  53. package/src/pool/workerClient.ts +64 -15
  54. package/src/pool/workerPool.ts +115 -36
  55. package/src/reactive.ts +87 -12
  56. package/src/reactiveGraph.ts +91 -0
  57. package/src/testing/inProcessWorker.ts +4 -3
  58. package/src/userTiming.ts +71 -0
  59. package/src/worker/workerBootstrap.ts +29 -3
@@ -1,6 +1,8 @@
1
1
  import type { Prettify, Schema } from './types';
2
2
  import { msgpackrCodec } from './msgpackrCodec';
3
3
  import { memberToSpec, zodArrayInfo, zodObjectShape, zodStringBytes } from './listSchema';
4
+ import { devtoolsEnabled, emitDevtools } from '../devtools';
5
+ import { checkWatchOnWrite, ensureMemoryCommands, memoryWatches } from './memoryDevtools';
4
6
  import { fmtBytes, scoped } from '../log';
5
7
  import { z, fluent } from './zod';
6
8
 
@@ -101,6 +103,8 @@ export interface ConnectorContext {
101
103
  codec: Codec;
102
104
  /** Slot in the shared version counter — bump + notify on granular writes. */
103
105
  version?: { view: Int32Array; index: number };
106
+ /** The field's contract path — for devtools write events on granular commits. */
107
+ path?: string;
104
108
  }
105
109
 
106
110
  /**
@@ -141,6 +145,8 @@ export interface Connector<T> {
141
145
  write(value: T): void;
142
146
  /** Internal: slot in the shared version counter block, bumped on every write. */
143
147
  readonly _version?: { view: Int32Array; index: number };
148
+ /** Internal: the field's contract path — devtools node labels. */
149
+ readonly _path?: string;
144
150
  }
145
151
 
146
152
  /* ------------------------------------------------------------------ */
@@ -670,10 +676,13 @@ function listFactory(d: FieldDescriptor, ctx: ConnectorContext, byteOffset: numb
670
676
  writeAt: writeAt as ListConnector<any>['writeAt'],
671
677
  commit: () => {
672
678
  if (ctx.version) {
673
- Atomics.add(ctx.version.view, ctx.version.index, 1);
679
+ const prev = Atomics.add(ctx.version.view, ctx.version.index, 1);
674
680
  // Wake EVERY waitAsync observer — several watchers may share this
675
681
  // field's counter; a bounded notify starves all but one.
676
682
  Atomics.notify(ctx.version.view, ctx.version.index);
683
+ if (ctx.path && devtoolsEnabled()) {
684
+ emitDevtools({ type: 'memory:write', path: ctx.path, version: prev + 1 });
685
+ }
677
686
  }
678
687
  },
679
688
  read: () => Array.from({ length: count }, (_, i) => readAt(i)),
@@ -803,8 +812,9 @@ export class SharedMemory<S extends SharedSpec = SharedSpec> {
803
812
  throw new Error(`Unknown shared memory field kind: ${descriptor.kind}`);
804
813
  }
805
814
  memLog.debug(`bind "${path}" (${descriptor.kind}, ${fmtBytes(descriptor.byteLength)}) via ${this.plugins?.[descriptor.kind] ? 'plugin' : 'built-in'} factory`);
806
- const ctx: ConnectorContext = { buffer, codec: this.codec, version: { view: versionView, index } };
815
+ const ctx: ConnectorContext = { buffer, codec: this.codec, version: { view: versionView, index }, path };
807
816
  const raw = factory(descriptor, ctx, this.offsets.get(path)!);
817
+ const commit = (raw as Partial<ListConnector<unknown>>).commit;
808
818
  this.connectors.set(path, {
809
819
  ...raw,
810
820
  write: (v) => {
@@ -812,12 +822,35 @@ export class SharedMemory<S extends SharedSpec = SharedSpec> {
812
822
  // Bump the version counter and explicitly wake waitAsync observers —
813
823
  // V8 only resolves waitAsync waiters on notify, not on value changes.
814
824
  // No count bound: every watcher on this field must wake.
815
- Atomics.add(versionView, index, 1);
825
+ const prev = Atomics.add(versionView, index, 1);
816
826
  Atomics.notify(versionView, index);
827
+ if (devtoolsEnabled()) {
828
+ emitDevtools({ type: 'memory:write', path, version: prev + 1 });
829
+ if (memoryWatches.size) checkWatchOnWrite(this, path, prev + 1);
830
+ }
817
831
  },
832
+ // List commits bump inside the factory — wrapped for watchpoints only
833
+ // when devtools is on at bind time, so the plain path stays direct.
834
+ ...(commit && devtoolsEnabled()
835
+ ? {
836
+ commit: () => {
837
+ commit();
838
+ if (memoryWatches.size) checkWatchOnWrite(this, path, Atomics.load(versionView, index));
839
+ },
840
+ }
841
+ : {}),
818
842
  _version: { view: versionView, index },
843
+ _path: path,
819
844
  });
820
845
  });
846
+ if (devtoolsEnabled()) {
847
+ ensureMemoryCommands(() => definedSharedMemories);
848
+ emitDevtools({
849
+ type: 'memory:bind',
850
+ fields: this.entries.map((e, i) => [i, e.path]),
851
+ totalBytes: this.totalBytes,
852
+ });
853
+ }
821
854
  this.isBound = true;
822
855
  this.boundBuffer = buffer;
823
856
  for (const cb of [...this.boundListeners]) cb();
@@ -854,15 +887,12 @@ export class SharedMemory<S extends SharedSpec = SharedSpec> {
854
887
  }
855
888
 
856
889
  /**
857
- * Fires when the contract is bound on this thread — immediately if already
858
- * bound. Returns an unsubscribe function.
890
+ * Fires when the contract is bound on this thread — on every bind, and
891
+ * immediately if already bound. Returns an unsubscribe function.
859
892
  */
860
893
  public onBound(cb: () => void): () => void {
861
- if (this.isBound) {
862
- cb();
863
- return () => {};
864
- }
865
894
  this.boundListeners.add(cb);
895
+ if (this.isBound) cb();
866
896
  return () => this.boundListeners.delete(cb);
867
897
  }
868
898
 
@@ -57,6 +57,17 @@ export interface WorkerPoolConfig<S extends SharedSpec = SharedSpec, T extends T
57
57
  * skipped and workers receive a plain `{ type: 'INIT' }` handshake.
58
58
  */
59
59
  sharedMemory?: SharedMemory<S> & Prettify<SharedAccess<S>>;
60
+ /**
61
+ * Hand an existing SharedArrayBuffer to every spawned worker instead of
62
+ * allocating a fresh `WebAssembly.Memory` — the worker-shell case: a worker
63
+ * already bound to a contract spawns sub-workers on the SAME buffer
64
+ * (`sharedBuffer: contract.buffer`), or a second pool shares the first
65
+ * pool's `pool.sharedBuffer`. A thunk is resolved once, when the pool
66
+ * constructs. With `sharedMemory` the contract binds locally to this
67
+ * buffer; without it the buffer still ships via INIT_MEMORY and the
68
+ * workers bind their own defined contracts.
69
+ */
70
+ sharedBuffer?: SharedArrayBuffer | (() => SharedArrayBuffer | undefined);
60
71
  /**
61
72
  * Persistence adapter for `sharedMemory` — invoked with the contract right
62
73
  * after the pool binds it, and its `stop()` runs on `terminate()`.
@@ -65,6 +76,8 @@ export interface WorkerPoolConfig<S extends SharedSpec = SharedSpec, T extends T
65
76
  persistence?: (memory: SharedMemory<S>) => MemoryPersistence | undefined;
66
77
  /** Worker count — a number, or 'auto' (the default) for navigator.hardwareConcurrency ?? 4. */
67
78
  poolSize?: number | 'auto';
79
+ /** Display label for devtools/dashboards — falls back to a generated id. */
80
+ name?: string;
68
81
  memory?: MemoryConfig;
69
82
  /** Max in-flight tasks per worker (default 1); excess tasks queue FIFO. */
70
83
  concurrency?: number;