@fictjs/runtime 0.1.0 → 0.2.1

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 (49) hide show
  1. package/dist/advanced.cjs +8 -8
  2. package/dist/advanced.d.cts +3 -3
  3. package/dist/advanced.d.ts +3 -3
  4. package/dist/advanced.js +3 -3
  5. package/dist/{chunk-YQ4IB7NC.cjs → chunk-7EAEROZ5.cjs} +7 -7
  6. package/dist/{chunk-YQ4IB7NC.cjs.map → chunk-7EAEROZ5.cjs.map} +1 -1
  7. package/dist/{chunk-CF3OHML2.js → chunk-7TPCESQS.js} +2 -2
  8. package/dist/{chunk-BWZFJXUI.js → chunk-FOLRR3NZ.js} +84 -10
  9. package/dist/chunk-FOLRR3NZ.js.map +1 -0
  10. package/dist/{chunk-7WAGAQLT.cjs → chunk-MWI3USXB.cjs} +84 -10
  11. package/dist/chunk-MWI3USXB.cjs.map +1 -0
  12. package/dist/{chunk-V62XZLDU.js → chunk-VVNMIER7.js} +2 -2
  13. package/dist/{chunk-V62XZLDU.js.map → chunk-VVNMIER7.js.map} +1 -1
  14. package/dist/{chunk-Q4EN6BXV.cjs → chunk-Z5WRKD7Y.cjs} +16 -16
  15. package/dist/{chunk-Q4EN6BXV.cjs.map → chunk-Z5WRKD7Y.cjs.map} +1 -1
  16. package/dist/{context-B7UYnfzM.d.ts → context-4woHo7-L.d.ts} +1 -1
  17. package/dist/{context-UXySaqI_.d.cts → context-9gFXOdJl.d.cts} +1 -1
  18. package/dist/{effect-Auji1rz9.d.cts → effect-ClARNUCc.d.cts} +23 -2
  19. package/dist/{effect-Auji1rz9.d.ts → effect-ClARNUCc.d.ts} +23 -2
  20. package/dist/index.cjs +51 -58
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +5 -5
  23. package/dist/index.d.ts +5 -5
  24. package/dist/index.dev.js +71 -28
  25. package/dist/index.dev.js.map +1 -1
  26. package/dist/index.js +15 -22
  27. package/dist/index.js.map +1 -1
  28. package/dist/internal.cjs +64 -42
  29. package/dist/internal.cjs.map +1 -1
  30. package/dist/internal.d.cts +4 -4
  31. package/dist/internal.d.ts +4 -4
  32. package/dist/internal.js +32 -10
  33. package/dist/internal.js.map +1 -1
  34. package/dist/{props-BfmSLuyp.d.cts → props-CBwuh35e.d.cts} +4 -4
  35. package/dist/{props-BBi8Tkks.d.ts → props-DAyeRPwH.d.ts} +4 -4
  36. package/dist/{scope-S6eAzBJZ.d.ts → scope-DvgMquEy.d.ts} +1 -1
  37. package/dist/{scope-DKYzWfTn.d.cts → scope-xmdo6lVU.d.cts} +1 -1
  38. package/package.json +1 -1
  39. package/src/binding.ts +58 -5
  40. package/src/context.ts +1 -1
  41. package/src/effect.ts +9 -2
  42. package/src/error-boundary.ts +9 -9
  43. package/src/lifecycle.ts +13 -3
  44. package/src/signal.ts +44 -4
  45. package/src/store.ts +42 -20
  46. package/src/suspense.ts +14 -15
  47. package/dist/chunk-7WAGAQLT.cjs.map +0 -1
  48. package/dist/chunk-BWZFJXUI.js.map +0 -1
  49. /package/dist/{chunk-CF3OHML2.js.map → chunk-7TPCESQS.js.map} +0 -0
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- export { F as Fragment, J as JSX, M as Memo, e as createElement, c as createMemo, d as createRoot, m as mergeProps, b as onCleanup, a as onDestroy, o as onMount, p as prop, r as render } from './props-BfmSLuyp.cjs';
2
- import { R as RefObject, B as BaseProps, F as FictNode, S as SuspenseToken } from './effect-Auji1rz9.cjs';
3
- export { p as ClassProp, C as Cleanup, l as Component, D as DOMElement, E as Effect, r as ErrorInfo, q as EventHandler, k as FictVNode, P as PropsWithChildren, m as Ref, n as RefCallback, o as StyleProp, h as createEffect, j as createPortal } from './effect-Auji1rz9.cjs';
4
- export { C as Context, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-UXySaqI_.cjs';
1
+ export { F as Fragment, J as JSX, M as Memo, e as createElement, c as createMemo, d as createRoot, m as mergeProps, b as onCleanup, a as onDestroy, o as onMount, p as prop, r as render } from './props-CBwuh35e.cjs';
2
+ import { R as RefObject, B as BaseProps, F as FictNode, S as SuspenseToken } from './effect-ClARNUCc.cjs';
3
+ export { p as ClassProp, C as Cleanup, l as Component, D as DOMElement, E as Effect, r as ErrorInfo, q as EventHandler, k as FictVNode, P as PropsWithChildren, m as Ref, n as RefCallback, o as StyleProp, h as createEffect, j as createPortal } from './effect-ClARNUCc.cjs';
4
+ export { C as Context, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-9gFXOdJl.cjs';
5
5
 
6
6
  /**
7
7
  * Create a ref object for DOM element references.
@@ -101,7 +101,7 @@ declare function batch<T>(fn: () => T): T;
101
101
  declare function untrack<T>(fn: () => T): T;
102
102
 
103
103
  interface ErrorBoundaryProps extends BaseProps {
104
- fallback: FictNode | ((err: unknown) => FictNode);
104
+ fallback: FictNode | ((err: unknown, reset?: () => void) => FictNode);
105
105
  onError?: (err: unknown) => void;
106
106
  resetKeys?: unknown | (() => unknown);
107
107
  }
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { F as Fragment, J as JSX, M as Memo, e as createElement, c as createMemo, d as createRoot, m as mergeProps, b as onCleanup, a as onDestroy, o as onMount, p as prop, r as render } from './props-BBi8Tkks.js';
2
- import { R as RefObject, B as BaseProps, F as FictNode, S as SuspenseToken } from './effect-Auji1rz9.js';
3
- export { p as ClassProp, C as Cleanup, l as Component, D as DOMElement, E as Effect, r as ErrorInfo, q as EventHandler, k as FictVNode, P as PropsWithChildren, m as Ref, n as RefCallback, o as StyleProp, h as createEffect, j as createPortal } from './effect-Auji1rz9.js';
4
- export { C as Context, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-B7UYnfzM.js';
1
+ export { F as Fragment, J as JSX, M as Memo, e as createElement, c as createMemo, d as createRoot, m as mergeProps, b as onCleanup, a as onDestroy, o as onMount, p as prop, r as render } from './props-DAyeRPwH.js';
2
+ import { R as RefObject, B as BaseProps, F as FictNode, S as SuspenseToken } from './effect-ClARNUCc.js';
3
+ export { p as ClassProp, C as Cleanup, l as Component, D as DOMElement, E as Effect, r as ErrorInfo, q as EventHandler, k as FictVNode, P as PropsWithChildren, m as Ref, n as RefCallback, o as StyleProp, h as createEffect, j as createPortal } from './effect-ClARNUCc.js';
4
+ export { C as Context, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-4woHo7-L.js';
5
5
 
6
6
  /**
7
7
  * Create a ref object for DOM element references.
@@ -101,7 +101,7 @@ declare function batch<T>(fn: () => T): T;
101
101
  declare function untrack<T>(fn: () => T): T;
102
102
 
103
103
  interface ErrorBoundaryProps extends BaseProps {
104
- fallback: FictNode | ((err: unknown) => FictNode);
104
+ fallback: FictNode | ((err: unknown, reset?: () => void) => FictNode);
105
105
  onError?: (err: unknown) => void;
106
106
  resetKeys?: unknown | (() => unknown);
107
107
  }
package/dist/index.dev.js CHANGED
@@ -133,7 +133,7 @@ var currentEffectCleanups;
133
133
  var globalErrorHandlers = /* @__PURE__ */ new WeakMap();
134
134
  var globalSuspenseHandlers = /* @__PURE__ */ new WeakMap();
135
135
  function createRootContext(parent) {
136
- return { parent, cleanups: [], destroyCallbacks: [] };
136
+ return { parent, cleanups: [], destroyCallbacks: [], suspended: false };
137
137
  }
138
138
  function pushRoot(root) {
139
139
  if (!enterRootGuard(root)) {
@@ -335,13 +335,17 @@ function handleError(err, info, startRoot) {
335
335
  }
336
336
  function handleSuspend(token, startRoot) {
337
337
  let root = startRoot ?? currentRoot;
338
+ const originRoot = root;
338
339
  while (root) {
339
340
  const handlers = root.suspenseHandlers;
340
341
  if (handlers && handlers.length) {
341
342
  for (let i = handlers.length - 1; i >= 0; i--) {
342
343
  const handler = handlers[i];
343
344
  const handled = handler(token);
344
- if (handled !== false) return true;
345
+ if (handled !== false) {
346
+ if (originRoot) originRoot.suspended = true;
347
+ return true;
348
+ }
345
349
  }
346
350
  }
347
351
  root = root.parent;
@@ -351,7 +355,10 @@ function handleSuspend(token, startRoot) {
351
355
  for (let i = globalForRoot.length - 1; i >= 0; i--) {
352
356
  const handler = globalForRoot[i];
353
357
  const handled = handler(token);
354
- if (handled !== false) return true;
358
+ if (handled !== false) {
359
+ if (originRoot) originRoot.suspended = true;
360
+ return true;
361
+ }
355
362
  }
356
363
  }
357
364
  return false;
@@ -675,7 +682,25 @@ function runEffect(e) {
675
682
  inCleanup = false;
676
683
  }
677
684
  }
678
- if (checkDirty(e.deps, e)) {
685
+ let isDirty = false;
686
+ try {
687
+ isDirty = checkDirty(e.deps, e);
688
+ } catch (err) {
689
+ if (handleSuspend(err, e.root)) {
690
+ if (e.flags !== 0) {
691
+ e.flags = Watching;
692
+ }
693
+ return;
694
+ }
695
+ if (handleError(err, { source: "effect" }, e.root)) {
696
+ if (e.flags !== 0) {
697
+ e.flags = Watching;
698
+ }
699
+ return;
700
+ }
701
+ throw err;
702
+ }
703
+ if (isDirty) {
679
704
  ++cycle;
680
705
  effectRunDevtools(e);
681
706
  e.depsTail = void 0;
@@ -852,7 +877,7 @@ function computedOper() {
852
877
  if (activeSub !== void 0) link(this, activeSub, cycle);
853
878
  return this.value;
854
879
  }
855
- function effectWithCleanup(fn, cleanupRunner) {
880
+ function effectWithCleanup(fn, cleanupRunner, root) {
856
881
  const e = {
857
882
  fn,
858
883
  subs: void 0,
@@ -863,6 +888,10 @@ function effectWithCleanup(fn, cleanupRunner) {
863
888
  runCleanup: cleanupRunner,
864
889
  __id: void 0
865
890
  };
891
+ const resolvedRoot = root ?? getCurrentRoot();
892
+ if (resolvedRoot) {
893
+ e.root = resolvedRoot;
894
+ }
866
895
  registerEffectDevtools(e);
867
896
  const prevSub = activeSub;
868
897
  if (prevSub !== void 0) link(e, prevSub, 0);
@@ -920,6 +949,18 @@ function untrack(fn) {
920
949
  activeSub = prev;
921
950
  }
922
951
  }
952
+ function isSignal(fn) {
953
+ return typeof fn === "function" && fn[SIGNAL_MARKER] === true;
954
+ }
955
+ function isComputed(fn) {
956
+ return typeof fn === "function" && fn[COMPUTED_MARKER] === true;
957
+ }
958
+ function isEffect(fn) {
959
+ return typeof fn === "function" && fn[EFFECT_MARKER] === true;
960
+ }
961
+ function isEffectScope(fn) {
962
+ return typeof fn === "function" && fn[EFFECT_SCOPE_MARKER] === true;
963
+ }
923
964
  function setTransitionContext(value) {
924
965
  const prev = isInTransition;
925
966
  isInTransition = value;
@@ -986,6 +1027,9 @@ function createEffect(fn) {
986
1027
  bucket.push(maybeCleanup);
987
1028
  }
988
1029
  } catch (err) {
1030
+ if (handleSuspend(err, rootForError)) {
1031
+ return;
1032
+ }
989
1033
  if (handleError(err, { source: "effect" }, rootForError)) {
990
1034
  return;
991
1035
  }
@@ -994,7 +1038,7 @@ function createEffect(fn) {
994
1038
  });
995
1039
  cleanups = bucket;
996
1040
  };
997
- const disposeEffect = effectWithCleanup(run, doCleanup);
1041
+ const disposeEffect = effectWithCleanup(run, doCleanup, rootForError);
998
1042
  const teardown = () => {
999
1043
  runCleanupList(cleanups);
1000
1044
  disposeEffect();
@@ -1018,6 +1062,9 @@ function createRenderEffect(fn) {
1018
1062
  cleanup = maybeCleanup;
1019
1063
  }
1020
1064
  } catch (err) {
1065
+ if (handleSuspend(err, rootForError)) {
1066
+ return;
1067
+ }
1021
1068
  const handled = handleError(err, { source: "effect" }, rootForError);
1022
1069
  if (handled) {
1023
1070
  return;
@@ -1025,7 +1072,7 @@ function createRenderEffect(fn) {
1025
1072
  throw err;
1026
1073
  }
1027
1074
  };
1028
- const disposeEffect = effectWithCleanup(run, doCleanup);
1075
+ const disposeEffect = effectWithCleanup(run, doCleanup, rootForError);
1029
1076
  const teardown = () => {
1030
1077
  if (cleanup) {
1031
1078
  cleanup();
@@ -1612,7 +1659,10 @@ function removeNodes(nodes) {
1612
1659
  // src/binding.ts
1613
1660
  var isDev5 = true ? true : typeof process === "undefined" || process.env?.NODE_ENV !== "production";
1614
1661
  function isReactive(value) {
1615
- return typeof value === "function" && value.length === 0;
1662
+ if (typeof value !== "function") return false;
1663
+ if (isSignal(value) || isComputed(value)) return true;
1664
+ if (isEffect(value) || isEffectScope(value)) return false;
1665
+ return value.length === 0;
1616
1666
  }
1617
1667
  function callEventHandler(handler, event, node, data) {
1618
1668
  if (!handler) return;
@@ -2580,14 +2630,15 @@ function ErrorBoundary(props) {
2580
2630
  const fragment = document.createDocumentFragment();
2581
2631
  const marker = document.createComment("fict:error-boundary");
2582
2632
  fragment.appendChild(marker);
2583
- const currentView = signal(props.children ?? null);
2584
2633
  const hostRoot = getCurrentRoot();
2585
2634
  let cleanup;
2586
2635
  let activeNodes = [];
2587
2636
  let renderingFallback = false;
2637
+ let reset = () => {
2638
+ };
2588
2639
  const toView = (err) => {
2589
2640
  if (err != null) {
2590
- return typeof props.fallback === "function" ? props.fallback(err) : props.fallback;
2641
+ return typeof props.fallback === "function" ? props.fallback(err, reset) : props.fallback;
2591
2642
  }
2592
2643
  return props.children ?? null;
2593
2644
  };
@@ -2615,7 +2666,6 @@ function ErrorBoundary(props) {
2615
2666
  }
2616
2667
  } catch (err) {
2617
2668
  popRoot(prev);
2618
- flushOnMount(root);
2619
2669
  destroyRoot(root);
2620
2670
  if (renderingFallback) {
2621
2671
  throw err;
@@ -2639,10 +2689,11 @@ function ErrorBoundary(props) {
2639
2689
  };
2640
2690
  activeNodes = nodes;
2641
2691
  };
2642
- createEffect(() => {
2643
- const value = currentView();
2644
- renderValue(value);
2645
- });
2692
+ reset = () => {
2693
+ renderingFallback = false;
2694
+ renderValue(toView(null));
2695
+ };
2696
+ renderValue(props.children ?? null);
2646
2697
  registerErrorHandler((err) => {
2647
2698
  renderValue(toView(err));
2648
2699
  props.onError?.(err);
@@ -2681,16 +2732,11 @@ function createSuspenseToken() {
2681
2732
  }
2682
2733
  var isThenable = (value) => typeof value === "object" && value !== null && typeof value.then === "function";
2683
2734
  function Suspense(props) {
2684
- const currentView = signal(props.children ?? null);
2685
2735
  const pending = signal(0);
2686
2736
  let resolvedOnce = false;
2687
2737
  let epoch = 0;
2688
2738
  const hostRoot = getCurrentRoot();
2689
2739
  const toFallback = (err) => typeof props.fallback === "function" ? props.fallback(err) : props.fallback;
2690
- const switchView = (view) => {
2691
- currentView(view);
2692
- renderView(view);
2693
- };
2694
2740
  const renderView = (view) => {
2695
2741
  if (cleanup) {
2696
2742
  cleanup();
@@ -2709,7 +2755,7 @@ function Suspense(props) {
2709
2755
  try {
2710
2756
  const output = createElement(view);
2711
2757
  nodes = toNodeArray(output);
2712
- const suspendedAttempt = nodes.length > 0 && nodes.every((node) => node instanceof Comment && node.data === "fict:suspend");
2758
+ const suspendedAttempt = root.suspended || nodes.length > 0 && nodes.every((node) => node instanceof Comment && node.data === "fict:suspend");
2713
2759
  if (suspendedAttempt) {
2714
2760
  popRoot(prev);
2715
2761
  destroyRoot(root);
@@ -2721,7 +2767,6 @@ function Suspense(props) {
2721
2767
  }
2722
2768
  } catch (err) {
2723
2769
  popRoot(prev);
2724
- flushOnMount(root);
2725
2770
  destroyRoot(root);
2726
2771
  if (!handleError(err, { source: "render" }, hostRoot)) {
2727
2772
  throw err;
@@ -2750,7 +2795,7 @@ function Suspense(props) {
2750
2795
  registerSuspenseHandler((token) => {
2751
2796
  const tokenEpoch = epoch;
2752
2797
  pending(pending() + 1);
2753
- switchView(toFallback());
2798
+ renderView(toFallback());
2754
2799
  const thenable = token.then ? token : isThenable(token) ? token : null;
2755
2800
  if (thenable) {
2756
2801
  thenable.then(
@@ -2761,7 +2806,7 @@ function Suspense(props) {
2761
2806
  const newPending = Math.max(0, pending() - 1);
2762
2807
  pending(newPending);
2763
2808
  if (newPending === 0) {
2764
- switchView(props.children ?? null);
2809
+ renderView(props.children ?? null);
2765
2810
  onResolveMaybe();
2766
2811
  }
2767
2812
  },
@@ -2781,9 +2826,7 @@ function Suspense(props) {
2781
2826
  }
2782
2827
  return false;
2783
2828
  });
2784
- createEffect(() => {
2785
- renderView(currentView());
2786
- });
2829
+ renderView(props.children ?? null);
2787
2830
  if (props.resetKeys !== void 0) {
2788
2831
  const isGetter = typeof props.resetKeys === "function" && props.resetKeys.length === 0;
2789
2832
  const getter = isGetter ? props.resetKeys : void 0;
@@ -2794,7 +2837,7 @@ function Suspense(props) {
2794
2837
  prev = next;
2795
2838
  epoch++;
2796
2839
  pending(0);
2797
- switchView(props.children ?? null);
2840
+ renderView(props.children ?? null);
2798
2841
  }
2799
2842
  });
2800
2843
  }