@solidjs/signals 0.9.1 → 0.9.2

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
@@ -132,6 +132,7 @@ function adjustHeight(el, heap) {
132
132
  }
133
133
  }
134
134
  const transitions = new Set();
135
+ let optimisticRun = false;
135
136
  const dirtyQueue = { _heap: new Array(2e3).fill(undefined), _marked: false, _min: 0, _max: 0 };
136
137
  const zombieQueue = { _heap: new Array(2e3).fill(undefined), _marked: false, _min: 0, _max: 0 };
137
138
  let clock = 0;
@@ -203,6 +204,7 @@ class Queue {
203
204
  class GlobalQueue extends Queue {
204
205
  _running = false;
205
206
  _pendingNodes = [];
207
+ _optimisticNodes = [];
206
208
  static _update;
207
209
  static _dispose;
208
210
  flush() {
@@ -212,6 +214,7 @@ class GlobalQueue extends Queue {
212
214
  runHeap(dirtyQueue, GlobalQueue._update);
213
215
  if (activeTransition) {
214
216
  if (!transitionComplete(activeTransition)) {
217
+ let t = activeTransition;
215
218
  runHeap(zombieQueue, GlobalQueue._update);
216
219
  this._pendingNodes = [];
217
220
  this.stashQueues(activeTransition.queueStash);
@@ -219,6 +222,7 @@ class GlobalQueue extends Queue {
219
222
  scheduled = false;
220
223
  runTransitionPending(activeTransition.pendingNodes, true);
221
224
  activeTransition = null;
225
+ runOptimistic(t);
222
226
  return;
223
227
  }
224
228
  this._pendingNodes.push(...activeTransition.pendingNodes);
@@ -226,13 +230,8 @@ class GlobalQueue extends Queue {
226
230
  transitions.delete(activeTransition);
227
231
  activeTransition = null;
228
232
  runTransitionPending(this._pendingNodes, false);
229
- dirtyQueue._max >= dirtyQueue._min && runHeap(dirtyQueue, GlobalQueue._update);
230
233
  } else if (transitions.size) runHeap(zombieQueue, GlobalQueue._update);
231
- runPending(this._pendingNodes);
232
- while (dirtyQueue._max >= dirtyQueue._min) {
233
- runHeap(dirtyQueue, GlobalQueue._update);
234
- runPending(this._pendingNodes);
235
- }
234
+ runOptimistic();
236
235
  clock++;
237
236
  scheduled = false;
238
237
  this.run(EFFECT_RENDER);
@@ -260,7 +259,9 @@ class GlobalQueue extends Queue {
260
259
  time: clock,
261
260
  pendingNodes: [],
262
261
  asyncNodes: [],
263
- queueStash: { _queues: [[], []], _children: [] }
262
+ optimisticNodes: [],
263
+ queueStash: { _queues: [[], []], _children: [] },
264
+ done: false
264
265
  };
265
266
  }
266
267
  transitions.add(activeTransition);
@@ -270,9 +271,47 @@ class GlobalQueue extends Queue {
270
271
  n._transition = activeTransition;
271
272
  activeTransition.pendingNodes.push(n);
272
273
  }
274
+ for (let i = 0; i < this._optimisticNodes.length; i++) {
275
+ const n = this._optimisticNodes[i];
276
+ n._transition = activeTransition;
277
+ activeTransition.optimisticNodes.push(n);
278
+ }
273
279
  this._pendingNodes = activeTransition.pendingNodes;
280
+ this._optimisticNodes = activeTransition.optimisticNodes;
281
+ }
282
+ }
283
+ function notifySubs(node) {
284
+ for (let s = node._subs; s !== null; s = s._nextSub) {
285
+ const queue = s._sub._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue;
286
+ if (queue._min > s._sub._height) queue._min = s._sub._height;
287
+ insertIntoHeap(s._sub, queue);
274
288
  }
275
289
  }
290
+ function runOptimistic(activeTransition = null) {
291
+ let resolvePending = !activeTransition;
292
+ const optimisticNodes = globalQueue._optimisticNodes;
293
+ optimisticRun = true;
294
+ for (let i = 0; i < optimisticNodes.length; i++) {
295
+ const n = optimisticNodes[i];
296
+ if (
297
+ !activeTransition &&
298
+ (!n._transition || n._transition.done) &&
299
+ n._pendingValue !== NOT_PENDING
300
+ ) {
301
+ n._value = n._pendingValue;
302
+ n._pendingValue = NOT_PENDING;
303
+ }
304
+ n._transition = activeTransition;
305
+ notifySubs(n);
306
+ }
307
+ globalQueue._optimisticNodes = [];
308
+ if (dirtyQueue._max >= dirtyQueue._min) {
309
+ resolvePending = true;
310
+ runHeap(dirtyQueue, GlobalQueue._update);
311
+ }
312
+ optimisticRun = false;
313
+ resolvePending && runPending(globalQueue._pendingNodes);
314
+ }
276
315
  function runPending(pendingNodes) {
277
316
  for (let i = 0; i < pendingNodes.length; i++) {
278
317
  const n = pendingNodes[i];
@@ -281,8 +320,6 @@ function runPending(pendingNodes) {
281
320
  n._pendingValue = NOT_PENDING;
282
321
  if (n._type) n._modified = true;
283
322
  }
284
- if (n._pendingSignal && n._pendingSignal._pendingValue !== NOT_PENDING)
285
- n._pendingSignal._set(n._pendingSignal._pendingValue);
286
323
  if (n._fn) GlobalQueue._dispose(n, false, true);
287
324
  }
288
325
  pendingNodes.length = 0;
@@ -293,10 +330,6 @@ function runTransitionPending(pendingNodes, value) {
293
330
  const n = p[i];
294
331
  n._transition = activeTransition;
295
332
  if (n._pendingCheck) n._pendingCheck._set(value);
296
- if (n._pendingSignal && n._pendingSignal._pendingValue !== NOT_PENDING) {
297
- n._pendingSignal._set(n._pendingSignal._pendingValue);
298
- n._pendingSignal._pendingValue = NOT_PENDING;
299
- }
300
333
  }
301
334
  }
302
335
  const globalQueue = new GlobalQueue();
@@ -311,6 +344,7 @@ function runQueue(queue, type) {
311
344
  for (let i = 0; i < queue.length; i++) queue[i](type);
312
345
  }
313
346
  function transitionComplete(transition) {
347
+ if (transition.done) return true;
314
348
  let done = true;
315
349
  for (let i = 0; i < transition.asyncNodes.length; i++) {
316
350
  if (transition.asyncNodes[i]._statusFlags & STATUS_PENDING) {
@@ -318,6 +352,7 @@ function transitionComplete(transition) {
318
352
  break;
319
353
  }
320
354
  }
355
+ done && (transition.done = true);
321
356
  return done;
322
357
  }
323
358
  function runInTransition(el, recompute) {
@@ -334,13 +369,6 @@ let pendingValueCheck = false;
334
369
  let pendingCheck = null;
335
370
  let refreshing = false;
336
371
  let context = null;
337
- function notifySubs(node) {
338
- for (let s = node._subs; s !== null; s = s._nextSub) {
339
- const queue = s._sub._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue;
340
- if (queue._min > s._sub._height) queue._min = s._sub._height;
341
- insertIntoHeap(s._sub, queue);
342
- }
343
- }
344
372
  function recompute(el, create = false) {
345
373
  const honoraryOptimistic = el._type && el._transition != activeTransition;
346
374
  if (!create) {
@@ -361,7 +389,10 @@ function recompute(el, create = false) {
361
389
  el._depsTail = null;
362
390
  el._flags = REACTIVE_RECOMPUTING_DEPS;
363
391
  el._time = clock;
364
- let value = el._pendingValue === NOT_PENDING ? el._value : el._pendingValue;
392
+ let value =
393
+ el._pendingValue === NOT_PENDING || (el._optimistic && el._transition)
394
+ ? el._value
395
+ : el._pendingValue;
365
396
  let oldHeight = el._height;
366
397
  let prevStatusFlags = el._statusFlags;
367
398
  let prevError = el._error;
@@ -406,21 +437,19 @@ function recompute(el, create = false) {
406
437
  if (valueChanged) {
407
438
  if (create || el._optimistic || honoraryOptimistic) el._value = value;
408
439
  else el._pendingValue = value;
409
- if (el._pendingSignal) el._pendingSignal._pendingValue = value;
410
- }
411
- for (let s = el._subs; s !== null; s = s._nextSub) {
412
- const queue = s._sub._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue;
413
- if (s._sub._height < el._height && queue._min > s._sub._height) queue._min = s._sub._height;
414
- insertIntoHeap(s._sub, queue);
440
+ if (el._pendingSignal) setSignal(el._pendingSignal, value);
415
441
  }
442
+ (!el._optimistic || optimisticRun) && notifySubs(el);
416
443
  } else if (el._height != oldHeight) {
417
444
  for (let s = el._subs; s !== null; s = s._nextSub) {
418
445
  insertIntoHeapHeight(s._sub, s._sub._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
419
446
  }
420
447
  }
421
- if ((!create || el._statusFlags & STATUS_PENDING) && !el._optimistic && !el._transition)
448
+ el._optimistic && !optimisticRun && globalQueue._optimisticNodes.push(el);
449
+ (!create || el._statusFlags & STATUS_PENDING) &&
450
+ !el._transition &&
422
451
  globalQueue._pendingNodes.push(el);
423
- if (el._transition && honoraryOptimistic) runInTransition(el, recompute);
452
+ el._transition && honoraryOptimistic && runInTransition(el, recompute);
424
453
  }
425
454
  function handleAsync(el, result, setter) {
426
455
  const isObject = typeof result === "object" && result !== null;
@@ -671,7 +700,7 @@ function computed(fn, initialValue, options) {
671
700
  }
672
701
  }
673
702
  if (parent) self._height = parent._height + 1;
674
- recompute(self, true);
703
+ !options?.lazy && recompute(self, true);
675
704
  return self;
676
705
  }
677
706
  function signal(v, options, firewall = null) {
@@ -741,7 +770,6 @@ function read(el) {
741
770
  if (!el._pendingSignal) {
742
771
  el._pendingSignal = signal(el._value);
743
772
  el._pendingSignal._optimistic = true;
744
- el._pendingSignal._set = v => setSignal(el._pendingSignal, v);
745
773
  }
746
774
  pendingValueCheck = false;
747
775
  try {
@@ -767,7 +795,9 @@ function read(el) {
767
795
  return !c ||
768
796
  el._optimistic ||
769
797
  el._pendingValue === NOT_PENDING ||
770
- (stale && !pendingCheck && el._transition && activeTransition !== el._transition)
798
+ (stale &&
799
+ !pendingCheck &&
800
+ (c._optimistic || (el._transition && activeTransition !== el._transition)))
771
801
  ? el._value
772
802
  : el._pendingValue;
773
803
  }
@@ -775,7 +805,11 @@ function setSignal(el, v) {
775
805
  if (!el._pureWrite && context && el._firewall !== context)
776
806
  console.warn("A Signal was written to in an owned scope.");
777
807
  if (typeof v === "function") {
778
- v = v(el._pendingValue === NOT_PENDING ? el._value : el._pendingValue);
808
+ v = v(
809
+ el._pendingValue === NOT_PENDING || (el._optimistic && el._transition)
810
+ ? el._value
811
+ : el._pendingValue
812
+ );
779
813
  }
780
814
  const valueChanged =
781
815
  !el._equals ||
@@ -790,11 +824,11 @@ function setSignal(el, v) {
790
824
  if (el._pendingValue === NOT_PENDING) globalQueue._pendingNodes.push(el);
791
825
  el._pendingValue = v;
792
826
  }
793
- if (el._pendingSignal) el._pendingSignal._pendingValue = v;
827
+ if (el._pendingSignal) setSignal(el._pendingSignal, v);
794
828
  }
795
829
  setStatusFlags(el, STATUS_NONE);
796
830
  el._time = clock;
797
- notifySubs(el);
831
+ el._optimistic && !optimisticRun ? globalQueue._optimisticNodes.push(el) : notifySubs(el);
798
832
  schedule();
799
833
  return v;
800
834
  }
@@ -1064,7 +1098,30 @@ function resolve(fn) {
1064
1098
  });
1065
1099
  }
1066
1100
  function createOptimistic(first, second, third) {
1067
- return {};
1101
+ if (typeof first === "function") {
1102
+ const node = computed(
1103
+ prev => {
1104
+ let n = node || getOwner();
1105
+ n._pendingValue = first(prev);
1106
+ return prev;
1107
+ },
1108
+ second,
1109
+ third
1110
+ );
1111
+ node._optimistic = true;
1112
+ return [read.bind(null, node), setSignal.bind(null, node)];
1113
+ }
1114
+ const o = getOwner();
1115
+ const needsId = o?.id != null;
1116
+ const node = signal(first, needsId ? { id: getNextChildId(o), ...second } : second);
1117
+ node._optimistic = true;
1118
+ return [
1119
+ read.bind(null, node),
1120
+ v => {
1121
+ node._pendingValue = first;
1122
+ return setSignal(node, v);
1123
+ }
1124
+ ];
1068
1125
  }
1069
1126
  function onSettled(callback) {
1070
1127
  let cleanup;