@mmstack/primitives 22.9.2 → 22.9.3

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.
@@ -1740,8 +1740,7 @@ function createImmutableObjectUpdater(source, key, vivifyFn) {
1740
1740
  return { ...vivified, [key]: next };
1741
1741
  });
1742
1742
  }
1743
- function createUpdater(source, key, vivify) {
1744
- const sample = untracked(source);
1743
+ function createUpdaterFromSample(source, key, vivify, sample) {
1745
1744
  // fast path for when vivification is off
1746
1745
  if (!vivify) {
1747
1746
  if (Array.isArray(sample) && typeof key === 'number') {
@@ -1789,6 +1788,19 @@ function createUpdater(source, key, vivify) {
1789
1788
  ? createMutableObjectUpdater(source, key, vivifyFn)
1790
1789
  : createImmutableObjectUpdater(source, key, vivifyFn);
1791
1790
  }
1791
+ /**
1792
+ * Selects the property updater once, on the first actual write. Construction must not sample the
1793
+ * source: a writable derivation may currently throw, and reads still need a child producer that can
1794
+ * subscribe and recover. The routing sample remains deliberately untracked, so deferring it adds no
1795
+ * dependency to the caller.
1796
+ */
1797
+ function createUpdater(source, key, vivify) {
1798
+ let update;
1799
+ return (next) => {
1800
+ update ??= createUpdaterFromSample(source, key, vivify, untracked(source));
1801
+ update(next);
1802
+ };
1803
+ }
1792
1804
  function derived(source, optOrKey, opt) {
1793
1805
  const vivify = typeof optOrKey === 'object' ? false : (opt?.vivify ?? false);
1794
1806
  // With vivification the source may legitimately be null/undefined
@@ -4218,14 +4230,19 @@ function alwaysFalse() {
4218
4230
  function markAsLeaf(sig, value, vivifyEnabled, noUnionLeaves) {
4219
4231
  if (typeof sig[LEAF] !== 'function') {
4220
4232
  let memo;
4233
+ let initialClassification;
4221
4234
  const probe = () => {
4222
4235
  if (memo)
4223
4236
  return memo();
4224
- memo = noUnionLeaves
4225
- ? isLeafValue(untracked(value), vivifyEnabled)
4226
- ? alwaysTrue
4227
- : alwaysFalse
4228
- : computed(() => isLeafValue(value(), vivifyEnabled));
4237
+ if (noUnionLeaves) {
4238
+ initialClassification ??= computed(() => isLeafValue(value(), vivifyEnabled));
4239
+ const result = initialClassification();
4240
+ memo = result ? alwaysTrue : alwaysFalse;
4241
+ initialClassification = undefined;
4242
+ }
4243
+ else {
4244
+ memo = computed(() => isLeafValue(value(), vivifyEnabled));
4245
+ }
4229
4246
  return memo();
4230
4247
  };
4231
4248
  Object.defineProperty(sig, LEAF, {
@@ -4573,21 +4590,19 @@ function mutableChildEqual(a, b) {
4573
4590
  * correct after it. The only place a child node is constructed — shared by every container kind.
4574
4591
  */
4575
4592
  function buildChildNode(target, prop, isMutableSource, options) {
4576
- const value = untracked(target);
4577
- const nodeVivify = resolveVivify(value, options.vivify);
4578
- const vivifyFn = createVivify(nodeVivify);
4579
- const equalFn = isMutableSource && (isRecord$1(value) || Array.isArray(value))
4580
- ? mutableChildEqual
4581
- : undefined;
4593
+ let vivifyFn = options.vivify === false ? createVivify(false) : undefined;
4594
+ const resolveVivifyFn = (sample) => (vivifyFn ??= createVivify(resolveVivify(sample, options.vivify)));
4595
+ const lazyVivify = (value, key) => resolveVivifyFn(value)(value, key);
4582
4596
  const computation = derived(target, {
4583
- from: (v) => v?.[prop],
4584
- onChange: createFallbackOnChange(target, prop, vivifyFn, isMutableSource),
4585
- equal: equalFn,
4597
+ from: (v) => {
4598
+ resolveVivifyFn(v);
4599
+ return v?.[prop];
4600
+ },
4601
+ onChange: createFallbackOnChange(target, prop, lazyVivify, isMutableSource),
4602
+ equal: isMutableSource ? mutableChildEqual : undefined,
4586
4603
  });
4587
- const childSample = untracked(computation);
4588
- const childVivify = resolveVivify(childSample, options.vivify);
4589
4604
  const proxy = toStore(computation, options);
4590
- markAsLeaf(proxy, computation, childVivify !== false, options.noUnionLeaves);
4605
+ markAsLeaf(proxy, computation, options.vivify !== false, options.noUnionLeaves);
4591
4606
  return proxy;
4592
4607
  }
4593
4608
  /**
@@ -4726,7 +4741,16 @@ function toStore(source, { injector, vivify = false, noUnionLeaves = false, ...r
4726
4741
  if ((typeof prop === 'symbol' && prop !== Symbol.iterator) ||
4727
4742
  (typeof prop === 'string' && SIGNAL_FN_PROP.has(prop)))
4728
4743
  return target[prop];
4729
- const k = untracked(kind);
4744
+ const child = (key) => getCachedChild(target, prop, () => buildChildNode(target, key, isMutableSource, STORE_OPTIONS), STORE_OPTIONS[STORE_SHARED_GLOBALS].cache, STORE_OPTIONS[STORE_SHARED_GLOBALS].registry);
4745
+ let k;
4746
+ try {
4747
+ k = untracked(kind);
4748
+ }
4749
+ catch (cause) {
4750
+ if (typeof prop === 'string' && prop !== 'extend')
4751
+ return child(isIndexProp(prop) ? +prop : prop);
4752
+ throw cause;
4753
+ }
4730
4754
  if (prop === 'extend' && k !== 'array')
4731
4755
  return (seed) => scopedStore(s, seed, isMutableSource
4732
4756
  ? 'mutable'
@@ -4745,7 +4769,7 @@ function toStore(source, { injector, vivify = false, noUnionLeaves = false, ...r
4745
4769
  }
4746
4770
  if (k === 'array' && !isIndexProp(prop))
4747
4771
  return Reflect.get(target, prop, receiver);
4748
- return getCachedChild(target, prop, () => buildChildNode(target, k === 'array' ? +prop : prop, isMutableSource, STORE_OPTIONS), STORE_OPTIONS[STORE_SHARED_GLOBALS].cache, STORE_OPTIONS[STORE_SHARED_GLOBALS].registry);
4772
+ return child(k === 'array' ? +prop : prop);
4749
4773
  },
4750
4774
  });
4751
4775
  return s;