@fictjs/runtime 0.0.11 → 0.0.12

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/index.d.cts CHANGED
@@ -1431,6 +1431,10 @@ declare const UnitlessStyles: Set<string>;
1431
1431
  * @param a - The old array of nodes (currently in DOM)
1432
1432
  * @param b - The new array of nodes (target state)
1433
1433
  *
1434
+ * **Note:** This function may mutate the input array `a` during the swap
1435
+ * optimization (step 5a). If you need to preserve the original array,
1436
+ * pass a shallow copy: `reconcileArrays(parent, [...oldNodes], newNodes)`.
1437
+ *
1434
1438
  * @example
1435
1439
  * ```ts
1436
1440
  * const oldNodes = [node1, node2, node3]
package/dist/index.d.ts CHANGED
@@ -1431,6 +1431,10 @@ declare const UnitlessStyles: Set<string>;
1431
1431
  * @param a - The old array of nodes (currently in DOM)
1432
1432
  * @param b - The new array of nodes (target state)
1433
1433
  *
1434
+ * **Note:** This function may mutate the input array `a` during the swap
1435
+ * optimization (step 5a). If you need to preserve the original array,
1436
+ * pass a shallow copy: `reconcileArrays(parent, [...oldNodes], newNodes)`.
1437
+ *
1434
1438
  * @example
1435
1439
  * ```ts
1436
1440
  * const oldNodes = [node1, node2, node3]
package/dist/index.dev.js CHANGED
@@ -301,7 +301,7 @@ function handleError(err, info, startRoot) {
301
301
  }
302
302
  }
303
303
  }
304
- throw error;
304
+ return false;
305
305
  }
