@fictjs/runtime 0.17.0 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/advanced.cjs +9 -9
  2. package/dist/advanced.d.cts +3 -3
  3. package/dist/advanced.d.ts +3 -3
  4. package/dist/advanced.js +4 -4
  5. package/dist/{binding-CQUGLLBI.d.ts → binding-BfzY9rae.d.ts} +2 -2
  6. package/dist/{binding-BlABuUiG.d.cts → binding-CDR2ERoq.d.cts} +2 -2
  7. package/dist/{chunk-5FVWBK4M.cjs → chunk-2J4INHDT.cjs} +40 -40
  8. package/dist/{chunk-5FVWBK4M.cjs.map → chunk-2J4INHDT.cjs.map} +1 -1
  9. package/dist/{chunk-6DNYVH5U.cjs → chunk-CKKZDUHM.cjs} +21 -18
  10. package/dist/chunk-CKKZDUHM.cjs.map +1 -0
  11. package/dist/{chunk-UQTWIV3S.js → chunk-DHRRJJ6W.js} +8 -5
  12. package/dist/chunk-DHRRJJ6W.js.map +1 -0
  13. package/dist/{chunk-IIWHTV23.js → chunk-LFLFSJFU.js} +3 -3
  14. package/dist/{chunk-ECKYFH5Q.cjs → chunk-NBDEMBBX.cjs} +43 -81
  15. package/dist/chunk-NBDEMBBX.cjs.map +1 -0
  16. package/dist/{chunk-CFAWL76V.js → chunk-OKPQWORE.js} +43 -81
  17. package/dist/chunk-OKPQWORE.js.map +1 -0
  18. package/dist/{chunk-M42N54LG.js → chunk-OLHZBAIF.js} +3 -3
  19. package/dist/{chunk-F5SDRX4J.js → chunk-R2HYEOP7.js} +470 -172
  20. package/dist/chunk-R2HYEOP7.js.map +1 -0
  21. package/dist/{chunk-INYTG4NG.cjs → chunk-UG2IFQOY.cjs} +650 -352
  22. package/dist/chunk-UG2IFQOY.cjs.map +1 -0
  23. package/dist/{chunk-WY4LI5PB.cjs → chunk-VP2WC7X3.cjs} +8 -8
  24. package/dist/{chunk-WY4LI5PB.cjs.map → chunk-VP2WC7X3.cjs.map} +1 -1
  25. package/dist/{devtools-DWIZRe7L.d.cts → devtools-BwkkQ6DN.d.cts} +1 -1
  26. package/dist/{devtools-DNnnDGu1.d.ts → devtools-CK3SVU_w.d.ts} +1 -1
  27. package/dist/index.cjs +55 -42
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +4 -4
  30. package/dist/index.d.ts +4 -4
  31. package/dist/index.dev.js +260 -156
  32. package/dist/index.dev.js.map +1 -1
  33. package/dist/index.js +16 -3
  34. package/dist/index.js.map +1 -1
  35. package/dist/internal-list.cjs +4 -4
  36. package/dist/internal-list.js +3 -3
  37. package/dist/internal.cjs +5 -5
  38. package/dist/internal.d.cts +3 -3
  39. package/dist/internal.d.ts +3 -3
  40. package/dist/internal.js +4 -4
  41. package/dist/loader.cjs +18 -18
  42. package/dist/loader.js +1 -1
  43. package/dist/{props-C04ScJgm.d.ts → props-CFoQ471Y.d.ts} +1 -1
  44. package/dist/{props-CdmuXCiu.d.cts → props-D4tK8Gn0.d.cts} +1 -1
  45. package/dist/{scope-gpOMWTlf.d.ts → scope-BFzD_7hx.d.ts} +1 -1
  46. package/dist/{scope-GwC4DJ50.d.cts → scope-Ck3mTQVS.d.cts} +1 -1
  47. package/package.json +1 -1
  48. package/src/binding.ts +561 -166
  49. package/src/context.ts +8 -1
  50. package/src/dom.ts +26 -44
  51. package/src/effect.ts +9 -12
  52. package/src/error-boundary.ts +8 -0
  53. package/src/hydration.ts +25 -6
  54. package/src/lifecycle.ts +31 -79
  55. package/src/signal.ts +4 -1
  56. package/src/suspense.ts +8 -0
  57. package/dist/chunk-6DNYVH5U.cjs.map +0 -1
  58. package/dist/chunk-CFAWL76V.js.map +0 -1
  59. package/dist/chunk-ECKYFH5Q.cjs.map +0 -1
  60. package/dist/chunk-F5SDRX4J.js.map +0 -1
  61. package/dist/chunk-INYTG4NG.cjs.map +0 -1
  62. package/dist/chunk-UQTWIV3S.js.map +0 -1
  63. /package/dist/{chunk-IIWHTV23.js.map → chunk-LFLFSJFU.js.map} +0 -0
  64. /package/dist/{chunk-M42N54LG.js.map → chunk-OLHZBAIF.js.map} +0 -0
