valdres 1.0.0-beta.13 → 1.0.0-beta.14

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 (2) hide show
  1. package/dist/index.js +141 -67
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1391,6 +1391,24 @@ var propagateDownstreamTopo = (seeds, data, collectedSubscribers, updatedInitial
1391
1391
  }
1392
1392
  const needsEval = new Set(seeds);
1393
1393
  let graphMutated = false;
1394
+ let resweep;
1395
+ const markForResweep = (selector) => {
1396
+ graphMutated = true;
1397
+ if (!resweep)
1398
+ resweep = new Set;
1399
+ const stack = [selector];
1400
+ for (let i = 0;i < stack.length; i++) {
1401
+ const s = stack[i];
1402
+ if (resweep.has(s))
1403
+ continue;
1404
+ resweep.add(s);
1405
+ const downstream = data.stateDependents.get(s);
1406
+ if (downstream) {
1407
+ for (const d of downstream)
1408
+ stack.push(d);
1409
+ }
1410
+ }
1411
+ };
1394
1412
  const advance = (selector, propagateChange) => {
1395
1413
  const downstream = data.stateDependents.get(selector);
1396
1414
  if (!downstream)
@@ -1406,7 +1424,13 @@ var propagateDownstreamTopo = (seeds, data, collectedSubscribers, updatedInitial
1406
1424
  }
1407
1425
  continue;
1408
1426
  }
1409
- const c = (pending.get(d) ?? 0) - 1;
1427
+ const cur = pending.get(d);
1428
+ if (cur === undefined) {
1429
+ if (propagateChange)
1430
+ markForResweep(d);
1431
+ continue;
1432
+ }
1433
+ const c = cur - 1;
1410
1434
  pending.set(d, c);
1411
1435
  if (propagateChange)
1412
1436
  needsEval.add(d);
