@abide/abide 0.123.3 → 0.124.0

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 (89) hide show
  1. package/ABIDE.md +8 -5
  2. package/CHANGELOG.md +31 -0
  3. package/docs/REGISTRY.md +45 -12
  4. package/docs/RULEBOOK.md +24 -14
  5. package/docs/abide.md +999 -459
  6. package/package.json +1 -1
  7. package/src/compiler/ARRAY_MUTATORS.ts +20 -0
  8. package/src/compiler/LoweredFile.ts +609 -0
  9. package/src/compiler/Lowering.ts +17 -0
  10. package/src/compiler/SHARED_NAMES.ts +2 -0
  11. package/src/compiler/ShadowHost.ts +670 -0
  12. package/src/compiler/ShadowMap.ts +1 -1
  13. package/src/compiler/TypeSession.ts +71 -1715
  14. package/src/compiler/appLints.ts +109 -0
  15. package/src/compiler/checkedShadow.ts +1 -1
  16. package/src/compiler/classifyRead.ts +16 -1
  17. package/src/compiler/compileApp.ts +2 -2
  18. package/src/compiler/declaredExports.ts +44 -17
  19. package/src/compiler/diagnoseSources.ts +232 -0
  20. package/src/compiler/formatAbide.ts +5 -6
  21. package/src/compiler/handlersUnder.ts +16 -35
  22. package/src/compiler/reactiveReads.ts +235 -0
  23. package/src/compiler/reactiveTypes.ts +13 -0
  24. package/src/compiler/readsIn.ts +180 -81
  25. package/src/compiler/routesDeclaration.ts +46 -0
  26. package/src/compiler/scaffold.ts +7 -2
  27. package/src/compiler/serveLanguage.ts +26 -20
  28. package/src/compiler/splitImports.ts +2 -2
  29. package/src/server/DesktopSession.ts +213 -0
  30. package/src/server/Followers.ts +399 -0
  31. package/src/server/MODULE_QUERIES.ts +6 -2
  32. package/src/server/PageRender.ts +201 -0
  33. package/src/server/abideModules.ts +7 -7
  34. package/src/server/answerFailure.ts +3 -2
  35. package/src/server/answerRequest.ts +6 -70
  36. package/src/server/answerRpc.ts +48 -260
  37. package/src/server/answerSocket.ts +41 -463
  38. package/src/server/appKit.ts +1 -1
  39. package/src/server/argsContract.ts +1 -1
  40. package/src/server/createApp.ts +8 -2
  41. package/src/server/csp.ts +1 -1
  42. package/src/server/deferredBuilds.ts +3 -16
  43. package/src/server/faceOf.ts +1 -1
  44. package/src/server/generatedSurfaces.ts +2 -1
  45. package/src/server/handlerFileMount.ts +1 -1
  46. package/src/server/index.ts +1 -1
  47. package/src/server/installServer.ts +5 -9
  48. package/src/server/invokeHandler.ts +230 -0
  49. package/src/server/mountHandlers.ts +184 -0
  50. package/src/server/openDesktopWindow.ts +308 -0
  51. package/src/server/preload.ts +18 -0
  52. package/src/server/principal.ts +1 -1
  53. package/src/server/remote.ts +1 -1
  54. package/src/server/render.ts +31 -59
  55. package/src/server/requestScope.ts +5 -36
  56. package/src/server/runDesktop.ts +19 -447
  57. package/src/server/seedBuffer.ts +11 -11
  58. package/src/server/servedApp.ts +1 -1
  59. package/src/server/shell.ts +1 -1
  60. package/src/server/surfaceOf.ts +1 -1
  61. package/src/server/versionOf.ts +1 -1
  62. package/src/shared/RPC_SERVER.ts +27 -31
  63. package/src/shared/Schema.ts +1 -2
  64. package/src/shared/index.ts +1 -1
  65. package/src/shared/{note.ts → issueReport.ts} +22 -0
  66. package/src/shared/loadCall.ts +66 -0
  67. package/src/shared/reactive/Keyed.ts +23 -15
  68. package/src/shared/reactive/Reactive.ts +34 -1001
  69. package/src/shared/reactive/byOf.ts +2 -5
  70. package/src/shared/reactive/callLoad.ts +8 -14
  71. package/src/shared/reactive/cellShape.ts +734 -0
  72. package/src/shared/reactive/index.ts +12 -24
  73. package/src/shared/reactive/pairReactive.ts +5 -3
  74. package/src/shared/reactive/producer.ts +121 -0
  75. package/src/shared/reactive/scoped.ts +3 -2
  76. package/src/shared/reactive/selections.ts +209 -0
  77. package/src/shared/reactive/watch.ts +3 -4
  78. package/src/shared/rpc.ts +8 -5
  79. package/src/shared/validateJson.ts +1 -2
  80. package/src/shared/writePath.ts +29 -0
  81. package/src/ui/Router.ts +53 -69
  82. package/src/ui/outboxQueue.ts +2 -8
  83. package/src/ui/outcomeOf.ts +120 -0
  84. package/src/ui/socketWire.ts +3 -3
  85. package/src/ui/wire.ts +9 -10
  86. package/src/shared/LOAD_OFFLINE.ts +0 -15
  87. package/src/shared/LOAD_SIGNAL.ts +0 -10
  88. package/src/shared/issuesOf.ts +0 -18
  89. package/src/shared/reactive/ENTRY_LIVES.ts +0 -7
@@ -8,7 +8,7 @@
8
8
  // holds one per row — and copying the shared ones onto each instance instead was 87% of
9
9
  // what a value cost to construct. See `MEMBER_PROTOTYPE`.
10
10
  //
11
- // Every field `Cell` declares is written in its constructor, in one order, `undefined`
11
+ // Every field `Cell` (`cellShape.ts`) declares is written in its constructor, in one order, `undefined`
12
12
  // included — a shape that grows a field on a later path is two hidden classes and every
13
13
  // read downstream of it deoptimizes.
14
14
 
@@ -19,24 +19,38 @@ import { type Found, runSchema, type Schema } from '../Schema.ts'
19
19
  import { UNEXPECTED } from '../UNEXPECTED.ts'
20
20
  import { WORK } from '../WORK.ts'
21
21
  import { CELL } from './CELL.ts'
22
+ import {
23
+ type Adoption,
24
+ type Callable,
25
+ type Cap,
26
+ Cell,
27
+ EMPTY_RING,
28
+ newStream,
29
+ OWES_ABOVE,
30
+ OWES_NOTHING,
31
+ OWES_RELOAD,
32
+ type Persisted,
33
+ simpleShape,
34
+ type Stream,
35
+ } from './cellShape.ts'
22
36
  import { CAUGHT_UP, Cursor, hasCursorBehind, keepPlaces } from './Cursor.ts'
23
- import { ENTRY_LIVES } from './ENTRY_LIVES.ts'
24
- import { armTimer, type Expiry, expiryFor } from './Expiry.ts'
37
+ import { armTimer, type Expiry } from './Expiry.ts'
25
38
  import { isReactive } from './isReactive.ts'
26
39
  import { isThenable } from './isThenable.ts'
27
- import { MUTATION } from './MUTATION.ts'
28
40
  import { NO_INITIAL } from './NO_INITIAL.ts'
29
41
  import { NotLanded } from './NotLanded.ts'
