@fictjs/runtime 0.9.0 → 0.11.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 (87) hide show
  1. package/dist/advanced.cjs +9 -9
  2. package/dist/advanced.d.cts +4 -4
  3. package/dist/advanced.d.ts +4 -4
  4. package/dist/advanced.js +4 -4
  5. package/dist/{binding-BWchH3Kp.d.cts → binding-DcnhUSQK.d.ts} +5 -3
  6. package/dist/{binding-BWchH3Kp.d.ts → binding-FRyTeLDn.d.cts} +5 -3
  7. package/dist/{chunk-FVX77557.js → chunk-2UR2UWE2.js} +3 -3
  8. package/dist/{chunk-LBE6DC3V.cjs → chunk-44EQF3AR.cjs} +63 -52
  9. package/dist/chunk-44EQF3AR.cjs.map +1 -0
  10. package/dist/{chunk-OAM7HABA.cjs → chunk-4QGEN5SJ.cjs} +340 -263
  11. package/dist/chunk-4QGEN5SJ.cjs.map +1 -0
  12. package/dist/{chunk-PD6IQY2Y.cjs → chunk-C5IE4WUG.cjs} +8 -8
  13. package/dist/{chunk-PD6IQY2Y.cjs.map → chunk-C5IE4WUG.cjs.map} +1 -1
  14. package/dist/{chunk-DXG3TARY.js → chunk-DIK33H5U.js} +202 -30
  15. package/dist/chunk-DIK33H5U.js.map +1 -0
  16. package/dist/{chunk-JVYH76ZX.js → chunk-FESAXMHT.js} +7 -6
  17. package/dist/{chunk-JVYH76ZX.js.map → chunk-FESAXMHT.js.map} +1 -1
  18. package/dist/chunk-FHQZCAAK.cjs +112 -0
  19. package/dist/chunk-FHQZCAAK.cjs.map +1 -0
  20. package/dist/{chunk-UBFDB6OL.cjs → chunk-QNMYVXRL.cjs} +222 -50
  21. package/dist/chunk-QNMYVXRL.cjs.map +1 -0
  22. package/dist/{chunk-N6ODUM2Y.js → chunk-S63VBIWN.js} +27 -16
  23. package/dist/chunk-S63VBIWN.js.map +1 -0
  24. package/dist/{chunk-T2LNV5Q5.js → chunk-WIHNVN6L.js} +153 -76
  25. package/dist/chunk-WIHNVN6L.js.map +1 -0
  26. package/dist/{devtools-BDp76luf.d.ts → devtools-BtIkN77t.d.cts} +14 -2
  27. package/dist/{devtools-5AipK9CX.d.cts → devtools-D2z4llpA.d.ts} +14 -2
  28. package/dist/index.cjs +60 -58
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +5 -5
  31. package/dist/index.d.ts +5 -5
  32. package/dist/index.dev.js +300 -74
  33. package/dist/index.dev.js.map +1 -1
  34. package/dist/index.js +13 -11
  35. package/dist/index.js.map +1 -1
  36. package/dist/internal-list.cjs +4 -4
  37. package/dist/internal-list.d.cts +2 -2
  38. package/dist/internal-list.d.ts +2 -2
  39. package/dist/internal-list.js +3 -3
  40. package/dist/internal.cjs +5 -5
  41. package/dist/internal.d.cts +6 -6
  42. package/dist/internal.d.ts +6 -6
  43. package/dist/internal.js +4 -4
  44. package/dist/jsx-dev-runtime.d.cts +671 -0
  45. package/dist/jsx-dev-runtime.d.ts +671 -0
  46. package/dist/jsx-runtime.d.cts +671 -0
  47. package/dist/jsx-runtime.d.ts +671 -0
  48. package/dist/{list-DL5DOFcO.d.ts → list-BKM6YOPq.d.ts} +2 -2
  49. package/dist/{list-hP7hQ9Vk.d.cts → list-Bi8dDF8Q.d.cts} +2 -2
  50. package/dist/loader.cjs +34 -28
  51. package/dist/loader.cjs.map +1 -1
  52. package/dist/loader.d.cts +2 -2
  53. package/dist/loader.d.ts +2 -2
  54. package/dist/loader.js +17 -11
  55. package/dist/loader.js.map +1 -1
  56. package/dist/{props-BpZz0AOq.d.cts → props-9chMyBGb.d.cts} +2 -2
  57. package/dist/{props-CjLH0JE-.d.ts → props-D1nj2p_3.d.ts} +2 -2
  58. package/dist/{resume-BJ4oHLi_.d.cts → resume-C5IKAIdh.d.ts} +2 -2
  59. package/dist/{resume-CuyJWXP_.d.ts → resume-DPZxmA95.d.cts} +2 -2
  60. package/dist/{scope-jPt5DHRT.d.ts → scope-BSkhJr0a.d.ts} +1 -1
  61. package/dist/{scope-BJCtq8hJ.d.cts → scope-Bn3sxem5.d.cts} +1 -1
  62. package/dist/{signal-C4ISF17w.d.cts → signal-Z4KkDk9h.d.cts} +12 -1
  63. package/dist/{signal-C4ISF17w.d.ts → signal-Z4KkDk9h.d.ts} +12 -1
  64. package/package.json +2 -2
  65. package/src/binding.ts +59 -29
  66. package/src/context.ts +4 -3
  67. package/src/devtools.ts +19 -2
  68. package/src/dom.ts +122 -42
  69. package/src/effect.ts +5 -5
  70. package/src/error-boundary.ts +5 -5
  71. package/src/hooks.ts +13 -5
  72. package/src/lifecycle.ts +48 -3
  73. package/src/list-helpers.ts +30 -13
  74. package/src/loader.ts +20 -12
  75. package/src/node-ops.ts +8 -5
  76. package/src/signal.ts +191 -18
  77. package/src/suspense.ts +5 -4
  78. package/src/transition.ts +9 -3
  79. package/dist/chunk-DXG3TARY.js.map +0 -1
  80. package/dist/chunk-LBE6DC3V.cjs.map +0 -1
  81. package/dist/chunk-N6ODUM2Y.js.map +0 -1
  82. package/dist/chunk-OAM7HABA.cjs.map +0 -1
  83. package/dist/chunk-PG4QX2I2.cjs +0 -111
  84. package/dist/chunk-PG4QX2I2.cjs.map +0 -1
  85. package/dist/chunk-T2LNV5Q5.js.map +0 -1
  86. package/dist/chunk-UBFDB6OL.cjs.map +0 -1
  87. /package/dist/{chunk-FVX77557.js.map → chunk-2UR2UWE2.js.map} +0 -0
