@solidjs/signals 2.0.0-rc.18 → 2.0.0-rc.19

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 (65) hide show
  1. package/dist/dev-shared.js +168 -88
  2. package/dist/dev.attribution.js +16 -13
  3. package/dist/dev.js +272 -129
  4. package/dist/observe/boundaries.js +88 -67
  5. package/dist/observe/core/action.js +8 -0
  6. package/dist/observe/core/async.js +46 -34
  7. package/dist/observe/core/attribution.js +30 -28
  8. package/dist/observe/core/constants.js +21 -1
  9. package/dist/observe/core/core.js +164 -136
  10. package/dist/observe/core/effect.js +6 -6
  11. package/dist/observe/core/graph.js +3 -3
  12. package/dist/observe/core/heap.js +5 -5
  13. package/dist/observe/core/lanes.js +104 -84
  14. package/dist/observe/core/owner.js +10 -9
  15. package/dist/observe/core/scheduler.js +38 -35
  16. package/dist/observe/core/truth.js +6 -6
  17. package/dist/observe/core/verdict.js +13 -13
  18. package/dist/observe/deferred.js +39 -40
  19. package/dist/observe/index.js +2 -2
  20. package/dist/observe/map.js +22 -22
  21. package/dist/observe/reveal.js +5 -5
  22. package/dist/observe/signals.js +57 -15
  23. package/dist/observe/store/affects.js +1 -1
  24. package/dist/observe/store/hooks.js +3 -0
  25. package/dist/observe/store/optimistic.js +11 -11
  26. package/dist/observe/store/projection.js +34 -21
  27. package/dist/observe/store/reconcile.js +2 -2
  28. package/dist/observe/store/store.js +63 -53
  29. package/dist/observe/store/utils.js +7 -2
  30. package/dist/prod/boundaries.js +153 -132
  31. package/dist/prod/core/action.js +8 -0
  32. package/dist/prod/core/async.js +55 -43
  33. package/dist/prod/core/constants.js +14 -1
  34. package/dist/prod/core/core.js +162 -134
  35. package/dist/prod/core/effect.js +9 -9
  36. package/dist/prod/core/graph.js +3 -3
  37. package/dist/prod/core/heap.js +12 -12
  38. package/dist/prod/core/lanes.js +98 -78
  39. package/dist/prod/core/owner.js +15 -14
  40. package/dist/prod/core/scheduler.js +43 -40
  41. package/dist/prod/core/truth.js +6 -6
  42. package/dist/prod/core/verdict.js +17 -17
  43. package/dist/prod/deferred.js +39 -40
  44. package/dist/prod/index.js +2 -2
  45. package/dist/prod/map.js +14 -14
  46. package/dist/prod/reveal.js +8 -8
  47. package/dist/prod/signals.js +46 -4
  48. package/dist/prod/store/affects.js +1 -1
  49. package/dist/prod/store/hooks.js +3 -0
  50. package/dist/prod/store/optimistic.js +16 -16
  51. package/dist/prod/store/projection.js +22 -9
  52. package/dist/prod/store/reconcile.js +2 -2
  53. package/dist/prod/store/store.js +262 -262
  54. package/dist/prod/store/utils.js +2 -0
  55. package/dist/types/core/action.d.ts +8 -0
  56. package/dist/types/core/constants.d.ts +20 -0
  57. package/dist/types/core/core.d.ts +14 -1
  58. package/dist/types/core/dev.d.ts +1 -1
  59. package/dist/types/core/index.d.ts +1 -1
  60. package/dist/types/core/lanes.d.ts +5 -1
  61. package/dist/types/core/scheduler.d.ts +2 -0
  62. package/dist/types/index.d.ts +3 -1
  63. package/dist/types/signals.d.ts +37 -0
  64. package/dist/types/store/target.d.ts +2 -0
  65. package/package.json +1 -1
