@solidjs/signals 0.13.4 → 0.13.5

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
@@ -1016,16 +1016,8 @@ function getObserver() {
1016
1016
  function getOwner() {
1017
1017
  return context;
1018
1018
  }
1019
- function onCleanup(fn) {
1020
- if (!context) {
1021
- console.warn("onCleanup called outside a reactive context will never be run");
1022
- return fn;
1023
- }
1024
- if (context._childrenForbidden) {
1025
- throw new Error(
1026
- "Cannot use onCleanup inside createTrackedEffect or onSettled; return a cleanup function instead"
1027
- );
1028
- }
1019
+ function cleanup(fn) {
1020
+ if (!context) return fn;
1029
1021
  if (!context._disposal) context._disposal = fn;
1030
1022
  else if (Array.isArray(context._disposal)) context._disposal.push(fn);
1031
1023
  else context._disposal = [context._disposal, fn];
@@ -1398,7 +1390,7 @@ function computed(fn, initialValue, options) {
1398
1390
  const source = externalSourceConfig.factory(self._fn, () => {
1399
1391
  setSignal(bridgeSignal, undefined);
1400
1392
  });
1401
- onCleanup(() => source.dispose());
1393
+ cleanup(() => source.dispose());
1402
1394
  self._fn = prev => {
1403
1395
  read(bridgeSignal);
1404
1396
  return source.track(prev);
@@ -1504,8 +1496,17 @@ function read(el) {
1504
1496
  const firewall = el._firewall;
1505
1497
  const prevCheck = pendingCheckActive;
1506
1498
  pendingCheckActive = false;
1507
- if (read(getPendingSignal(el))) foundPending = true;
1508
- if (firewall && read(getPendingSignal(firewall))) foundPending = true;
1499
+ if (firewall && el._overrideValue !== undefined) {
1500
+ if (
1501
+ el._overrideValue !== NOT_PENDING &&
1502
+ (firewall._inFlight || !!(firewall._statusFlags & STATUS_PENDING))
1503
+ ) {
1504
+ foundPending = true;
1505
+ }
1506
+ } else {
1507
+ if (read(getPendingSignal(el))) foundPending = true;
1508
+ if (firewall && read(getPendingSignal(firewall))) foundPending = true;
1509
+ }
1509
1510
  pendingCheckActive = prevCheck;
1510
1511
  return el._value;
1511
1512
  }
@@ -1686,6 +1687,9 @@ function computePendingState(el) {
1686
1687
  }
1687
1688
  return true;
1688
1689
  }
1690
+ if (el._overrideValue !== undefined && el._overrideValue === NOT_PENDING && !el._parentSource) {
1691
+ return false;
1692
+ }
1689
1693
  if (el._pendingValue !== NOT_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED)) return true;
1690
1694
  return !!(comp._statusFlags & STATUS_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED));
1691
1695
  }
@@ -1857,7 +1861,7 @@ function effect(compute, effect, error, initialValue, options) {
1857
1861
  ? node._queue.enqueue(node._type, runEffect.bind(node))
1858
1862
  : runEffect.call(node));
1859
1863
  initialized = true;
1860
- onCleanup(() => node._cleanup?.());
1864
+ cleanup(() => node._cleanup?.());
1861
1865
  if (!node._parent)
1862
1866
  console.warn("Effects created outside a reactive context will never be disposed");
1863
1867
  }
@@ -1910,7 +1914,7 @@ function trackedEffect(fn, options) {
1910
1914
  };
1911
1915
  node._run = run;
1912
1916
  node._queue.enqueue(EFFECT_USER, run);
1913
- onCleanup(() => node._cleanup?.());
1917
+ cleanup(() => node._cleanup?.());
1914
1918
  if (!node._parent)
1915
1919
  console.warn("Effects created outside a reactive context will never be disposed");
1916
1920
  }
@@ -1958,6 +1962,17 @@ function action(genFn) {
1958
1962
  step();
1959
1963
  });
1960
1964
  }