@@ -1418,12 +1442,18 @@ var propagateDownstreamTopo = (seeds, data, collectedSubscribers, updatedInitial
1418
1442
  let head = 0;
1419
1443
  while (head < ready.length) {
1420
1444
  const selector = ready[head++];
1445
+ if (resweep?.has(selector))
1446
+ continue;
1447
+ if (!pending.has(selector))
1448
+ continue;
1421
1449
  const currentValue = data.values.get(selector);
1422
1450
  if (isPromiseLike(currentValue) && isInitOnly) {
1451
+ pending.delete(selector);
1423
1452
  advance(selector, false);
1424
1453
  continue;
1425
1454
  }
1426
1455
  if (!needsEval.has(selector)) {
1456
+ pending.delete(selector);
1427
1457
  advance(selector, false);
1428
1458
  continue;
1429
1459
  }
@@ -1431,6 +1461,7 @@ var propagateDownstreamTopo = (seeds, data, collectedSubscribers, updatedInitial
1431
1461
  const subscribers = data.subscriptions.get(selector);
1432
1462
  if (!isPromiseLike(currentValue) && (!dependents || dependents.size === 0) && (!subscribers || subscribers.size === 0)) {
1433
1463
  data.values.delete(selector);
1464
+ pending.delete(selector);
1434
1465
  advance(selector, false);
1435
1466
  continue;
1436
1467
  }
@@ -1456,6 +1487,7 @@ var propagateDownstreamTopo = (seeds, data, collectedSubscribers, updatedInitial
1456
1487
  }
1457
1488
  }
1458
1489
  }
1490
+ pending.delete(selector);
1459
1491
  advance(selector, wasValueUpdated);
1460
1492
  if (wasValueUpdated) {
1461
1493
  if (changedSelectors)
@@ -1466,9 +1498,9 @@ var propagateDownstreamTopo = (seeds, data, collectedSubscribers, updatedInitial
1466
1498
  }
1467
1499
  if (!graphMutated)
1468
1500
  return;
1469
- let stranded;
1501
+ let stranded = resweep;
1470
1502
  for (const s of closure) {
1471
- if (needsEval.has(s) && (pending.get(s) ?? 0) > 0) {
1503
+ if (needsEval.has(s) && pending.has(s)) {
1472
1504
  if (!stranded)
1473
1505
  stranded = new Set;
1474
1506
  stranded.add(s);
@@ -1477,50 +1509,81 @@ var propagateDownstreamTopo = (seeds, data, collectedSubscribers, updatedInitial
1477
1509
  if (!stranded)
1478
1510
  return;
1479
1511
  let work = stranded;
1480
- while (work.size > 0) {
1481
- const next = new Set;
1482
- for (const selector of work) {
1483
- const currentValue = data.values.get(selector);
1484
- if (isPromiseLike(currentValue) && isInitOnly)
1485
- continue;
1486
- const dependents = data.stateDependents.get(selector);
1487
- const subscribers = data.subscriptions.get(selector);
1488
- if (!isPromiseLike(currentValue) && (!dependents || dependents.size === 0) && (!subscribers || subscribers.size === 0)) {
1489
- data.values.delete(selector);
1490
- continue;
1491
- }
1492
- depsChange.added = undefined;
1493
- depsChange.removed = undefined;
1494
- const wasValueUpdated = reEvaluateSelector(selector, data, updatedInitializedAtoms, depsChange, currentValue);
1495
- const added = depsChange.added;
1496
- const removed = depsChange.removed;
1497
- if ((added || removed) && isLive(selector, data)) {
1498
- if (added) {
1499
- for (const dep of added) {
1500
- onLiveDependencyAdded(dep, data);
1501
- mountTransitiveDeps(dep, data);
1502
- }
1503
- }
1504
- if (removed) {
1505
- for (const dep of removed) {
1506
- onLiveDependencyRemoved(dep, data);
1507
- unmountOrphanedDeps(dep, data);
1508
- }
1512
+ const hasUnsettledDependency = (selector) => {
1513
+ const deps = data.stateDependencies.get(selector);
1514
+ if (!deps)
1515
+ return false;
1516
+ for (const dep of deps) {
1517
+ if (dep !== selector && work.has(dep))
1518
+ return true;
1519
+ }
1520
+ return false;
1521
+ };
1522
+ const enqueueDownstream = (selector) => {
1523
+ const downstream = data.stateDependents.get(selector);
1524
+ if (!downstream)
1525
+ return;
1526
+ for (const d of downstream) {
1527
+ work.add(d);
1528
+ }
1529
+ };
1530
+ const evaluateStrandedSelector = (selector) => {
1531
+ const currentValue = data.values.get(selector);
1532
+ if (isPromiseLike(currentValue) && isInitOnly)
1533
+ return false;
1534
+ const dependents = data.stateDependents.get(selector);
1535
+ const subscribers = data.subscriptions.get(selector);
1536
+ if (!isPromiseLike(currentValue) && (!dependents || dependents.size === 0) && (!subscribers || subscribers.size === 0)) {
1537
+ data.values.delete(selector);
1538
+ return false;
1539
+ }
1540
+ depsChange.added = undefined;
1541
+ depsChange.removed = undefined;
1542
+ const wasValueUpdated = reEvaluateSelector(selector, data, updatedInitializedAtoms, depsChange, currentValue);
1543
+ const added = depsChange.added;
1544
+ const removed = depsChange.removed;
1545
+ if ((added || removed) && isLive(selector, data)) {
1546
+ if (added) {
1547
+ for (const dep of added) {
1548
+ onLiveDependencyAdded(dep, data);
1549
+ mountTransitiveDeps(dep, data);
1509
1550
  }
1510
1551
  }
1511
- if (wasValueUpdated) {
1512
- if (changedSelectors)
1513
- changedSelectors.add(selector);
1514
- if (subscribers)
1515
- addSetToSet(subscribers, collectedSubscribers);
1516
- const downstream = data.stateDependents.get(selector);
1517
- if (downstream) {
1518
- for (const d of downstream)
1519
- next.add(d);
1552
+ if (removed) {
1553
+ for (const dep of removed) {
1554
+ onLiveDependencyRemoved(dep, data);
1555
+ unmountOrphanedDeps(dep, data);
1520
1556
  }
1521
1557
  }
1522
1558
  }
1523
- work = next;
1559
+ if (wasValueUpdated) {
1560
+ if (changedSelectors)
1561
+ changedSelectors.add(selector);
1562
+ if (subscribers)
1563
+ addSetToSet(subscribers, collectedSubscribers);
1564
+ enqueueDownstream(selector);
1565
+ }
1566
+ return wasValueUpdated;
1567
+ };
1568
+ while (work.size > 0) {
1569
+ let progressed = false;
1570
+ const batch = [...work];
1571
+ for (const selector of batch) {
1572
+ if (!work.has(selector))
1573
+ continue;
1574
+ if (hasUnsettledDependency(selector))
1575
+ continue;
1576
+ work.delete(selector);
1577
+ progressed = true;
1578
+ evaluateStrandedSelector(selector);
1579
+ }
1580
+ if (progressed)
1581
+ continue;
1582
+ const cyclicBatch = [...work];
1583
+ work = new Set;
1584
+ for (const selector of cyclicBatch) {
1585
+ evaluateStrandedSelector(selector);
1586
+ }
1524
1587
  }
1525
1588
  };
1526
1589
  var orderInitialSelectors = (selectors, data) => {
@@ -2156,31 +2219,42 @@ var unsubscribe = (state, subscription, data) => {
2156
2219
  }
2157
2220
  }
2158
2221
  };
2159
- var cleanupOrphanedDeps = (state, data, visited = new Set) => {
2160
- if (visited.has(state))
2161
- return;
2162
- visited.add(state);
2163
- if (isLive(state, data))
2164
- return;
2165
- const deps = data.stateDependencies.get(state);
2166
- if (deps) {
2167
- for (const dep of deps) {
2168
- const depDependents = data.stateDependents.get(dep);
2169
- if (depDependents) {
2170
- depDependents.delete(state);
2222
+ var cleanupOrphanedDeps = (state, data) => {
2223
+ const visited = new Set;
2224
+ const stack = [state];
2225
+ while (stack.length > 0) {
2226
+ const current = stack.pop();
2227
+ if (visited.has(current))
2228
+ continue;
2229
+ visited.add(current);
2230
+ if (isLive(current, data))
2231
+ continue;
2232
+ const dependents = data.stateDependents.get(current);
2233
+ const deps = data.stateDependencies.get(current);
2234
+ if (deps) {
2235
+ for (const dep of deps) {
2236
+ const depDependents = data.stateDependents.get(dep);
2237
+ if (depDependents) {
2238
+ depDependents.delete(current);
2239
+ }
2171
2240
  }
2241
+ data.stateDependencies.delete(current);
2242
+ data.values.delete(current);
2243
+ data.abortControllers.delete(current);
2244
+ if (dependents) {
2245
+ for (const dep of dependents) {
2246
+ stack.push(dep);
2247
+ }
2248
+ }
2249
+ for (const dep of deps) {
2250
+ stack.push(dep);
2251
+ }
2252
+ continue;
2172
2253
  }
2173
- data.stateDependencies.delete(state);
2174
- data.values.delete(state);
2175
- data.abortControllers.delete(state);
2176
- for (const dep of deps) {
2177
- cleanupOrphanedDeps(dep, data, visited);
2178
- }
2179
- }
2180
- const dependents = data.stateDependents.get(state);
2181
- if (dependents) {
2182
- for (const dep of [...dependents]) {
2183
- cleanupOrphanedDeps(dep, data, visited);
2254
+ if (dependents) {
2255
+ for (const dep of dependents) {
2256
+ stack.push(dep);
2257
+ }
2184
2258
  }
2185
2259
  }
2186
2260
  };
@@ -4017,9 +4091,9 @@ var isFamilySelector = (state) => isFamilyState(state) && isSelector(state);
4017
4091
  // src/index.ts
4018
4092
  var slot = valdresGlobal();
4019
4093
  if (slot.version) {
4020
- throw new Error(`Error! An instance of valdres is already loaded. Loaded: ${slot.version}. Attempted to load: ${"1.0.0-beta.13"}`);
4094
+ throw new Error(`Error! An instance of valdres is already loaded. Loaded: ${slot.version}. Attempted to load: ${"1.0.0-beta.14"}`);
4021
4095
  } else {
4022
- slot.version = "1.0.0-beta.13";
4096
+ slot.version = "1.0.0-beta.14";
4023
4097
  }
4024
4098
  export {
4025
4099
  store,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "valdres",
3
3
  "description": "Fast atom-based state management for JavaScript. Inspired by Recoil and Jotai.",
4
- "version": "1.0.0-beta.13",
4
+ "version": "1.0.0-beta.14",
5
5
  "license": "MIT",
6
6
  "author": {
7
7
  "name": "Eigil Sagafos"