package/dist/index.dev.js CHANGED
@@ -181,8 +181,41 @@ var currentRoot;
181
181
  var currentEffectCleanups;
182
182
  var globalErrorHandlers = /* @__PURE__ */ new WeakMap();
183
183
  var globalSuspenseHandlers = /* @__PURE__ */ new WeakMap();
184
+ var rootDevtoolsIds = /* @__PURE__ */ new WeakMap();
185
+ var nextRootDevtoolsId = 0;
186
+ function registerRootDevtools(root) {
187
+ if (!isDev2) return;
188
+ const hook = getDevtoolsHook();
189
+ if (!hook?.registerRoot) return;
190
+ const id = ++nextRootDevtoolsId;
191
+ rootDevtoolsIds.set(root, id);
192
+ hook.registerRoot(id);
193
+ }
194
+ function disposeRootDevtools(root) {
195
+ if (!isDev2) return;
196
+ const id = rootDevtoolsIds.get(root);
197
+ if (id === void 0) return;
198
+ const hook = getDevtoolsHook();
199
+ hook?.disposeRoot?.(id);
200
+ rootDevtoolsIds.delete(root);
201
+ }
202
+ function setRootSuspendDevtools(root, suspended) {
203
+ if (!isDev2) return;
204
+ const id = rootDevtoolsIds.get(root);
205
+ if (id === void 0) return;
206
+ const hook = getDevtoolsHook();
207
+ hook?.rootSuspend?.(id, suspended);
208
+ }
184
209
  function createRootContext(parent) {
185
- return { parent, cleanups: [], destroyCallbacks: [], suspended: false };
210
+ const root = {
211
+ parent,
212
+ ownerDocument: parent?.ownerDocument,
213
+ cleanups: [],
214
+ destroyCallbacks: [],
215
+ suspended: false
216
+ };
217
+ registerRootDevtools(root);
218
+ return root;
186
219
  }
