@solidjs/signals 0.2.4 → 0.3.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.
package/dist/dev.js CHANGED
@@ -75,8 +75,8 @@ var Queue = class {
75
75
  for (let i = 0; i < this._children.length; i++) {
76
76
  rerun = this._children[i].run(type) || rerun;
77
77
  }
78
- if (type === EFFECT_PURE && this._queues[type].length)
79
- return true;
78
+ if (type === EFFECT_PURE)
79
+ return rerun || !!this._queues[type].length;
80
80
  }
81
81
  flush() {
82
82
  if (this._running)
@@ -138,6 +138,26 @@ function runEffectQueue(queue) {
138
138
  function isUndefined(value) {
139
139
  return typeof value === "undefined";
140
140
  }
141
+ function tryCatch(fn) {
142
+ try {
143
+ const v = fn();
144
+ if (v instanceof Promise) {
145
+ return v.then(
146
+ (v2) => [void 0, v2],
147
+ (e) => {
148
+ if (e instanceof NotReadyError)
149
+ throw e;
150
+ return [e];
151
+ }
152
+ );
153
+ }
154
+ return [void 0, v];
155
+ } catch (e) {
156
+ if (e instanceof NotReadyError)
157
+ throw e;
158
+ return [e];
159
+ }
160
+ }
141
161
 
142
162
  // src/core/owner.ts
143
163
  var currentOwner = null;
@@ -150,6 +170,10 @@ function setOwner(owner) {
150
170
  currentOwner = owner;
151
171
  return out;
152
172
  }
173
+ function formatId(prefix, id) {
174
+ const num = id.toString(36), len = num.length - 1;
175
+ return prefix + (len ? String.fromCharCode(64 + len) : "") + num;
176
+ }
153
177
  var Owner = class {
154
178
  // We flatten the owner tree into a linked list so that we don't need a pointer to .firstChild
155
179
  // However, the children are actually added in reverse creation order
@@ -162,13 +186,21 @@ var Owner = class {
162
186
  _context = defaultContext;
163
187
  _handlers = null;
164
188
  _queue = globalQueue;
165
- constructor(signal = false) {
166
- if (currentOwner && !signal)
189
+ _siblingCount = null;
190
+ _childCount = 0;
191
+ id = null;
192
+ constructor(id = null, skipAppend = false) {
193
+ this.id = id;
194
+ if (currentOwner && !skipAppend)
167
195
  currentOwner.append(this);
168
196
  }
169
197
  append(child) {
170
198
  child._parent = this;
171
199
  child._prevSibling = this;
200
+ if (this.id) {
201
+ child._siblingCount = this._nextSibling ? this._nextSibling._siblingCount + 1 : 0;
202
+ child.id = formatId(this.id, child._siblingCount);
203
+ }
172
204
  if (this._nextSibling)
173
205
  this._nextSibling._prevSibling = child;
174
206
  child._nextSibling = this._nextSibling;
@@ -223,6 +255,9 @@ var Owner = class {
223
255
  }
224
256
  this._disposal = null;
225
257
  }
258
+ addErrorHandler(handler) {
259
+ this._handlers = this._handlers ? [handler, ...this._handlers] : [handler];
260
+ }
226
261
  handleError(error) {
227
262
  if (!this._handlers)
228
263
  throw error;
@@ -238,6 +273,11 @@ var Owner = class {
238
273
  if (i === len)
239
274
  throw error;
240
275
  }
276
+ getNextChildId() {
277
+ if (this.id)
278
+ return formatId(this.id + "-", this._childCount++);
279
+ throw new Error("Cannot get child id from owner without an id");
280
+ }
241
281
  };
242
282
  function createContext(defaultValue, description) {
243
283
  return { id: Symbol(description), defaultValue };
@@ -316,11 +356,10 @@ var Computation = class extends Owner {
316
356
  _stateFlags = 0;
317
357
  /** Which flags raised by sources are handled, vs. being passed through. */
318
358
  _handlerMask = DEFAULT_FLAGS;
319
- _loading = null;
320
359
  _time = -1;
321
360
  _forceNotify = false;
322
361
  constructor(initialValue, compute2, options) {
323
- super(compute2 === null);
362
+ super(null, compute2 === null);
324
363
  this._compute = compute2;
325
364
  this._state = compute2 ? STATE_DIRTY : STATE_CLEAN;
326
365
  this._stateFlags = compute2 && initialValue === void 0 ? UNINITIALIZED_BIT : 0;
@@ -338,8 +377,7 @@ var Computation = class extends Owner {
338
377
  else
339
378
  this._updateIfNecessary();
340
379
  }
341
- if (!this._compute || this._sources?.length)
342
- track(this);
380
+ track(this);
343
381
  newFlags |= this._stateFlags & ~currentMask;
344
382
  if (this._stateFlags & ERROR_BIT) {
345
383
  throw this._error;
@@ -364,31 +402,22 @@ var Computation = class extends Owner {
364
402
  wait() {
365
403
  if (this._compute && this._stateFlags & ERROR_BIT && this._time <= getClock()) {
366
404
  update(this);
405
+ } else {
406
+ this._updateIfNecessary();
367
407
  }
368
- if ((notStale || this._stateFlags & UNINITIALIZED_BIT) && this.loading()) {
408
+ track(this);
409
+ if ((notStale || this._stateFlags & UNINITIALIZED_BIT) && this._stateFlags & LOADING_BIT) {
369
410
  throw new NotReadyError();
370
411
  }
371
- if (staleCheck && this.loading())
412
+ if (staleCheck && this._stateFlags & LOADING_BIT) {
372
413
  staleCheck._value = true;
373
- return this._read();
374
- }
375
- /**
376
- * Return true if the computation is the value is dependent on an unresolved promise
377
- * Triggers re-execution of the computation when the loading state changes
378
- *
379
- * This is useful especially when effects want to re-execute when a computation's
380
- * loading state changes
381
- */
382
- loading() {
383
- if (this._loading === null) {
384
- this._loading = loadingState(this);
385
414
  }
386
- return this._loading.read();
415
+ return this._read();
387
416
  }
388
417
  /** Update the computation with a new value. */
389
418
  write(value, flags = 0, raw = false) {
390
419
  const newValue = !raw && typeof value === "function" ? value(this._value) : value;
391
- const valueChanged = newValue !== UNCHANGED && (!!(this._stateFlags & UNINITIALIZED_BIT) || this._equals === false || !this._equals(this._value, newValue));
420
+ const valueChanged = newValue !== UNCHANGED && (!!(this._stateFlags & UNINITIALIZED_BIT) || this._stateFlags & LOADING_BIT & ~flags || this._equals === false || !this._equals(this._value, newValue));
392
421
  if (valueChanged) {
393
422
  this._value = newValue;
394
423
  this._error = void 0;
@@ -461,8 +490,11 @@ var Computation = class extends Owner {
461
490
  * This function will ensure that the value and states we read from the computation are up to date
462
491
  */
463
492
  _updateIfNecessary() {
493
+ if (!this._compute) {
494
+ return;
495
+ }
464
496
  if (this._state === STATE_DISPOSED) {
465
- throw new Error("Tried to read a disposed computation");
497
+ return;
466
498
  }
467
499
  if (this._state === STATE_CLEAN) {
468
500
  return;
@@ -495,22 +527,6 @@ var Computation = class extends Owner {
495
527
  super._disposeNode();
496
528
  }
497
529
  };
498
- function loadingState(node) {
499
- const prevOwner = setOwner(node._parent);
500
- const options = { name: node._name ? `loading ${node._name}` : "loading" } ;
501
- const computation = new Computation(
502
- void 0,
503
- () => {
504
- track(node);
505
- node._updateIfNecessary();
506
- return !!(node._stateFlags & LOADING_BIT);
507
- },
508
- options
509
- );
510
- computation._handlerMask = ERROR_BIT | LOADING_BIT;
511
- setOwner(prevOwner);
512
- return computation;
513
- }
514
530
  function track(computation) {
515
531
  if (currentObserver) {
516
532
  if (!newSources && currentObserver._sources && currentObserver._sources[newSourcesIndex] === computation) {
@@ -604,8 +620,7 @@ function hasUpdated(fn) {
604
620
  updateCheck = current;
605
621
  }
606
622
  }
607
- function isPending(fn, loadingValue) {
608
- const argLength = arguments.length;
623
+ function pendingCheck(fn, loadingValue) {
609
624
  const current = staleCheck;
610
625
  staleCheck = { _value: false };
611
626
  try {
@@ -614,13 +629,20 @@ function isPending(fn, loadingValue) {
614
629
  } catch (err) {
615
630
  if (!(err instanceof NotReadyError))
616
631
  return false;
617
- if (argLength > 1)
632
+ if (loadingValue !== void 0)
618
633
  return loadingValue;
619
634
  throw err;
620
635
  } finally {
621
636
  staleCheck = current;
622
637
  }
623
638
  }
639
+ function isPending(fn, loadingValue) {
640
+ if (!currentObserver)
641
+ return pendingCheck(fn, loadingValue);
642
+ const c = new Computation(void 0, () => pendingCheck(fn, loadingValue));
643
+ c._handlerMask |= LOADING_BIT;
644
+ return c.read();
645
+ }
624
646
  function latest(fn, fallback) {
625
647
  const argLength = arguments.length;
626
648
  const prevFlags = newFlags;
@@ -637,15 +659,6 @@ function latest(fn, fallback) {
637
659
  notStale = prevNotStale;
638
660
  }
639
661
  }
640
- function catchError(fn) {
641
- try {
642
- fn();
643
- } catch (e) {
644
- if (e instanceof NotReadyError)
645
- throw e;
646
- return e;
647
- }
648
- }
649
662
  function runWithObserver(observer, run) {
650
663
  const prevSources = newSources, prevSourcesIndex = newSourcesIndex, prevFlags = newFlags;
651
664
  newSources = null;
@@ -762,13 +775,6 @@ function flattenArray(children, results = [], options) {
762
775
  throw notReady;
763
776
  return needsUnwrap;
764
777
  }
765
- function createBoundary(fn, queue) {
766
- const owner = new Owner();
767
- const parentQueue = owner._queue;
768
- parentQueue.addChild(owner._queue = queue);
769
- onCleanup(() => parentQueue.removeChild(owner._queue));
770
- return compute(owner, fn, null);
771
- }
772
778
 
773
779
  // src/core/effect.ts
774
780
  var Effect = class extends Computation {
@@ -869,7 +875,7 @@ var EagerComputation = class extends Computation {
869
875
  };
870
876
  var ProjectionComputation = class extends Computation {
871
877
  constructor(compute2) {
872
- super(null, compute2);
878
+ super(void 0, compute2);
873
879
  if (!this._parent)
874
880
  console.warn("Eager Computations created outside a reactive context will never be disposed");
875
881
  }
@@ -882,52 +888,103 @@ var ProjectionComputation = class extends Computation {
882
888
  }
883
889
  };
884
890
 
885
- // src/core/suspense.ts
891
+ // src/core/boundaries.ts
892
+ function createBoundary(owner, fn, queue) {
893
+ if (queue) {
894
+ const parentQueue = owner._queue;
895
+ parentQueue.addChild(owner._queue = queue);
896
+ onCleanup(() => parentQueue.removeChild(owner._queue));
897
+ }
898
+ return compute(
899
+ owner,
900
+ () => {
901
+ const c = new Computation(void 0, fn);
902
+ return new EagerComputation(void 0, () => flatten(c.wait()), { defer: true });
903
+ },
904
+ null
905
+ );
906
+ }
907
+ function createDecision(main, condition, fallback) {
908
+ const decision = new Computation(void 0, () => {
909
+ if (!condition.read()) {
910
+ const resolved = main.read();
911
+ if (!condition.read())
912
+ return resolved;
913
+ }
914
+ return fallback();
915
+ });
916
+ return decision.read.bind(decision);
917
+ }
886
918
  var SuspenseQueue = class extends Queue {
887
919
  _nodes = /* @__PURE__ */ new Set();
888
- _fallback = false;
889
- _signal = new Computation(false, null);
920
+ _fallback = new Computation(false, null);
890
921
  run(type) {
891
- if (type && this._fallback)
922
+ if (type && this._fallback.read())
892
923
  return;
893
924
  return super.run(type);
894
925
  }
895
926
  _update(node) {
896
927
  if (node._stateFlags & LOADING_BIT) {
897
928
  this._nodes.add(node);
898
- if (!this._fallback) {
899
- this._fallback = true;
900
- this._signal.write(true);
901
- }
929
+ if (this._nodes.size === 1)
930
+ this._fallback.write(true);
902
931
  } else {
903
932
  this._nodes.delete(node);
904
- if (this._nodes.size === 0) {
905
- this._fallback = false;
906
- this._signal.write(false);
907
- }
933
+ if (this._nodes.size === 0)
934
+ this._fallback.write(false);
908
935
  }
909
936
  }
910
937
  };
911
- var LiveComputation = class extends EagerComputation {
912
- write(value, flags = 0) {
938
+ function createSuspense(fn, fallback) {
939
+ const owner = new Owner();
940
+ const queue = new SuspenseQueue();
941
+ const tree = createBoundary(owner, fn, queue);
942
+ const ogWrite = tree.write;
943
+ tree.write = function(value, flags = 0) {
913
944
  const currentFlags = this._stateFlags;
914
945
  const dirty = this._state === STATE_DIRTY;
915
- super.write(value, flags);
946
+ ogWrite.call(this, value, flags);
916
947
  if (dirty && (flags & LOADING_BIT) !== (currentFlags & LOADING_BIT)) {
917
948
  this._queue._update?.(this);
918
949
  }
919
950
  return this._value;
951
+ };
952
+ return createDecision(tree, queue._fallback, fallback);
953
+ }
954
+ function createErrorBoundary(fn, fallback) {
955
+ const owner = new Owner();
956
+ const error = new Computation(void 0, null);
957
+ const nodes = /* @__PURE__ */ new Set();
958
+ function handler(err, node) {
959
+ if (nodes.has(node))
960
+ return;
961
+ compute(
962
+ node,
963
+ () => onCleanup(() => {
964
+ nodes.delete(node);
965
+ if (!nodes.size)
966
+ error.write(void 0);
967
+ }),
968
+ null
969
+ );
970
+ nodes.add(node);
971
+ if (nodes.size === 1)
972
+ error.write({ _error: err });
920
973
  }
921
- };
922
- function createSuspense(fn, fallback) {
923
- const queue = new SuspenseQueue();
924
- const tree = createBoundary(() => {
925
- const child = new Computation(null, fn);
926
- return new LiveComputation(null, () => flatten(child.wait()));
927
- }, queue);
928
- const equality = new Computation(null, () => queue._signal.read() || queue._fallback);
929
- const comp = new Computation(null, () => equality.read() ? fallback() : tree.read());
930
- return comp.read.bind(comp);
974
+ owner.addErrorHandler(handler);
975
+ const tree = createBoundary(owner, fn);
976
+ tree._setError = tree.handleError;
977
+ return createDecision(
978
+ tree,
979
+ error,
980
+ () => fallback(error.read()._error, () => {
981
+ incrementClock();
982
+ for (let node of nodes) {
983
+ node._state = STATE_DIRTY;
984
+ node._queue?.enqueue(node._type, node);
985
+ }
986
+ })
987
+ );
931
988
  }
932
989
 
933
990
  // src/signals.ts
@@ -955,77 +1012,64 @@ function createMemo(compute2, value, options) {
955
1012
  let resolvedValue;
956
1013
  return () => {
957
1014
  if (node) {
1015
+ if (node._state === STATE_DISPOSED) {
1016
+ node = void 0;
1017
+ return resolvedValue;
1018
+ }
958
1019
  resolvedValue = node.wait();
959
1020
  if (!node._sources?.length && node._nextSibling?._parent !== node) {
960
1021
  node.dispose();
961
1022
  node = void 0;
962
- } else if (!node._parent && !node._observers?.length) {
963
- node.dispose();
964
- node._state = STATE_DIRTY;
965
1023
  }
966
1024
  }
967
1025
  return resolvedValue;
968
1026
  };
969
1027
  }
970
1028
  function createAsync(compute2, value, options) {
971
- let uninitialized = value === void 0;
972
- const lhs = new EagerComputation(
973
- {
974
- _value: value
975
- },
1029
+ const node = new EagerComputation(
1030
+ value,
976
1031
  (p) => {
977
- const value2 = p?._value;
978
- const source = compute2(value2);
1032
+ const source = compute2(p);
979
1033
  const isPromise = source instanceof Promise;
980
1034
  const iterator = source[Symbol.asyncIterator];
981
1035
  if (!isPromise && !iterator) {
982
- return {
983
- wait() {
984
- return source;
985
- },
986
- _value: source
987
- };
1036
+ return source;
988
1037
  }
989
- const signal = new Computation(value2, null, options);
990
- const w = signal.wait;
991
- signal.wait = function() {
992
- if (signal._stateFlags & ERROR_BIT && signal._time <= getClock()) {
993
- lhs._notify(STATE_DIRTY);
994
- throw new NotReadyError();
995
- }
996
- return w.call(this);
997
- };
998
- signal.write(UNCHANGED, LOADING_BIT | (uninitialized ? UNINITIALIZED_BIT : 0));
1038
+ let abort = false;
1039
+ onCleanup(() => abort = true);
999
1040
  if (isPromise) {
1000
1041
  source.then(
1001
1042
  (value3) => {
1002
- uninitialized = false;
1003
- signal.write(value3, 0, true);
1043
+ if (abort)
1044
+ return;
1045
+ node.write(value3, 0, true);
1004
1046
  },
1005
1047
  (error) => {
1006
- uninitialized = true;
1007
- signal._setError(error);
1048
+ if (abort)
1049
+ return;
1050
+ node._setError(error);
1008
1051
  }
1009
1052
  );
1010
1053
  } else {
1011
- let abort = false;
1012
- onCleanup(() => abort = true);
1013
1054
  (async () => {
1014
1055
  try {
1015
1056
  for await (let value3 of source) {
1016
1057
  if (abort)
1017
1058
  return;
1018
- signal.write(value3, 0, true);
1059
+ node.write(value3, 0, true);
1019
1060
  }
1020
1061
  } catch (error) {
1021
- signal.write(error, ERROR_BIT);
1062
+ if (abort)
1063
+ return;
1064
+ node.write(error, ERROR_BIT);
1022
1065
  }
1023
1066
  })();
1024
1067
  }
1025
- return signal;
1026
- }
1068
+ throw new NotReadyError();
1069
+ },
1070
+ options
1027
1071
  );
1028
- return () => lhs.wait().wait();
1072
+ return node.wait.bind(node);
1029
1073
  }
1030
1074
  function createEffect(compute2, effect, error, value, options) {
1031
1075
  void new Effect(
@@ -1042,62 +1086,13 @@ function createRenderEffect(compute2, effect, value, options) {
1042
1086
  ...{ ...options, name: options?.name ?? "effect" }
1043
1087
  });
1044
1088
  }
1045
- function createRoot(init) {
1046
- const owner = new Owner();
1089
+ function createRoot(init, options) {
1090
+ const owner = new Owner(options?.id);
1047
1091
  return compute(owner, !init.length ? init : () => init(() => owner.dispose()), null);
1048
1092
  }
1049
1093
  function runWithOwner(owner, run) {
1050
1094
  return compute(owner, run, null);
1051
1095
  }
1052
- function createErrorBoundary(fn, fallback) {
1053
- const owner = new Owner();
1054
- const error = new Computation(void 0, null);
1055
- const nodes = /* @__PURE__ */ new Set();
1056
- function handler(err, node) {
1057
- if (nodes.has(node))
1058
- return;
1059
- compute(
1060
- node,
1061
- () => onCleanup(() => {
1062
- nodes.delete(node);
1063
- if (!nodes.size)
1064
- error.write(void 0);
1065
- }),
1066
- null
1067
- );
1068
- nodes.add(node);
1069
- if (nodes.size === 1)
1070
- error.write({ _error: err });
1071
- }
1072
- owner._handlers = owner._handlers ? [handler, ...owner._handlers] : [handler];
1073
- const guarded = compute(
1074
- owner,
1075
- () => {
1076
- const c = new Computation(void 0, fn);
1077
- const f = new EagerComputation(void 0, () => flatten(c.read()), { defer: true });
1078
- f._setError = function(error2) {
1079
- this.handleError(error2);
1080
- };
1081
- return f;
1082
- },
1083
- null
1084
- );
1085
- const decision = new Computation(null, () => {
1086
- if (!error.read()) {
1087
- const resolved = guarded.read();
1088
- if (!error.read())
1089
- return resolved;
1090
- }
1091
- return fallback(error.read()._error, () => {
1092
- incrementClock();
1093
- for (let node of nodes) {
1094
- node._state = STATE_DIRTY;
1095
- node._queue?.enqueue(node._type, node);
1096
- }
1097
- });
1098
- });
1099
- return decision.read.bind(decision);
1100
- }
1101
1096
  function resolve(fn) {
1102
1097
  return new Promise((res, rej) => {
1103
1098
  createRoot((dispose) => {
@@ -1150,8 +1145,10 @@ function wrap(source, node, wrapped) {
1150
1145
  // src/store/store.ts
1151
1146
  var $RAW = Symbol("STORE_RAW" );
1152
1147
  var $TRACK = Symbol("STORE_TRACK" );
1148
+ var $DEEP = Symbol("STORE_DEEP" );
1153
1149
  var $TARGET = Symbol("STORE_TARGET" );
1154
1150
  var $PROXY = Symbol("STORE_PROXY" );
1151
+ var PARENTS = /* @__PURE__ */ new WeakMap();
1155
1152
  var STORE_VALUE = "v";
1156
1153
  var STORE_NODE = "n";
1157
1154
  var STORE_HAS = "h";
@@ -1174,11 +1171,11 @@ function wrap2(value) {
1174
1171
  function isWrappable(obj) {
1175
1172
  return obj != null && typeof obj === "object" && !Object.isFrozen(obj);
1176
1173
  }
1177
- function unwrap(item, deep = true, set) {
1174
+ function unwrap(item, deep2 = true, set) {
1178
1175
  let result, unwrapped, v, prop;
1179
1176
  if (result = item != null && item[$RAW])
1180
1177
  return result;
1181
- if (!deep)
1178
+ if (!deep2)
1182
1179
  return item;
1183
1180
  if (!isWrappable(item) || set?.has(item))
1184
1181
  return item;
@@ -1188,11 +1185,11 @@ function unwrap(item, deep = true, set) {
1188
1185
  if (Array.isArray(item)) {
1189
1186
  for (let i = 0, l = item.length; i < l; i++) {
1190
1187
  v = item[i];
1191
- if ((unwrapped = unwrap(v, deep, set)) !== v)
1188
+ if ((unwrapped = unwrap(v, deep2, set)) !== v)
1192
1189
  item[i] = unwrapped;
1193
1190
  }
1194
1191
  } else {
1195
- if (!deep)
1192
+ if (!deep2)
1196
1193
  return item;
1197
1194
  const keys = Object.keys(item);
1198
1195
  for (let i = 0, l = keys.length; i < l; i++) {
@@ -1201,7 +1198,7 @@ function unwrap(item, deep = true, set) {
1201
1198
  if (desc.get)
1202
1199
  continue;
1203
1200
  v = item[prop];
1204
- if ((unwrapped = unwrap(v, deep, set)) !== v)
1201
+ if ((unwrapped = unwrap(v, deep2, set)) !== v)
1205
1202
  item[prop] = unwrapped;
1206
1203
  }
1207
1204
  }
@@ -1234,8 +1231,8 @@ function proxyDescriptor(target, property) {
1234
1231
  desc.get = () => target[STORE_VALUE][$PROXY][property];
1235
1232
  return desc;
1236
1233
  }
1237
- function trackSelf(target) {
1238
- getObserver() && getNode(getNodes(target, STORE_NODE), $TRACK, void 0, false).read();
1234
+ function trackSelf(target, symbol = $TRACK) {
1235
+ getObserver() && getNode(getNodes(target, STORE_NODE), symbol, void 0, false).read();
1239
1236
  }
1240
1237
  function ownKeys(target) {
1241
1238
  trackSelf(target);
@@ -1250,8 +1247,8 @@ var proxyTraps = {
1250
1247
  return target[STORE_VALUE];
1251
1248
  if (property === $PROXY)
1252
1249
  return receiver;
1253
- if (property === $TRACK) {
1254
- trackSelf(target);
1250
+ if (property === $TRACK || property === $DEEP) {
1251
+ trackSelf(target, property);
1255
1252
  return receiver;
1256
1253
  }
1257
1254
  const nodes = getNodes(target, STORE_NODE);
@@ -1272,7 +1269,7 @@ var proxyTraps = {
1272
1269
  let proto;
1273
1270
  return !Array.isArray(storeValue) && (proto = Object.getPrototypeOf(storeValue)) && proto !== Object.prototype ? value.bind(storeValue) : value;
1274
1271
  } else if (getObserver()) {
1275
- value = getNode(nodes, property, isWrappable(value) ? wrap2(value) : value).read();
1272
+ return getNode(nodes, property, isWrappable(value) ? wrap2(value) : value).read();
1276
1273
  }
1277
1274
  }
1278
1275
  return isWrappable(value) ? wrap2(value) : value;
@@ -1307,6 +1304,13 @@ function setProperty(state, property, value, deleting = false) {
1307
1304
  delete state[property];
1308
1305
  else
1309
1306
  state[property] = value;
1307
+ const wrappable = isWrappable(value);
1308
+ if (isWrappable(prev)) {
1309
+ const parents = PARENTS.get(prev);
1310
+ parents && (parents instanceof Set ? parents.delete(state) : PARENTS.delete(prev));
1311
+ }
1312
+ if (recursivelyNotify(state) && wrappable)
1313
+ recursivelyAddParent(value[$RAW] || value, state);
1310
1314
  const target = state[$PROXY]?.[$TARGET];
1311
1315
  if (!target)
1312
1316
  return;
@@ -1315,15 +1319,54 @@ function setProperty(state, property, value, deleting = false) {
1315
1319
  else
1316
1320
  target[STORE_HAS]?.[property]?.write(true);
1317
1321
  const nodes = getNodes(target, STORE_NODE);
1318
- let node;
1319
- if (node = nodes[property])
1320
- node.write(isWrappable(value) ? wrap2(value) : value);
1321
- Array.isArray(state) && state.length !== len && (node = nodes.length) && node.write(state.length);
1322
- (node = nodes[$TRACK]) && node.write(void 0);
1322
+ nodes[property]?.write(wrappable ? wrap2(value) : value);
1323
+ Array.isArray(state) && state.length !== len && nodes.length?.write(state.length);
1324
+ nodes[$TRACK]?.write(void 0);
1325
+ }
1326
+ function recursivelyNotify(state) {
1327
+ let target = state[$PROXY]?.[$TARGET];
1328
+ let notified = false;
1329
+ target && (getNodes(target, STORE_NODE)[$DEEP]?.write(void 0), notified = true);
1330
+ const parents = PARENTS.get(state);
1331
+ if (!parents)
1332
+ return notified;
1333
+ if (parents instanceof Set) {
1334
+ for (let parent of parents)
1335
+ notified = recursivelyNotify(parent) || notified;
1336
+ } else
1337
+ notified = recursivelyNotify(parents) || notified;
1338
+ return notified;
1339
+ }
1340
+ function recursivelyAddParent(state, parent) {
1341
+ if (parent) {
1342
+ let parents = PARENTS.get(state);
1343
+ if (!parents)
1344
+ PARENTS.set(state, parent);
1345
+ else if (parents !== parent) {
1346
+ if (!(parents instanceof Set))
1347
+ PARENTS.set(state, parents = /* @__PURE__ */ new Set([parents]));
1348
+ else if (parents.has(parent))
1349
+ return;
1350
+ parents.add(parent);
1351
+ } else
1352
+ return;
1353
+ }
1354
+ if (Array.isArray(state)) {
1355
+ for (let i = 0; i < state.length; i++) {
1356
+ const item = state[i];
1357
+ isWrappable(item) && recursivelyAddParent(item[$RAW] || item, state);
1358
+ }
1359
+ } else {
1360
+ const keys = Object.keys(state);
1361
+ for (let i = 0; i < keys.length; i++) {
1362
+ const item = state[keys[i]];
1363
+ isWrappable(item) && recursivelyAddParent(item[$RAW] || item, state);
1364
+ }
1365
+ }
1323
1366
  }
1324
1367
  function createStore(first, second) {
1325
1368
  const derived = typeof first === "function", store = derived ? second : first;
1326
- const unwrappedStore = unwrap(store, false);
1369
+ const unwrappedStore = unwrap(store);
1327
1370
  let wrappedStore = wrap2(unwrappedStore);
1328
1371
  const setStore = (fn) => {
1329
1372
  try {
@@ -1337,6 +1380,10 @@ function createStore(first, second) {
1337
1380
  return wrapProjection(first, wrappedStore, setStore);
1338
1381
  return [wrappedStore, setStore];
1339
1382
  }
1383
+ function deep(store) {
1384
+ recursivelyAddParent(store[$RAW] || store);
1385
+ return store[$DEEP];
1386
+ }
1340
1387
 
1341
1388
  // src/store/reconcile.ts
1342
1389
  function applyState(next, state, keyFn) {
@@ -1796,4 +1843,4 @@ function compare(key, a, b) {
1796
1843
  return key ? key(a) === key(b) : true;
1797
1844
  }
1798
1845
 
1799
- export { $PROXY, $RAW, $TARGET, $TRACK, Computation, ContextNotFoundError, NoOwnerError, NotReadyError, Owner, Queue, SUPPORTS_PROXY, catchError, createAsync, createBoundary, createContext, createEffect, createErrorBoundary, createMemo, createProjection, createRenderEffect, createRoot, createSignal, createStore, createSuspense, flatten, flushSync, getContext, getObserver, getOwner, hasContext, hasUpdated, isEqual, isPending, isWrappable, latest, mapArray, merge, omit, onCleanup, reconcile, repeat, resolve, runWithObserver, runWithOwner, setContext, untrack, unwrap };
1846
+ export { $PROXY, $RAW, $TARGET, $TRACK, Computation, ContextNotFoundError, NoOwnerError, NotReadyError, Owner, Queue, SUPPORTS_PROXY, createAsync, createContext, createEffect, createErrorBoundary, createMemo, createProjection, createRenderEffect, createRoot, createSignal, createStore, createSuspense, deep, flatten, flushSync, getContext, getObserver, getOwner, hasContext, hasUpdated, isEqual, isPending, isWrappable, latest, mapArray, merge, omit, onCleanup, reconcile, repeat, resolve, runWithObserver, runWithOwner, setContext, tryCatch, untrack, unwrap };