package/dist/index.dev.js CHANGED
@@ -179,8 +179,6 @@ var reportCycle = (reason, detail = void 0) => {
179
179
  var isDev2 = true ? true : typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
180
180
  var currentRoot;
181
181
  var currentEffectCleanups;
182
- var globalErrorHandlers = /* @__PURE__ */ new WeakMap();
183
- var globalSuspenseHandlers = /* @__PURE__ */ new WeakMap();
184
182
  var rootDevtoolsIds = /* @__PURE__ */ new WeakMap();
185
183
  var nextRootDevtoolsId = 0;
186
184
  function registerRootDevtools(root) {
@@ -255,18 +253,27 @@ function onCleanup(fn) {
255
253
  function flushOnMount(root) {
256
254
  const cbs = root.onMountCallbacks;
257
255
  if (!cbs || cbs.length === 0) return;
256
+ try {
257
+ withRootContext(root, () => {
258
+ for (let i = 0; i < cbs.length; i++) {
259
+ const cleanup = cbs[i]();
260
+ if (typeof cleanup === "function") {
261
+ root.cleanups.push(cleanup);
262
+ }
263
+ }
264
+ });
265
+ } finally {
266
+ cbs.length = 0;
267
+ }
268
+ }
269
+ function withRootContext(root, fn) {
270
+ if (!root) return fn();
258
271
  const prevRoot = currentRoot;
259
272
  currentRoot = root;
260
273
  try {
261
- for (let i = 0; i < cbs.length; i++) {
262
- const cleanup = cbs[i]();
263
- if (typeof cleanup === "function") {
264
- root.cleanups.push(cleanup);
265
- }
266
- }
274
+ return fn();
267
275
  } finally {
268
276
  currentRoot = prevRoot;
269
- cbs.length = 0;
270
277
  }
271
278
  }
272
279
  function registerRootCleanup(fn) {
@@ -275,26 +282,20 @@ function registerRootCleanup(fn) {
275
282
  }
276
283
  }
277
284
  function clearRoot(root) {
278
- runCleanupList(root.cleanups);
285
+ runCleanupList(root.cleanups, root);
279
286
  if (root.onMountCallbacks) {
280
287
  root.onMountCallbacks.length = 0;
281
288
  }
282
289
  }
283
290
  function destroyRoot(root) {
284
291
  clearRoot(root);
285
- runCleanupList(root.destroyCallbacks);
292
+ runCleanupList(root.destroyCallbacks, root);
286
293
  if (root.errorHandlers) {
287
294
  root.errorHandlers.length = 0;
288
295
  }
289
- if (globalErrorHandlers.has(root)) {
290
- globalErrorHandlers.delete(root);
291
- }
292
296
  if (root.suspenseHandlers) {
293
297
  root.suspenseHandlers.length = 0;
294
298
  }
295
- if (globalSuspenseHandlers.has(root)) {
296
- globalSuspenseHandlers.delete(root);
297
- }
298
299
  disposeRootDevtools(root);
299
300
  }
300
301
  function createRoot(fn, options2) {
@@ -329,21 +330,23 @@ function registerEffectCleanup(fn) {
329
330
  registerRootCleanup(fn);
330
331
  }
331
332
  }
332
- function runCleanupList(list) {
333
+ function runCleanupList(list, root) {
333
334
  let error;
334
- for (let i = list.length - 1; i >= 0; i--) {
335
- try {
336
- const cleanup = list[i];
337
- if (cleanup) cleanup();
338
- } catch (err) {
339
- if (error === void 0) {
340
- error = err;
335
+ withRootContext(root, () => {
336
+ for (let i = list.length - 1; i >= 0; i--) {
337
+ try {
338
+ const cleanup = list[i];
339
+ if (cleanup) cleanup();
340
+ } catch (err) {
341
+ if (error === void 0) {
342
+ error = err;
343
+ }
341
344
  }
342
345
  }
343
- }
346
+ });
344
347
  list.length = 0;
345
348
  if (error !== void 0) {
346
- if (!handleError(error, { source: "cleanup" })) {
349
+ if (!handleError(error, { source: "cleanup" }, root)) {
347
350
  throw error;
348
351
  }
349
352
  }
@@ -363,12 +366,6 @@ function registerErrorHandler(fn) {
363
366
  currentRoot.errorHandlers = [];
364
367
  }
365
368
  currentRoot.errorHandlers.push(fn);
366
- const existing = globalErrorHandlers.get(currentRoot);
367
- if (existing) {
368
- existing.push(fn);
369
- } else {
370
- globalErrorHandlers.set(currentRoot, [fn]);
371
- }
372
369
  }
373
370
  function registerSuspenseHandler(fn) {
374
371
  if (!currentRoot) {
@@ -379,12 +376,6 @@ function registerSuspenseHandler(fn) {
379
376
  currentRoot.suspenseHandlers = [];
380
377
  }
381
378
  currentRoot.suspenseHandlers.push(fn);
382
- const existing = globalSuspenseHandlers.get(currentRoot);
383
- if (existing) {
384
- existing.push(fn);
385
- } else {
386
- globalSuspenseHandlers.set(currentRoot, [fn]);
387
- }
388
379
  }
389
380
  function handleError(err, info, startRoot) {
390
381
  let root = startRoot ?? currentRoot;
@@ -406,20 +397,6 @@ function handleError(err, info, startRoot) {
406
397
  }
407
398
  root = root.parent;
408
399
  }
409
- const globalForRoot = startRoot ? globalErrorHandlers.get(startRoot) : currentRoot ? globalErrorHandlers.get(currentRoot) : void 0;
410
- if (globalForRoot && globalForRoot.length) {
411
- for (let i = globalForRoot.length - 1; i >= 0; i--) {
412
- const handler = globalForRoot[i];
413
- try {
414
- const handled = handler(error, info);
415
- if (handled !== false) {
416
- return true;
417
- }
418
- } catch (nextErr) {
419
- error = nextErr;
420
- }
421
- }
422
- }
423
400
  return false;
424
401
  }
425
402
  function handleSuspend(token, startRoot) {
@@ -442,20 +419,6 @@ function handleSuspend(token, startRoot) {
442
419
  }
443
420
  root = root.parent;
444
421
  }
445
- const globalForRoot = startRoot && globalSuspenseHandlers.get(startRoot) ? globalSuspenseHandlers.get(startRoot) : currentRoot ? globalSuspenseHandlers.get(currentRoot) : void 0;
446
- if (globalForRoot && globalForRoot.length) {
447
- for (let i = globalForRoot.length - 1; i >= 0; i--) {
448
- const handler = globalForRoot[i];
449
- const handled = handler(token);
450
- if (handled !== false) {
451
- if (originRoot) {
452
- originRoot.suspended = true;
453
- setRootSuspendDevtools(originRoot, true);
454
- }
455
- return true;
456
- }
457
- }
458
- }
459
422
  return false;
460
423
  }
461
424
 
@@ -464,7 +427,7 @@ function createEffect(fn, options2) {
464
427
  let cleanups = [];
465
428
  const rootForError = getCurrentRoot();
466
429
  const doCleanup = () => {
467
- runCleanupList(cleanups);
430
+ runCleanupList(cleanups, rootForError);
468
431
  cleanups = [];
469
432
  };
470
433
  const run = () => {
@@ -489,26 +452,26 @@ function createEffect(fn, options2) {
489
452
  };
490
453
  const disposeEffect = effectWithCleanup(run, doCleanup, rootForError, options2);
491
454
  const teardown = () => {
492
- runCleanupList(cleanups);
455
+ runCleanupList(cleanups, rootForError);
493
456
  disposeEffect();
494
457
  };
495
458
  registerRootCleanup(teardown);
496
459
  return teardown;
497
460
  }
498
461
  function createRenderEffect(fn, options2) {
499
- let cleanup;
462
+ let cleanups = [];
500
463
  const rootForError = getCurrentRoot();
501
464
  const doCleanup = () => {
502
- if (cleanup) {
503
- cleanup();
504
- cleanup = void 0;
505
- }
465
+ runCleanupList(cleanups, rootForError);
466
+ cleanups = [];
506
467
  };
507
468
  const run = () => {
508
469
  try {
509
470
  const maybeCleanup = fn();
510
471
  if (typeof maybeCleanup === "function") {
511
- cleanup = maybeCleanup;
472
+ cleanups = [maybeCleanup];
473
+ } else {
474
+ cleanups = [];
512
475
  }
513
476
  } catch (err) {
514
477
  if (handleSuspend(err, rootForError)) {
@@ -523,10 +486,7 @@ function createRenderEffect(fn, options2) {
523
486
  };
524
487
  const disposeEffect = effectWithCleanup(run, doCleanup, rootForError, options2);
525
488
  const teardown = () => {
526
- if (cleanup) {
527
- cleanup();
528
- cleanup = void 0;
529
- }
489
+ runCleanupList(cleanups, rootForError);
530
490
  disposeEffect();
531
491
  };
532
492
  registerRootCleanup(teardown);
@@ -865,7 +825,9 @@ function runEffect(e) {
865
825
  inCleanup = true;
866
826
  activeCleanupFlushId = currentFlushId;
867
827
  try {
868
- e.runCleanup();
828
+ withRootContext(e.root, () => {
829
+ e.runCleanup();
830
+ });
869
831
  } finally {
870
832
  activeCleanupFlushId = 0;
871
833
  inCleanup = false;
@@ -1925,11 +1887,26 @@ function withHydration(root, fn) {
1925
1887
  owner
1926
1888
  });
1927
1889
  try {
1928
- fn();
1890
+ return fn();
1929
1891
  } finally {
1930
1892
  hydrationStack.pop();
1931
1893
  }
1932
1894
  }
1895
+ function claimText(value, fallback) {
1896
+ const ctx = hydrationStack[hydrationStack.length - 1];
1897
+ if (!ctx || !ctx.cursor || ctx.cursor === ctx.boundary || ctx.cursor.nodeType !== Node.TEXT_NODE) {
1898
+ return fallback();
1899
+ }
1900
+ const text = ctx.cursor;
1901
+ ctx.cursor = text.nextSibling;
1902
+ if (text.data !== value) {
1903
+ text.data = value;
1904
+ }
1905
+ return text;
1906
+ }
1907
+ function isHydratingActive() {
1908
+ return hydrationStack.length > 0;
1909
+ }
1933
1910
 
1934
1911
  // src/node-ops.ts
1935
1912
  function toNodeArray(node, ownerDocument = document) {
@@ -2149,7 +2126,9 @@ var PROP_CACHE = Symbol("fict:prop");
2149
2126
  var STYLE_CACHE = Symbol("fict:style");
2150
2127
  var CLASS_STATE_CACHE = Symbol("fict:class-state");
2151
2128
  var CLASS_VALUE_CACHE = Symbol("fict:class-value");
2152
- var EVENT_TUPLE_LISTENER_CACHE = Symbol("fict:event-tuple-listener-cache");
2129
+ var EVENT_LISTENER_CACHE = Symbol("fict:event-listener-cache");
2130
+ var REF_ASSIGN_CACHE = Symbol("fict:ref-assign-cache");
2131
+ var CHILDREN_BINDING_CACHE = Symbol("fict:children-binding-cache");
2153
2132
  var NON_REACTIVE_FN_MARKER = Symbol.for("fict:non-reactive-fn");
2154
2133
  var REACTIVE_FN_MARKER = Symbol.for("fict:reactive-fn");
2155
2134
  var NON_REACTIVE_FN_REGISTRY_KEY = Symbol.for("fict:non-reactive-fn-registry");
@@ -2168,6 +2147,10 @@ function isExplicitReactiveFn(value) {
2168
2147
  if (typeof value !== "function") return false;
2169
2148
  return value[REACTIVE_FN_MARKER] === true;
2170
2149
  }
2150
+ var registeredCreateElement;
2151
+ function registerCreateElement(fn) {
2152
+ registeredCreateElement = fn;
2153
+ }
2171
2154
  function isReactive(value) {
2172
2155
  if (typeof value !== "function") return false;
2173
2156
  if (isNonReactiveFn(value)) return false;
@@ -2440,26 +2423,18 @@ function globalEventHandler(e) {
2440
2423
  if (!node) return false;
2441
2424
  const handler = node[key];
2442
2425
  if (handler && !node.disabled) {
2443
- const resolveData = (value) => {
2444
- if (typeof value === "function") {
2445
- try {
2446
- const fn = value;
2447
- return fn.length > 0 ? fn(e) : fn();
2448
- } catch {
2449
- return value();
2450
- }
2451
- }
2452
- return value;
2453
- };
2454
2426
  const rawData = node[dataKey];
2455
2427
  const hasData = rawData !== void 0;
2456
- const resolvedNodeData = hasData ? resolveData(rawData) : void 0;
2428
+ const resolvedNodeData = hasData ? resolveEventData(rawData, e) : void 0;
2457
2429
  batch2(() => {
2458
2430
  if (typeof handler === "function") {
2459
2431
  callEventHandler(handler, e, node, hasData ? resolvedNodeData : void 0);
2460
2432
  } else if (Array.isArray(handler)) {
2461
- const tupleData = resolveData(handler[1]);
2462
- callEventHandler(handler[0], e, node, tupleData);
2433
+ const tupleHandler = resolveEventHandlerValue(
2434
+ handler[0]
2435
+ );
2436
+ const tupleData = resolveEventData(handler[1], e);
2437
+ callEventHandler(tupleHandler, e, node, tupleData);
2463
2438
  }
2464
2439
  });
2465
2440
  if (e.cancelBubble) return false;
@@ -2507,34 +2482,104 @@ function globalEventHandler(e) {
2507
2482
  }
2508
2483
  retarget(oriTarget);
2509
2484
  }
2510
- function bindEvent(el, eventName, handler, options2) {
2511
- if (handler == null) return () => {
2512
- };
2485
+ function addEventListener(node, name, handler, delegate, options2) {
2486
+ if (delegate) {
2487
+ const key = `$$${name}`;
2488
+ const dataKey = `${key}Data`;
2489
+ const rootRef2 = getCurrentRoot();
2490
+ const delegationDocument = resolveDelegationDocument(node, rootRef2);
2491
+ delegateEvents([name], delegationDocument);
2492
+ if (handler == null) {
2493
+ ;
2494
+ node[key] = void 0;
2495
+ node[dataKey] = void 0;
2496
+ return;
2497
+ }
2498
+ ;
2499
+ node[key] = createEventInvoker(
2500
+ name,
2501
+ handler,
2502
+ node,
2503
+ rootRef2
2504
+ );
2505
+ node[dataKey] = void 0;
2506
+ return;
2507
+ }
2508
+ removeStoredEventListener(node, name, options2);
2509
+ if (handler == null) return;
2513
2510
  const rootRef = getCurrentRoot();
2514
- const shouldDelegate = options2 == null && DelegatedEvents.has(eventName);
2515
- if (shouldDelegate) {
2516
- const key = `$$${eventName}`;
2517
- delegateEvents([eventName]);
2518
- const resolveHandler = isStrictlyReactive(handler) ? handler : () => handler;
2519
- el[key] = function(...args) {
2520
- try {
2521
- const fn = resolveHandler();
2522
- callEventHandler(fn, args[0], el);
2523
- } catch (err) {
2524
- if (!handleError(err, { source: "event", eventName }, rootRef)) {
2525
- throw err;
2526
- }
2527
- }
2528
- };
2529
- return () => {
2530
- el[key] = void 0;
2531
- };
2511
+ const wrapped = createEventInvoker(name, handler, node, rootRef);
2512
+ node.addEventListener(name, wrapped, options2);
2513
+ getStoredEventListenerStore(node).set(getEventListenerStoreKey(name, options2), {
2514
+ listener: wrapped,
2515
+ options: options2
2516
+ });
2517
+ }
2518
+ function resolveDelegationDocument(node, rootRef) {
2519
+ const nodeDocument = node.ownerDocument ?? void 0;
2520
+ if (rootRef?.ownerDocument && nodeDocument?.defaultView == null) {
2521
+ return rootRef.ownerDocument;
2532
2522
  }
2533
- const getHandler = isStrictlyReactive(handler) ? handler : () => handler;
2534
- const wrapped = (event) => {
2523
+ return nodeDocument ?? rootRef?.ownerDocument ?? document;
2524
+ }
2525
+ function getStoredEventListenerStore(node) {
2526
+ const host = node;
2527
+ if (!host[EVENT_LISTENER_CACHE]) {
2528
+ host[EVENT_LISTENER_CACHE] = /* @__PURE__ */ new Map();
2529
+ }
2530
+ return host[EVENT_LISTENER_CACHE];
2531
+ }
2532
+ function getEventListenerStoreKey(name, options2) {
2533
+ const capture = typeof options2 === "boolean" ? options2 : options2?.capture === true;
2534
+ const passive = typeof options2 === "object" && options2?.passive === true;
2535
+ const once = typeof options2 === "object" && options2?.once === true;
2536
+ return `${name}:${capture ? 1 : 0}:${passive ? 1 : 0}:${once ? 1 : 0}`;
2537
+ }
2538
+ function removeStoredEventListener(node, name, options2) {
2539
+ const host = node;
2540
+ const store = host[EVENT_LISTENER_CACHE];
2541
+ if (!store) return;
2542
+ const entry = store.get(getEventListenerStoreKey(name, options2));
2543
+ if (!entry) return;
2544
+ node.removeEventListener(name, entry.listener, entry.options);
2545
+ store.delete(getEventListenerStoreKey(name, options2));
2546
+ if (store.size === 0) {
2547
+ delete host[EVENT_LISTENER_CACHE];
2548
+ }
2549
+ }
2550
+ function resolveEventData(value, event) {
2551
+ if (typeof value !== "function") return value;
2552
+ if (isReactive(value)) {
2553
+ return value();
2554
+ }
2555
+ try {
2556
+ const fn = value;
2557
+ return fn.length > 0 ? fn(event) : fn();
2558
+ } catch {
2559
+ return value();
2560
+ }
2561
+ }
2562
+ function resolveEventHandlerValue(value) {
2563
+ if (isStrictlyReactive(value)) {
2564
+ return value();
2565
+ }
2566
+ return value;
2567
+ }
2568
+ function createEventInvoker(eventName, handler, node, rootRef) {
2569
+ return (event) => {
2535
2570
  try {
2536
- const resolved = getHandler();
2537
- callEventHandler(resolved, event, el);
2571
+ if (Array.isArray(handler)) {
2572
+ const resolvedHandler2 = resolveEventHandlerValue(
2573
+ handler[0]
2574
+ );
2575
+ const data = resolveEventData(handler[1], event);
2576
+ callEventHandler(resolvedHandler2, event, node, data);
2577
+ return;
2578
+ }
2579
+ const resolvedHandler = resolveEventHandlerValue(
2580
+ handler
2581
+ );
2582
+ callEventHandler(resolvedHandler, event, node);
2538
2583
  } catch (err) {
2539
2584
  if (handleError(err, { source: "event", eventName }, rootRef)) {
2540
2585
  return;
@@ -2542,11 +2587,70 @@ function bindEvent(el, eventName, handler, options2) {
2542
2587
  throw err;
2543
2588
  }
2544
2589
  };
2545
- el.addEventListener(eventName, wrapped, options2);
2546
- const cleanup = () => el.removeEventListener(eventName, wrapped, options2);
2590
+ }
2591
+ function bindEvent(el, eventName, handler, options2) {
2592
+ if (handler == null) return () => {
2593
+ };
2594
+ const shouldDelegate = options2 == null && DelegatedEvents.has(eventName);
2595
+ if (shouldDelegate) {
2596
+ addEventListener(el, eventName, handler, true);
2597
+ return () => {
2598
+ addEventListener(el, eventName, null, true);
2599
+ };
2600
+ }
2601
+ addEventListener(
2602
+ el,
2603
+ eventName,
2604
+ handler,
2605
+ false,
2606
+ options2
2607
+ );
2608
+ const cleanup = () => removeStoredEventListener(el, eventName, options2);
2547
2609
  registerRootCleanup(cleanup);
2548
2610
  return cleanup;
2549
2611
  }
2612
+ function bindRef(el, ref, registerCleanup = true) {
2613
+ if (ref == null) return () => {
2614
+ };
2615
+ const getRef = isReactive(ref) ? ref : () => ref;
2616
+ let currentRef;
2617
+ const applyRefValue = (refValue, value) => {
2618
+ if (refValue == null) return;
2619
+ if (typeof refValue === "function") {
2620
+ ;
2621
+ refValue(value);
2622
+ } else if (typeof refValue === "object" && "current" in refValue) {
2623
+ ;
2624
+ refValue.current = value;
2625
+ }
2626
+ };
2627
+ const clearCurrentRef = () => {
2628
+ if (currentRef == null) return;
2629
+ applyRefValue(currentRef, null);
2630
+ currentRef = void 0;
2631
+ };
2632
+ const syncRef = (nextRef) => {
2633
+ if (nextRef === currentRef) return;
2634
+ clearCurrentRef();
2635
+ currentRef = nextRef;
2636
+ applyRefValue(currentRef, el);
2637
+ };
2638
+ let disposeTracking;
2639
+ if (isReactive(ref)) {
2640
+ disposeTracking = createRenderEffect(() => {
2641
+ syncRef(getRef());
2642
+ });
2643
+ } else {
2644
+ syncRef(getRef());
2645
+ }
2646
+ if (registerCleanup) {
2647
+ registerRootCleanup(clearCurrentRef);
2648
+ }
2649
+ return () => {
2650
+ disposeTracking?.();
2651
+ clearCurrentRef();
2652
+ };
2653
+ }
2550
2654
  function createPortal(container, render2, createElementFn) {
2551
2655
  const parentRoot = getCurrentRoot();
2552
2656
  const markerOwnerDocument = container.ownerDocument ?? document;
@@ -2882,6 +2986,7 @@ function render(view, container) {
2882
2986
  function createElement(node) {
2883
2987
  return createElementWithContext(node, null, resolveOwnerDocument());
2884
2988
  }
2989
+ registerCreateElement(createElement);
2885
2990
  function resolveNamespace(tagName, namespace) {
2886
2991
  if (tagName === "svg") return "svg";
2887
2992
  if (tagName === "math") return "mathml";
@@ -2893,22 +2998,28 @@ function resolveNamespace(tagName, namespace) {
2893
2998
  function resolveOwnerDocument(ownerDocument) {
2894
2999
  return ownerDocument ?? getCurrentRoot()?.ownerDocument ?? document;
2895
3000
  }
3001
+ function createTextNodeWithHydration(value, ownerDocument) {
3002
+ if (!isHydratingActive()) {
3003
+ return ownerDocument.createTextNode(value);
3004
+ }
3005
+ return claimText(value, () => ownerDocument.createTextNode(value));
3006
+ }
2896
3007
  function createElementWithContext(node, namespace, ownerDocument) {
2897
3008
  if (node instanceof Node) {
2898
3009
  return node;
2899
3010
  }
2900
3011
  if (node === null || node === void 0 || node === false) {
2901
- return ownerDocument.createTextNode("");
3012
+ return createTextNodeWithHydration("", ownerDocument);
2902
3013
  }
2903
3014
  if (isReactive(node)) {
2904
3015
  const resolved = node();
2905
3016
  if (resolved === node) {
2906
- return ownerDocument.createTextNode("");
3017
+ return createTextNodeWithHydration("", ownerDocument);
2907
3018
  }
2908
3019
  return createElementWithContext(resolved, namespace, ownerDocument);
2909
3020
  }
2910
3021
  if (typeof node === "function") {
2911
- return ownerDocument.createTextNode("");
3022
+ return createTextNodeWithHydration("", ownerDocument);
2912
3023
  }
2913
3024
  if (typeof node === "object" && node !== null && !(node instanceof Node)) {
2914
3025
  if ("marker" in node) {
@@ -2935,10 +3046,10 @@ function createElementWithContext(node, namespace, ownerDocument) {
2935
3046
  return frag;
2936
3047
  }
2937
3048
  if (typeof node === "string" || typeof node === "number") {
2938
- return ownerDocument.createTextNode(String(node));
3049
+ return createTextNodeWithHydration(String(node), ownerDocument);
2939
3050
  }
2940
3051
  if (typeof node === "boolean") {
2941
- return ownerDocument.createTextNode("");
3052
+ return createTextNodeWithHydration("", ownerDocument);
2942
3053
  }
2943
3054
  const vnode = node;
2944
3055
  if (typeof vnode.type === "function") {
@@ -3083,7 +3194,7 @@ function appendChildNode(parent, child, namespace, ownerDocument) {
3083
3194
  }
3084
3195
  let domNode;
3085
3196
  if (typeof child !== "object" || child === null) {
3086
- domNode = parentOwnerDocument.createTextNode(String(child ?? ""));
3197
+ domNode = createTextNodeWithHydration(String(child ?? ""), parentOwnerDocument);
3087
3198
  } else {
3088
3199
  domNode = createElementWithContext(child, namespace, parentOwnerDocument);
3089
3200
  }
@@ -3119,33 +3230,12 @@ function appendChildren(parent, children, namespace, ownerDocument) {
3119
3230
  appendChildNode(parent, children, namespace, ownerDocument);
3120
3231
  }
3121
3232
  function applyRef(el, value) {
3122
- if (typeof value === "function") {
3123
- const refFn = value;
3124
- refFn(el);
3125
- const root = getCurrentRoot();
3126
- if (root) {
3127
- registerRootCleanup(() => {
3128
- refFn(null);
3129
- });
3130
- } else if (isDev7) {
3131
- console.warn(
3132
- "[fict] Ref applied outside of a root context. The ref cleanup (setting to null) will not run automatically. Consider using createRoot() or ensure the element is created within a component."
3133
- );
3134
- }
3135
- } else if (value && typeof value === "object" && "current" in value) {
3136
- const refObj = value;
3137
- refObj.current = el;
3138
- const root = getCurrentRoot();
3139
- if (root) {
3140
- registerRootCleanup(() => {
3141
- refObj.current = null;
3142
- });
3143
- } else if (isDev7) {
3144
- console.warn(
3145
- "[fict] Ref applied outside of a root context. The ref cleanup (setting to null) will not run automatically. Consider using createRoot() or ensure the element is created within a component."
3146
- );
3147
- }
3233
+ if (!getCurrentRoot() && isDev7) {
3234
+ console.warn(
3235
+ "[fict] Ref applied outside of a root context. The ref cleanup (setting to null) will not run automatically. Consider using createRoot() or ensure the element is created within a component."
3236
+ );
3148
3237
  }
3238
+ bindRef(el, value);
3149
3239
  }
3150
3240
  function applyProps(el, props, isSVG = false) {
3151
3241
  props = unwrapProps(props);
@@ -3400,6 +3490,12 @@ function ErrorBoundary(props) {
3400
3490
  renderValue(toView(null));
3401
3491
  };
3402
3492
  renderValue(props.children ?? null);
3493
+ registerRootCleanup(() => {
3494
+ if (cleanup) {
3495
+ cleanup();
3496
+ cleanup = void 0;
3497
+ }
3498
+ });
3403
3499
  registerErrorHandler((err) => {
3404
3500
  renderValue(toView(err));
3405
3501
  props.onError?.(err);
@@ -3577,6 +3673,12 @@ function Suspense(props) {
3577
3673
  return false;
3578
3674
  });
3579
3675
  renderView(props.children ?? null);
3676
+ registerRootCleanup(() => {
3677
+ if (cleanup) {
3678
+ cleanup();
3679
+ cleanup = void 0;
3680
+ }
3681
+ });
3580
3682
  if (props.resetKeys !== void 0) {
3581
3683
  const isGetter = typeof props.resetKeys === "function" && props.resetKeys.length === 0;
3582
3684
  const getter = isGetter ? props.resetKeys : void 0;
@@ -3659,7 +3761,9 @@ function createContext(defaultValue) {
3659
3761
  };
3660
3762
  createRenderEffect(() => {
3661
3763
  contextMap.set(id, props.value);
3662
- renderChildren(props.children);
3764
+ untrack(() => {
3765
+ renderChildren(props.children);
3766
+ });
3663
3767
  });
3664
3768
  return fragment;
3665
3769
  };