@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.
- package/dist/advanced.cjs +8 -8
- package/dist/advanced.d.cts +3 -3
- package/dist/advanced.d.ts +3 -3
- package/dist/advanced.js +3 -3
- package/dist/{chunk-Q4EN6BXV.cjs → chunk-527QSKFM.cjs} +16 -16
- package/dist/{chunk-Q4EN6BXV.cjs.map → chunk-527QSKFM.cjs.map} +1 -1
- package/dist/{chunk-BWZFJXUI.js → chunk-5KXEEQUO.js} +84 -10
- package/dist/chunk-5KXEEQUO.js.map +1 -0
- package/dist/{chunk-YQ4IB7NC.cjs → chunk-BSUMPMKX.cjs} +7 -7
- package/dist/{chunk-YQ4IB7NC.cjs.map → chunk-BSUMPMKX.cjs.map} +1 -1
- package/dist/{chunk-V62XZLDU.js → chunk-FG3M7EBL.js} +2 -2
- package/dist/{chunk-7WAGAQLT.cjs → chunk-J74L7UYP.cjs} +84 -10
- package/dist/chunk-J74L7UYP.cjs.map +1 -0
- package/dist/{chunk-CF3OHML2.js → chunk-QV5GOCR5.js} +2 -2
- package/dist/{context-B7UYnfzM.d.ts → context-4woHo7-L.d.ts} +1 -1
- package/dist/{context-UXySaqI_.d.cts → context-9gFXOdJl.d.cts} +1 -1
- package/dist/{effect-Auji1rz9.d.cts → effect-ClARNUCc.d.cts} +23 -2
- package/dist/{effect-Auji1rz9.d.ts → effect-ClARNUCc.d.ts} +23 -2
- package/dist/index.cjs +51 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.dev.js +66 -19
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +10 -13
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +34 -34
- package/dist/internal.d.cts +4 -4
- package/dist/internal.d.ts +4 -4
- package/dist/internal.js +2 -2
- package/dist/jsx-runtime.d.cts +671 -0
- package/dist/jsx-runtime.d.ts +671 -0
- package/dist/{props-BfmSLuyp.d.cts → props-CBwuh35e.d.cts} +4 -4
- package/dist/{props-BBi8Tkks.d.ts → props-DAyeRPwH.d.ts} +4 -4
- package/dist/{scope-S6eAzBJZ.d.ts → scope-DvgMquEy.d.ts} +1 -1
- package/dist/{scope-DKYzWfTn.d.cts → scope-xmdo6lVU.d.cts} +1 -1
- package/package.json +1 -1
- package/src/binding.ts +58 -5
- package/src/effect.ts +9 -2
- package/src/lifecycle.ts +13 -3
- package/src/signal.ts +43 -4
- package/src/suspense.ts +17 -13
- package/dist/chunk-7WAGAQLT.cjs.map +0 -1
- package/dist/chunk-BWZFJXUI.js.map +0 -1
- /package/dist/{chunk-V62XZLDU.js.map → chunk-FG3M7EBL.js.map} +0 -0
- /package/dist/{chunk-CF3OHML2.js.map → chunk-QV5GOCR5.js.map} +0 -0
|
@@ -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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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 =
|
|
50
|
-
const hostRoot =
|
|
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
|
-
|
|
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 =
|
|
73
|
-
const prev =
|
|
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 =
|
|
77
|
-
nodes =
|
|
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
|
-
|
|
80
|
+
_chunkJ74L7UYPcjs.insertNodesBefore.call(void 0, parentNode, nodes, marker);
|
|
81
81
|
}
|
|
82
82
|
} catch (err) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
101
|
-
|
|
100
|
+
_chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
|
|
101
|
+
_chunkJ74L7UYPcjs.flushOnMount.call(void 0, root);
|
|
102
102
|
cleanup = () => {
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
_chunkJ74L7UYPcjs.destroyRoot.call(void 0, root);
|
|
104
|
+
_chunkJ74L7UYPcjs.removeNodes.call(void 0, nodes);
|
|
105
105
|
};
|
|
106
106
|
activeNodes = nodes;
|
|
107
107
|
};
|
|
108
|
-
|
|
108
|
+
_chunkJ74L7UYPcjs.createEffect.call(void 0, () => {
|
|
109
109
|
const value = currentView();
|
|
110
110
|
renderValue(value);
|
|
111
111
|
});
|
|
112
|
-
|
|
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
|
-
|
|
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 =
|
|
151
|
-
const pending =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
173
|
-
const prev =
|
|
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 =
|
|
177
|
-
nodes =
|
|
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
|
-
|
|
181
|
-
|
|
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
|
-
|
|
182
|
+
_chunkJ74L7UYPcjs.insertNodesBefore.call(void 0, parentNode, nodes, marker);
|
|
187
183
|
}
|
|
188
184
|
} catch (err) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if (!
|
|
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
|
-
|
|
198
|
-
|
|
193
|
+
_chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
|
|
194
|
+
_chunkJ74L7UYPcjs.flushOnMount.call(void 0, root);
|
|
199
195
|
cleanup = () => {
|
|
200
|
-
|
|
201
|
-
|
|
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
|
-
|
|
212
|
+
_chunkJ74L7UYPcjs.registerSuspenseHandler.call(void 0, (token) => {
|
|
217
213
|
const tokenEpoch = epoch;
|
|
218
214
|
pending(pending() + 1);
|
|
219
|
-
|
|
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
|
-
|
|
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 (!
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
package/dist/index.cjs.map
CHANGED
|
@@ -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-
|
|
2
|
-
import { R as RefObject, B as BaseProps, F as FictNode, S as SuspenseToken } from './effect-
|
|
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-
|
|
4
|
-
export { C as Context, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-
|
|
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-
|
|
2
|
-
import { R as RefObject, B as BaseProps, F as FictNode, S as SuspenseToken } from './effect-
|
|
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-
|
|
4
|
-
export { C as Context, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-
|
|
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)
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2843
|
+
currentView(props.children ?? null);
|
|
2844
|
+
renderView(props.children ?? null);
|
|
2798
2845
|
}
|
|
2799
2846
|
});
|
|
2800
2847
|
}
|