@@ -251,7 +251,7 @@ function releaseSlot(e) {
251
251
  // holds: its release waits for the commit that resolves it. So does a leaf of
252
252
  // a held container (#4146): a mainline write it carried is in the held
253
253
  // staging too, where it would read as the hold's until the landing.
254
- const slotKept = e => e.ue !== NOT_PENDING || e.l & CONFIG_OVERRIDE || e.O.k?.l & CONFIG_HELD;
254
+ const slotKept = e => e.ie !== NOT_PENDING || e.l & CONFIG_OVERRIDE || e.O.k?.l & CONFIG_HELD;
255
255
 
256
256
  setSlotUnobserved(e => {
257
257
  if (slotKept(e)) deferredReleases.add(e); else releaseSlot(e);
@@ -262,9 +262,9 @@ setSlotUnobserved(e => {
262
262
  * pending one — and held by the container's transaction when the container
263
263
  * is held (#3706: the unit of the hold is the key — a key the batch left
264
264
  * unchanged stages nothing and holds no one). */ function bornStaged(e, t, n, r) {
265
- if (t.Ye && t.Ye(t.Ie, n)) return;
265
+ if (t.je && t.je(t.le, n)) return;
266
266
  queuePendingNode(t);
267
- t.ue = n;
267
+ t.ie = n;
268
268
  const o = e.k;
269
269
  if (o === null) return;
270
270
  // a node-less staging holds nothing (`stageOn`)
@@ -343,8 +343,8 @@ function getHasNode(e, t) {
343
343
  // pending backing staged — so whoever asked for it reads the frame it
344
344
  // would have read had the node been there from the write.
345
345
  if (e.pb !== null && !directCommit) {
346
- t.Ie = preBatch(e);
347
- t.ue = e.pb;
346
+ t.le = preBatch(e);
347
+ t.ie = e.pb;
348
348
  queuePendingNode(t);
349
349
  }
350
350
  }
@@ -363,8 +363,8 @@ function getHasNode(e, t) {
363
363
  * (`storeParkHook`) — the one case the staging home exists for. */ function stageOn(e, t) {
364
364
  if (e.k === null && passLane === null && (context === null || globalQueue.q) && !deriveHolds(e)) return;
365
365
  const n = getContainerNode(e);
366
- if (n.ue === NOT_PENDING) queuePendingNode(n);
367
- n.ue = t;
366
+ if (n.ie === NOT_PENDING) queuePendingNode(n);
367
+ n.ie = t;
368
368
  // A28 (4): a write issued inside a pass outside a flush (a creation-time
369
369
  // derive) is promoted at the pass's end — the batch with it.
370
370
  if (context !== null) notePromotedWrite(n);
@@ -408,7 +408,7 @@ function bumpDeep(e) {
408
408
  // the node; the comparator is the store's, done).
409
409
  if (e.l & CONFIG_OVERRIDE) setSignal(e, t); else {
410
410
  if (e.l & CONFIG_HELD) joinFuture(txOf(e));
411
- if (snapshotCaptureActive) captureWriteSnapshot(e, e.Ie);
411
+ if (snapshotCaptureActive) captureWriteSnapshot(e, e.le);
412
412
  insertSubs(e);
413
413
  schedule();
414
414
  }
@@ -543,7 +543,7 @@ const plainProto = e => {
543
543
  const n = overlayOnto(e, e.sc === 2 ? wideClone(e.v, e) : cloneRaw(e.v, e), t);
544
544
  e.pb = n;
545
545
  // The staging IS the pending backing: re-point the container node.
546
- if (e.k?.ue === t) e.k.ue = n;
546
+ if (e.k?.ie === t) e.k.ie = n;
547
547
  return n;
548
548
  }
549
549
 
@@ -555,7 +555,7 @@ const plainProto = e => {
555
555
  // An optimistic edit composes on the view the user saw and becomes
556
556
  // guesses at the setter's exit: nothing is staged, nothing folds
557
557
  // (optimistic.ts).
558
- if (userWrite && e.fam?.opt === true && !pendingNotify.has(e)) return e.pb = optHooks.draft(e);
558
+ if (optHooks && userWrite && e.fam?.opt === true && !pendingNotify.has(e)) return e.pb = optHooks.draft(e);
559
559
  if (t !== null && !isOwned(t)) {
560
560
  // An adopted object awaiting its fold is the user's: the draft writes a
561
561
  // clone of it. The clone is the batch's staging — unless the adoption is
@@ -564,7 +564,7 @@ const plainProto = e => {
564
564
  // mainline setter mid-hold publishes mainline; the held keys stay held).
565
565
  t = e.pb = cloneRaw(t, e);
566
566
  const n = e.k;
567
- if (n !== null && !(n.l & CONFIG_HELD)) n.ue = t;
567
+ if (n !== null && !(n.l & CONFIG_HELD)) n.ie = t;
568
568
  } else if (t === null) {
569
569
  const n = e.v;
570
570
  if (!directCommit) queueFold(e);
@@ -645,7 +645,7 @@ const plainProto = e => {
645
645
  } else r = e.v;
646
646
  if (directCommit) {
647
647
  e.pb = null;
648
- if (e.k !== null) e.k.Ie = t;
648
+ if (e.k !== null) e.k.le = t;
649
649
  } else {
650
650
  // Eager (INTERNALS §3): the backing swaps now — handlers read the
651
651
  // adopted object before the flush — while the container node, when
@@ -741,7 +741,7 @@ let foldIndex = null;
741
741
  if (r.pb === null) continue;
742
742
  // folded already (a direct commit)
743
743
  const o = r.k;
744
- if (o !== null && o.ue !== NOT_PENDING) {
744
+ if (o !== null && o.ie !== NOT_PENDING) {
745
745
  // held: commits with its hold
746
746
  foldList.push(r);
747
747
  foldOlds.push(t[n]);
@@ -776,9 +776,9 @@ let foldIndex = null;
776
776
  if (t.ch) {
777
777
  const n = e.Vt;
778
778
  const r = t.v;
779
- if (t.h?.[n] === e) e.Ie = untrack(() => n in r); else if (t.n?.[n] === e) e.Ie = untrack(() => unwrapValue(r[n]));
779
+ if (t.h?.[n] === e) e.le = untrack(() => n in r); else if (t.n?.[n] === e) e.le = untrack(() => unwrapValue(r[n]));
780
780
  }
781
- return e.Ie;
781
+ return e.le;
782
782
  };
783
783
 
784
784
  installStoreHooks(storePark, () => {
@@ -812,7 +812,7 @@ function runDirect(e) {
812
812
  const n = e.k;
813
813
  const r = e.pb;
814
814
  if (r !== null) {
815
- if (r === e.v) ; else if (e.ovl && (e.v !== t || !overlayRebuilds(e, r) && n?.T?.lt !== t)) {
815
+ if (r === e.v) ; else if (e.ovl && (e.v !== t || !overlayRebuilds(e, r) && n?.T?.st !== t)) {
816
816
  // Overlay flatten (#3044): the backing keeps its identity, so the
817
817
  // `t.v === old` gate below skips path copying (the parent slot
818
818
  // already points here) and the adopted-notify (setter
@@ -830,9 +830,9 @@ function runDirect(e) {
830
830
  if (hasOwn.call(r, t)) copyOwn(n, r, t); else delete n[t];
831
831
  }
832
832
  } else {
833
- for (const e of Reflect.ownKeys(r)) copyOwn(n, r, e);
833
+ for (const e of Reflect.ownKeys(r)) if (e !== $OWNER) copyOwn(n, r, e);
834
834
  for (const e of Reflect.ownKeys(t)) {
835
- if (!hasOwn.call(r, e)) delete n[e];
835
+ if (e !== $OWNER && !hasOwn.call(r, e)) delete n[e];
836
836
  }
837
837
  }
838
838
  } else {
@@ -850,7 +850,7 @@ function runDirect(e) {
850
850
  // subscribes to was a transient staging home (INTERNALS §5: an
851
851
  // observer-less write holds a transient record until the fold,
852
852
  // discarded with it) — gone with the batch.
853
- if (n.o === null) e.k = null; else if (n.Ie instanceof LaneView) n.Ie.base = e.v; else n.Ie = e.v;
853
+ if (n.o === null) e.k = null; else if (n.le instanceof LaneView) n.le.base = e.v; else n.le = e.v;
854
854
  }
855
855
  if (e.v !== t && e.u) {
856
856
  const n = parentSlotKey(e, t);
@@ -883,29 +883,39 @@ function reportReplacedContainers(e, t, n, r) {
883
883
  const o = r ?? Reflect.ownKeys(n);
884
884
  const i = Array.isArray(n);
885
885
  const l = storeRootOwner(e);
886
+ // Items the array held before the write: an index that now holds one of
887
+ // them was moved into place (an in-place splice / shift), not replaced.
888
+ let u = null;
886
889
  for (const r of o) {
887
890
  if (i && r === "length" || r === $OWNER) continue;
888
891
  if (e.del?.has(r)) continue;
889
892
  const o = unwrapValue(t[r]);
890
- const u = unwrapValue(n[r]);
891
- if (o === null || u === null || typeof o !== "object" || typeof u !== "object" || o === u || targetsEqual(o, u)) continue;
892
- const f = Array.isArray(u);
893
- if (f !== Array.isArray(o)) continue;
894
- let s;
895
- let a = 0;
896
- if (f) {
897
- s = u.length;
898
- if (s > REPLACED_CENSUS_MAX) continue;
893
+ const f = unwrapValue(n[r]);
894
+ if (o === null || f === null || typeof o !== "object" || typeof f !== "object" || o === f || targetsEqual(o, f)) continue;
895
+ if (i) {
896
+ if (u === null) {
897
+ u = new Set;
898
+ for (const e of t) u.add(unwrapValue(e));
899
+ }
900
+ if (u.has(f)) continue;
901
+ }
902
+ const s = Array.isArray(f);
903
+ if (s !== Array.isArray(o)) continue;
904
+ let a;
905
+ let c = 0;
906
+ if (s) {
907
+ a = f.length;
908
+ if (a > REPLACED_CENSUS_MAX) continue;
899
909
  const e = new Set;
900
910
  for (const t of o) e.add(unwrapValue(t));
901
- for (const t of u) if (e.has(unwrapValue(t))) a++;
911
+ for (const t of f) if (e.has(unwrapValue(t))) c++;
902
912
  } else {
903
- const e = Object.keys(u);
904
- s = e.length;
905
- if (s > REPLACED_CENSUS_MAX) continue;
906
- for (const t of e) if (sameLeaf(o[t], u[t])) a++;
913
+ const e = Object.keys(f);
914
+ a = e.length;
915
+ if (a > REPLACED_CENSUS_MAX) continue;
916
+ for (const t of e) if (sameLeaf(o[t], f[t])) c++;
907
917
  }
908
- attrHooks.storeReplaced(storePathOf(e) + "." + String(r), f, s, a, f ? o.length : Object.keys(o).length, l);
918
+ attrHooks.storeReplaced(storePathOf(e) + "." + String(r), s, a, c, s ? o.length : Object.keys(o).length, l);
909
919
  }
910
920
  }
911
921
 
@@ -935,7 +945,7 @@ function heldDerivation(e, t, n) {
935
945
  // Optimistic channel: a user's writes on an optimistic family become
936
946
  // guesses on the nodes (lanes); the draft is discarded, the committed
937
947
  // backing never touched.
938
- if (userWrite && e.fam?.opt === true) {
948
+ if (optHooks && userWrite && e.fam?.opt === true) {
939
949
  // The draft is discarded first: the diff reads the target (its nodes
940
950
  // are born from the committed frame, not the draft).
941
951
  e.pb = null;
@@ -1185,7 +1195,7 @@ function inDraft(e) {
1185
1195
  * "adoption is eager by contract" — and the node keeps the frame committed
1186
1196
  * readers under a hold still see), `t.v` otherwise. */ function committed(e) {
1187
1197
  const t = e.k;
1188
- if (t !== null) return t.ue !== NOT_PENDING ? asBacking(t.Ie) : e.v;
1198
+ if (t !== null) return t.ie !== NOT_PENDING ? asBacking(t.le) : e.v;
1189
1199
  // A node-less staging (`stageOn`): the fold queue remembers the frame.
1190
1200
  return e.pb !== null ? preBatch(e) : e.v;
1191
1201
  }
@@ -1197,7 +1207,7 @@ function inDraft(e) {
1197
1207
  * committed frame. */ function stagingReader() {
1198
1208
  let e = context;
1199
1209
  if (e === null) return null;
1200
- if (e.Pt) e = e.Ht ?? null;
1210
+ if (e.Pt) e = e.ht ?? null;
1201
1211
  return e === null || e.l & CONFIG_CHILDREN_FORBIDDEN ? null : e;
1202
1212
  }
1203
1213
 
@@ -1271,7 +1281,7 @@ function inDraft(e) {
1271
1281
  // probe) judges the container like any node — for a key the batch
1272
1282
  // changed; an unchanged key is committed and final (A22: pending is per
1273
1283
  // key). A held container's committed frame is the node's.
1274
- if (verdict === null || !i && t !== undefined && !keyChanged(e, t, n)) return i ? asBacking(o.Ie) : e.v;
1284
+ if (verdict === null || !i && t !== undefined && !keyChanged(e, t, n)) return i ? asBacking(o.le) : e.v;
1275
1285
  return o === null ? committed(e) : asBacking(read(o));
1276
1286
  }
1277
1287
  // A pass reading a key the batch left unchanged: the same value in both
@@ -1304,7 +1314,7 @@ function inDraft(e) {
1304
1314
 
1305
1315
  /** Did the HELD staging (the container node's, not a mainline layer above
1306
1316
  * it) change `key`? */ function heldKeyChanged(e, t, n = true) {
1307
- return changedBetween(e, e.k.Ie, e.k.ue, t, n) && !adoptChild(e, t);
1317
+ return changedBetween(e, e.k.le, e.k.ie, t, n) && !adoptChild(e, t);
1308
1318
  }
1309
1319
 
1310
1320
  /** The values of a held frame, built once per frame: neither the committed
@@ -1331,14 +1341,14 @@ function rawsOf(e) {
1331
1341
  * `version` holds. A record's keys pair by name; an array's by the family's
1332
1342
  * key — without a family the pairing is not known here and the hold stands. */ function adoptChild(e, t) {
1333
1343
  const n = e.k;
1334
- const r = asBacking(n.Ie);
1344
+ const r = asBacking(n.le);
1335
1345
  const o = r[t];
1336
- const i = n.ue[t];
1346
+ const i = n.ie[t];
1337
1347
  const l = Array.isArray(r) ? e.fam?.key : null;
1338
1348
  if (e.s || l === undefined || !sameRow(o, i, l) || !isWrappable(o) || !isWrappable(i) || Array.isArray(o) !== Array.isArray(i) || lookupTarget(o, e.fam) !== undefined || lookupTarget(i, e.fam) !== undefined ||
1339
1349
  // A raw in both frames (the same objects swapped or reordered) is its
1340
1350
  // own row: pairing it with another would alias the two after the commit.
1341
- rawsOf(r).has(i) || rawsOf(n.ue).has(o)) return false;
1351
+ rawsOf(r).has(i) || rawsOf(n.ie).has(o)) return false;
1342
1352
  // A raw-marked value wraps to itself, a proxy to its own target: neither
1343
1353
  // is a fresh target around `ov`.
1344
1354
  const u = wrap(o, e, t)[$TARGET];
@@ -1383,7 +1393,7 @@ function changedBetween(e, t, n, r, o) {
1383
1393
  * tracked or not, applies the hold and A28 rules a signal's read does. A
1384
1394
  * projection's unheld staging is ahead for a handler (`familyAhead`). */ function nodeValue(e, t, n) {
1385
1395
  let r = read(e);
1386
- if (e.ue !== NOT_PENDING && !(e.l & CONFIG_HELD) && context === null && n.fam !== null) r = e.ue;
1396
+ if (e.ie !== NOT_PENDING && !(e.l & CONFIG_HELD) && context === null && n.fam !== null) r = e.ie;
1387
1397
  return r === FORCE ? t : r;
1388
1398
  }
1389
1399
 
@@ -1403,7 +1413,7 @@ function changedBetween(e, t, n, r, o) {
1403
1413
  if (l) {
1404
1414
  // The link's committed value follows the inner store's (what a lane
1405
1415
  // over it covers — its reveal and revert compare against it, S4).
1406
- o.Ie = n;
1416
+ o.le = n;
1407
1417
  if (o.l & CONFIG_OVERRIDE) u = t;
1408
1418
  } else u = t;
1409
1419
  }
@@ -1476,7 +1486,7 @@ function changedBetween(e, t, n, r, o) {
1476
1486
  * classification, as core reads it — `heldNotFinal`). */ function holdWithDerive(e, t) {
1477
1487
  const n = e.fam?.node;
1478
1488
  if (n !== undefined && n !== null && !userWrite && // the derive's own write (its draft or landing), not a user setter's
1479
- n.l & CONFIG_HELD && t.ue !== NOT_PENDING &&
1489
+ n.l & CONFIG_HELD && t.ie !== NOT_PENDING &&
1480
1490
  // A node carrying a guess is the lane's: its staging is the truth beneath
1481
1491
  // the guess (`setSignal` → `laneWrite`), never re-homed by the store.
1482
1492
  !(t.l & (CONFIG_HELD | CONFIG_OVERRIDE))) {
@@ -1508,10 +1518,10 @@ function changedBetween(e, t, n, r, o) {
1508
1518
  // A container's arrangement guess is not a backing: the view composes
1509
1519
  // over the base it is shown over.
1510
1520
  const t = asBacking(read(getContainerNode(e)));
1511
- return e.fam?.opt === true ? optHooks.view(e, t) : t;
1521
+ return optHooks && e.fam?.opt === true ? optHooks.view(e, t) : t;
1512
1522
  }
1513
1523
  const t = readSource(e);
1514
- return optRead(e) ? optHooks.view(e, t) : t;
1524
+ return optHooks && optRead(e) ? optHooks.view(e, t) : t;
1515
1525
  }
1516
1526
 
1517
1527
  /** A read on an optimistic family that composes the lanes' values: not the
@@ -1678,11 +1688,11 @@ const traps = {
1678
1688
  const o = read(r);
1679
1689
  if (!e.ch || n !== e.v) return !!o;
1680
1690
  const i = t in n;
1681
- r.Ie = i;
1691
+ r.le = i;
1682
1692
  // the link follows the inner store (S4)
1683
1693
  if (r.l & CONFIG_OVERRIDE) return !!o;
1684
1694
  return i;
1685
- } else if (optRead(e)) {
1695
+ } else if (optHooks && optRead(e)) {
1686
1696
  const n = optHooks.has(e, t);
1687
1697
  if (n !== undefined) return n;
1688
1698
  }
@@ -1718,7 +1728,7 @@ const traps = {
1718
1728
  if (!r && (!e.ch || n.l & CONFIG_OVERRIDE || !(t in i))) return undefined;
1719
1729
  } else i = readSource(e, t, true);
1720
1730
  let l;
1721
- if (!o && optRead(e)) {
1731
+ if (optHooks && !o && optRead(e)) {
1722
1732
  const n = optHooks.descriptor(e, t);
1723
1733
  if (n === null) return undefined;
1724
1734
  l = n;
@@ -1825,7 +1835,7 @@ const traps = {
1825
1835
  const n = e.k;
1826
1836
  if (n === null) return false;
1827
1837
  const r = n.Ct;
1828
- return r !== null && r.u === t && (!(t.R & REACTIVE_RECOMPUTING_DEPS) || r.Te === t.Ne);
1838
+ return r !== null && r.u === t && (!(t.R & REACTIVE_RECOMPUTING_DEPS) || r.Ie === t.Ne);
1829
1839
  }
1830
1840
 
1831
1841
  function storeSetter(e, t, n = true) {
@@ -1863,7 +1873,7 @@ function storeSetter(e, t, n = true) {
1863
1873
  // A returned replacement: on an optimistic family a user's is itself an
1864
1874
  // optimistic edit — diffed against the view as guesses (`next` parity);
1865
1875
  // otherwise it is adopted as the incoming truth.
1866
- if (n && r.fam?.opt === true && !writeOverride) optHooks.writes(r, unwrapValue(l)); else adoptPB(r, unwrapValue(l));
1876
+ if (optHooks && n && r.fam?.opt === true && !writeOverride) optHooks.writes(r, unwrapValue(l)); else adoptPB(r, unwrapValue(l));
1867
1877
  }
1868
1878
  // A34 (3), #3612 — the derived store's twin of `setMemo`: a user write to
1869
1879
  // a derivation another transaction holds is nobody's proposal; it becomes
@@ -2030,7 +2040,7 @@ function snapshotWalk(e, t, n) {
2030
2040
  if (o.ovl) materializePB(o);
2031
2041
  i = o.pb;
2032
2042
  }
2033
- if (optRead(o)) i = optHooks.view(o, i);
2043
+ if (optHooks && optRead(o)) i = optHooks.view(o, i);
2034
2044
  if (i === r) break;
2035
2045
  r = i;
2036
2046
  }
@@ -1,4 +1,4 @@
1
- import { SUPPORTS_PROXY } from "../core/constants.js";
1
+ import { SUPPORTS_PROXY, CONFIG_KEY_BAG } from "../core/constants.js";
2
2
 
3
3
  import { createMemo } from "../signals.js";
4
4
 
@@ -921,7 +921,12 @@ const omitTraps = {
921
921
  f++;
922
922
  i = o;
923
923
  if (typeof o === "function") {
924
- n[r] = createMemo(o);
924
+ // Observe tiers name it and exempt it from UNSTABLE_MEMO_OUTPUT (see
925
+ // CONFIG_KEY_BAG); prod passes no options.
926
+ n[r] = createMemo(o, {
927
+ name: "merge",
928
+ St: CONFIG_KEY_BAG
929
+ });
925
930
  t[r++] = SOURCE_MEMO;
926
931
  continue;
927
932
  }