@fictjs/runtime 0.1.0 → 0.2.0

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 (46) 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-Q4EN6BXV.cjs → chunk-527QSKFM.cjs} +16 -16
  6. package/dist/{chunk-Q4EN6BXV.cjs.map → chunk-527QSKFM.cjs.map} +1 -1
  7. package/dist/{chunk-BWZFJXUI.js → chunk-5KXEEQUO.js} +84 -10
  8. package/dist/chunk-5KXEEQUO.js.map +1 -0
  9. package/dist/{chunk-YQ4IB7NC.cjs → chunk-BSUMPMKX.cjs} +7 -7
  10. package/dist/{chunk-YQ4IB7NC.cjs.map → chunk-BSUMPMKX.cjs.map} +1 -1
  11. package/dist/{chunk-V62XZLDU.js → chunk-FG3M7EBL.js} +2 -2
  12. package/dist/{chunk-7WAGAQLT.cjs → chunk-J74L7UYP.cjs} +84 -10
  13. package/dist/chunk-J74L7UYP.cjs.map +1 -0
  14. package/dist/{chunk-CF3OHML2.js → chunk-QV5GOCR5.js} +2 -2
  15. package/dist/{context-B7UYnfzM.d.ts → context-4woHo7-L.d.ts} +1 -1
  16. package/dist/{context-UXySaqI_.d.cts → context-9gFXOdJl.d.cts} +1 -1
  17. package/dist/{effect-Auji1rz9.d.cts → effect-ClARNUCc.d.cts} +23 -2
  18. package/dist/{effect-Auji1rz9.d.ts → effect-ClARNUCc.d.ts} +23 -2
  19. package/dist/index.cjs +51 -54
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +4 -4
  22. package/dist/index.d.ts +4 -4
  23. package/dist/index.dev.js +66 -19
  24. package/dist/index.dev.js.map +1 -1
  25. package/dist/index.js +10 -13
  26. package/dist/index.js.map +1 -1
  27. package/dist/internal.cjs +34 -34
  28. package/dist/internal.d.cts +4 -4
  29. package/dist/internal.d.ts +4 -4
  30. package/dist/internal.js +2 -2
  31. package/dist/jsx-runtime.d.cts +671 -0
  32. package/dist/jsx-runtime.d.ts +671 -0
  33. package/dist/{props-BfmSLuyp.d.cts → props-CBwuh35e.d.cts} +4 -4
  34. package/dist/{props-BBi8Tkks.d.ts → props-DAyeRPwH.d.ts} +4 -4
  35. package/dist/{scope-S6eAzBJZ.d.ts → scope-DvgMquEy.d.ts} +1 -1
  36. package/dist/{scope-DKYzWfTn.d.cts → scope-xmdo6lVU.d.cts} +1 -1
  37. package/package.json +1 -1
  38. package/src/binding.ts +58 -5
  39. package/src/effect.ts +9 -2
  40. package/src/lifecycle.ts +13 -3
  41. package/src/signal.ts +43 -4
  42. package/src/suspense.ts +17 -13
  43. package/dist/chunk-7WAGAQLT.cjs.map +0 -1
  44. package/dist/chunk-BWZFJXUI.js.map +0 -1
  45. /package/dist/{chunk-V62XZLDU.js.map → chunk-FG3M7EBL.js.map} +0 -0
  46. /package/dist/{chunk-CF3OHML2.js.map → chunk-QV5GOCR5.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import { B as BaseProps, F as FictNode } from './effect-Auji1rz9.cjs';
1
+ import { B as BaseProps, F as FictNode } from './effect-ClARNUCc.cjs';
2
2
 
3
3
  /**
4
4
  * @fileoverview Context API for Fict
@@ -88,8 +88,29 @@ interface BindingHandle {
88
88
  }
89
89
  /** Managed child node with its dispose function */
90
90
  /**
91
- * Check if a value is reactive (a getter function)
92
- * Note: Event handlers (functions that take arguments) are NOT reactive values
91
+ * Check if a value is reactive (a getter function that returns a value).
92
+ *
93
+ * A value is considered reactive if:
94
+ * 1. It's a signal or computed value created by the runtime (marked with Symbol)
95
+ * 2. It's a zero-argument function (getter pattern used by the compiler)
96
+ *
97
+ * NOT considered reactive:
98
+ * - Event handlers (functions that take arguments)
99
+ * - Effect disposers (zero-arg but for cleanup, not value access)
100
+ * - Effect scopes (zero-arg but for scope management)
101
+ *
102
+ * @param value - The value to check
103
+ * @returns true if the value is a reactive getter
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * const [count, setCount] = createSignal(0)
108
+ * isReactive(count) // true - signal accessor
109
+ * isReactive(() => 42) // true - getter pattern
110
+ * isReactive((x) => x) // false - takes argument
111
+ * isReactive('hello') // false - not a function
112
+ * isReactive(effectDisposer) // false - effect cleanup function
113
+ * ```
93
114
  */
94
115
  declare function isReactive(value: unknown): value is () => unknown;
95
116
  /**
@@ -88,8 +88,29 @@ interface BindingHandle {
88
88
  }
89
89
  /** Managed child node with its dispose function */
90
90
  /**
91
- * Check if a value is reactive (a getter function)
92
- * Note: Event handlers (functions that take arguments) are NOT reactive values
91
+ * Check if a value is reactive (a getter function that returns a value).
92
+ *
93
+ * A value is considered reactive if:
94
+ * 1. It's a signal or computed value created by the runtime (marked with Symbol)
95
+ * 2. It's a zero-argument function (getter pattern used by the compiler)
96
+ *
97
+ * NOT considered reactive:
98
+ * - Event handlers (functions that take arguments)
99
+ * - Effect disposers (zero-arg but for cleanup, not value access)
100
+ * - Effect scopes (zero-arg but for scope management)
101
+ *
102
+ * @param value - The value to check
103
+ * @returns true if the value is a reactive getter
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * const [count, setCount] = createSignal(0)
108
+ * isReactive(count) // true - signal accessor
109
+ * isReactive(() => 42) // true - getter pattern
110
+ * isReactive((x) => x) // false - takes argument
111
+ * isReactive('hello') // false - not a function
112
+ * isReactive(effectDisposer) // false - effect cleanup function
113
+ * ```
93
114
  */
94
115
  declare function isReactive(value: unknown): value is () => unknown;
95
116
  /**
package/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- var _chunkQ4EN6BXVcjs = require('./chunk-Q4EN6BXV.cjs');
5
+ var _chunk527QSKFMcjs = require('./chunk-527QSKFM.cjs');
6
6
 
7
7
 
8
8
 
@@ -34,7 +34,7 @@ var _chunkQ4EN6BXVcjs = require('./chunk-Q4EN6BXV.cjs');
34
34
 
35
35
 
36
36
 
37
- var _chunk7WAGAQLTcjs = require('./chunk-7WAGAQLT.cjs');
37
+ var _chunkJ74L7UYPcjs = require('./chunk-J74L7UYP.cjs');
38
38
 
39
39
  // src/ref.ts
40
40
  function createRef() {
@@ -46,8 +46,8 @@ function ErrorBoundary(props) {
46
46
  const fragment = document.createDocumentFragment();
47
47
  const marker = document.createComment("fict:error-boundary");
48
48
  fragment.appendChild(marker);
49
- const currentView = _chunk7WAGAQLTcjs.signal.call(void 0, _nullishCoalesce(props.children, () => ( null)));
50
- const hostRoot = _chunk7WAGAQLTcjs.getCurrentRoot.call(void 0, );
49
+ const currentView = _chunkJ74L7UYPcjs.signal.call(void 0, _nullishCoalesce(props.children, () => ( null)));
50
+ const hostRoot = _chunkJ74L7UYPcjs.getCurrentRoot.call(void 0, );
51
51
  let cleanup;
52
52
  let activeNodes = [];
53
53
  let renderingFallback = false;
@@ -63,26 +63,26 @@ function ErrorBoundary(props) {
63
63
  cleanup = void 0;
64
64
  }
65
65
  if (activeNodes.length) {
66
- _chunk7WAGAQLTcjs.removeNodes.call(void 0, activeNodes);
66
+ _chunkJ74L7UYPcjs.removeNodes.call(void 0, activeNodes);
67
67
  activeNodes = [];
68
68
  }
69
69
  if (value == null || value === false) {
70
70
  return;
71
71
  }
72
- const root = _chunk7WAGAQLTcjs.createRootContext.call(void 0, hostRoot);
73
- const prev = _chunk7WAGAQLTcjs.pushRoot.call(void 0, root);
72
+ const root = _chunkJ74L7UYPcjs.createRootContext.call(void 0, hostRoot);
73
+ const prev = _chunkJ74L7UYPcjs.pushRoot.call(void 0, root);
74
74
  let nodes = [];
75
75
  try {
76
- const output = _chunk7WAGAQLTcjs.createElement.call(void 0, value);
77
- nodes = _chunk7WAGAQLTcjs.toNodeArray.call(void 0, output);
76
+ const output = _chunkJ74L7UYPcjs.createElement.call(void 0, value);
77
+ nodes = _chunkJ74L7UYPcjs.toNodeArray.call(void 0, output);
78
78
  const parentNode = marker.parentNode;
79
79
  if (parentNode) {
80
- _chunk7WAGAQLTcjs.insertNodesBefore.call(void 0, parentNode, nodes, marker);
80
+ _chunkJ74L7UYPcjs.insertNodesBefore.call(void 0, parentNode, nodes, marker);
81
81
  }
82
82
  } catch (err) {
83
- _chunk7WAGAQLTcjs.popRoot.call(void 0, prev);
84
- _chunk7WAGAQLTcjs.flushOnMount.call(void 0, root);
85
- _chunk7WAGAQLTcjs.destroyRoot.call(void 0, root);
83
+ _chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
84
+ _chunkJ74L7UYPcjs.flushOnMount.call(void 0, root);
85
+ _chunkJ74L7UYPcjs.destroyRoot.call(void 0, root);
86
86
  if (renderingFallback) {
87
87
  throw err;
88
88
  }
@@ -97,19 +97,19 @@ function ErrorBoundary(props) {
97
97
  }
98
98
  return;
99
99
  }
100
- _chunk7WAGAQLTcjs.popRoot.call(void 0, prev);
101
- _chunk7WAGAQLTcjs.flushOnMount.call(void 0, root);
100
+ _chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
101
+ _chunkJ74L7UYPcjs.flushOnMount.call(void 0, root);
102
102
  cleanup = () => {
103
- _chunk7WAGAQLTcjs.destroyRoot.call(void 0, root);
104
- _chunk7WAGAQLTcjs.removeNodes.call(void 0, nodes);
103
+ _chunkJ74L7UYPcjs.destroyRoot.call(void 0, root);
104
+ _chunkJ74L7UYPcjs.removeNodes.call(void 0, nodes);
105
105
  };
106
106
  activeNodes = nodes;
107
107
  };
108
- _chunk7WAGAQLTcjs.createEffect.call(void 0, () => {
108
+ _chunkJ74L7UYPcjs.createEffect.call(void 0, () => {
109
109
  const value = currentView();
110
110
  renderValue(value);
111
111
  });
112
- _chunk7WAGAQLTcjs.registerErrorHandler.call(void 0, (err) => {
112
+ _chunkJ74L7UYPcjs.registerErrorHandler.call(void 0, (err) => {
113
113
  renderValue(toView(err));
114
114
  _optionalChain([props, 'access', _5 => _5.onError, 'optionalCall', _6 => _6(err)]);
115
115
  return true;
@@ -118,7 +118,7 @@ function ErrorBoundary(props) {
118
118
  const isGetter = typeof props.resetKeys === "function" && props.resetKeys.length === 0;
119
119
  const getter = isGetter ? props.resetKeys : void 0;
120
120
  let prev = isGetter ? getter() : props.resetKeys;
121
- _chunk7WAGAQLTcjs.createEffect.call(void 0, () => {
121
+ _chunkJ74L7UYPcjs.createEffect.call(void 0, () => {
122
122
  const next = getter ? getter() : props.resetKeys;
123
123
  if (prev !== next) {
124
124
  prev = next;
@@ -147,58 +147,54 @@ function createSuspenseToken() {
147
147
  }
148
148
  var isThenable = (value) => typeof value === "object" && value !== null && typeof value.then === "function";
149
149
  function Suspense(props) {
150
- const currentView = _chunk7WAGAQLTcjs.signal.call(void 0, _nullishCoalesce(props.children, () => ( null)));
151
- const pending = _chunk7WAGAQLTcjs.signal.call(void 0, 0);
150
+ const currentView = _chunkJ74L7UYPcjs.signal.call(void 0, _nullishCoalesce(props.children, () => ( null)));
151
+ const pending = _chunkJ74L7UYPcjs.signal.call(void 0, 0);
152
152
  let resolvedOnce = false;
153
153
  let epoch = 0;
154
- const hostRoot = _chunk7WAGAQLTcjs.getCurrentRoot.call(void 0, );
154
+ const hostRoot = _chunkJ74L7UYPcjs.getCurrentRoot.call(void 0, );
155
155
  const toFallback = (err) => typeof props.fallback === "function" ? props.fallback(err) : props.fallback;
156
- const switchView = (view) => {
157
- currentView(view);
158
- renderView(view);
159
- };
160
156
  const renderView = (view) => {
161
157
  if (cleanup) {
162
158
  cleanup();
163
159
  cleanup = void 0;
164
160
  }
165
161
  if (activeNodes.length) {
166
- _chunk7WAGAQLTcjs.removeNodes.call(void 0, activeNodes);
162
+ _chunkJ74L7UYPcjs.removeNodes.call(void 0, activeNodes);
167
163
  activeNodes = [];
168
164
  }
169
165
  if (view == null || view === false) {
170
166
  return;
171
167
  }
172
- const root = _chunk7WAGAQLTcjs.createRootContext.call(void 0, hostRoot);
173
- const prev = _chunk7WAGAQLTcjs.pushRoot.call(void 0, root);
168
+ const root = _chunkJ74L7UYPcjs.createRootContext.call(void 0, hostRoot);
169
+ const prev = _chunkJ74L7UYPcjs.pushRoot.call(void 0, root);
174
170
  let nodes = [];
175
171
  try {
176
- const output = _chunk7WAGAQLTcjs.createElement.call(void 0, view);
177
- nodes = _chunk7WAGAQLTcjs.toNodeArray.call(void 0, output);
178
- const suspendedAttempt = nodes.length > 0 && nodes.every((node) => node instanceof Comment && node.data === "fict:suspend");
172
+ const output = _chunkJ74L7UYPcjs.createElement.call(void 0, view);
173
+ nodes = _chunkJ74L7UYPcjs.toNodeArray.call(void 0, output);
174
+ const suspendedAttempt = root.suspended || nodes.length > 0 && nodes.every((node) => node instanceof Comment && node.data === "fict:suspend");
179
175
  if (suspendedAttempt) {
180
- _chunk7WAGAQLTcjs.popRoot.call(void 0, prev);
181
- _chunk7WAGAQLTcjs.destroyRoot.call(void 0, root);
176
+ _chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
177
+ _chunkJ74L7UYPcjs.destroyRoot.call(void 0, root);
182
178
  return;
183
179
  }
184
180
  const parentNode = marker.parentNode;
185
181
  if (parentNode) {
186
- _chunk7WAGAQLTcjs.insertNodesBefore.call(void 0, parentNode, nodes, marker);
182
+ _chunkJ74L7UYPcjs.insertNodesBefore.call(void 0, parentNode, nodes, marker);
187
183
  }
188
184
  } catch (err) {
189
- _chunk7WAGAQLTcjs.popRoot.call(void 0, prev);
190
- _chunk7WAGAQLTcjs.flushOnMount.call(void 0, root);
191
- _chunk7WAGAQLTcjs.destroyRoot.call(void 0, root);
192
- if (!_chunk7WAGAQLTcjs.handleError.call(void 0, err, { source: "render" }, hostRoot)) {
185
+ _chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
186
+ _chunkJ74L7UYPcjs.flushOnMount.call(void 0, root);
187
+ _chunkJ74L7UYPcjs.destroyRoot.call(void 0, root);
188
+ if (!_chunkJ74L7UYPcjs.handleError.call(void 0, err, { source: "render" }, hostRoot)) {
193
189
  throw err;
194
190
  }
195
191
  return;
196
192
  }
197
- _chunk7WAGAQLTcjs.popRoot.call(void 0, prev);
198
- _chunk7WAGAQLTcjs.flushOnMount.call(void 0, root);
193
+ _chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
194
+ _chunkJ74L7UYPcjs.flushOnMount.call(void 0, root);
199
195
  cleanup = () => {
200
- _chunk7WAGAQLTcjs.destroyRoot.call(void 0, root);
201
- _chunk7WAGAQLTcjs.removeNodes.call(void 0, nodes);
196
+ _chunkJ74L7UYPcjs.destroyRoot.call(void 0, root);
197
+ _chunkJ74L7UYPcjs.removeNodes.call(void 0, nodes);
202
198
  };
203
199
  activeNodes = nodes;
204
200
  };
@@ -213,10 +209,11 @@ function Suspense(props) {
213
209
  _optionalChain([props, 'access', _7 => _7.onResolve, 'optionalCall', _8 => _8()]);
214
210
  }
215
211
  };
216
- _chunk7WAGAQLTcjs.registerSuspenseHandler.call(void 0, (token) => {
212
+ _chunkJ74L7UYPcjs.registerSuspenseHandler.call(void 0, (token) => {
217
213
  const tokenEpoch = epoch;
218
214
  pending(pending() + 1);
219
- switchView(toFallback());
215
+ currentView(toFallback());
216
+ renderView(toFallback());
220
217
  const thenable = token.then ? token : isThenable(token) ? token : null;
221
218
  if (thenable) {
222
219
  thenable.then(
@@ -227,7 +224,8 @@ function Suspense(props) {
227
224
  const newPending = Math.max(0, pending() - 1);
228
225
  pending(newPending);
229
226
  if (newPending === 0) {
230
- switchView(_nullishCoalesce(props.children, () => ( null)));
227
+ currentView(_nullishCoalesce(props.children, () => ( null)));
228
+ renderView(_nullishCoalesce(props.children, () => ( null)));
231
229
  onResolveMaybe();
232
230
  }
233
231
  },
@@ -238,7 +236,7 @@ function Suspense(props) {
238
236
  const newPending = Math.max(0, pending() - 1);
239
237
  pending(newPending);
240
238
  _optionalChain([props, 'access', _9 => _9.onReject, 'optionalCall', _10 => _10(err)]);
241
- if (!_chunk7WAGAQLTcjs.handleError.call(void 0, err, { source: "render" }, hostRoot)) {
239
+ if (!_chunkJ74L7UYPcjs.handleError.call(void 0, err, { source: "render" }, hostRoot)) {
242
240
  throw err;
243
241
  }
244
242
  }
@@ -247,20 +245,19 @@ function Suspense(props) {
247
245
  }
248
246
  return false;
249
247
  });
250
- _chunk7WAGAQLTcjs.createEffect.call(void 0, () => {
251
- renderView(currentView());
252
- });
248
+ renderView(_nullishCoalesce(props.children, () => ( null)));
253
249
  if (props.resetKeys !== void 0) {
254
250
  const isGetter = typeof props.resetKeys === "function" && props.resetKeys.length === 0;
255
251
  const getter = isGetter ? props.resetKeys : void 0;
256
252
  let prev = isGetter ? getter() : props.resetKeys;
257
- _chunk7WAGAQLTcjs.createEffect.call(void 0, () => {
253
+ _chunkJ74L7UYPcjs.createEffect.call(void 0, () => {
258
254
  const next = getter ? getter() : props.resetKeys;
259
255
  if (prev !== next) {
260
256
  prev = next;
261
257
  epoch++;
262
258
  pending(0);
263
- switchView(_nullishCoalesce(props.children, () => ( null)));
259
+ currentView(_nullishCoalesce(props.children, () => ( null)));
260
+ renderView(_nullishCoalesce(props.children, () => ( null)));
264
261
  }
265
262
  });
266
263
  }
@@ -291,5 +288,5 @@ function Suspense(props) {
291
288
 
292
289
 
293
290
 
294
- exports.ErrorBoundary = ErrorBoundary; exports.Fragment = _chunk7WAGAQLTcjs.Fragment; exports.Suspense = Suspense; exports.batch = _chunk7WAGAQLTcjs.batch2; exports.createContext = _chunkQ4EN6BXVcjs.createContext; exports.createEffect = _chunk7WAGAQLTcjs.createEffect; exports.createElement = _chunk7WAGAQLTcjs.createElement; exports.createMemo = _chunk7WAGAQLTcjs.createMemo; exports.createPortal = _chunk7WAGAQLTcjs.createPortal; exports.createRef = createRef; exports.createRoot = _chunk7WAGAQLTcjs.createRoot; exports.createSuspenseToken = createSuspenseToken; exports.hasContext = _chunkQ4EN6BXVcjs.hasContext; exports.mergeProps = _chunk7WAGAQLTcjs.mergeProps; exports.onCleanup = _chunk7WAGAQLTcjs.onCleanup; exports.onDestroy = _chunk7WAGAQLTcjs.onDestroy; exports.onMount = _chunk7WAGAQLTcjs.onMount; exports.prop = _chunk7WAGAQLTcjs.prop; exports.render = _chunk7WAGAQLTcjs.render; exports.startTransition = _chunk7WAGAQLTcjs.startTransition; exports.untrack = _chunk7WAGAQLTcjs.untrack2; exports.useContext = _chunkQ4EN6BXVcjs.useContext; exports.useDeferredValue = _chunk7WAGAQLTcjs.useDeferredValue; exports.useTransition = _chunk7WAGAQLTcjs.useTransition;
291
+ exports.ErrorBoundary = ErrorBoundary; exports.Fragment = _chunkJ74L7UYPcjs.Fragment; exports.Suspense = Suspense; exports.batch = _chunkJ74L7UYPcjs.batch2; exports.createContext = _chunk527QSKFMcjs.createContext; exports.createEffect = _chunkJ74L7UYPcjs.createEffect; exports.createElement = _chunkJ74L7UYPcjs.createElement; exports.createMemo = _chunkJ74L7UYPcjs.createMemo; exports.createPortal = _chunkJ74L7UYPcjs.createPortal; exports.createRef = createRef; exports.createRoot = _chunkJ74L7UYPcjs.createRoot; exports.createSuspenseToken = createSuspenseToken; exports.hasContext = _chunk527QSKFMcjs.hasContext; exports.mergeProps = _chunkJ74L7UYPcjs.mergeProps; exports.onCleanup = _chunkJ74L7UYPcjs.onCleanup; exports.onDestroy = _chunkJ74L7UYPcjs.onDestroy; exports.onMount = _chunkJ74L7UYPcjs.onMount; exports.prop = _chunkJ74L7UYPcjs.prop; exports.render = _chunkJ74L7UYPcjs.render; exports.startTransition = _chunkJ74L7UYPcjs.startTransition; exports.untrack = _chunkJ74L7UYPcjs.untrack2; exports.useContext = _chunk527QSKFMcjs.useContext; exports.useDeferredValue = _chunkJ74L7UYPcjs.useDeferredValue; exports.useTransition = _chunkJ74L7UYPcjs.useTransition;
295
292
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/fict/fict/packages/runtime/dist/index.cjs","../src/ref.ts","../src/error-boundary.ts","../src/suspense.ts"],"names":[],"mappings":"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","file":"/home/runner/work/fict/fict/packages/runtime/dist/index.cjs","sourcesContent":[null,"import type { RefObject } from './types'\n\n/**\n * Create a ref object for DOM element references.\n *\n * @returns A ref object with a `current` property initialized to `null`\n *\n * @example\n * ```tsx\n * import { createRef } from 'fict'\n *\n * function Component() {\n * const inputRef = createRef<HTMLInputElement>()\n *\n * $effect(() => {\n * inputRef.current?.focus()\n * })\n *\n * return <input ref={inputRef} />\n * }\n * ```\n */\nexport function createRef<T extends Element = HTMLElement>(): RefObject<T> {\n return { current: null }\n}\n","import { createElement } from './dom'\nimport { createEffect } from './effect'\nimport {\n createRootContext,\n destroyRoot,\n flushOnMount,\n getCurrentRoot,\n pushRoot,\n popRoot,\n registerErrorHandler,\n} from './lifecycle'\nimport { insertNodesBefore, removeNodes, toNodeArray } from './node-ops'\nimport { createSignal } from './signal'\nimport type { BaseProps, FictNode } from './types'\n\ninterface ErrorBoundaryProps extends BaseProps {\n fallback: FictNode | ((err: unknown) => FictNode)\n onError?: (err: unknown) => void\n resetKeys?: unknown | (() => unknown)\n}\n\nexport function ErrorBoundary(props: ErrorBoundaryProps): FictNode {\n const fragment = document.createDocumentFragment()\n const marker = document.createComment('fict:error-boundary')\n fragment.appendChild(marker)\n\n const currentView = createSignal<FictNode | null>(props.children ?? null)\n const hostRoot = getCurrentRoot()\n\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n let renderingFallback = false\n\n const toView = (err: unknown | null): FictNode | null => {\n if (err != null) {\n return typeof props.fallback === 'function'\n ? (props.fallback as (e: unknown) => FictNode)(err)\n : props.fallback\n }\n return props.children ?? null\n }\n\n const renderValue = (value: FictNode | null) => {\n if (cleanup) {\n cleanup()\n cleanup = undefined\n }\n if (activeNodes.length) {\n removeNodes(activeNodes)\n activeNodes = []\n }\n\n if (value == null || value === false) {\n return\n }\n\n const root = createRootContext(hostRoot)\n const prev = pushRoot(root)\n let nodes: Node[] = []\n try {\n const output = createElement(value)\n nodes = toNodeArray(output)\n const parentNode = marker.parentNode as (ParentNode & Node) | null\n if (parentNode) {\n insertNodesBefore(parentNode, nodes, marker)\n }\n } catch (err) {\n popRoot(prev)\n flushOnMount(root)\n destroyRoot(root)\n // Fall back immediately on render errors, avoid infinite recursion\n if (renderingFallback) {\n throw err\n }\n // nested errors. If fallback rendering also throws, we should NOT reset\n // the flag until we're sure no more recursion is happening.\n renderingFallback = true\n try {\n renderValue(toView(err))\n // Only reset if successful - if renderValue threw, we want to keep\n // renderingFallback = true to prevent infinite recursion\n renderingFallback = false\n props.onError?.(err)\n } catch (fallbackErr) {\n // Fallback rendering failed - keep renderingFallback = true\n // to prevent further attempts, then rethrow\n // If fallback fails, report both errors\n props.onError?.(err)\n throw fallbackErr\n }\n return\n }\n popRoot(prev)\n flushOnMount(root)\n\n cleanup = () => {\n destroyRoot(root)\n removeNodes(nodes)\n }\n activeNodes = nodes\n }\n\n createEffect(() => {\n const value = currentView()\n renderValue(value)\n })\n\n registerErrorHandler(err => {\n renderValue(toView(err))\n props.onError?.(err)\n return true\n })\n\n if (props.resetKeys !== undefined) {\n const isGetter =\n typeof props.resetKeys === 'function' && (props.resetKeys as () => unknown).length === 0\n const getter = isGetter ? (props.resetKeys as () => unknown) : undefined\n let prev = isGetter ? getter!() : props.resetKeys\n createEffect(() => {\n const next = getter ? getter() : props.resetKeys\n if (prev !== next) {\n prev = next\n renderValue(toView(null))\n }\n })\n }\n\n return fragment\n}\n","import { createElement } from './dom'\nimport { createEffect } from './effect'\nimport {\n createRootContext,\n destroyRoot,\n flushOnMount,\n getCurrentRoot,\n handleError,\n pushRoot,\n popRoot,\n registerSuspenseHandler,\n} from './lifecycle'\nimport { insertNodesBefore, removeNodes, toNodeArray } from './node-ops'\nimport { createSignal } from './signal'\nimport type { BaseProps, FictNode, SuspenseToken } from './types'\n\nexport interface SuspenseProps extends BaseProps {\n fallback: FictNode | ((err?: unknown) => FictNode)\n onResolve?: () => void\n onReject?: (err: unknown) => void\n resetKeys?: unknown | (() => unknown)\n}\n\nexport interface SuspenseHandle {\n token: SuspenseToken\n resolve: () => void\n reject: (err: unknown) => void\n}\n\nexport function createSuspenseToken(): SuspenseHandle {\n let resolve!: () => void\n let reject!: (err: unknown) => void\n const promise = new Promise<void>((res, rej) => {\n resolve = res\n reject = rej\n })\n return {\n token: {\n then: promise.then.bind(promise),\n },\n resolve,\n reject,\n }\n}\n\nconst isThenable = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as PromiseLike<unknown>).then === 'function'\n\nexport function Suspense(props: SuspenseProps): FictNode {\n const currentView = createSignal<FictNode | null>(props.children ?? null)\n const pending = createSignal(0)\n let resolvedOnce = false\n let epoch = 0\n const hostRoot = getCurrentRoot()\n\n const toFallback = (err?: unknown) =>\n typeof props.fallback === 'function'\n ? (props.fallback as (e?: unknown) => FictNode)(err)\n : props.fallback\n\n const switchView = (view: FictNode | null) => {\n currentView(view)\n renderView(view)\n }\n\n const renderView = (view: FictNode | null) => {\n if (cleanup) {\n cleanup()\n cleanup = undefined\n }\n if (activeNodes.length) {\n removeNodes(activeNodes)\n activeNodes = []\n }\n\n if (view == null || view === false) {\n return\n }\n\n const root = createRootContext(hostRoot)\n const prev = pushRoot(root)\n let nodes: Node[] = []\n try {\n const output = createElement(view)\n nodes = toNodeArray(output)\n // Suspended view: child threw a suspense token and was handled upstream.\n // Avoid replacing existing fallback content; tear down this attempt.\n const suspendedAttempt =\n nodes.length > 0 &&\n nodes.every(node => node instanceof Comment && (node as Comment).data === 'fict:suspend')\n if (suspendedAttempt) {\n popRoot(prev)\n destroyRoot(root)\n return\n }\n const parentNode = marker.parentNode as (ParentNode & Node) | null\n if (parentNode) {\n insertNodesBefore(parentNode, nodes, marker)\n }\n } catch (err) {\n popRoot(prev)\n flushOnMount(root)\n destroyRoot(root)\n if (!handleError(err, { source: 'render' }, hostRoot)) {\n throw err\n }\n return\n }\n popRoot(prev)\n flushOnMount(root)\n\n cleanup = () => {\n destroyRoot(root)\n removeNodes(nodes)\n }\n activeNodes = nodes\n }\n\n const fragment = document.createDocumentFragment()\n const marker = document.createComment('fict:suspense')\n fragment.appendChild(marker)\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n\n const onResolveMaybe = () => {\n if (!resolvedOnce) {\n resolvedOnce = true\n props.onResolve?.()\n }\n }\n\n registerSuspenseHandler(token => {\n const tokenEpoch = epoch\n pending(pending() + 1)\n switchView(toFallback())\n\n const thenable = (token as SuspenseToken).then\n ? (token as SuspenseToken)\n : isThenable(token)\n ? token\n : null\n\n if (thenable) {\n thenable.then(\n () => {\n // This prevents stale token resolutions from affecting state after\n // a reset. The order is important: check epoch first, then update state.\n if (epoch !== tokenEpoch) {\n // Token is stale (from before a reset), ignore it completely\n return\n }\n // Use Math.max as a defensive measure - pending should never go below 0,\n // but this protects against edge cases where a token might resolve twice\n // or after the component has been reset.\n const newPending = Math.max(0, pending() - 1)\n pending(newPending)\n if (newPending === 0) {\n switchView(props.children ?? null)\n onResolveMaybe()\n }\n },\n err => {\n // Same epoch check - ignore stale tokens\n if (epoch !== tokenEpoch) {\n return\n }\n const newPending = Math.max(0, pending() - 1)\n pending(newPending)\n props.onReject?.(err)\n if (!handleError(err, { source: 'render' }, hostRoot)) {\n throw err\n }\n },\n )\n return true\n }\n\n return false\n })\n\n createEffect(() => {\n renderView(currentView())\n })\n\n if (props.resetKeys !== undefined) {\n const isGetter =\n typeof props.resetKeys === 'function' && (props.resetKeys as () => unknown).length === 0\n const getter = isGetter ? (props.resetKeys as () => unknown) : undefined\n let prev = isGetter ? getter!() : props.resetKeys\n createEffect(() => {\n const next = getter ? getter() : props.resetKeys\n if (prev !== next) {\n prev = next\n epoch++\n pending(0)\n switchView(props.children ?? null)\n }\n })\n }\n\n return fragment\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/fict/fict/packages/runtime/dist/index.cjs","../src/ref.ts","../src/error-boundary.ts","../src/suspense.ts"],"names":[],"mappings":"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","file":"/home/runner/work/fict/fict/packages/runtime/dist/index.cjs","sourcesContent":[null,"import type { RefObject } from './types'\n\n/**\n * Create a ref object for DOM element references.\n *\n * @returns A ref object with a `current` property initialized to `null`\n *\n * @example\n * ```tsx\n * import { createRef } from 'fict'\n *\n * function Component() {\n * const inputRef = createRef<HTMLInputElement>()\n *\n * $effect(() => {\n * inputRef.current?.focus()\n * })\n *\n * return <input ref={inputRef} />\n * }\n * ```\n */\nexport function createRef<T extends Element = HTMLElement>(): RefObject<T> {\n return { current: null }\n}\n","import { createElement } from './dom'\nimport { createEffect } from './effect'\nimport {\n createRootContext,\n destroyRoot,\n flushOnMount,\n getCurrentRoot,\n pushRoot,\n popRoot,\n registerErrorHandler,\n} from './lifecycle'\nimport { insertNodesBefore, removeNodes, toNodeArray } from './node-ops'\nimport { createSignal } from './signal'\nimport type { BaseProps, FictNode } from './types'\n\ninterface ErrorBoundaryProps extends BaseProps {\n fallback: FictNode | ((err: unknown) => FictNode)\n onError?: (err: unknown) => void\n resetKeys?: unknown | (() => unknown)\n}\n\nexport function ErrorBoundary(props: ErrorBoundaryProps): FictNode {\n const fragment = document.createDocumentFragment()\n const marker = document.createComment('fict:error-boundary')\n fragment.appendChild(marker)\n\n const currentView = createSignal<FictNode | null>(props.children ?? null)\n const hostRoot = getCurrentRoot()\n\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n let renderingFallback = false\n\n const toView = (err: unknown | null): FictNode | null => {\n if (err != null) {\n return typeof props.fallback === 'function'\n ? (props.fallback as (e: unknown) => FictNode)(err)\n : props.fallback\n }\n return props.children ?? null\n }\n\n const renderValue = (value: FictNode | null) => {\n if (cleanup) {\n cleanup()\n cleanup = undefined\n }\n if (activeNodes.length) {\n removeNodes(activeNodes)\n activeNodes = []\n }\n\n if (value == null || value === false) {\n return\n }\n\n const root = createRootContext(hostRoot)\n const prev = pushRoot(root)\n let nodes: Node[] = []\n try {\n const output = createElement(value)\n nodes = toNodeArray(output)\n const parentNode = marker.parentNode as (ParentNode & Node) | null\n if (parentNode) {\n insertNodesBefore(parentNode, nodes, marker)\n }\n } catch (err) {\n popRoot(prev)\n flushOnMount(root)\n destroyRoot(root)\n // Fall back immediately on render errors, avoid infinite recursion\n if (renderingFallback) {\n throw err\n }\n // nested errors. If fallback rendering also throws, we should NOT reset\n // the flag until we're sure no more recursion is happening.\n renderingFallback = true\n try {\n renderValue(toView(err))\n // Only reset if successful - if renderValue threw, we want to keep\n // renderingFallback = true to prevent infinite recursion\n renderingFallback = false\n props.onError?.(err)\n } catch (fallbackErr) {\n // Fallback rendering failed - keep renderingFallback = true\n // to prevent further attempts, then rethrow\n // If fallback fails, report both errors\n props.onError?.(err)\n throw fallbackErr\n }\n return\n }\n popRoot(prev)\n flushOnMount(root)\n\n cleanup = () => {\n destroyRoot(root)\n removeNodes(nodes)\n }\n activeNodes = nodes\n }\n\n createEffect(() => {\n const value = currentView()\n renderValue(value)\n })\n\n registerErrorHandler(err => {\n renderValue(toView(err))\n props.onError?.(err)\n return true\n })\n\n if (props.resetKeys !== undefined) {\n const isGetter =\n typeof props.resetKeys === 'function' && (props.resetKeys as () => unknown).length === 0\n const getter = isGetter ? (props.resetKeys as () => unknown) : undefined\n let prev = isGetter ? getter!() : props.resetKeys\n createEffect(() => {\n const next = getter ? getter() : props.resetKeys\n if (prev !== next) {\n prev = next\n renderValue(toView(null))\n }\n })\n }\n\n return fragment\n}\n","import { createElement } from './dom'\nimport { createEffect } from './effect'\nimport {\n createRootContext,\n destroyRoot,\n flushOnMount,\n getCurrentRoot,\n handleError,\n pushRoot,\n popRoot,\n registerSuspenseHandler,\n} from './lifecycle'\nimport { insertNodesBefore, removeNodes, toNodeArray } from './node-ops'\nimport { createSignal } from './signal'\nimport type { BaseProps, FictNode, SuspenseToken } from './types'\n\nexport interface SuspenseProps extends BaseProps {\n fallback: FictNode | ((err?: unknown) => FictNode)\n onResolve?: () => void\n onReject?: (err: unknown) => void\n resetKeys?: unknown | (() => unknown)\n}\n\nexport interface SuspenseHandle {\n token: SuspenseToken\n resolve: () => void\n reject: (err: unknown) => void\n}\n\nexport function createSuspenseToken(): SuspenseHandle {\n let resolve!: () => void\n let reject!: (err: unknown) => void\n const promise = new Promise<void>((res, rej) => {\n resolve = res\n reject = rej\n })\n return {\n token: {\n then: promise.then.bind(promise),\n },\n resolve,\n reject,\n }\n}\n\nconst isThenable = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as PromiseLike<unknown>).then === 'function'\n\nexport function Suspense(props: SuspenseProps): FictNode {\n const currentView = createSignal<FictNode | null>(props.children ?? null)\n const pending = createSignal(0)\n let resolvedOnce = false\n let epoch = 0\n const hostRoot = getCurrentRoot()\n\n const toFallback = (err?: unknown) =>\n typeof props.fallback === 'function'\n ? (props.fallback as (e?: unknown) => FictNode)(err)\n : props.fallback\n\n const renderView = (view: FictNode | null) => {\n if (cleanup) {\n cleanup()\n cleanup = undefined\n }\n if (activeNodes.length) {\n removeNodes(activeNodes)\n activeNodes = []\n }\n\n if (view == null || view === false) {\n return\n }\n\n const root = createRootContext(hostRoot)\n const prev = pushRoot(root)\n let nodes: Node[] = []\n try {\n const output = createElement(view)\n nodes = toNodeArray(output)\n // Suspended view: child threw a suspense token and was handled upstream.\n // Avoid replacing existing fallback content; tear down this attempt.\n const suspendedAttempt =\n root.suspended ||\n (nodes.length > 0 &&\n nodes.every(node => node instanceof Comment && (node as Comment).data === 'fict:suspend'))\n if (suspendedAttempt) {\n popRoot(prev)\n destroyRoot(root)\n return\n }\n const parentNode = marker.parentNode as (ParentNode & Node) | null\n if (parentNode) {\n insertNodesBefore(parentNode, nodes, marker)\n }\n } catch (err) {\n popRoot(prev)\n flushOnMount(root)\n destroyRoot(root)\n if (!handleError(err, { source: 'render' }, hostRoot)) {\n throw err\n }\n return\n }\n popRoot(prev)\n flushOnMount(root)\n\n cleanup = () => {\n destroyRoot(root)\n removeNodes(nodes)\n }\n activeNodes = nodes\n }\n\n const fragment = document.createDocumentFragment()\n const marker = document.createComment('fict:suspense')\n fragment.appendChild(marker)\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n\n const onResolveMaybe = () => {\n if (!resolvedOnce) {\n resolvedOnce = true\n props.onResolve?.()\n }\n }\n\n registerSuspenseHandler(token => {\n const tokenEpoch = epoch\n pending(pending() + 1)\n // Directly render fallback instead of using switchView to avoid\n // triggering the effect which would cause duplicate renders\n currentView(toFallback())\n renderView(toFallback())\n\n const thenable = (token as SuspenseToken).then\n ? (token as SuspenseToken)\n : isThenable(token)\n ? token\n : null\n\n if (thenable) {\n thenable.then(\n () => {\n // This prevents stale token resolutions from affecting state after\n // a reset. The order is important: check epoch first, then update state.\n if (epoch !== tokenEpoch) {\n // Token is stale (from before a reset), ignore it completely\n return\n }\n // Use Math.max as a defensive measure - pending should never go below 0,\n // but this protects against edge cases where a token might resolve twice\n // or after the component has been reset.\n const newPending = Math.max(0, pending() - 1)\n pending(newPending)\n if (newPending === 0) {\n // Directly render children instead of using switchView\n currentView(props.children ?? null)\n renderView(props.children ?? null)\n onResolveMaybe()\n }\n },\n err => {\n // Same epoch check - ignore stale tokens\n if (epoch !== tokenEpoch) {\n return\n }\n const newPending = Math.max(0, pending() - 1)\n pending(newPending)\n props.onReject?.(err)\n if (!handleError(err, { source: 'render' }, hostRoot)) {\n throw err\n }\n },\n )\n return true\n }\n\n return false\n })\n\n // Initial render - render children directly\n // Note: This will be called synchronously during component creation.\n // If children suspend, the handler above will be called and switch to fallback.\n renderView(props.children ?? null)\n\n if (props.resetKeys !== undefined) {\n const isGetter =\n typeof props.resetKeys === 'function' && (props.resetKeys as () => unknown).length === 0\n const getter = isGetter ? (props.resetKeys as () => unknown) : undefined\n let prev = isGetter ? getter!() : props.resetKeys\n createEffect(() => {\n const next = getter ? getter() : props.resetKeys\n if (prev !== next) {\n prev = next\n epoch++\n pending(0)\n // Directly render children instead of using switchView\n currentView(props.children ?? null)\n renderView(props.children ?? null)\n }\n })\n }\n\n return fragment\n}\n"]}
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.
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.
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;
@@ -2687,10 +2737,6 @@ function Suspense(props) {
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);
@@ -2750,7 +2796,8 @@ function Suspense(props) {
2750
2796
  registerSuspenseHandler((token) => {
2751
2797
  const tokenEpoch = epoch;
2752
2798
  pending(pending() + 1);
2753
- switchView(toFallback());
2799
+ currentView(toFallback());
2800
+ renderView(toFallback());
2754
2801
  const thenable = token.then ? token : isThenable(token) ? token : null;
2755
2802
  if (thenable) {
2756
2803
  thenable.then(
@@ -2761,7 +2808,8 @@ function Suspense(props) {
2761
2808
  const newPending = Math.max(0, pending() - 1);
2762
2809
  pending(newPending);
2763
2810
  if (newPending === 0) {
2764
- switchView(props.children ?? null);
2811
+ currentView(props.children ?? null);
2812
+ renderView(props.children ?? null);
2765
2813
  onResolveMaybe();
2766
2814
  }
2767
2815
  },
@@ -2781,9 +2829,7 @@ function Suspense(props) {
2781
2829
  }
2782
2830
  return false;
2783
2831
  });
2784
- createEffect(() => {
2785
- renderView(currentView());
2786
- });
2832
+ renderView(props.children ?? null);
2787
2833
  if (props.resetKeys !== void 0) {
2788
2834
  const isGetter = typeof props.resetKeys === "function" && props.resetKeys.length === 0;
2789
2835
  const getter = isGetter ? props.resetKeys : void 0;
@@ -2794,7 +2840,8 @@ function Suspense(props) {
2794
2840
  prev = next;
2795
2841
  epoch++;
2796
2842
  pending(0);
2797
- switchView(props.children ?? null);
2843
+ currentView(props.children ?? null);
2844
+ renderView(props.children ?? null);
2798
2845
  }
2799
2846
  });
2800
2847
  }