306
306
  function handleSuspend(token, startRoot) {
307
307
  let root = startRoot ?? currentRoot;
@@ -349,6 +349,10 @@ var enqueueMicrotask = typeof queueMicrotask === "function" ? queueMicrotask : (
349
349
  Promise.resolve().then(fn);
350
350
  };
351
351
  var inCleanup = false;
352
+ var SIGNAL_MARKER = Symbol.for("fict:signal");
353
+ var COMPUTED_MARKER = Symbol.for("fict:computed");
354
+ var EFFECT_MARKER = Symbol.for("fict:effect");
355
+ var EFFECT_SCOPE_MARKER = Symbol.for("fict:effectScope");
352
356
  function link(dep, sub, version) {
353
357
  const prevDep = sub.depsTail;
354
358
  if (prevDep !== void 0 && prevDep.dep === dep) return;
@@ -472,13 +476,21 @@ function checkDirty(firstLink, sub) {
472
476
  dirty = true;
473
477
  }
474
478
  } else if ((depFlags & MutablePending) === MutablePending) {
475
- if (link2.nextSub !== void 0 || link2.prevSub !== void 0) {
476
- stack = { value: link2, prev: stack };
479
+ if (!dep.deps) {
480
+ const nextDep = link2.nextDep;
481
+ if (nextDep !== void 0) {
482
+ link2 = nextDep;
483
+ continue;
484
+ }
485
+ } else {
486
+ if (link2.nextSub !== void 0 || link2.prevSub !== void 0) {
487
+ stack = { value: link2, prev: stack };
488
+ }
489
+ link2 = dep.deps;
490
+ sub = dep;
491
+ ++checkDepth;
492
+ continue;
477
493
  }
478
- link2 = dep.deps;
479
- sub = dep;
480
- ++checkDepth;
481
- continue;
482
494
  }
483
495
  if (!dirty) {
484
496
  const nextDep = link2.nextDep;
@@ -556,8 +568,12 @@ function disposeNode(node) {
556
568
  node.depsTail = void 0;
557
569
  node.flags = 0;
558
570
  purgeDeps(node);
559
- const sub = node.subs;
560
- if (sub !== void 0) unlink(sub, node);
571
+ let sub = node.subs;
572
+ while (sub !== void 0) {
573
+ const next = sub.nextSub;
574
+ unlink(sub);
575
+ sub = next;
576
+ }
561
577
  }
562
578
  function updateSignal(s) {
563
579
  s.flags = Mutable;
@@ -726,7 +742,9 @@ function signal(initialValue) {
726
742
  __id: void 0
727
743
  };
728
744
  registerSignalDevtools(initialValue, s);
729
- return signalOper.bind(s);
745
+ const accessor = signalOper.bind(s);
746
+ accessor[SIGNAL_MARKER] = true;
747
+ return accessor;
730
748
  }
731
749
  function signalOper(value) {
732
750
  if (arguments.length > 0) {
@@ -771,6 +789,7 @@ function computed(getter) {
771
789
  getter
772
790
  };
773
791
  const bound = computedOper.bind(c);
792
+ bound[COMPUTED_MARKER] = true;
774
793
  return bound;
775
794
  }
776
795
  function computedOper() {
@@ -823,7 +842,9 @@ function effect(fn) {
823
842
  activeSub = prevSub;
824
843
  e.flags &= ~Running;
825
844
  }
826
- return effectOper.bind(e);
845
+ const disposer = effectOper.bind(e);
846
+ disposer[EFFECT_MARKER] = true;
847
+ return disposer;
827
848
  }
828
849
  function effectWithCleanup(fn, cleanupRunner) {
829
850
  const e = {
@@ -847,7 +868,9 @@ function effectWithCleanup(fn, cleanupRunner) {
847
868
  activeSub = prevSub;
848
869
  e.flags &= ~Running;
849
870
  }
850
- return effectOper.bind(e);
871
+ const disposer = effectOper.bind(e);
872
+ disposer[EFFECT_MARKER] = true;
873
+ return disposer;
851
874
  }
852
875
  function effectOper() {
853
876
  disposeNode(this);
@@ -862,7 +885,9 @@ function effectScope(fn) {
862
885
  } finally {
863
886
  activeSub = prevSub;
864
887
  }
865
- return effectScopeOper.bind(e);
888
+ const disposer = effectScopeOper.bind(e);
889
+ disposer[EFFECT_SCOPE_MARKER] = true;
890
+ return disposer;
866
891
  }
867
892
  function effectScopeOper() {
868
893
  disposeNode(this);
@@ -1681,9 +1706,6 @@ function mergeProps(...sources) {
1681
1706
  };
1682
1707
  return new Proxy({}, {
1683
1708
  get(_, prop) {
1684
- if (typeof prop === "symbol") {
1685
- return void 0;
1686
- }
1687
1709
  for (let i = validSources.length - 1; i >= 0; i--) {
1688
1710
  const src = validSources[i];
1689
1711
  const raw = resolveSource(src);
@@ -1756,8 +1778,8 @@ function startTransition(fn) {
1756
1778
  function useTransition() {
1757
1779
  const pending = signal(false);
1758
1780
  const start = (fn) => {
1759
- pending(true);
1760
1781
  startTransition(() => {
1782
+ pending(true);
1761
1783
  try {
1762
1784
  fn();
1763
1785
  } finally {
@@ -1792,6 +1814,7 @@ function untrack2(fn) {
1792
1814
  // src/dom.ts
1793
1815
  var SVG_NS = "http://www.w3.org/2000/svg";
1794
1816
  var MATHML_NS = "http://www.w3.org/1998/Math/MathML";
1817
+ var isDev = true ? true : typeof process === "undefined" || process.env?.NODE_ENV !== "production";
1795
1818
  function render(view, container) {
1796
1819
  const root = createRootContext();
1797
1820
  const prev = pushRoot(root);
@@ -2002,18 +2025,28 @@ function applyRef(el, value) {
2002
2025
  if (typeof value === "function") {
2003
2026
  const refFn = value;
2004
2027
  refFn(el);
2005
- if (getCurrentRoot()) {
2028
+ const root = getCurrentRoot();
2029
+ if (root) {
2006
2030
  registerRootCleanup(() => {
2007
2031
  refFn(null);
2008
2032
  });
2033
+ } else if (isDev) {
2034
+ console.warn(
2035
+ "[fict] Ref applied outside of a root context. The ref cleanup (setting to null) will not run automatically. Consider using createRoot() or ensure the element is created within a component."
2036
+ );
2009
2037
  }
2010
2038
  } else if (value && typeof value === "object" && "current" in value) {
2011
2039
  const refObj = value;
2012
2040
  refObj.current = el;
2013
- if (getCurrentRoot()) {
2041
+ const root = getCurrentRoot();
2042
+ if (root) {
2014
2043
  registerRootCleanup(() => {
2015
2044
  refObj.current = null;
2016
2045
  });
2046
+ } else if (isDev) {
2047
+ console.warn(
2048
+ "[fict] Ref applied outside of a root context. The ref cleanup (setting to null) will not run automatically. Consider using createRoot() or ensure the element is created within a component."
2049
+ );
2017
2050
  }
2018
2051
  }
2019
2052
  }
@@ -2427,6 +2460,7 @@ function reconcileArrays(parentNode, a, b) {
2427
2460
  }
2428
2461
 
2429
2462
  // src/list-helpers.ts
2463
+ var isDev2 = true ? true : typeof process === "undefined" || process.env?.NODE_ENV !== "production";
2430
2464
  function moveNodesBefore(parent, nodes, anchor) {
2431
2465
  for (let i = nodes.length - 1; i >= 0; i--) {
2432
2466
  const node = nodes[i];
@@ -2488,6 +2522,7 @@ function removeBlockRange(block) {
2488
2522
  cursor = next;
2489
2523
  }
2490
2524
  }
2525
+ var MAX_SAFE_VERSION = 9007199254740991;
2491
2526
  function createVersionedSignalAccessor(initialValue) {
2492
2527
  let current = initialValue;
2493
2528
  let version = 0;
@@ -2498,7 +2533,7 @@ function createVersionedSignalAccessor(initialValue) {
2498
2533
  return current;
2499
2534
  }
2500
2535
  current = value;
2501
- version++;
2536
+ version = version >= MAX_SAFE_VERSION ? 1 : version + 1;
2502
2537
  track2(version);
2503
2538
  }
2504
2539
  return accessor;
@@ -2554,15 +2589,21 @@ function createKeyedBlock(key, item, index, render2, needsIndex = true, hostRoot
2554
2589
  });
2555
2590
  const root = createRootContext(hostRoot);
2556
2591
  const prevRoot = pushRoot(root);
2557
- const prevSub = setActiveSub(void 0);
2558
2592
  let nodes = [];
2593
+ let scopeDispose;
2594
+ const prevSub = setActiveSub(void 0);
2559
2595
  try {
2560
- const rendered = render2(itemSig, indexSig, key);
2561
- if (rendered instanceof Node || Array.isArray(rendered) && rendered.every((n) => n instanceof Node)) {
2562
- nodes = toNodeArray(rendered);
2563
- } else {
2564
- const element = createElement(rendered);
2565
- nodes = toNodeArray(element);
2596
+ scopeDispose = effectScope(() => {
2597
+ const rendered = render2(itemSig, indexSig, key);
2598
+ if (rendered instanceof Node || Array.isArray(rendered) && rendered.every((n) => n instanceof Node)) {
2599
+ nodes = toNodeArray(rendered);
2600
+ } else {
2601
+ const element = createElement(rendered);
2602
+ nodes = toNodeArray(element);
2603
+ }
2604
+ });
2605
+ if (scopeDispose) {
2606
+ root.cleanups.push(scopeDispose);
2566
2607
  }
2567
2608
  } finally {
2568
2609
  setActiveSub(prevSub);
@@ -2589,6 +2630,86 @@ function isNodeBetweenMarkers(node, startMarker, endMarker) {
2589
2630
  }
2590
2631
  return false;
2591
2632
  }
2633
+ function reorderBySwap(parent, first, second) {
2634
+ if (first === second) return false;
2635
+ const firstNodes = first.nodes;
2636
+ const secondNodes = second.nodes;
2637
+ if (firstNodes.length === 0 || secondNodes.length === 0) return false;
2638
+ const lastFirst = firstNodes[firstNodes.length - 1];
2639
+ const lastSecond = secondNodes[secondNodes.length - 1];
2640
+ const afterFirst = lastFirst.nextSibling;
2641
+ const afterSecond = lastSecond.nextSibling;
2642
+ moveNodesBefore(parent, firstNodes, afterSecond);
2643
+ moveNodesBefore(parent, secondNodes, afterFirst);
2644
+ return true;
2645
+ }
2646
+ function getLISIndices(sequence) {
2647
+ const predecessors = new Array(sequence.length);
2648
+ const result = [];
2649
+ for (let i = 0; i < sequence.length; i++) {
2650
+ const value = sequence[i];
2651
+ if (value < 0) {
2652
+ predecessors[i] = -1;
2653
+ continue;
2654
+ }
2655
+ let low = 0;
2656
+ let high = result.length;
2657
+ while (low < high) {
2658
+ const mid = low + high >> 1;
2659
+ if (sequence[result[mid]] < value) {
2660
+ low = mid + 1;
2661
+ } else {
2662
+ high = mid;
2663
+ }
2664
+ }
2665
+ predecessors[i] = low > 0 ? result[low - 1] : -1;
2666
+ if (low === result.length) {
2667
+ result.push(i);
2668
+ } else {
2669
+ result[low] = i;
2670
+ }
2671
+ }
2672
+ const lis = new Array(result.length);
2673
+ let k = result.length > 0 ? result[result.length - 1] : -1;
2674
+ for (let i = result.length - 1; i >= 0; i--) {
2675
+ lis[i] = k;
2676
+ k = predecessors[k];
2677
+ }
2678
+ return lis;
2679
+ }
2680
+ function reorderByLIS(parent, endMarker, prev, next) {
2681
+ const positions = /* @__PURE__ */ new Map();
2682
+ for (let i = 0; i < prev.length; i++) {
2683
+ positions.set(prev[i], i);
2684
+ }
2685
+ const sequence = new Array(next.length);
2686
+ for (let i = 0; i < next.length; i++) {
2687
+ const position = positions.get(next[i]);
2688
+ if (position === void 0) return false;
2689
+ sequence[i] = position;
2690
+ }
2691
+ const lisIndices = getLISIndices(sequence);
2692
+ if (lisIndices.length === sequence.length) return true;
2693
+ const inLIS = new Array(sequence.length).fill(false);
2694
+ for (let i = 0; i < lisIndices.length; i++) {
2695
+ inLIS[lisIndices[i]] = true;
2696
+ }
2697
+ let anchor = endMarker;
2698
+ let moved = false;
2699
+ for (let i = next.length - 1; i >= 0; i--) {
2700
+ const block = next[i];
2701
+ const nodes = block.nodes;
2702
+ if (nodes.length === 0) continue;
2703
+ if (inLIS[i]) {
2704
+ anchor = nodes[0];
2705
+ continue;
2706
+ }
2707
+ moveNodesBefore(parent, nodes, anchor);
2708
+ anchor = nodes[0];
2709
+ moved = true;
2710
+ }
2711
+ return moved;
2712
+ }
2592
2713
  function createKeyedList(getItems, keyFn, renderItem, needsIndex) {
2593
2714
  const resolvedNeedsIndex = arguments.length >= 4 ? !!needsIndex : renderItem.length > 1;
2594
2715
  return createFineGrainedKeyedList(getItems, keyFn, renderItem, resolvedNeedsIndex);
@@ -2621,10 +2742,6 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
2621
2742
  const prevOrderedBlocks = container.orderedBlocks;
2622
2743
  const nextOrderedBlocks = container.nextOrderedBlocks;
2623
2744
  const orderedIndexByKey = container.orderedIndexByKey;
2624
- newBlocks.clear();
2625
- nextOrderedBlocks.length = 0;
2626
- orderedIndexByKey.clear();
2627
- const createdBlocks = [];
2628
2745
  const newItems = getItems();
2629
2746
  if (newItems.length === 0) {
2630
2747
  if (oldBlocks.size > 0) {
@@ -2647,8 +2764,44 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
2647
2764
  return;
2648
2765
  }
2649
2766
  const prevCount = prevOrderedBlocks.length;
2767
+ if (prevCount > 0 && newItems.length === prevCount && orderedIndexByKey.size === prevCount) {
2768
+ let stableOrder = true;
2769
+ const seen = /* @__PURE__ */ new Set();
2770
+ for (let i = 0; i < prevCount; i++) {
2771
+ const item = newItems[i];
2772
+ const key = keyFn(item, i);
2773
+ if (seen.has(key) || prevOrderedBlocks[i].key !== key) {
2774
+ stableOrder = false;
2775
+ break;
2776
+ }
2777
+ seen.add(key);
2778
+ }
2779
+ if (stableOrder) {
2780
+ for (let i = 0; i < prevCount; i++) {
2781
+ const item = newItems[i];
2782
+ const block = prevOrderedBlocks[i];
2783
+ if (block.rawItem !== item) {
2784
+ block.rawItem = item;
2785
+ block.item(item);
2786
+ }
2787
+ if (needsIndex && block.rawIndex !== i) {
2788
+ block.rawIndex = i;
2789
+ block.index(i);
2790
+ }
2791
+ }
2792
+ return;
2793
+ }
2794
+ }
2795
+ newBlocks.clear();
2796
+ nextOrderedBlocks.length = 0;
2797
+ orderedIndexByKey.clear();
2798
+ const createdBlocks = [];
2650
2799
  let appendCandidate = prevCount > 0 && newItems.length >= prevCount;
2651
2800
  const appendedBlocks = [];
2801
+ let mismatchCount = 0;
2802
+ let mismatchFirst = -1;
2803
+ let mismatchSecond = -1;
2804
+ let hasDuplicateKey = false;
2652
2805
  newItems.forEach((item, index) => {
2653
2806
  const key = keyFn(item, index);
2654
2807
  let block = oldBlocks.get(key);
@@ -2669,6 +2822,11 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
2669
2822
  } else {
2670
2823
  const existingBlock = newBlocks.get(key);
2671
2824
  if (existingBlock) {
2825
+ if (isDev2) {
2826
+ console.warn(
2827
+ `[fict] Duplicate key "${String(key)}" detected in list rendering. Each item should have a unique key. The previous item with this key will be replaced.`
2828
+ );
2829
+ }
2672
2830
  destroyRoot(existingBlock.root);
2673
2831
  removeNodes(existingBlock.nodes);
2674
2832
  }
@@ -2680,6 +2838,7 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
2680
2838
  const position = orderedIndexByKey.get(key);
2681
2839
  if (position !== void 0) {
2682
2840
  appendCandidate = false;
2841
+ hasDuplicateKey = true;
2683
2842
  const prior = nextOrderedBlocks[position];
2684
2843
  if (prior && prior !== resolvedBlock) {
2685
2844
  destroyRoot(prior.root);
@@ -2696,8 +2855,17 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
2696
2855
  appendCandidate = false;
2697
2856
  }
2698
2857
  }
2699
- orderedIndexByKey.set(key, nextOrderedBlocks.length);
2858
+ const nextIndex = nextOrderedBlocks.length;
2859
+ orderedIndexByKey.set(key, nextIndex);
2700
2860
  nextOrderedBlocks.push(resolvedBlock);
2861
+ if (mismatchCount < 3 && (nextIndex >= prevCount || prevOrderedBlocks[nextIndex] !== resolvedBlock)) {
2862
+ if (mismatchCount === 0) {
2863
+ mismatchFirst = nextIndex;
2864
+ } else if (mismatchCount === 1) {
2865
+ mismatchSecond = nextIndex;
2866
+ }
2867
+ mismatchCount++;
2868
+ }
2701
2869
  }
2702
2870
  if (appendCandidate && index >= prevCount) {
2703
2871
  appendedBlocks.push(resolvedBlock);
@@ -2738,7 +2906,26 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
2738
2906
  }
2739
2907
  oldBlocks.clear();
2740
2908
  }
2741
- if (newBlocks.size > 0 || container.currentNodes.length > 0) {
2909
+ const canReorderInPlace = createdBlocks.length === 0 && oldBlocks.size === 0 && nextOrderedBlocks.length === prevOrderedBlocks.length;
2910
+ let skipReconcile = false;
2911
+ let updateNodeBuffer = true;
2912
+ if (canReorderInPlace && nextOrderedBlocks.length > 0 && !hasDuplicateKey) {
2913
+ if (mismatchCount === 0) {
2914
+ skipReconcile = true;
2915
+ updateNodeBuffer = false;
2916
+ } else if (mismatchCount === 2 && prevOrderedBlocks[mismatchFirst] === nextOrderedBlocks[mismatchSecond] && prevOrderedBlocks[mismatchSecond] === nextOrderedBlocks[mismatchFirst]) {
2917
+ if (reorderBySwap(
2918
+ parent,
2919
+ prevOrderedBlocks[mismatchFirst],
2920
+ prevOrderedBlocks[mismatchSecond]
2921
+ )) {
2922
+ skipReconcile = true;
2923
+ }
2924
+ } else if (reorderByLIS(parent, container.endMarker, prevOrderedBlocks, nextOrderedBlocks)) {
2925
+ skipReconcile = true;
2926
+ }
2927
+ }
2928
+ if (!skipReconcile && (newBlocks.size > 0 || container.currentNodes.length > 0)) {
2742
2929
  const prevNodes = container.currentNodes;
2743
2930
  const nextNodes = container.nextNodes;
2744
2931
  nextNodes.length = 0;
@@ -2753,6 +2940,20 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
2753
2940
  reconcileArrays(parent, prevNodes, nextNodes);
2754
2941
  container.currentNodes = nextNodes;
2755
2942
  container.nextNodes = prevNodes;
2943
+ } else if (skipReconcile && updateNodeBuffer) {
2944
+ const prevNodes = container.currentNodes;
2945
+ const nextNodes = container.nextNodes;
2946
+ nextNodes.length = 0;
2947
+ nextNodes.push(container.startMarker);
2948
+ for (let i = 0; i < nextOrderedBlocks.length; i++) {
2949
+ const nodes = nextOrderedBlocks[i].nodes;
2950
+ for (let j = 0; j < nodes.length; j++) {
2951
+ nextNodes.push(nodes[j]);
2952
+ }
2953
+ }
2954
+ nextNodes.push(container.endMarker);
2955
+ container.currentNodes = nextNodes;
2956
+ container.nextNodes = prevNodes;
2756
2957
  }
2757
2958
  container.blocks = newBlocks;
2758
2959
  container.nextBlocks = oldBlocks;
@@ -3399,7 +3600,9 @@ function bindEvent(el, eventName, handler, options2) {
3399
3600
  const fn = resolveHandler();
3400
3601
  callEventHandler(fn, args[0], el);
3401
3602
  } catch (err) {
3402
- handleError(err, { source: "event", eventName }, rootRef);
3603
+ if (!handleError(err, { source: "event", eventName }, rootRef)) {
3604
+ throw err;
3605
+ }
3403
3606
  }
3404
3607
  };
3405
3608
  return () => {
@@ -4186,10 +4389,12 @@ function ErrorBoundary(props) {
4186
4389
  renderingFallback = true;
4187
4390
  try {
4188
4391
  renderValue(toView(err));
4189
- } finally {
4190
4392
  renderingFallback = false;
4393
+ props.onError?.(err);
4394
+ } catch (fallbackErr) {
4395
+ props.onError?.(err);
4396
+ throw fallbackErr;
4191
4397
  }
4192
- props.onError?.(err);
4193
4398
  return;
4194
4399
  }
4195
4400
  popRoot(prev);
@@ -4284,7 +4489,9 @@ function Suspense(props) {
4284
4489
  popRoot(prev);
4285
4490
  flushOnMount(root);
4286
4491
  destroyRoot(root);
4287
- handleError(err, { source: "render" });
4492
+ if (!handleError(err, { source: "render" }, hostRoot)) {
4493
+ throw err;
4494
+ }
4288
4495
  return;
4289
4496
  }
4290
4497
  popRoot(prev);
@@ -4314,18 +4521,26 @@ function Suspense(props) {
4314
4521
  if (thenable) {
4315
4522
  thenable.then(
4316
4523
  () => {
4317
- if (epoch !== tokenEpoch) return;
4318
- pending(Math.max(0, pending() - 1));
4319
- if (pending() === 0) {
4524
+ if (epoch !== tokenEpoch) {
4525
+ return;
4526
+ }
4527
+ const newPending = Math.max(0, pending() - 1);
4528
+ pending(newPending);
4529
+ if (newPending === 0) {
4320
4530
  switchView(props.children ?? null);
4321
4531
  onResolveMaybe();
4322
4532
  }
4323
4533
  },
4324
4534
  (err) => {
4325
- if (epoch !== tokenEpoch) return;
4326
- pending(Math.max(0, pending() - 1));
4535
+ if (epoch !== tokenEpoch) {
4536
+ return;
4537
+ }
4538
+ const newPending = Math.max(0, pending() - 1);
4539
+ pending(newPending);
4327
4540
  props.onReject?.(err);
4328
- handleError(err, { source: "render" }, hostRoot);
4541
+ if (!handleError(err, { source: "render" }, hostRoot)) {
4542
+ throw err;
4543
+ }
4329
4544
  }
4330
4545
  );
4331
4546
  return true;