187
220
  function pushRoot(root) {
188
221
  if (!enterRootGuard(root)) {
@@ -262,6 +295,7 @@ function destroyRoot(root) {
262
295
  if (globalSuspenseHandlers.has(root)) {
263
296
  globalSuspenseHandlers.delete(root);
264
297
  }
298
+ disposeRootDevtools(root);
265
299
  }
266
300
  function createRoot(fn, options2) {
267
301
  const parent = options2?.inherit ? currentRoot : void 0;
@@ -398,7 +432,10 @@ function handleSuspend(token, startRoot) {
398
432
  const handler = handlers[i];
399
433
  const handled = handler(token);
400
434
  if (handled !== false) {
401
- if (originRoot) originRoot.suspended = true;
435
+ if (originRoot) {
436
+ originRoot.suspended = true;
437
+ setRootSuspendDevtools(originRoot, true);
438
+ }
402
439
  return true;
403
440
  }
404
441
  }
@@ -411,7 +448,10 @@ function handleSuspend(token, startRoot) {
411
448
  const handler = globalForRoot[i];
412
449
  const handled = handler(token);
413
450
  if (handled !== false) {
414
- if (originRoot) originRoot.suspended = true;
451
+ if (originRoot) {
452
+ originRoot.suspended = true;
453
+ setRootSuspendDevtools(originRoot, true);
454
+ }
415
455
  return true;
416
456
  }
417
457
  }
@@ -420,7 +460,7 @@ function handleSuspend(token, startRoot) {
420
460
  }
421
461
 
422
462
  // src/effect.ts
423
- function createEffect(fn) {
463
+ function createEffect(fn, options2) {
424
464
  let cleanups = [];
425
465
  const rootForError = getCurrentRoot();
426
466
  const doCleanup = () => {
@@ -447,7 +487,7 @@ function createEffect(fn) {
447
487
  });
448
488
  cleanups = bucket;
449
489
  };
450
- const disposeEffect = effectWithCleanup(run, doCleanup, rootForError);
490
+ const disposeEffect = effectWithCleanup(run, doCleanup, rootForError, options2);
451
491
  const teardown = () => {
452
492
  runCleanupList(cleanups);
453
493
  disposeEffect();
@@ -455,7 +495,7 @@ function createEffect(fn) {
455
495
  registerRootCleanup(teardown);
456
496
  return teardown;
457
497
  }
458
- function createRenderEffect(fn) {
498
+ function createRenderEffect(fn, options2) {
459
499
  let cleanup;
460
500
  const rootForError = getCurrentRoot();
461
501
  const doCleanup = () => {
@@ -481,7 +521,7 @@ function createRenderEffect(fn) {
481
521
  throw err;
482
522
  }
483
523
  };
484
- const disposeEffect = effectWithCleanup(run, doCleanup, rootForError);
524
+ const disposeEffect = effectWithCleanup(run, doCleanup, rootForError, options2);
485
525
  const teardown = () => {
486
526
  if (cleanup) {
487
527
  cleanup();
@@ -759,6 +799,15 @@ function purgeDeps(sub) {
759
799
  while (dep !== void 0) dep = unlink(dep, sub);
760
800
  }
761
801
  function disposeNode(node) {
802
+ if (isDev4) {
803
+ if ("fn" in node && typeof node.fn === "function") {
804
+ disposeEffectDevtools(node);
805
+ } else if ("getter" in node && typeof node.getter === "function") {
806
+ disposeComputedDevtools(node);
807
+ } else if ("currentValue" in node) {
808
+ disposeSignalDevtools(node);
809
+ }
810
+ }
762
811
  node.depsTail = void 0;
763
812
  node.flags = 0;
764
813
  purgeDeps(node);
@@ -812,6 +861,7 @@ function runEffect(e) {
812
861
  const flags = e.flags;
813
862
  const runCleanup = () => {
814
863
  if (!e.runCleanup) return;
864
+ if (isDev4) effectCleanupDevtools(e);
815
865
  inCleanup = true;
816
866
  activeCleanupFlushId = currentFlushId;
817
867
  try {
@@ -824,7 +874,6 @@ function runEffect(e) {
824
874
  if (flags & Dirty) {
825
875
  runCleanup();
826
876
  ++cycle;
827
- if (isDev4) effectRunDevtools(e);
828
877
  e.depsTail = void 0;
829
878
  e.flags = WatchingRunning;
830
879
  const prevSub = activeSub;
@@ -862,7 +911,6 @@ function runEffect(e) {
862
911
  if (isDirty) {
863
912
  runCleanup();
864
913
  ++cycle;
865
- if (isDev4) effectRunDevtools(e);
866
914
  e.depsTail = void 0;
867
915
  e.flags = WatchingRunning;
868
916
  const prevSub = activeSub;
@@ -896,19 +944,30 @@ function scheduleFlush() {
896
944
  }
897
945
  function flush() {
898
946
  beginFlushGuard();
947
+ let flushReported = false;
948
+ const finishFlush = () => {
949
+ if (flushReported && isDev4) {
950
+ flushEndDevtools();
951
+ }
952
+ endFlushGuard();
953
+ };
899
954
  if (batchDepth > 0) {
900
955
  scheduleFlush();
901
- endFlushGuard();
956
+ finishFlush();
902
957
  return;
903
958
  }
904
959
  const hasWork = highPriorityQueue.length > 0 || lowPriorityQueue.length > 0;
905
960
  if (!hasWork) {
906
961
  flushScheduled = false;
907
- endFlushGuard();
962
+ finishFlush();
908
963
  return;
909
964
  }
910
965
  currentFlushId++;
911
966
  flushScheduled = false;
967
+ if (isDev4) {
968
+ flushStartDevtools();
969
+ flushReported = true;
970
+ }
912
971
  let highIndex = 0;
913
972
  while (highIndex < highPriorityQueue.length) {
914
973
  const e = highPriorityQueue[highIndex];
@@ -928,7 +987,7 @@ function flush() {
928
987
  highPriorityQueue.length = 0;
929
988
  lowPriorityQueue.length = 0;
930
989
  flushScheduled = false;
931
- endFlushGuard();
990
+ finishFlush();
932
991
  return;
933
992
  }
934
993
  highIndex++;
@@ -943,7 +1002,7 @@ function flush() {
943
1002
  lowPriorityQueue.length -= lowIndex;
944
1003
  }
945
1004
  scheduleFlush();
946
- endFlushGuard();
1005
+ finishFlush();
947
1006
  return;
948
1007
  }
949
1008
  const e = lowPriorityQueue[lowIndex];
@@ -963,14 +1022,14 @@ function flush() {
963
1022
  highPriorityQueue.length = 0;
964
1023
  lowPriorityQueue.length = 0;
965
1024
  flushScheduled = false;
966
- endFlushGuard();
1025
+ finishFlush();
967
1026
  return;
968
1027
  }
969
1028
  lowIndex++;
970
1029
  runEffect(e);
971
1030
  }
972
1031
  lowPriorityQueue.length = 0;
973
- endFlushGuard();
1032
+ finishFlush();
974
1033
  }
975
1034
  function signal(initialValue, options2) {
976
1035
  const s = {
@@ -1043,6 +1102,7 @@ function computed(getter, options2) {
1043
1102
  if (options2?.equals !== void 0) c.equals = options2.equals;
1044
1103
  if (options2?.name !== void 0) c.name = options2.name;
1045
1104
  if (options2?.devToolsSource !== void 0) c.devToolsSource = options2.devToolsSource;
1105
+ if (options2?.internal === true) c.devToolsInternal = true;
1046
1106
  if (isDev4) registerComputedDevtools(c);
1047
1107
  const bound = computedOper.bind(
1048
1108
  c
@@ -1093,7 +1153,7 @@ function computedOper() {
1093
1153
  if (activeSub !== void 0) link(this, activeSub, cycle);
1094
1154
  return this.value;
1095
1155
  }
1096
- function effectWithCleanup(fn, cleanupRunner, root) {
1156
+ function effectWithCleanup(fn, cleanupRunner, root, options2) {
1097
1157
  const e = {
1098
1158
  fn,
1099
1159
  subs: void 0,
@@ -1102,6 +1162,8 @@ function effectWithCleanup(fn, cleanupRunner, root) {
1102
1162
  depsTail: void 0,
1103
1163
  flags: WatchingRunning,
1104
1164
  runCleanup: cleanupRunner,
1165
+ ...options2?.name !== void 0 ? { name: options2.name } : {},
1166
+ ...options2?.devToolsSource !== void 0 ? { devToolsSource: options2.devToolsSource } : {},
1105
1167
  __id: void 0
1106
1168
  };
1107
1169
  const resolvedRoot = root ?? getCurrentRoot();
@@ -1109,14 +1171,14 @@ function effectWithCleanup(fn, cleanupRunner, root) {
1109
1171
  e.root = resolvedRoot;
1110
1172
  }
1111
1173
  if (isDev4) registerEffectDevtools(e);
1174
+ e.fn = wrapEffectFnWithDevtoolsTiming(e, fn);
1112
1175
  const prevSub = activeSub;
1113
1176
  if (prevSub !== void 0) link(e, prevSub, 0);
1114
1177
  activeSub = e;
1115
1178
  let didThrow = false;
1116
1179
  let thrown;
1117
1180
  try {
1118
- if (isDev4) effectRunDevtools(e);
1119
- fn();
1181
+ e.fn();
1120
1182
  } catch (err) {
1121
1183
  didThrow = true;
1122
1184
  thrown = err;
@@ -1137,7 +1199,11 @@ function effectOper() {
1137
1199
  disposeNode(this);
1138
1200
  }
1139
1201
  function batch(fn) {
1202
+ const enteringOuterBatch = batchDepth === 0;
1140
1203
  ++batchDepth;
1204
+ if (enteringOuterBatch && isDev4) {
1205
+ batchStartDevtools();
1206
+ }
1141
1207
  let result;
1142
1208
  let error;
1143
1209
  try {
@@ -1147,6 +1213,9 @@ function batch(fn) {
1147
1213
  } finally {
1148
1214
  --batchDepth;
1149
1215
  if (batchDepth === 0) {
1216
+ if (isDev4) {
1217
+ batchEndDevtools();
1218
+ }
1150
1219
  try {
1151
1220
  flush();
1152
1221
  } catch (flushErr) {
@@ -1195,18 +1264,49 @@ function setTransitionContext(value) {
1195
1264
  var registerSignalDevtools = () => void 0;
1196
1265
  var updateSignalDevtools = () => {
1197
1266
  };
1267
+ var disposeSignalDevtools = () => {
1268
+ };
1198
1269
  var registerComputedDevtools = () => void 0;
1199
1270
  var updateComputedDevtools = () => {
1200
1271
  };
1272
+ var disposeComputedDevtools = () => {
1273
+ };
1201
1274
  var registerEffectDevtools = () => void 0;
1202
1275
  var effectRunDevtools = () => {
1203
1276
  };
1277
+ var wrapEffectFnWithDevtoolsTiming = (_node, fn) => fn;
1278
+ var effectCleanupDevtools = () => {
1279
+ };
1280
+ var disposeEffectDevtools = () => {
1281
+ };
1204
1282
  var trackDependencyDevtools = () => {
1205
1283
  };
1206
1284
  var untrackDependencyDevtools = () => {
1207
1285
  };
1286
+ var batchStartDevtools = () => {
1287
+ };
1288
+ var batchEndDevtools = () => {
1289
+ };
1290
+ var flushStartDevtools = () => {
1291
+ };
1292
+ var flushEndDevtools = () => {
1293
+ };
1294
+ var clearDevtoolsSignalSetters = () => {
1295
+ };
1208
1296
  if (true ? true : typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
1209
1297
  let nextDevtoolsId = 0;
1298
+ const getSignalSetterMap = () => {
1299
+ if (typeof globalThis === "undefined") return void 0;
1300
+ const global = globalThis;
1301
+ if (!global.__FICT_DEVTOOLS_SIGNALS__) {
1302
+ global.__FICT_DEVTOOLS_SIGNALS__ = /* @__PURE__ */ new Map();
1303
+ }
1304
+ return global.__FICT_DEVTOOLS_SIGNALS__;
1305
+ };
1306
+ const getExistingSignalSetterMap = () => {
1307
+ if (typeof globalThis === "undefined") return void 0;
1308
+ return globalThis.__FICT_DEVTOOLS_SIGNALS__;
1309
+ };
1210
1310
  registerSignalDevtools = (node) => {
1211
1311
  const hook = getDevtoolsHook();
1212
1312
  if (!hook) return void 0;
@@ -1218,6 +1318,9 @@ if (true ? true : typeof process !== "undefined" && process.env?.NODE_ENV !== "p
1218
1318
  if (ownerId !== void 0) options2.ownerId = ownerId;
1219
1319
  hook.registerSignal(id, node.currentValue, options2);
1220
1320
  node.__id = id;
1321
+ getSignalSetterMap()?.set(id, (value) => {
1322
+ signalOper.call(node, value);
1323
+ });
1221
1324
  return id;
1222
1325
  };
1223
1326
  updateSignalDevtools = (node, value) => {
@@ -1226,9 +1329,19 @@ if (true ? true : typeof process !== "undefined" && process.env?.NODE_ENV !== "p
1226
1329
  const id = node.__id;
1227
1330
  if (id) hook.updateSignal(id, value);
1228
1331
  };
1332
+ disposeSignalDevtools = (node) => {
1333
+ const identifiable = node;
1334
+ const id = identifiable.__id;
1335
+ if (!id) return;
1336
+ const hook = getDevtoolsHook();
1337
+ hook?.disposeSignal?.(id);
1338
+ getExistingSignalSetterMap()?.delete(id);
1339
+ delete identifiable.__id;
1340
+ };
1229
1341
  registerComputedDevtools = (node) => {
1230
1342
  const hook = getDevtoolsHook();
1231
1343
  if (!hook) return void 0;
1344
+ if (node.devToolsInternal) return void 0;
1232
1345
  const id = ++nextDevtoolsId;
1233
1346
  const options2 = {};
1234
1347
  if (node.name !== void 0) options2.name = node.name;
@@ -1246,20 +1359,55 @@ if (true ? true : typeof process !== "undefined" && process.env?.NODE_ENV !== "p
1246
1359
  const id = node.__id;
1247
1360
  if (id) hook.updateComputed(id, value);
1248
1361
  };
1362
+ disposeComputedDevtools = (node) => {
1363
+ const identifiable = node;
1364
+ const id = identifiable.__id;
1365
+ if (!id) return;
1366
+ const hook = getDevtoolsHook();
1367
+ hook?.disposeComputed?.(id);
1368
+ delete identifiable.__id;
1369
+ };
1249
1370
  registerEffectDevtools = (node) => {
1250
1371
  const hook = getDevtoolsHook();
1251
1372
  if (!hook) return void 0;
1252
1373
  const id = ++nextDevtoolsId;
1374
+ const options2 = {};
1253
1375
  const ownerId = __fictGetCurrentComponentId();
1254
- hook.registerEffect(id, ownerId !== void 0 ? { ownerId } : void 0);
1376
+ if (ownerId !== void 0) options2.ownerId = ownerId;
1377
+ if (node.devToolsSource !== void 0) options2.source = node.devToolsSource;
1378
+ hook.registerEffect(id, Object.keys(options2).length > 0 ? options2 : void 0);
1255
1379
  node.__id = id;
1256
1380
  return id;
1257
1381
  };
1258
- effectRunDevtools = (node) => {
1382
+ effectRunDevtools = (node, duration) => {
1259
1383
  const hook = getDevtoolsHook();
1260
1384
  if (!hook) return;
1261
1385
  const id = node.__id;
1262
- if (id) hook.effectRun(id);
1386
+ if (id) hook.effectRun(id, duration);
1387
+ };
1388
+ wrapEffectFnWithDevtoolsTiming = (node, fn) => {
1389
+ return () => {
1390
+ const startedAt = performance.now();
1391
+ try {
1392
+ fn();
1393
+ } finally {
1394
+ effectRunDevtools(node, performance.now() - startedAt);
1395
+ }
1396
+ };
1397
+ };
1398
+ effectCleanupDevtools = (node) => {
1399
+ const hook = getDevtoolsHook();
1400
+ if (!hook) return;
1401
+ const id = node.__id;
1402
+ if (id) hook.effectCleanup?.(id);
1403
+ };
1404
+ disposeEffectDevtools = (node) => {
1405
+ const identifiable = node;
1406
+ const id = identifiable.__id;
1407
+ if (!id) return;
1408
+ const hook = getDevtoolsHook();
1409
+ hook?.disposeEffect?.(id);
1410
+ delete identifiable.__id;
1263
1411
  };
1264
1412
  trackDependencyDevtools = (dep, sub) => {
1265
1413
  const hook = getDevtoolsHook();
@@ -1275,6 +1423,25 @@ if (true ? true : typeof process !== "undefined" && process.env?.NODE_ENV !== "p
1275
1423
  const subId = sub.__id;
1276
1424
  if (depId && subId) hook.untrackDependency(subId, depId);
1277
1425
  };
1426
+ batchStartDevtools = () => {
1427
+ const hook = getDevtoolsHook();
1428
+ hook?.batchStart?.();
1429
+ };
1430
+ batchEndDevtools = () => {
1431
+ const hook = getDevtoolsHook();
1432
+ hook?.batchEnd?.();
1433
+ };
1434
+ flushStartDevtools = () => {
1435
+ const hook = getDevtoolsHook();
1436
+ hook?.flushStart?.();
1437
+ };
1438
+ flushEndDevtools = () => {
1439
+ const hook = getDevtoolsHook();
1440
+ hook?.flushEnd?.();
1441
+ };
1442
+ clearDevtoolsSignalSetters = () => {
1443
+ getExistingSignalSetterMap()?.clear();
1444
+ };
1278
1445
  }
1279
1446
 
1280
1447
  // src/memo.ts
@@ -1331,7 +1498,11 @@ function useTransition() {
1331
1498
  throw thrown;
1332
1499
  }
1333
1500
  if (result && typeof result.then === "function") {
1334
- Promise.resolve(result).finally(() => {
1501
+ void Promise.resolve(result).catch((error) => {
1502
+ if (typeof console !== "undefined" && typeof console.error === "function") {
1503
+ console.error("[fict/transition] Async transition failed.", error);
1504
+ }
1505
+ }).finally(() => {
1335
1506
  endPending();
1336
1507
  });
1337
1508
  return;
@@ -1761,7 +1932,7 @@ function withHydration(root, fn) {
1761
1932
  }
1762
1933
 
1763
1934
  // src/node-ops.ts
1764
- function toNodeArray(node) {
1935
+ function toNodeArray(node, ownerDocument = document) {
1765
1936
  try {
1766
1937
  if (Array.isArray(node)) {
1767
1938
  let allNodes = true;
@@ -1782,7 +1953,7 @@ function toNodeArray(node) {
1782
1953
  }
1783
1954
  const result = [];
1784
1955
  for (const item of node) {
1785
- result.push(...toNodeArray(item));
1956
+ result.push(...toNodeArray(item, ownerDocument));
1786
1957
  }
1787
1958
  return result;
1788
1959
  }
@@ -1809,14 +1980,14 @@ function toNodeArray(node) {
1809
1980
  }
1810
1981
  try {
1811
1982
  if (typeof node === "object" && node !== null && "marker" in node) {
1812
- return toNodeArray(node.marker);
1983
+ return toNodeArray(node.marker, ownerDocument);
1813
1984
  }
1814
1985
  } catch {
1815
1986
  }
1816
1987
  try {
1817
- return [document.createTextNode(String(node))];
1988
+ return [ownerDocument.createTextNode(String(node))];
1818
1989
  } catch {
1819
- return [document.createTextNode("")];
1990
+ return [ownerDocument.createTextNode("")];
1820
1991
  }
1821
1992
  }
1822
1993
  function insertNodesBefore(parent, nodes, anchor) {
@@ -2186,7 +2357,7 @@ function applyClass(el, value, prev) {
2186
2357
  return prevState;
2187
2358
  }
2188
2359
  function createChildBinding(parent, getValue, createElementFn) {
2189
- const marker = document.createComment("fict:child");
2360
+ const marker = (parent.ownerDocument ?? document).createComment("fict:child");
2190
2361
  parent.appendChild(marker);
2191
2362
  const hostRoot = getCurrentRoot();
2192
2363
  const dispose = createRenderEffect(() => {
@@ -2200,7 +2371,7 @@ function createChildBinding(parent, getValue, createElementFn) {
2200
2371
  return;
2201
2372
  }
2202
2373
  const output = createElementFn(value);
2203
- nodes = toNodeArray(output);
2374
+ nodes = toNodeArray(output, marker.ownerDocument ?? parent.ownerDocument ?? document);
2204
2375
  const parentNode = marker.parentNode;
2205
2376
  if (parentNode) {
2206
2377
  insertNodesBefore(parentNode, nodes, marker);
@@ -2309,7 +2480,7 @@ function globalEventHandler(e) {
2309
2480
  Object.defineProperty(e, "currentTarget", {
2310
2481
  configurable: true,
2311
2482
  get() {
2312
- return node || document;
2483
+ return node || oriCurrentTarget || asNode(oriTarget)?.ownerDocument || document;
2313
2484
  }
2314
2485
  });
2315
2486
  if (e.composedPath) {
@@ -2377,7 +2548,8 @@ function bindEvent(el, eventName, handler, options2) {
2377
2548
  }
2378
2549
  function createPortal(container, render2, createElementFn) {
2379
2550
  const parentRoot = getCurrentRoot();
2380
- const marker = document.createComment("fict:portal");
2551
+ const markerOwnerDocument = container.ownerDocument ?? document;
2552
+ const marker = markerOwnerDocument.createComment("fict:portal");
2381
2553
  container.appendChild(marker);
2382
2554
  let currentNodes = [];
2383
2555
  let currentRoot2 = null;
@@ -2391,13 +2563,14 @@ function createPortal(container, render2, createElementFn) {
2391
2563
  currentNodes = [];
2392
2564
  }
2393
2565
  const root = createRootContext(parentRoot);
2566
+ root.ownerDocument = container.ownerDocument ?? parentRoot?.ownerDocument ?? document;
2394
2567
  const prev = pushRoot(root);
2395
2568
  let handledError = false;
2396
2569
  try {
2397
2570
  const output = render2();
2398
2571
  if (output != null && output !== false) {
2399
2572
  const el = createElementFn(output);
2400
- const nodes = toNodeArray(el);
2573
+ const nodes = toNodeArray(el, markerOwnerDocument);
2401
2574
  if (marker.parentNode) {
2402
2575
  insertNodesBefore(marker.parentNode, nodes, marker);
2403
2576
  }
@@ -2651,8 +2824,35 @@ var SVG_NS = "http://www.w3.org/2000/svg";
2651
2824
  var MATHML_NS = "http://www.w3.org/1998/Math/MathML";
2652
2825
  var isDev7 = true ? true : typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
2653
2826
  var nextComponentId = 1;
2827
+ function collectComponentMountElements(node) {
2828
+ if (node instanceof DocumentFragment) {
2829
+ return Array.from(node.childNodes).filter(
2830
+ (child) => child instanceof HTMLElement
2831
+ );
2832
+ }
2833
+ if (node instanceof HTMLElement) {
2834
+ if (node.hasAttribute("data-fict-host")) {
2835
+ const children = Array.from(node.children).filter(
2836
+ (child) => child instanceof HTMLElement
2837
+ );
2838
+ if (children.length > 0) return children;
2839
+ }
2840
+ return [node];
2841
+ }
2842
+ return [];
2843
+ }
2844
+ function annotateComponentElements(elements, componentId, componentName) {
2845
+ for (const element of elements) {
2846
+ element.setAttribute("data-fict-component", componentName);
2847
+ element.setAttribute("data-fict-component-id", String(componentId));
2848
+ const annotated = element;
2849
+ annotated.__fict_component_id__ = componentId;
2850
+ annotated.__fict_component_name__ = componentName;
2851
+ }
2852
+ }
2654
2853
  function render(view, container) {
2655
2854
  const root = createRootContext();
2855
+ root.ownerDocument = container.ownerDocument ?? document;
2656
2856
  const prev = pushRoot(root);
2657
2857
  let dom = void 0;
2658
2858
  try {
@@ -2679,7 +2879,7 @@ function render(view, container) {
2679
2879
  return teardown;
2680
2880
  }
2681
2881
  function createElement(node) {
2682
- return createElementWithContext(node, null);
2882
+ return createElementWithContext(node, null, resolveOwnerDocument());
2683
2883
  }
2684
2884
  function resolveNamespace(tagName, namespace) {
2685
2885
  if (tagName === "svg") return "svg";
@@ -2689,22 +2889,25 @@ function resolveNamespace(tagName, namespace) {
2689
2889
  if (isDev7 && SVGElements.has(tagName)) return "svg";
2690
2890
  return null;
2691
2891
  }
2692
- function createElementWithContext(node, namespace) {
2892
+ function resolveOwnerDocument(ownerDocument) {
2893
+ return ownerDocument ?? getCurrentRoot()?.ownerDocument ?? document;
2894
+ }
2895
+ function createElementWithContext(node, namespace, ownerDocument) {
2693
2896
  if (node instanceof Node) {
2694
2897
  return node;
2695
2898
  }
2696
2899
  if (node === null || node === void 0 || node === false) {
2697
- return document.createTextNode("");
2900
+ return ownerDocument.createTextNode("");
2698
2901
  }
2699
2902
  if (isReactive(node)) {
2700
2903
  const resolved = node();
2701
2904
  if (resolved === node) {
2702
- return document.createTextNode("");
2905
+ return ownerDocument.createTextNode("");
2703
2906
  }
2704
- return createElementWithContext(resolved, namespace);
2907
+ return createElementWithContext(resolved, namespace, ownerDocument);
2705
2908
  }
2706
2909
  if (typeof node === "function") {
2707
- return document.createTextNode("");
2910
+ return ownerDocument.createTextNode("");
2708
2911
  }
2709
2912
  if (typeof node === "object" && node !== null && !(node instanceof Node)) {
2710
2913
  if ("marker" in node) {
@@ -2720,21 +2923,21 @@ function createElementWithContext(node, namespace) {
2720
2923
  Promise.resolve().then(runFlush).catch(() => void 0);
2721
2924
  }
2722
2925
  }
2723
- return createElement(handle.marker);
2926
+ return createElementWithContext(handle.marker, namespace, ownerDocument);
2724
2927
  }
2725
2928
  }
2726
2929
  if (Array.isArray(node)) {
2727
- const frag = document.createDocumentFragment();
2930
+ const frag = ownerDocument.createDocumentFragment();
2728
2931
  for (const child of node) {
2729
- appendChildNode(frag, child, namespace);
2932
+ appendChildNode(frag, child, namespace, ownerDocument);
2730
2933
  }
2731
2934
  return frag;
2732
2935
  }
2733
2936
  if (typeof node === "string" || typeof node === "number") {
2734
- return document.createTextNode(String(node));
2937
+ return ownerDocument.createTextNode(String(node));
2735
2938
  }
2736
2939
  if (typeof node === "boolean") {
2737
- return document.createTextNode("");
2940
+ return ownerDocument.createTextNode("");
2738
2941
  }
2739
2942
  const vnode = node;
2740
2943
  if (typeof vnode.type === "function") {
@@ -2762,10 +2965,11 @@ function createElementWithContext(node, namespace) {
2762
2965
  });
2763
2966
  const props = createPropsProxy(baseProps);
2764
2967
  const hook = isDev7 ? getDevtoolsHook() : void 0;
2968
+ const componentName = vnode.type.name || "Anonymous";
2765
2969
  const parentId = hook ? __fictGetCurrentComponentId() : void 0;
2766
2970
  const componentId = hook ? nextComponentId++ : void 0;
2767
2971
  if (hook?.registerComponent && componentId !== void 0) {
2768
- hook.registerComponent(componentId, vnode.type.name || "Anonymous", parentId);
2972
+ hook.registerComponent(componentId, componentName, parentId);
2769
2973
  }
2770
2974
  const ctx = __fictPushContext();
2771
2975
  if (componentId !== void 0) {
@@ -2776,15 +2980,19 @@ function createElementWithContext(node, namespace) {
2776
2980
  }
2777
2981
  try {
2778
2982
  const rendered = vnode.type(props);
2983
+ let mountElements;
2984
+ if (hook && componentId !== void 0) {
2985
+ hook.componentRender?.(componentId);
2986
+ }
2779
2987
  if (hook && componentId !== void 0) {
2780
2988
  onMount(() => {
2781
- hook.componentMount?.(componentId);
2989
+ hook.componentMount?.(componentId, mountElements);
2782
2990
  });
2783
2991
  onCleanup(() => hook.componentUnmount?.(componentId));
2784
2992
  }
2785
2993
  if (__fictIsResumable() && !__fictIsHydrating()) {
2786
- const content = createElementWithContext(rendered, namespace);
2787
- const host = namespace === "svg" ? document.createElementNS(SVG_NS, "fict-host") : namespace === "mathml" ? document.createElementNS(MATHML_NS, "fict-host") : document.createElement("fict-host");
2994
+ const content = createElementWithContext(rendered, namespace, ownerDocument);
2995
+ const host = namespace === "svg" ? ownerDocument.createElementNS(SVG_NS, "fict-host") : namespace === "mathml" ? ownerDocument.createElementNS(MATHML_NS, "fict-host") : ownerDocument.createElement("fict-host");
2788
2996
  host.setAttribute("data-fict-host", "");
2789
2997
  if (namespace === null && host.style) {
2790
2998
  ;
@@ -2801,12 +3009,21 @@ function createElementWithContext(node, namespace) {
2801
3009
  } else {
2802
3010
  host.appendChild(content);
2803
3011
  }
3012
+ if (hook && componentId !== void 0) {
3013
+ mountElements = collectComponentMountElements(host);
3014
+ annotateComponentElements(mountElements, componentId, componentName);
3015
+ }
2804
3016
  return host;
2805
3017
  }
2806
- return createElementWithContext(rendered, namespace);
3018
+ const componentRoot = createElementWithContext(rendered, namespace, ownerDocument);
3019
+ if (hook && componentId !== void 0) {
3020
+ mountElements = collectComponentMountElements(componentRoot);
3021
+ annotateComponentElements(mountElements, componentId, componentName);
3022
+ }
3023
+ return componentRoot;
2807
3024
  } catch (err) {
2808
3025
  if (handleSuspend(err)) {
2809
- return document.createComment("fict:suspend");
3026
+ return ownerDocument.createComment("fict:suspend");
2810
3027
  }
2811
3028
  handleError(err, { source: "render", componentName: vnode.type.name });
2812
3029
  throw err;
@@ -2815,58 +3032,64 @@ function createElementWithContext(node, namespace) {
2815
3032
  }
2816
3033
  }
2817
3034
  if (vnode.type === Fragment) {
2818
- const frag = document.createDocumentFragment();
3035
+ const frag = ownerDocument.createDocumentFragment();
2819
3036
  const children = vnode.props?.children;
2820
- appendChildren(frag, children, namespace);
3037
+ appendChildren(frag, children, namespace, ownerDocument);
2821
3038
  return frag;
2822
3039
  }
2823
3040
  const tagName = typeof vnode.type === "string" ? vnode.type : "div";
2824
3041
  const resolvedNamespace = resolveNamespace(tagName, namespace);
2825
- const el = resolvedNamespace === "svg" ? document.createElementNS(SVG_NS, tagName) : resolvedNamespace === "mathml" ? document.createElementNS(MATHML_NS, tagName) : document.createElement(tagName);
3042
+ const el = resolvedNamespace === "svg" ? ownerDocument.createElementNS(SVG_NS, tagName) : resolvedNamespace === "mathml" ? ownerDocument.createElementNS(MATHML_NS, tagName) : ownerDocument.createElement(tagName);
2826
3043
  applyProps(el, vnode.props ?? {}, resolvedNamespace === "svg");
2827
3044
  appendChildren(
2828
3045
  el,
2829
3046
  vnode.props?.children,
2830
- tagName === "foreignObject" ? null : resolvedNamespace
3047
+ tagName === "foreignObject" ? null : resolvedNamespace,
3048
+ ownerDocument
2831
3049
  );
2832
3050
  return el;
2833
3051
  }
2834
3052
  function isBindingHandle(node) {
2835
3053
  return node !== null && typeof node === "object" && "marker" in node && "dispose" in node && typeof node.dispose === "function";
2836
3054
  }
2837
- function appendChildNode(parent, child, namespace) {
3055
+ function appendChildNode(parent, child, namespace, ownerDocument) {
3056
+ const parentOwnerDocument = parent.ownerDocument ?? ownerDocument;
2838
3057
  if (child === null || child === void 0 || child === false) {
2839
3058
  return;
2840
3059
  }
2841
3060
  if (isBindingHandle(child)) {
2842
- appendChildNode(parent, child.marker, namespace);
3061
+ appendChildNode(parent, child.marker, namespace, parentOwnerDocument);
2843
3062
  child.flush?.();
2844
3063
  return;
2845
3064
  }
2846
3065
  if (typeof child === "function") {
2847
3066
  const childGetter = child;
2848
3067
  if (isReactive(childGetter)) {
2849
- createChildBinding(parent, childGetter, (node) => createElementWithContext(node, namespace));
3068
+ createChildBinding(
3069
+ parent,
3070
+ childGetter,
3071
+ (node) => createElementWithContext(node, namespace, parentOwnerDocument)
3072
+ );
2850
3073
  return;
2851
3074
  }
2852
3075
  return;
2853
3076
  }
2854
3077
  if (Array.isArray(child)) {
2855
3078
  for (const item of child) {
2856
- appendChildNode(parent, item, namespace);
3079
+ appendChildNode(parent, item, namespace, parentOwnerDocument);
2857
3080
  }
2858
3081
  return;
2859
3082
  }
2860
3083
  let domNode;
2861
3084
  if (typeof child !== "object" || child === null) {
2862
- domNode = document.createTextNode(String(child ?? ""));
3085
+ domNode = parentOwnerDocument.createTextNode(String(child ?? ""));
2863
3086
  } else {
2864
- domNode = createElementWithContext(child, namespace);
3087
+ domNode = createElementWithContext(child, namespace, parentOwnerDocument);
2865
3088
  }
2866
3089
  if (domNode.nodeType === 11) {
2867
3090
  const children = Array.from(domNode.childNodes);
2868
3091
  for (const node of children) {
2869
- appendChildNode(parent, node, namespace);
3092
+ appendChildNode(parent, node, namespace, parentOwnerDocument);
2870
3093
  }
2871
3094
  return;
2872
3095
  }
@@ -2884,15 +3107,15 @@ function appendChildNode(parent, child, namespace) {
2884
3107
  throw e;
2885
3108
  }
2886
3109
  }
2887
- function appendChildren(parent, children, namespace) {
3110
+ function appendChildren(parent, children, namespace, ownerDocument) {
2888
3111
  if (children === void 0) return;
2889
3112
  if (Array.isArray(children)) {
2890
3113
  for (const child of children) {
2891
- appendChildren(parent, child, namespace);
3114
+ appendChildren(parent, child, namespace, ownerDocument);
2892
3115
  }
2893
3116
  return;
2894
3117
  }
2895
- appendChildNode(parent, children, namespace);
3118
+ appendChildNode(parent, children, namespace, ownerDocument);
2896
3119
  }
2897
3120
  function applyRef(el, value) {
2898
3121
  if (typeof value === "function") {
@@ -3108,10 +3331,11 @@ function eventNameFromProp(key) {
3108
3331
 
3109
3332
  // src/error-boundary.ts
3110
3333
  function ErrorBoundary(props) {
3111
- const fragment = document.createDocumentFragment();
3112
- const marker = document.createComment("fict:error-boundary");
3113
- fragment.appendChild(marker);
3114
3334
  const hostRoot = getCurrentRoot();
3335
+ const markerOwnerDocument = hostRoot?.ownerDocument ?? document;
3336
+ const fragment = markerOwnerDocument.createDocumentFragment();
3337
+ const marker = markerOwnerDocument.createComment("fict:error-boundary");
3338
+ fragment.appendChild(marker);
3115
3339
  let cleanup;
3116
3340
  let activeNodes = [];
3117
3341
  let renderingFallback = false;
@@ -3140,7 +3364,7 @@ function ErrorBoundary(props) {
3140
3364
  let nodes = [];
3141
3365
  try {
3142
3366
  const output = createElement(value);
3143
- nodes = toNodeArray(output);
3367
+ nodes = toNodeArray(output, markerOwnerDocument);
3144
3368
  const parentNode = marker.parentNode;
3145
3369
  if (parentNode) {
3146
3370
  insertNodesBefore(parentNode, nodes, marker);
@@ -3218,6 +3442,7 @@ function Suspense(props) {
3218
3442
  let resolvedOnce = false;
3219
3443
  let epoch = 0;
3220
3444
  const hostRoot = getCurrentRoot();
3445
+ const markerOwnerDocument = hostRoot?.ownerDocument ?? document;
3221
3446
  const toFallback = (err) => typeof props.fallback === "function" ? props.fallback(err) : props.fallback;
3222
3447
  const renderView = (view) => {
3223
3448
  if (cleanup) {
@@ -3241,7 +3466,7 @@ function Suspense(props) {
3241
3466
  boundaryPushed = true;
3242
3467
  }
3243
3468
  const output = createElement(view);
3244
- nodes = toNodeArray(output);
3469
+ nodes = toNodeArray(output, markerOwnerDocument);
3245
3470
  const suspendedAttempt = root.suspended || nodes.length > 0 && nodes.every((node) => node instanceof Comment && node.data === "fict:suspend");
3246
3471
  if (suspendedAttempt) {
3247
3472
  popRoot(prev);
@@ -3272,9 +3497,9 @@ function Suspense(props) {
3272
3497
  };
3273
3498
  activeNodes = nodes;
3274
3499
  };
3275
- const fragment = document.createDocumentFragment();
3276
- const startMarker = document.createComment("fict:suspense-start");
3277
- const endMarker = document.createComment("fict:suspense-end");
3500
+ const fragment = markerOwnerDocument.createDocumentFragment();
3501
+ const startMarker = markerOwnerDocument.createComment("fict:suspense-start");
3502
+ const endMarker = markerOwnerDocument.createComment("fict:suspense-end");
3278
3503
  fragment.appendChild(startMarker);
3279
3504
  fragment.appendChild(endMarker);
3280
3505
  let cleanup;
@@ -3394,8 +3619,9 @@ function createContext(defaultValue) {
3394
3619
  const providerRoot = createRootContext(hostRoot);
3395
3620
  const contextMap = getContextMap(providerRoot);
3396
3621
  contextMap.set(id, props.value);
3397
- const fragment = document.createDocumentFragment();
3398
- const marker = document.createComment("fict:ctx");
3622
+ const markerOwnerDocument = providerRoot.ownerDocument ?? hostRoot?.ownerDocument ?? document;
3623
+ const fragment = markerOwnerDocument.createDocumentFragment();
3624
+ const marker = markerOwnerDocument.createComment("fict:ctx");
3399
3625
  fragment.appendChild(marker);
3400
3626
  let cleanup;
3401
3627
  let activeNodes = [];
@@ -3415,7 +3641,7 @@ function createContext(defaultValue) {
3415
3641
  let nodes = [];
3416
3642
  try {
3417
3643
  const output = createElement(children);
3418
- nodes = toNodeArray(output);
3644
+ nodes = toNodeArray(output, markerOwnerDocument);
3419
3645
  const parentNode = marker.parentNode;
3420
3646
  if (parentNode) {
3421
3647
  insertNodesBefore(parentNode, nodes, marker);