30
- import {
31
- holdLog,
32
- logOf,
33
- PatchLog,
34
- type PatchOp,
35
- sendInvalidate,
36
- } from './patchLog.ts'
42
+ import { logOf, PatchLog, type PatchOp, sendInvalidate } from './patchLog.ts'
37
43
  import { REACTIVE_BRAND } from './REACTIVE_BRAND.ts'
38
44
  import { recordWrites } from './recordWrites.ts'
39
- import { currentScope, runInScope, type Scope } from './scoping.ts'
45
+ import { runInScope } from './scoping.ts'
46
+ import {
47
+ EVERY_PRODUCER,
48
+ fileProducer,
49
+ inReach,
50
+ markSignals,
51
+ tagCell,
52
+ trackSignal,
53
+ } from './selections.ts'
40
54
  import { STREAMING } from './STREAMING.ts'
41
55
  import {
42
56
  CHECK,
@@ -45,7 +59,6 @@ import {
45
59
  DIRTY,
46
60
  dropProbeReader,
47
61
  newSubscriber,
48
- newTracked,
49
62
  RELEASING,
50
63
  revive,
51
64
  type Subscriber,
@@ -276,228 +289,13 @@ export type Reactive<
276
289
  finally(onSettled: () => void): Promise<Stored>
277
290
  }
278
291
 
279
- /** The standing adoption: what is adopted, and the way to stop mirroring it. */
280
- type Adoption = { source: Cell; stop: () => void }
281
-
282
- /**
283
- * The window a `throttle` or a `debounce` holds open, allocated only where one is declared.
284
- *
285
- * THE WINDOW A `throttle` OR A `debounce` HOLDS OPEN (RULEBOOK 5.8). One field on the
286
- * cell rather than one per window field, allocated only where a value declared one — the
287
- * shape `adoption` already uses, and for the same reason.
288
- *
289
- * WHAT A WINDOW CAPS IS THE WAKE, NEVER THE PRODUCTION (5.9). Every write still mints and
290
- * the ordinal moves. What waits is the value a READER sees and the cascade that tells it so,
291
- * which is the whole of 5.8's "how often a value changes for a reader".
292
- *
293
- * WHAT IT COSTS EVERY VALUE THAT NEVER CAPS: one field load and one branch on the write
294
- * path, plus `serve` as a frame rather than five stores inline. Measured at 0.99x -> 1.08x
295
- * against the hand-written arm on the since-removed `publish into a capped ring` case, consistent across three
296
- * runs over a 0.7% floor — about 1.3 ns on a 14.7 ns op. Moving the comparison target
297
- * behind the gate did not recover it, so it is the frame and the branch rather than a
298
- * wasted load. Inlining `serve` into the uncapped arm would buy it back for a second copy
299
- * of the reader-visible transition, and this file has already paid for one of those: the
300
- * trade is stated rather than taken, 1.3 ns being nowhere near perception.
301
- */
302
- type Cap = {
303
- /**
304
- * True for a throttle, which lets the leading change through; false for a debounce.
305
- *
306
- * 5.12 against 5.13, and the only difference between the two mechanisms: a throttle
307
- * lets the leading change through and holds what follows, a debounce holds everything
308
- * until the changes stop.
309
- */
310
- leading: boolean
311
- ms: number
312
- timer: ReturnType<typeof setTimeout> | null
313
- /**
314
- * The production the window is holding back, while `holding` is set.
315
- *
316
- * The production the window is holding back. `holding` is a field rather than a test
317
- * against `held`, because `undefined` is a value an app can write and so cannot carry
318
- * the absence.
319
- */
320
- held: unknown
321
- holding: boolean
322
- /**
323
- * The last production minted, which the identity gate compares against.
324
- *
325
- * WHAT THE IDENTITY GATE COMPARES AGAINST. On every uncapped value that is `cell.value`
326
- * and the two are one thing; a window moves the last production MINTED apart from the
327
- * last one RELEASED, and comparing against the released one would collapse a production
328
- * 5.9 forbids dropping — A, B, A inside one window is three productions, and only the
329
- * third's own predecessor makes it a repeat.
330
- */
331
- minted: unknown
332
- /**
333
- * Whether the window is holding back a body run.
334
- *
335
- * A BODY RUN THE WINDOW IS HOLDING BACK (5.11), against `holding`'s production. The two
336
- * are separate flags because they can stand together: a stream has a body AND tells its
337
- * chunks through the window (5.17), so one close can owe a run and a telling at once.
338
- */
339
- owed: boolean
340
- /**
341
- * Whether the window is holding back a refresh, started when it closes.
342
- *
343
- * 5.24 — A RELOAD THE WINDOW IS HOLDING BACK: a refresh made inside it, started when it closes.
344
- * Started there rather than owed like a run, because 7.11 reloads whether or not anything reads
345
- * and an owed run waits for a read to pull it.
346
- */
347
- reloading: boolean
348
- }
349
-
350
- /**
351
- * A value's store and the state of its writes, allocated only where a `store` was declared.
352
- *
353
- * A VALUE'S STORE AND WHAT ITS WRITES ARE DOING, allocated only where a `store` was declared.
354
- *
355
- * 8.10: ONE WRITE IN FLIGHT AND ONE PENDING. A production arriving while a write is out replaces
356
- * the pending value rather than queueing behind it: a slow store handed every intermediate is doing
357
- * work nobody can observe, and a queue is how it grows without bound behind a fast writer.
358
- */
359
- type Persisted = {
360
- store: Store<unknown>
361
- /** The value's own `ttl`, taken once, and infinity where it declares none (8.13). */
362
- ttl: number
363
- /**
364
- * Set while a restore mints its production, so what was just read is not written back (8.8).
365
- */
366
- restoring: boolean
367
- writing: boolean
368
- pending: boolean
369
- /**
370
- * The newest value handed to the store and not yet confirmed.
371
- *
372
- * THE NEWEST VALUE THE APP HAS HANDED THE STORE, standing until the store confirms it. It is
373
- * what `pending` sends next, and what 8.18 serves a re-read in place of calling `get`.
374
- */
375
- unconfirmed: unknown
376
- /** What stops the store's `watch`, where it has one (8.21). */
377
- unwatch: (() => void) | null
378
- }
379
-
380
- /**
381
- * A streaming producer's own state; `null` on every value whose body is not an async generator.
382
- *
383
- * A STREAMING PRODUCER'S OWN STATE (9.1, 9.2, 9.6), and `null` on every value whose body is
384
- * not an async generator — the shape `cap` and `adoption` already use.
385
- *
386
- * THE ACCUMULATION IS PUSHED INTO AND MATERIALIZED ON THE READ. A chunk is one push and one
387
- * cascade; the copy a reader is handed is taken by the read that follows, so a hundred
388
- * chunks between two reads are one copy rather than a hundred (9.2). The copy is FRESH per
389
- * chunk count and has to be: a reader holding an earlier snapshot still holds what it read,
390
- * and a value derived from this one compares by reference — the live buffer handed out would
391
- * be collapsed at every derived identity gate after the first chunk.
392
- *
393
- * WHAT THAT COSTS WHERE A READ FOLLOWS EVERY CHUNK is a copy of the accumulation per read,
394
- * and a reader woken per chunk made that a copy per chunk: twenty thousand chunks landing in
395
- * one task took 61 ms against 1.9 ms for the hand-written arm. 9.9 is what bounds it — the
396
- * wake is held to one per task, which is the unit a browser paints between, so the reads it
397
- * drops were never visible. A reader that reads per chunk on its own, unwoken, is still a
398
- * copy per read.
399
- */
400
- type Stream = {
401
- /**
402
- * The accumulation of the run being served — and the same array as `ring`, so a cursor
403
- * walks the chunks this holds rather than a second copy of them.
404
- */
405
- chunks: unknown[]
406
- /** The accumulation's version: moves on every release, patch and new run. */
407
- version: number
408
- /**
409
- * Which accumulation `value` stands for, as a `version` rather than a chunk count.
410
- *
411
- * A version rather than a chunk count because a patch changes the accumulation without
412
- * changing its length (9.13), and a write stands at the version it was made at until the
413
- * accumulation moves past it (9.11). -1 where nothing has been materialized.
414
- */
415
- materializedAt: number
416
- /**
417
- * Whether `value` is a write rather than a materialization.
418
- *
419
- * WHETHER `value` IS A WRITE rather than a materialization, while `materializedAt` stands. A value
420
- * forwarding this stream serves the write the way it would have served a production (11.59).
421
- */
422
- written: boolean
423
- /**
424
- * How many chunks a reader has been told of.
425
- *
426
- * HOW MANY CHUNKS A READER HAS BEEN TOLD OF. Every chunk as it lands, without a cap; with one,
427
- * only what the window has released (5.18) — the rest are in `chunks` for a cursor (5.10) and
428
- * out of what a read materializes until the release.
429
- */
430
- visible: number
431
- /** The run in flight, told to return when a newer run supersedes it. */
432
- iterator: AsyncIterator<unknown> | null
433
- /**
434
- * Which run is current; only a new run moves it.
435
- *
436
- * WHICH RUN IS CURRENT, and only a new run moves it. Apart from `generation`, which every
437
- * write moves so that a load it overtook lands nowhere — a write over a stream stands beside
438
- * the stream (9.11) rather than superseding it, and sharing the counter stopped the stream.
439
- */
440
- run: number
441
- /**
442
- * Whether a wake is already held for this task, so the next chunk only pushes.
443
- *
444
- * 9.9: chunks have landed that the readers have not been told about, and the value is
445
- * already in `WAKING` — so the next chunk in this task pushes and does nothing else.
446
- */
447
- waking: boolean
448
- /**
449
- * A probe moved under the held wake — the first chunk making the value ready, or one
450
- * clearing a standing error — and the wake owes it to the guards as well.
451
- */
452
- probesOwed: boolean
453
- /**
454
- * The stream this one forwards, and `null` on a value that produces its own.
455
- *
456
- * THE STREAM THIS ONE FORWARDS (11.15), and `null` on a value that produces its own. A
457
- * value adopting a stream IS that stream to a cursor, a guard and an await, so it holds
458
- * the adopted value's buffer and ring rather than copies — and this is what stops a
459
- * trigger on it starting its body as though the body were the generator.
460
- */
461
- source: Cell | null
462
- /**
463
- * How far the forwarding value's ordinals run ahead of the adopted value's, fixed when
464
- * the forwarding begins so the adopter's cursor positions go on from its own.
465
- */
466
- ordinalOffset: number
467
- /**
468
- * Whether what is served is a run that closed.
469
- *
470
- * WHETHER WHAT IS SERVED IS A RUN THAT CLOSED, which is the only accumulation a deadline
471
- * reaches (6.10). A run in flight has minted nothing, so `expiry.at` says nothing about it —
472
- * without this the standing arm reads `at` as 0 and drops the value on its first read.
473
- */
474
- closed: boolean
475
- }
476
-
477
- function newStream(source: Cell | null): Stream {
478
- return {
479
- chunks: EMPTY_RING,
480
- version: 0,
481
- visible: 0,
482
- materializedAt: -1,
483
- written: false,
484
- iterator: null,
485
- run: 0,
486
- waking: false,
487
- probesOwed: false,
488
- source,
489
- ordinalOffset: 0,
490
- closed: false,
491
- }
492
- }
493
-
494
292
  /**
495
293
  * The stream `cell` produces itself, or `null`: it has none, or the one it has is forwarded (11.15).
496
294
  *
497
295
  * THE ONE DISCRIMINATOR between following and forwarding. An own stream's `adoption` is a write it
498
296
  * follows (9.11), and a forwarding value's is the stream it forwards.
499
297
  */
500
- function ownStream(cell: Cell): Stream | null {
298
+ export function ownStream(cell: Cell): Stream | null {
501
299
  const stream = cell.stream
502
300
  return stream !== null && stream.source === null ? stream : null
503
301
  }
@@ -556,480 +354,6 @@ export function isStreamBody(body: (args: never) => unknown): boolean {
556
354
  return Object.getPrototypeOf(body) === ASYNC_GENERATOR_FUNCTION
557
355
  }
558
356
 
559
- /**
560
- * A value's internal state record, apart from the callable an app holds.
561
- *
562
- * THE INTERNAL FACE, AND A SECOND OBJECT. With the fields on the callable itself, every
563
- * one was a property added to a FUNCTION at construction, and that was most of what a
564
- * value cost to make: moving them here took `construct a value` from 123 ns to 87 under
565
- * JSC and from 101 to 83 under V8, and a derived value's construction, a chain and a
566
- * layered DAG 7-13% with it. Nothing measured moved the other way. The callable captures
567
- * its record, so a read is one context load — the hand-written arm's one captured
568
- * variable — and a member reaches the record through `CELL`, one load ahead of what it
569
- * did before.
570
- *
571
- * THE FIELD COUNT SITS ON A VM BOUNDARY AND IT IS NOT A LEVER. Both engines give an
572
- * object a fixed inline slot budget and spill the rest to an out-of-line store, and this
573
- * record is over it — so the count moves numbers that have nothing to do with the work.
574
- * Two independent measurements say the same thing from opposite ends. Taking `Cell` to
575
- * 38 is worth ~11% of `construct a value` and ~6-9% of the derived case, and it does not
576
- * matter HOW the four go: a consolidation into one record and four fields simply deleted
577
- * buy the same number, so the consolidation is not what pays. Going the other way,
578
- * 42 -> 46, is FREE — above the budget the out-of-line store already exists. And dropping
579
- * ONE field moved chain 20 and both layered DAGs +4.2% under V8 while moving nothing
580
- * under JSC; adding a DEAD boolean back put all three within 0.6%, which is the proof it
581
- * was layout and not work — that same dead boolean then cost the probe walk 6-7%.
582
- *
583
- * Above the budget is not free under JSC, though: three fields more (the dead-reader
584
- * counts and `probeCursor`) moved `construct a value` and the derived case +6-8% there,
585
- * and three UNUSED fields on the old record moved them the same — layout, not work.
586
- *
587
- * So the boundary is worth KNOWING and not worth engineering around. A field costs a few
588
- * ns of construction; getting under costs a structural change that the next field added here
589
- * silently undoes, and it re-rolls in a different direction for every row. If
590
- * construction ever needs that 11%, shed fields — do not build machinery to shed them.
591
- * And when a V8-only move of this size shows up on a graph row, the first thing to check
592
- * is whether the field count changed.
593
- */
594
- class Cell {
595
- /**
596
- * Who reads this value, on the value edge.
597
- *
598
- * ARRAYS, not sets. The mark walk walks this per write and a set's iterator
599
- * allocates. A disposed reader is left in place and counted rather than found — see
600
- * `dropFrom` in `tracking.ts` — so a walk over this skips `!alive`.
601
- */
602
- declare readers: Subscriber[]
603
- declare deadReaders: number
604
- /**
605
- * Who asked about this value's PROBES — a different edge from `readers`, and see
606
- * `markProbes` for what that buys.
607
- */
608
- declare probeReaders: Subscriber[]
609
- declare deadProbeReaders: number
610
- declare sources: Cell[]
611
- /**
612
- * The values whose PROBES this body asked about — a `Cell` is a `Subscriber`, so it
613
- * carries the reader half of the probe edge as well as the source half.
614
- */
615
- declare probeSources: Cell[]
616
- declare probeCursor: number
617
- declare cursor: number
618
- /** See `Subscriber.seen`. */
619
- declare seen: Set<Cell> | null
620
- declare seenThrough: number
621
- declare scanningFrom: number
622
- declare label: string
623
- declare body: ((args: unknown) => unknown) | null
624
- declare args: unknown
625
- declare value: unknown
626
- declare landed: boolean
627
- /**
628
- * Whether a read may answer with `value`.
629
- *
630
- * WHETHER A READ MAY ANSWER WITH `value`. Implies `landed`, and is false over a landed value
631
- * a trigger, an abort or an adoption has stopped serving — which is the state `landed`
632
- * alone cannot say.
633
- */
634
- declare servable: boolean
635
- /**
636
- * Whether a read can return `value` straight, without going a frame in.
637
- *
638
- * `state === CLEAN && servable` — the whole of "this read can return the field",
639
- * maintained rather than recomputed. A read is the hottest path in the design and it
640
- * was three loads and three branches to decide.
641
- *
642
- * THE INVARIANT IS ONE-DIRECTIONAL and that is what makes it safe to maintain by
643
- * hand: `true` is written only where all three are known to hold, and every
644
- * transition that can break one of them writes `false`. So a site that forgets to
645
- * set it true costs a frame on the reads that follow and cannot serve a wrong value,
646
- * which is the opposite of how a maintained flag usually fails.
647
- */
648
- declare direct: boolean
649
- declare loading: boolean
650
- declare failure: unknown
651
- /**
652
- * The compiled `identity` comparator.
653
- *
654
- * `null` IS the default — see `comparatorFor`.
655
- */
656
- declare identityFn: ((next: unknown, previous: unknown) => boolean) | null
657
- /**
658
- * The comparator this value DECLARED, which `identityFn` returns to when an adoption ends.
659
- *
660
- * 11.17 inherits the adopted value's `identity` only where the outer declared none, and only
661
- * for as long as it adopts: kept on `identityFn` alone, the inherited comparator outlived the
662
- * adoption and gated the outer's own productions — `flag() ? inner : count()` with `inner`
663
- * keyed on `.id` read every number as the same `undefined` and never woke again.
664
- */
665
- declare declaredIdentityFn:
666
- ((next: unknown, previous: unknown) => boolean) | null
667
- declare transform: ((value: unknown) => unknown) | null
668
- /**
669
- * `null` on every value that declares no `schema`, which keeps the gate off the write
670
- * path of everything that did not ask for one.
671
- */
672
- declare schema: Schema<unknown> | null
673
- /**
674
- * A streaming producer's chunk buffer, for a cursor to walk (2.6); `EMPTY_RING` on every
675
- * other value.
676
- */
677
- declare ring: unknown[]
678
- /**
679
- * The ordinal before `ring[0]`, so `ring[index]` carries ordinal `ringBase + index + 1` and a
680
- * cursor finds its place from the ordinal it holds.
681
- */
682
- declare ringBase: number
683
- /**
684
- * `null` on every value that declares no `ttl`, and on every value 6.2 makes it inert
685
- * for. Its presence is also what holds `direct` false — see `serve`.
686
- */
687
- declare expiry: Expiry | null
688
- declare ordinal: number
689
- declare generation: number
690
- declare alive: boolean
691
- declare isEffect: boolean
692
- declare isMirror: boolean
693
- declare adopter: Tracked | null
694
- /**
695
- * The mark: `CLEAN`, `CHECK` or `DIRTY`.
696
- *
697
- * `CLEAN`, `CHECK` or `DIRTY` — see `tracking.ts`. Stamped on every transitive
698
- * reader BEFORE anything runs, so a body that reaches a source which has not caught
699
- * up yet pulls it forward; `running` is what stops a body already on the stack being
700
- * re-entered.
701
- *
702
- * ONE RUN PER NODE PER WRITE is the contract, and the state carries it without a
703
- * cascade counter: a node that has run is `CLEAN`, and only a source PRODUCING can
704
- * mark it again — which a source it already read cannot do, because reading it is
705
- * what resolved it.
706
- */
707
- declare state: number
708
- declare running: boolean
709
- /**
710
- * Whether the last run aborted on a value that had not landed.
711
- *
712
- * 2.13: A RUN THAT ABORTED ON A VALUE THAT HAD NOT LANDED, and is owed the rest of itself
713
- * when that value arrives. Push-pull leaves a marked body for the read that wants it, and
714
- * that is right for a body which RAN — this one did not, so nothing downstream can pull it:
715
- * a reader guarding on `ready()` asks the probe edge and never the value, and the guard would
716
- * answer false for as long as nobody read through it.
717
- */
718
- declare aborted: boolean
719
- /**
720
- * The value this one adopted, or `null`.
721
- *
722
- * WHAT THIS VALUE'S BODY HANDED BACK, where it handed back another `Reactive`
723
- * (11.12). `null` on every value that is not adopting, which is nearly all of them —
724
- * one field rather than two, and the record is allocated only where there is one.
725
- */
726
- declare adoption: Adoption | null
727
- /**
728
- * `null` on every value declaring neither `throttle` nor `debounce`, which is nearly
729
- * all of them.
730
- */
731
- declare cap: Cap | null
732
- /**
733
- * `null` on every value declaring no `tags`, which keeps `markProbes` from looking up a
734
- * selection signal for any of them.
735
- */
736
- declare tags: string[] | null
737
- /** Whether `declare` built this value for a mutation, which a sweep invalidates (13.16). */
738
- declare mutation: boolean
739
- /**
740
- * Whether what is held was written here since the producer last produced (3.10).
741
- *
742
- * Only ever true on a value with a body: a value with no producer has nothing to be out of
743
- * step with (3.12). Moved by `writtenHere` and `producedAgain` alone, each owning its probe move.
744
- */
745
- declare local: boolean
746
- /** `null` on every value declaring no `store`, which is what keeps `serve` from persisting. */
747
- declare store: Persisted | null
748
- /**
749
- * The declared `by`.
750
- *
751
- * 5.22 — held as declared rather than as a function, so the property name is still there to send.
752
- */
753
- declare by: string | ((element: unknown) => unknown) | null
754
- /** The probe pass this cell was last visited in. See `walkBusy` and `walkReady`. */
755
- declare probePass: number
756
- /**
757
- * `OWES_NOTHING`, `OWES_ABOVE` or `OWES_RELOAD` — what an `invalidate` left for the next read
758
- * to do. See `invalidateOne`.
759
- */
760
- declare owes: number
761
- /** The value this record is the state of — what `NotLanded` names as its source. */
762
- declare callable: Reactive<unknown> | null
763
- /** `null` on every value whose body is not an async generator, which is nearly all. */
764
- declare stream: Stream | null
765
- /**
766
- * Whether a read may ever take the field straight, fixed at construction.
767
- *
768
- * WHETHER A READ MAY EVER TAKE THE FIELD STRAIGHT, fixed at construction: no expiry to
769
- * check and no accumulation to materialize. `setDirect` reads this one field where it
770
- * would otherwise read one per mechanism that needs the read to go a frame in.
771
- */
772
- declare plain: boolean
773
- /**
774
- * Whether a settled write goes straight to `produce`, past no gate.
775
- *
776
- * NOTHING STANDS BETWEEN A SETTLED WRITE AND `produce`: no `schema`, no `transform`, and no
777
- * stream whose writes stand apart from its chunks (9.11, 9.12). One field where the write and
778
- * the recompute each tested two, maintained where a forwarded stream comes and goes.
779
- */
780
- declare bareWrite: boolean
781
- /**
782
- * Whether a gated write can take `SIMPLE_PROTOTYPE`'s short path.
783
- *
784
- * EVERYTHING A GATED WRITE WOULD OTHERWISE ASK, IN ONE FIELD: no cap holding the
785
- * production back, no expiry, no store to persist through, no
786
- * declared `identity`, and `bareWrite`'s own three. A value carrying none of them has a
787
- * `produce` -> `serve` -> `cascade` that reduces to three stores and a mark — which is
788
- * what `SIMPLE_PROTOTYPE.set` spells out rather than calls.
789
- *
790
- * IT SELECTS A PROTOTYPE AND IS NOT READ ON THE WRITE PATH. See `SIMPLE_PROTOTYPE`.
791
- *
792
- * MAINTAINED, NOT FIXED: three of the fields under it move after construction —
793
- * `bareWrite` and `plain` where a forwarded stream comes and goes, `identityFn` where an
794
- * adoption takes the inner value's. `simpleShape` is called at each of those.
795
- */
796
- declare simple: boolean
797
- /**
798
- * The scope this value was built in, and so the one its body runs under.
799
- *
800
- * 11.32 — THE SCOPE THIS VALUE WAS BUILT IN, and so the one its body runs under. `undefined` in a
801
- * browser, and on a server for a value built outside any request.
802
- */
803
- declare scope: Scope | undefined
804
- /**
805
- * Whether this value is one for the whole process, in every scope.
806
- *
807
- * 11.34, 13.13 — one value for the process, and so inside every scope a selection is made in. An
808
- * entry of a `global` keyed value is one too, whichever request first reached it.
809
- */
810
- declare global: boolean
811
- /**
812
- * The one weak handle every selection index holds this value by, or `null` where none does.
813
- *
814
- * 13.1 AND 13.6: a value filed for the bare sweep or carrying `tags` is findable by one, and
815
- * every index holds the same handle, so an eviction drops it from all of them at once.
816
- */
817
- declare ref: WeakRef<Cell> | null
818
- /**
819
- * Whether this value is filed for the bare selection — once, where it first becomes a load.
820
- *
821
- * See `fileProducer`. Not cleared by an eviction: dropping `ref` is what takes an evicted entry
822
- * out, and this staying set is what keeps its next load from filing it again.
823
- */
824
- declare filed: boolean
825
- /**
826
- * Whether what this value was built in has stopped — the setup or the request that owned it.
827
- *
828
- * 12.14. Set by `orphan`; the value lets go of its sources once nothing
829
- * reads it (`releaseOrphan`), which may be at once or when the last reader outside its owner leaves.
830
- */
831
- declare orphaned: boolean
832
-
833
- constructor(
834
- label: string,
835
- body: ((args: unknown) => unknown) | null,
836
- args: unknown,
837
- options: ReactiveOptions<unknown, unknown, never> | undefined,
838
- streaming: boolean,
839
- ) {
840
- // Every field, in one order, `undefined` included.
841
- this.readers = []
842
- this.deadReaders = 0
843
- this.probeReaders = []
844
- this.deadProbeReaders = 0
845
- this.sources = []
846
- this.probeSources = []
847
- this.probeCursor = 0
848
- this.cursor = 0
849
- this.seen = null
850
- this.seenThrough = 0
851
- this.scanningFrom = -1
852
- this.label = label
853
- this.body = body
854
- this.args = args
855
- this.value = undefined
856
- this.landed = false
857
- this.servable = false
858
- this.direct = false
859
- this.loading = false
860
- this.failure = undefined
861
- this.identityFn = comparatorFor(
862
- options?.identity as Identity<unknown> | undefined,
863
- )
864
- this.declaredIdentityFn = this.identityFn
865
- this.transform = (options?.transform ?? null) as
866
- ((value: unknown) => unknown) | null
867
- this.schema = (options?.schema ?? null) as Schema<unknown> | null
868
- this.ring = EMPTY_RING
869
- this.ringBase = 0
870
- // 6.2 DECIDED ONCE, here rather than per production: a body is what makes a value a
871
- // producer, and a plain state is the one this must not reach. See `expiryFor`.
872
- this.expiry = expiryFor(
873
- options?.ttl,
874
- // A store is a producer too (8.2): there is somewhere to get the value back from, so
875
- // `ttl` on a value holding one drops rather than being inert.
876
- body !== null || options?.store !== undefined,
877
- )
878
- this.ordinal = 0
879
- this.generation = 0
880
- this.alive = true
881
- this.state = CLEAN
882
- this.running = false
883
- this.aborted = false
884
- this.adoption = null
885
- this.cap = capFor(label, options?.throttle, options?.debounce)
886
- const tags = options?.tags
887
- this.tags =
888
- tags === undefined
889
- ? null
890
- : typeof tags === 'function'
891
- ? tags(args as never)
892
- : tags
893
- this.mutation =
894
- (options as { [MUTATION]?: true } | undefined)?.[MUTATION] === true
895
- this.local = false
896
- const store = options?.store
897
- this.store =
898
- store === undefined
899
- ? null
900
- : {
901
- store: (typeof store === 'function'
902
- ? store(args as never)
903
- : store) as Store<unknown>,
904
- ttl: options?.ttl ?? Number.POSITIVE_INFINITY,
905
- restoring: false,
906
- writing: false,
907
- pending: false,
908
- unconfirmed: undefined,
909
- unwatch: null,
910
- }
911
- this.by = (options?.by ?? null) as
912
- string | ((element: unknown) => unknown) | null
913
- this.probePass = 0
914
- this.owes = OWES_NOTHING
915
- this.isEffect = false
916
- this.isMirror = false
917
- this.adopter = null
918
- this.callable = null
919
- this.stream = streaming ? newStream(null) : null
920
- this.plain = this.expiry === null && this.stream === null
921
- this.bareWrite =
922
- this.schema === null && this.transform === null && !streaming
923
- this.simple = false
924
- this.scope = currentScope()
925
- this.global = options?.global === true
926
- this.ref = null
927
- this.filed = false
928
- this.orphaned = false
929
- simpleShape(this)
930
- }
931
-
932
- notify(): void {
933
- run(this)
934
- }
935
- }
936
-
937
- /** What a member's `this` is, and the one way from the value an app holds to its record. */
938
- type Callable = { [CELL]: Cell }
939
-
940
- /**
941
- * Throws where a value declares both `throttle` and `debounce`.
942
- *
943
- * 5.14 is a BUILD error and there is no build yet, so it lands at construction — the
944
- * earliest moment that exists, and the one the app still has a stack for. Naming the value
945
- * is the clause's own requirement; without it a page declaring both on one of forty values
946
- * says only that something did. One statement for both producers of a window: a value's
947
- * (5.8) and a keyed value's, which caps starts rather than wakes (5.19).
948
- */
949
- export function refuseBothCaps(
950
- label: string,
951
- throttle: number | undefined,
952
- debounce: number | undefined,
953
- ): void {
954
- if (throttle !== undefined && debounce !== undefined)
955
- throw new Error(
956
- `${label} declares both throttle and debounce. A value is capped one way or the other.`,
957
- )
958
- }
959
-
960
- function capFor(
961
- label: string,
962
- throttle: number | undefined,
963
- debounce: number | undefined,
964
- ): Cap | null {
965
- refuseBothCaps(label, throttle, debounce)
966
- const ms = throttle ?? debounce
967
- if (ms === undefined) return null
968
- return {
969
- leading: throttle !== undefined,
970
- ms,
971
- timer: null,
972
- held: undefined,
973
- holding: false,
974
- minted: undefined,
975
- owed: false,
976
- reloading: false,
977
- }
978
- }
979
-
980
- /**
981
- * Compiles `identity` into a comparator, or `null` for the default `Object.is`.
982
- *
983
- * THE DEFAULT IS THE REFERENCE, and `structural` is exported for an app to pass.
984
- *
985
- * THE CASE FOR A STRUCTURAL DEFAULT IS REAL: a reload that fetched an equal
986
- * payload builds a FRESH object, so a reference compare never fires and every reader
987
- * wakes on a value that did not change. What decides it against that is the cost on
988
- * the shape an app actually holds — a compare walks the whole value on EVERY write,
989
- * where the wake it avoids is paid only when the payload really is equal. A grid of
990
- * rows re-assembled per recompute pays the deep walk every time and collapses never.
991
- *
992
- * So the framework takes the cheap, predictable default — `===` is what JavaScript
993
- * means by "the same value" — and the app names `identity: structural` on the values
994
- * where re-materialization is the common case. 5.5's "not equal wherever it cannot
995
- * decide" is unchanged; it is just no longer the default reading.
996
- *
997
- * `identity` is discriminated by ARITY (5.3), once, at construction — not per compare.
998
- *
999
- * NULL IS THE DEFAULT, not a function that implements it. `produce` compares against
1000
- * `null` and calls `Object.is` directly, which takes an INDIRECT call off the write path:
1001
- * the site is polymorphic across the default, a projection closure and whatever an app
1002
- * passed, so it is not one an engine can speculate through. The saving is the indirection
1003
- * rather than the comparison — `Object.is` is itself the fastest spelling of it.
1004
- */
1005
- function comparatorFor(
1006
- identity: Identity<unknown> | undefined,
1007
- ): ((next: unknown, previous: unknown) => boolean) | null {
1008
- if (identity === undefined) return null
1009
- if (identity.length >= 2)
1010
- return identity as (next: unknown, previous: unknown) => boolean
1011
- const project = identity as (value: unknown) => unknown
1012
- return (next, previous) => project(next) === project(previous)
1013
- }
1014
-
1015
- /**
1016
- * Recomputes `simple` and re-seats the callable on the matching prototype.
1017
- *
1018
- * `simple` IN ONE PLACE. A second copy of this conjunction is the drift that would let one of the
1019
- * sites go on reading `true` after the field under it moved — and what the short write would then
1020
- * skip is a cap, a ring or a declared `identity`, silently. The prototype that goes with it is
1021
- * `seat`'s, taken where the transition that moved a field under it ends.
1022
- */
1023
- function simpleShape(cell: Cell): void {
1024
- cell.simple =
1025
- cell.bareWrite &&
1026
- // `plain` carries `expiry === null` and `stream === null` already.
1027
- cell.plain &&
1028
- cell.cap === null &&
1029
- cell.store === null &&
1030
- cell.identityFn === null
1031
- }
1032
-
1033
357
  /**
1034
358
  * The prototype a value's state calls for: its own stream's writes (9.11), an adoption's (11.59),
1035
359
  * the short write of a `simple` value, or the members alone.
@@ -1345,7 +669,7 @@ function markProbes(cell: Cell, pass: number): void {
1345
669
  markAsked(cell.probeReaders)
1346
670
  // 13.3: a guard over a tag selection asked the SELECTION, so it hears through the selection's
1347
671
  // signal rather than through this value's own probe readers.
1348
- if (cell.tags !== null) markSignals(cell.tags)
672
+ if (cell.tags !== null) markSignals(cell.tags, markAsked)
1349
673
  // The bare selection's guard hears every filed value's floor move; one load where nothing asks.
1350
674
  if (EVERY_PRODUCER.probeReaders.length !== 0 && cell.filed)
1351
675
  markAsked(EVERY_PRODUCER.probeReaders)
@@ -2462,6 +1786,12 @@ function run(cell: Cell): void {
2462
1786
  absorb(cell, produced, true)
2463
1787
  }
2464
1788
 
1789
+ // A CELL'S WAKE IS ITS RUN — on the prototype, where the class method stood, so `reader.notify()`
1790
+ // reaches it the way it always did; `cellShape.ts` cannot import `run` and stay off the cycle.
1791
+ Cell.prototype.notify = function notify(this: Cell): void {
1792
+ run(this)
1793
+ }
1794
+
2465
1795
  /**
2466
1796
  * Leaves a run that read a value which had not landed owing the rest of itself (2.13).
2467
1797
  *
@@ -3106,13 +2436,6 @@ function readIndirect(cell: Cell): unknown {
3106
2436
  return cell.value
3107
2437
  }
3108
2438
 
3109
- /**
3110
- * Every value that is not streaming shares this as its `ring`. The field stays monomorphically an
3111
- * Array — CLAUDE.md's shape rule — and only a stream's own chunk buffer is ever pushed to. Frozen so
3112
- * that if anything ever does push here, it says so rather than corrupting every other value at once.
3113
- */
3114
- const EMPTY_RING = Object.freeze([]) as unknown as unknown[]
3115
-
3116
2439
  /**
3117
2440
  * The current probe pass, stamped on each cell a probe walk visits.
3118
2441
  *
@@ -3415,11 +2738,6 @@ export function refuseInto(value: Reactive<unknown>, failure: unknown): void {
3415
2738
  refused((value as unknown as Callable)[CELL], failure)
3416
2739
  }
3417
2740
 
3418
- /** Whether `value` holds what was written here, without subscribing — for a caller that is not a reader. */
3419
- export function writtenLocally(value: Reactive<unknown>): boolean {
3420
- return (value as unknown as Callable)[CELL].local
3421
- }
3422
-
3423
2741
  /**
3424
2742
  * A promise of the value once it is servable and not busy, or of its failure.
3425
2743
  *
@@ -3600,20 +2918,6 @@ function wakePatched(cell: Cell, head: unknown): void {
3600
2918
  }
3601
2919
  }
3602
2920
 
3603
- /**
3604
- * What an `invalidate` leaves behind: nothing owed, a look above, or a reload.
3605
- *
3606
- * WHAT AN INVALIDATE LEAVES BEHIND, and it is a debt rather than a mark. The mark walk's states
3607
- * are the wrong tool: a node marked `CHECK` or `DIRTY` without its effects queued is one a later
3608
- * write's walk stops at — `state >= wanted` — and the effects below it are never woken for a
3609
- * change that really happened. So nothing in the graph's state moves; the invalidated value OWES
3610
- * A RELOAD, the values built from it OWE A LOOK ABOVE, and none of them is directly servable, so
3611
- * the read that reaches any of them goes a frame in and settles the debt first (7.12, 7.13).
3612
- */
3613
- const OWES_NOTHING: number = 0
3614
- const OWES_ABOVE: number = 1
3615
- const OWES_RELOAD: number = 2
3616
-
3617
2921
  /**
3618
2922
  * Visits a value and each value down its adoption chain.
3619
2923
  *
@@ -4110,193 +3414,6 @@ function storeWritten(cell: Cell, persisted: Persisted): void {
4110
3414
 
4111
3415
  // ── Selections over `tags`, and the bare sweep ──────────────────────────────────────────
4112
3416
 
4113
- /**
4114
- * Each tag to the values carrying it, held weakly.
4115
- *
4116
- * THE INDEX HOLDS VALUES WEAKLY. A tag is a way to find a value, never a reason to keep one, and a
4117
- * strong index would hold every tagged value a page ever made for the life of the process. A
4118
- * collected value is pruned from its sets by the next sweep that finds it gone.
4119
- */
4120
- const TAGGED = new Map<string, Set<WeakRef<Cell>>>()
4121
-
4122
- /**
4123
- * Every value whose producer is a LOAD, held weakly — what a bare selection sweeps.
4124
- *
4125
- * 13.6: A BARE SWEEP REACHES PRODUCERS, and of those it files the ones that LOAD: a value holding
4126
- * a `store`, filed where it is built, and a body the first time it starts a load — a pending
4127
- * answer or a stream (`beginLoad`). A synchronous body is a derivation: reloading it recomputes
4128
- * what its sources already say, and whatever load it reads is filed on its own. And filing is
4129
- * what every filed value pays — a weak handle measured ~230 ns a value under V8 against ~20 under
4130
- * JSC — so a value with nothing to load never pays it: a derivation per cell per row stays at
4131
- * what it cost before, and a load pays it beside the promise it already allocates.
4132
- *
4133
- * Held weakly for `TAGGED`'s reason. AN ARRAY, COMPACTED, RATHER THAN A `Set`: a `Set` of weak
4134
- * handles measured ~120 ns a filing under JSC against ~10 for a push. What a `Set` bought was an
4135
- * O(1) delete on eviction; here an evicted value drops its `ref` instead, and a handle whose value
4136
- * no longer points back at it is dead, the same as one whose value was collected. Because a bare
4137
- * sweep may never run, the filing that finds the array past `compactProducersAt` compacts it, and
4138
- * the bar doubles past what survives, so the walk is amortized over the filings between two.
4139
- */
4140
- let filedProducers: WeakRef<Cell>[] = []
4141
- let compactProducersAt = 1024
4142
-
4143
- /**
4144
- * The probe signal a guard over a selection subscribes to.
4145
- *
4146
- * 13.3 AND 13.9: ONE SIGNAL PER SELECTION, keyed by its canonical tags. A guard over a selection
4147
- * subscribes to this, never to each entry — the probe edge `trackProbe` makes, from a node that
4148
- * is nothing but that edge.
4149
- */
4150
- const SIGNALS = new Map<string, Tracked>()
4151
- const SIGNALS_BY_TAG = new Map<string, Tracked[]>()
4152
- /**
4153
- * The bare selection's one signal. Not a key in `SIGNALS`: `{ tags: [] }` canonicalizes to the
4154
- * empty set and matches nothing, where the bare selection matches every filed load in reach.
4155
- */
4156
- const EVERY_PRODUCER = newTracked()
4157
-
4158
- function refOf(cell: Cell): WeakRef<Cell> {
4159
- let ref = cell.ref
4160
- if (ref === null) {
4161
- ref = new WeakRef(cell)
4162
- cell.ref = ref
4163
- }
4164
- return ref
4165
- }
4166
-
4167
- function tagCell(cell: Cell): void {
4168
- const ref = refOf(cell)
4169
- for (const tag of cell.tags as string[]) {
4170
- let carrying = TAGGED.get(tag)
4171
- if (carrying === undefined) {
4172
- carrying = new Set()
4173
- TAGGED.set(tag, carrying)
4174
- }
4175
- carrying.add(ref)
4176
- }
4177
- }
4178
-
4179
- function fileProducer(cell: Cell): void {
4180
- cell.filed = true
4181
- filedProducers.push(refOf(cell))
4182
- if (filedProducers.length > compactProducersAt) {
4183
- filedProducers = liveProducers()
4184
- compactProducersAt = Math.max(1024, filedProducers.length * 2)
4185
- }
4186
- }
4187
-
4188
- /** The handles whose value is still standing and still filed — neither collected nor evicted. */
4189
- function liveProducers(): WeakRef<Cell>[] {
4190
- const live: WeakRef<Cell>[] = []
4191
- for (let index = 0; index < filedProducers.length; index += 1) {
4192
- const ref = filedProducers[index] as WeakRef<Cell>
4193
- if (ref.deref()?.ref === ref) live.push(ref)
4194
- }
4195
- return live
4196
- }
4197
-
4198
- /**
4199
- * Removes an evicted value from every selection index.
4200
- *
4201
- * What an eviction calls: an entry out of its `Keyed` is out of every selection with it, rather
4202
- * than reachable by a sweep until a collection happens to run.
4203
- */
4204
- export function leaveSelections(value: unknown): void {
4205
- const cell = (value as Callable)[CELL]
4206
- const ref = cell.ref
4207
- if (ref === null) return
4208
- // What takes it out of `filedProducers`: a handle its value no longer points back at is dead.
4209
- cell.ref = null
4210
- if (cell.tags === null) return
4211
- for (const tag of cell.tags) {
4212
- const carrying = TAGGED.get(tag)
4213
- if (carrying === undefined) continue
4214
- carrying.delete(ref)
4215
- if (carrying.size === 0) TAGGED.delete(tag)
4216
- }
4217
- }
4218
-
4219
- /**
4220
- * Takes every value filed so far out of the bare selection, each filed again by its next load.
4221
- *
4222
- * A TEST'S SEAM, with no caller in the framework — `bareSelection.test.ts` calls it before its
4223
- * first case: a page's process ends with the page, and a test process runs every file before this
4224
- * one in it. What those files left held — a module's `global`
4225
- * value, a follow the page keeps for its life — is in reach of a bare sweep (13.13), and a bare
4226
- * `refresh()` reloads it and reads `busy()` true while it asks.
4227
- */
4228
- export function unfileProducers(): void {
4229
- for (let index = 0; index < filedProducers.length; index += 1) {
4230
- const cell = (filedProducers[index] as WeakRef<Cell>).deref()
4231
- if (cell !== undefined) cell.filed = false
4232
- }
4233
- filedProducers = []
4234
- }
4235
-
4236
- /**
4237
- * The values a selection reaches in the current scope, `global` values included: those carrying
4238
- * any of `tags`, or every filed load where `tags` is `null` — the bare selection.
4239
- *
4240
- * 13.8 — A SELECTION IS SCOPE-BOUNDED, and a tag with it, so a selection inside one request never
4241
- * reaches the values another request filed. 13.13 — a `global` value is in every scope, so every
4242
- * selection reaches it, and 13.10 is the bare case of that. In a browser every cell's scope is
4243
- * `undefined`, and so is this.
4244
- */
4245
- function inReach(tags: string[] | null): Cell[] {
4246
- const scope = currentScope()
4247
- if (tags === null) {
4248
- filedProducers = liveProducers()
4249
- const found: Cell[] = []
4250
- for (let index = 0; index < filedProducers.length; index += 1) {
4251
- const cell = (
4252
- filedProducers[index] as WeakRef<Cell>
4253
- ).deref() as Cell
4254
- if (cell.scope === scope || cell.global) found.push(cell)
4255
- }
4256
- return found
4257
- }
4258
- const found = new Set<Cell>()
4259
- for (const tag of tags) {
4260
- const refs = TAGGED.get(tag)
4261
- if (refs === undefined) continue
4262
- for (const ref of refs) {
4263
- const cell = ref.deref()
4264
- if (cell === undefined) refs.delete(ref)
4265
- else if (cell.scope === scope || cell.global) found.add(cell)
4266
- }
4267
- }
4268
- return [...found]
4269
- }
4270
-
4271
- function trackSignal(tags: string[] | null): void {
4272
- const reader = TRACKING.reader
4273
- if (reader === null) return
4274
- if (tags === null) {
4275
- trackProbe(EVERY_PRODUCER, reader)
4276
- return
4277
- }
4278
- const key = JSON.stringify([...new Set(tags)].sort())
4279
- let signal = SIGNALS.get(key)
4280
- if (signal === undefined) {
4281
- signal = newTracked()
4282
- SIGNALS.set(key, signal)
4283
- for (const tag of tags) {
4284
- const signals = SIGNALS_BY_TAG.get(tag)
4285
- if (signals === undefined) SIGNALS_BY_TAG.set(tag, [signal])
4286
- else signals.push(signal)
4287
- }
4288
- }
4289
- trackProbe(signal, reader)
4290
- }
4291
-
4292
- function markSignals(tags: string[]): void {
4293
- for (const tag of tags) {
4294
- const signals = SIGNALS_BY_TAG.get(tag)
4295
- if (signals === undefined) continue
4296
- for (const signal of signals) markAsked(signal.probeReaders)
4297
- }
4298
- }
4299
-
4300
3417
  /**
4301
3418
  * Whether any value in the selection is busy; a reader subscribes to the selection.
4302
3419
  *
@@ -4484,60 +3601,6 @@ const MEMBERS = {
4484
3601
  },
4485
3602
  }
4486
3603
 
4487
- /**
4488
- * The cell `value` serves from, through every adoption: its identity and its ordinal, and nothing
4489
- * else of it the server can reach.
4490
- *
4491
- * 11.12: an adopting value serves the adopted value's production, and an adoption of an adoption
4492
- * goes on down — so a follow's version (18.7) and its feed name the cell that actually produced.
4493
- */
4494
- export function servedCellOf(value: unknown): { readonly ordinal: number } {
4495
- return adoptedCellOf(value)
4496
- }
4497
-
4498
- /**
4499
- * Holds a patch log on the cell `value` serves from, with `invalidated` called on its every
4500
- * invalidate; returns what releases both. 18.11, 7.10.
4501
- */
4502
- export function followServed(
4503
- value: unknown,
4504
- invalidated: () => void,
4505
- ): () => void {
4506
- return holdLog(adoptedCellOf(value), invalidated)
4507
- }
4508
-
4509
- /**
4510
- * When the production `value` serves stops being servable, as a wall-clock time.
4511
- *
4512
- * 21.8 — WHEN THE PRODUCTION A VALUE IS SERVING STOPS BEING SERVABLE, as a wall-clock time: its
4513
- * own `ttl` from when it was minted (6.5), or its entry's from when the entry last produced
4514
- * (11.45), through whatever it adopts. Infinity where neither bounds it.
4515
- */
4516
- export function deadlineOf(value: unknown): number {
4517
- const cell = adoptedCellOf(value)
4518
- if (cell.expiry !== null) return cell.expiry.at + cell.expiry.ms
4519
- const entry = ENTRY_LIVES.get(cell)
4520
- return entry === undefined ? Number.POSITIVE_INFINITY : entry.at + entry.ms
4521
- }
4522
-
4523
- /**
4524
- * The generation of the load `value` has in flight, or `undefined`.
4525
- *
4526
- * 16.48 — WHICH LOAD A VALUE HAS IN FLIGHT, as the generation that started it, or `undefined` where
4527
- * none is. Read off the cell rather than through `busy`, which is a probe and would subscribe the
4528
- * caller that asked (3.3).
4529
- *
4530
- * A WINDOW HOLDING A PRODUCTION IS BUSY AND IS NO LOAD (5.15): nothing is in flight for a call to end
4531
- * or time, and the window's close is its own bound. Told apart by the hold, which only a value with
4532
- * neither body nor stream makes — so a write's load taken in under a hold is not one a call times.
4533
- */
4534
- export function loadOf(value: unknown): number | undefined {
4535
- const cell = (value as Callable)[CELL]
4536
- if (!cell.loading) return undefined
4537
- if (cell.cap?.holding && cell.stream === null) return undefined
4538
- return cell.generation
4539
- }
4540
-
4541
3604
  // The cells a mutation's call has been answered from, so the next call knows the answer is spent.
4542
3605
  const ANSWERED = new WeakSet<object>()
4543
3606
 
@@ -4568,16 +3631,6 @@ export function dropAnswered(value: unknown): void {
4568
3631
  dropStanding(cell, expiry)
4569
3632
  }
4570
3633
 
4571
- /**
4572
- * The generation `value`'s past stands at, or `undefined` while a load is in flight.
4573
- *
4574
- * What 21.15's `Cached` compares across a call, read through adoption as `servedCellOf` is.
4575
- */
4576
- export function heldGenerationOf(value: unknown): number | undefined {
4577
- const cell = adoptedCellOf(value)
4578
- return cell.loading ? undefined : cell.generation
4579
- }
4580
-
4581
3634
  /**
4582
3635
  * Whether `value` stands on a failure the next reach runs again rather than serves.
4583
3636
  *
@@ -4617,26 +3670,6 @@ export function streamingOrSettled(value: unknown): Promise<unknown> {
4617
3670
  return settled((value as Callable)[CELL], true)
4618
3671
  }
4619
3672
 
4620
- /**
4621
- * Whether `value` is a streaming producer's `Reactive`.
4622
- *
4623
- * A streaming producer's own `Reactive` — a body declared as an async generator, or one whose run
4624
- * handed one back (9.6).
4625
- */
4626
- export function isStreaming(value: unknown): boolean {
4627
- if (!isReactive(value)) return false
4628
- const stream = (value as Partial<Callable>)[CELL]?.stream
4629
- return stream !== null && stream !== undefined
4630
- }
4631
-
4632
- function adoptedCellOf(value: unknown): Cell {
4633
- let cell = (value as Callable)[CELL]
4634
- // A stream's own `adoption` is a write it follows (9.11), and its past is its own.
4635
- while (cell.adoption !== null && ownStream(cell) === null)
4636
- cell = cell.adoption.source
4637
- return cell
4638
- }
4639
-
4640
3673
  /**
4641
3674
  * The keys of every `Reactive` member.
4642
3675
  *