1965
+ function onCleanup(fn) {
1966
+ {
1967
+ const owner = getOwner();
1968
+ if (!owner) console.warn("onCleanup called outside a reactive context will never be run");
1969
+ else if (owner._childrenForbidden)
1970
+ throw new Error(
1971
+ "Cannot use onCleanup inside createTrackedEffect or onSettled; return a cleanup function instead"
1972
+ );
1973
+ }
1974
+ return cleanup(fn);
1975
+ }
1961
1976
  function accessor(node) {
1962
1977
  const fn = read.bind(null, node);
1963
1978
  fn.$r = true;
@@ -1991,16 +2006,16 @@ function createTrackedEffect(compute, options) {
1991
2006
  trackedEffect(compute, { ...options, name: options?.name ?? "trackedEffect" });
1992
2007
  }
1993
2008
  function createReaction(effectFn, options) {
1994
- let cleanup = undefined;
1995
- onCleanup(() => cleanup?.());
2009
+ let cl = undefined;
2010
+ cleanup(() => cl?.());
1996
2011
  const owner = getOwner();
1997
2012
  return tracking => {
1998
2013
  runWithOwner(owner, () => {
1999
2014
  effect(
2000
2015
  () => (tracking(), getOwner()),
2001
2016
  node => {
2002
- cleanup?.();
2003
- cleanup = (effectFn.effect || effectFn)?.();
2017
+ cl?.();
2018
+ cl = (effectFn.effect || effectFn)?.();
2004
2019
  dispose(node);
2005
2020
  },
2006
2021
  effectFn.error,
@@ -2214,8 +2229,16 @@ function createProjectionInternal(fn, initialValue = {}, options) {
2214
2229
  const wrappedStore = wrapProjection(initialValue);
2215
2230
  node = computed(() => {
2216
2231
  const owner = getOwner();
2217
- storeSetter(new Proxy(wrappedStore, writeTraps), s => {
2218
- const value = handleAsync(owner, fn(s), value => {
2232
+ let settled = false;
2233
+ let result;
2234
+ const draft = new Proxy(
2235
+ wrappedStore,
2236
+ createWriteTraps(() => !settled || owner._inFlight === result)
2237
+ );
2238
+ storeSetter(draft, s => {
2239
+ result = fn(s);
2240
+ settled = true;
2241
+ const value = handleAsync(owner, result, value => {
2219
2242
  value !== s &&
2220
2243
  value !== undefined &&
2221
2244
  storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
@@ -2229,42 +2252,47 @@ function createProjectionInternal(fn, initialValue = {}, options) {
2229
2252
  function createProjection(fn, initialValue = {}, options) {
2230
2253
  return createProjectionInternal(fn, initialValue, options).store;
2231
2254
  }
2232
- const writeTraps = {
2233
- get(_, prop) {
2234
- let value;
2235
- setWriteOverride(true);
2236
- setProjectionWriteActive(true);
2237
- try {
2238
- value = _[prop];
2239
- } finally {
2240
- setWriteOverride(false);
2241
- setProjectionWriteActive(false);
2242
- }
2243
- return typeof value === "object" && value !== null ? new Proxy(value, writeTraps) : value;
2244
- },
2245
- set(_, prop, value) {
2246
- setWriteOverride(true);
2247
- setProjectionWriteActive(true);
2248
- try {
2249
- _[prop] = value;
2250
- } finally {
2251
- setWriteOverride(false);
2252
- setProjectionWriteActive(false);
2253
- }
2254
- return true;
2255
- },
2256
- deleteProperty(_, prop) {
2257
- setWriteOverride(true);
2258
- setProjectionWriteActive(true);
2259
- try {
2260
- delete _[prop];
2261
- } finally {
2262
- setWriteOverride(false);
2263
- setProjectionWriteActive(false);
2255
+ function createWriteTraps(isActive) {
2256
+ const traps = {
2257
+ get(_, prop) {
2258
+ let value;
2259
+ setWriteOverride(true);
2260
+ setProjectionWriteActive(true);
2261
+ try {
2262
+ value = _[prop];
2263
+ } finally {
2264
+ setWriteOverride(false);
2265
+ setProjectionWriteActive(false);
2266
+ }
2267
+ return typeof value === "object" && value !== null ? new Proxy(value, traps) : value;
2268
+ },
2269
+ set(_, prop, value) {
2270
+ if (isActive && !isActive()) return true;
2271
+ setWriteOverride(true);
2272
+ setProjectionWriteActive(true);
2273
+ try {
2274
+ _[prop] = value;
2275
+ } finally {
2276
+ setWriteOverride(false);
2277
+ setProjectionWriteActive(false);
2278
+ }
2279
+ return true;
2280
+ },
2281
+ deleteProperty(_, prop) {
2282
+ if (isActive && !isActive()) return true;
2283
+ setWriteOverride(true);
2284
+ setProjectionWriteActive(true);
2285
+ try {
2286
+ delete _[prop];
2287
+ } finally {
2288
+ setWriteOverride(false);
2289
+ setProjectionWriteActive(false);
2290
+ }
2291
+ return true;
2264
2292
  }
2265
- return true;
2266
- }
2267
- };
2293
+ };
2294
+ return traps;
2295
+ }
2268
2296
  const $TRACK = Symbol("STORE_TRACK"),
2269
2297
  $TARGET = Symbol("STORE_TARGET"),
2270
2298
  $PROXY = Symbol("STORE_PROXY"),
@@ -2674,10 +2702,18 @@ function createOptimisticProjectionInternal(fn, initialValue = {}, options) {
2674
2702
  if (fn) {
2675
2703
  node = computed(() => {
2676
2704
  const owner = getOwner();
2705
+ let settled = false;
2706
+ let result;
2707
+ const draft = new Proxy(
2708
+ wrappedStore,
2709
+ createWriteTraps(() => !settled || owner._inFlight === result)
2710
+ );
2677
2711
  setProjectionWriteActive(true);
2678
2712
  try {
2679
- storeSetter(new Proxy(wrappedStore, writeTraps), s => {
2680
- const value = handleAsync(owner, fn(s), value => {
2713
+ storeSetter(draft, s => {
2714
+ result = fn(s);
2715
+ settled = true;
2716
+ const value = handleAsync(owner, result, value => {
2681
2717
  setProjectionWriteActive(true);
2682
2718
  try {
2683
2719
  value !== s &&
@@ -3202,7 +3238,7 @@ function boundaryComputed(fn, propagationMask) {
3202
3238
  function createBoundChildren(owner, fn, queue, mask) {
3203
3239
  const parentQueue = owner._queue;
3204
3240
  parentQueue.addChild((owner._queue = queue));
3205
- onCleanup(() => parentQueue.removeChild(owner._queue));
3241
+ cleanup(() => parentQueue.removeChild(owner._queue));
3206
3242
  return runWithOwner(owner, () => {
3207
3243
  const c = computed(fn);
3208
3244
  return boundaryComputed(() => staleValues(() => flatten(read(c))), mask);