@alloy-js/core 0.24.0-dev.1 → 0.24.0-dev.6

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 (532) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/dev/src/components/AccessExpression.test.js +1 -1
  3. package/dist/dev/src/components/AccessExpression.test.js.map +1 -1
  4. package/dist/dev/src/components/Output.js +3 -2
  5. package/dist/dev/src/components/Output.js.map +1 -1
  6. package/dist/dev/src/components/SourceFile.js.map +1 -1
  7. package/dist/dev/src/content-slot.test.js +1 -1
  8. package/dist/dev/src/content-slot.test.js.map +1 -1
  9. package/dist/dev/src/context.js +30 -3
  10. package/dist/dev/src/context.js.map +1 -1
  11. package/dist/dev/src/debug/cli.browser.js +14 -0
  12. package/dist/dev/src/debug/cli.browser.js.map +1 -0
  13. package/dist/dev/src/debug/diagnostics.test.js +1 -1
  14. package/dist/dev/src/debug/diagnostics.test.js.map +1 -1
  15. package/dist/dev/src/debug/effects.test.js +1 -1
  16. package/dist/dev/src/debug/effects.test.js.map +1 -1
  17. package/dist/dev/src/debug/file-streaming.js +103 -0
  18. package/dist/dev/src/debug/file-streaming.js.map +1 -0
  19. package/dist/dev/src/debug/files.test.js +4 -5
  20. package/dist/dev/src/debug/files.test.js.map +1 -1
  21. package/dist/dev/src/debug/index.js +4 -6
  22. package/dist/dev/src/debug/index.js.map +1 -1
  23. package/dist/dev/src/debug/message-format.test.js +50 -52
  24. package/dist/dev/src/debug/message-format.test.js.map +1 -1
  25. package/dist/dev/src/debug/render-tree-orphans.test.js +13 -23
  26. package/dist/dev/src/debug/render-tree-orphans.test.js.map +1 -1
  27. package/dist/dev/src/debug/render.js +529 -352
  28. package/dist/dev/src/debug/render.js.map +1 -1
  29. package/dist/dev/src/debug/render.test.js +171 -92
  30. package/dist/dev/src/debug/render.test.js.map +1 -1
  31. package/dist/dev/src/debug/trace-db.browser.js +11 -0
  32. package/dist/dev/src/debug/trace-db.browser.js.map +1 -0
  33. package/dist/dev/src/debug/trace-db.js +40 -0
  34. package/dist/dev/src/debug/trace-db.js.map +1 -0
  35. package/dist/dev/src/debug/trace-writer.js +130 -39
  36. package/dist/dev/src/debug/trace-writer.js.map +1 -1
  37. package/dist/dev/src/debug/trace.js +0 -36
  38. package/dist/dev/src/debug/trace.js.map +1 -1
  39. package/dist/dev/src/devtools/devtools-server.js +55 -32
  40. package/dist/dev/src/devtools/devtools-server.js.map +1 -1
  41. package/dist/dev/src/devtools-entry.browser.js.map +1 -1
  42. package/dist/dev/src/devtools-entry.js.map +1 -1
  43. package/dist/dev/src/diagnostics.js +19 -1
  44. package/dist/dev/src/diagnostics.js.map +1 -1
  45. package/dist/dev/src/index.js +5 -2
  46. package/dist/dev/src/index.js.map +1 -1
  47. package/dist/dev/src/jsx-runtime.js +14 -8
  48. package/dist/dev/src/jsx-runtime.js.map +1 -1
  49. package/dist/dev/src/output-types.js +2 -0
  50. package/dist/dev/src/output-types.js.map +1 -0
  51. package/dist/dev/src/reactivity.js +155 -13
  52. package/dist/dev/src/reactivity.js.map +1 -1
  53. package/dist/dev/src/render/get-string-width.js +61 -0
  54. package/dist/dev/src/render/get-string-width.js.map +1 -0
  55. package/dist/dev/src/render/index.js +2 -0
  56. package/dist/dev/src/render/index.js.map +1 -0
  57. package/dist/dev/src/render/node-context.js +7 -0
  58. package/dist/dev/src/render/node-context.js.map +1 -0
  59. package/dist/dev/src/render/node.js +386 -0
  60. package/dist/dev/src/render/node.js.map +1 -0
  61. package/dist/dev/src/render/printer-support.js +180 -0
  62. package/dist/dev/src/render/printer-support.js.map +1 -0
  63. package/dist/dev/src/render/printer.js +797 -0
  64. package/dist/dev/src/render/printer.js.map +1 -0
  65. package/dist/dev/src/render-error.js +79 -0
  66. package/dist/dev/src/render-error.js.map +1 -0
  67. package/dist/dev/src/render-output.js +209 -0
  68. package/dist/dev/src/render-output.js.map +1 -0
  69. package/dist/dev/src/runtime/create-intrinsic.js +53 -0
  70. package/dist/dev/src/runtime/create-intrinsic.js.map +1 -0
  71. package/dist/dev/src/runtime/fragment.js +21 -0
  72. package/dist/dev/src/runtime/fragment.js.map +1 -0
  73. package/dist/dev/src/runtime/index.js +13 -0
  74. package/dist/dev/src/runtime/index.js.map +1 -0
  75. package/dist/dev/src/runtime/insert.js +453 -0
  76. package/dist/dev/src/runtime/insert.js.map +1 -0
  77. package/dist/dev/src/runtime/intrinsic.js +1 -11
  78. package/dist/dev/src/runtime/intrinsic.js.map +1 -1
  79. package/dist/dev/src/scheduler.js +38 -14
  80. package/dist/dev/src/scheduler.js.map +1 -1
  81. package/dist/dev/src/stc.js +2 -0
  82. package/dist/dev/src/stc.js.map +1 -1
  83. package/dist/dev/src/sti.js +1 -1
  84. package/dist/dev/src/sti.js.map +1 -1
  85. package/dist/dev/src/symbols/symbol-slot.test.js +1 -1
  86. package/dist/dev/src/symbols/symbol-slot.test.js.map +1 -1
  87. package/dist/dev/src/test-render.js +78 -0
  88. package/dist/dev/src/test-render.js.map +1 -0
  89. package/dist/dev/src/utils.js +47 -35
  90. package/dist/dev/src/utils.js.map +1 -1
  91. package/dist/dev/test/babel-e2e.test.js +218 -0
  92. package/dist/dev/test/babel-e2e.test.js.map +1 -0
  93. package/dist/dev/test/browser-build.test.js +70 -9
  94. package/dist/dev/test/browser-build.test.js.map +1 -1
  95. package/dist/dev/test/components/block.test.js +1 -1
  96. package/dist/dev/test/components/block.test.js.map +1 -1
  97. package/dist/dev/test/components/copy-file.test.js +7 -7
  98. package/dist/dev/test/components/copy-file.test.js.map +1 -1
  99. package/dist/dev/test/components/update-file.test.js +1 -1
  100. package/dist/dev/test/components/update-file.test.js.map +1 -1
  101. package/dist/dev/test/components/wrap.test.js +1 -1
  102. package/dist/dev/test/components/wrap.test.js.map +1 -1
  103. package/dist/dev/test/control-flow/match.test.js +1 -1
  104. package/dist/dev/test/control-flow/match.test.js.map +1 -1
  105. package/dist/dev/test/control-flow/show.test.js +1 -1
  106. package/dist/dev/test/control-flow/show.test.js.map +1 -1
  107. package/dist/dev/test/lazy-isempty.test.js +6 -6
  108. package/dist/dev/test/lazy-isempty.test.js.map +1 -1
  109. package/dist/dev/test/node.test.js +80 -0
  110. package/dist/dev/test/node.test.js.map +1 -0
  111. package/dist/dev/test/output-e2e.test.js +194 -0
  112. package/dist/dev/test/output-e2e.test.js.map +1 -0
  113. package/dist/dev/test/reactivity/circular-reactives.test.js +1 -1
  114. package/dist/dev/test/reactivity/circular-reactives.test.js.map +1 -1
  115. package/dist/dev/test/reactivity/cleanup.test.js +1 -1
  116. package/dist/dev/test/reactivity/cleanup.test.js.map +1 -1
  117. package/dist/dev/test/rendering/memoization.test.js +6 -1
  118. package/dist/dev/test/rendering/memoization.test.js.map +1 -1
  119. package/dist/dev/test/rendering/render-output-diagnostics.test.js +102 -0
  120. package/dist/dev/test/rendering/render-output-diagnostics.test.js.map +1 -0
  121. package/dist/dev/test/runtime.test.js +385 -0
  122. package/dist/dev/test/runtime.test.js.map +1 -0
  123. package/dist/dev/test/tree-test-utils.js +16 -0
  124. package/dist/dev/test/tree-test-utils.js.map +1 -0
  125. package/dist/dev/test/utils.test.js +1 -1
  126. package/dist/dev/test/utils.test.js.map +1 -1
  127. package/dist/dev/testing/devtools-utils.js +1 -1
  128. package/dist/dev/testing/devtools-utils.js.map +1 -1
  129. package/dist/dev/testing/extend-expect.js +7 -33
  130. package/dist/dev/testing/extend-expect.js.map +1 -1
  131. package/dist/dev/testing/render.js +7 -17
  132. package/dist/dev/testing/render.js.map +1 -1
  133. package/dist/devtools/index.html +17 -17
  134. package/dist/src/components/AccessExpression.test.js +1 -1
  135. package/dist/src/components/AccessExpression.test.js.map +1 -1
  136. package/dist/src/components/Output.d.ts +1 -1
  137. package/dist/src/components/Output.d.ts.map +1 -1
  138. package/dist/src/components/Output.js +2 -1
  139. package/dist/src/components/Output.js.map +1 -1
  140. package/dist/src/components/ReferenceOrContent.d.ts +1 -1
  141. package/dist/src/components/ReferenceOrContent.d.ts.map +1 -1
  142. package/dist/src/components/SourceFile.d.ts +1 -1
  143. package/dist/src/components/SourceFile.d.ts.map +1 -1
  144. package/dist/src/components/SourceFile.js.map +1 -1
  145. package/dist/src/content-slot.test.js +1 -1
  146. package/dist/src/content-slot.test.js.map +1 -1
  147. package/dist/src/context/format-options.d.ts +1 -1
  148. package/dist/src/context/format-options.d.ts.map +1 -1
  149. package/dist/src/context.d.ts +9 -1
  150. package/dist/src/context.d.ts.map +1 -1
  151. package/dist/src/context.js +30 -3
  152. package/dist/src/context.js.map +1 -1
  153. package/dist/src/debug/cli.browser.d.ts +13 -0
  154. package/dist/src/debug/cli.browser.d.ts.map +1 -0
  155. package/dist/src/debug/cli.browser.js +14 -0
  156. package/dist/src/debug/cli.browser.js.map +1 -0
  157. package/dist/src/debug/diagnostics.test.js +1 -1
  158. package/dist/src/debug/diagnostics.test.js.map +1 -1
  159. package/dist/src/debug/effects.test.js +1 -1
  160. package/dist/src/debug/effects.test.js.map +1 -1
  161. package/dist/src/debug/file-streaming.d.ts +22 -0
  162. package/dist/src/debug/file-streaming.d.ts.map +1 -0
  163. package/dist/src/debug/file-streaming.js +103 -0
  164. package/dist/src/debug/file-streaming.js.map +1 -0
  165. package/dist/src/debug/files.test.js +4 -5
  166. package/dist/src/debug/files.test.js.map +1 -1
  167. package/dist/src/debug/index.d.ts +5 -7
  168. package/dist/src/debug/index.d.ts.map +1 -1
  169. package/dist/src/debug/index.js +4 -6
  170. package/dist/src/debug/index.js.map +1 -1
  171. package/dist/src/debug/message-format.test.js +16 -18
  172. package/dist/src/debug/message-format.test.js.map +1 -1
  173. package/dist/src/debug/render-tree-orphans.test.js +8 -18
  174. package/dist/src/debug/render-tree-orphans.test.js.map +1 -1
  175. package/dist/src/debug/render.d.ts +71 -21
  176. package/dist/src/debug/render.d.ts.map +1 -1
  177. package/dist/src/debug/render.js +529 -352
  178. package/dist/src/debug/render.js.map +1 -1
  179. package/dist/src/debug/render.test.js +137 -74
  180. package/dist/src/debug/render.test.js.map +1 -1
  181. package/dist/src/debug/trace-db.browser.d.ts +9 -0
  182. package/dist/src/debug/trace-db.browser.d.ts.map +1 -0
  183. package/dist/src/debug/trace-db.browser.js +11 -0
  184. package/dist/src/debug/trace-db.browser.js.map +1 -0
  185. package/dist/src/debug/trace-db.d.ts +16 -0
  186. package/dist/src/debug/trace-db.d.ts.map +1 -0
  187. package/dist/src/debug/trace-db.js +40 -0
  188. package/dist/src/debug/trace-db.js.map +1 -0
  189. package/dist/src/debug/trace-writer.d.ts +6 -1
  190. package/dist/src/debug/trace-writer.d.ts.map +1 -1
  191. package/dist/src/debug/trace-writer.js +130 -39
  192. package/dist/src/debug/trace-writer.js.map +1 -1
  193. package/dist/src/debug/trace.d.ts +0 -36
  194. package/dist/src/debug/trace.d.ts.map +1 -1
  195. package/dist/src/debug/trace.js +0 -36
  196. package/dist/src/debug/trace.js.map +1 -1
  197. package/dist/src/devtools/devtools-protocol.d.ts +34 -1
  198. package/dist/src/devtools/devtools-protocol.d.ts.map +1 -1
  199. package/dist/src/devtools/devtools-server.d.ts.map +1 -1
  200. package/dist/src/devtools/devtools-server.js +55 -32
  201. package/dist/src/devtools/devtools-server.js.map +1 -1
  202. package/dist/src/devtools-entry.browser.d.ts +1 -1
  203. package/dist/src/devtools-entry.browser.d.ts.map +1 -1
  204. package/dist/src/devtools-entry.browser.js.map +1 -1
  205. package/dist/src/devtools-entry.d.ts +1 -1
  206. package/dist/src/devtools-entry.d.ts.map +1 -1
  207. package/dist/src/devtools-entry.js.map +1 -1
  208. package/dist/src/diagnostics.d.ts +4 -0
  209. package/dist/src/diagnostics.d.ts.map +1 -1
  210. package/dist/src/diagnostics.js +19 -1
  211. package/dist/src/diagnostics.js.map +1 -1
  212. package/dist/src/index.d.ts +5 -2
  213. package/dist/src/index.d.ts.map +1 -1
  214. package/dist/src/index.js +5 -2
  215. package/dist/src/index.js.map +1 -1
  216. package/dist/src/jsx-runtime.d.ts +13 -4
  217. package/dist/src/jsx-runtime.d.ts.map +1 -1
  218. package/dist/src/jsx-runtime.js +14 -8
  219. package/dist/src/jsx-runtime.js.map +1 -1
  220. package/dist/src/output-types.d.ts +40 -0
  221. package/dist/src/output-types.d.ts.map +1 -0
  222. package/dist/src/output-types.js +2 -0
  223. package/dist/src/output-types.js.map +1 -0
  224. package/dist/src/reactivity.d.ts +49 -18
  225. package/dist/src/reactivity.d.ts.map +1 -1
  226. package/dist/src/reactivity.js +155 -13
  227. package/dist/src/reactivity.js.map +1 -1
  228. package/dist/src/render/get-string-width.d.ts +19 -0
  229. package/dist/src/render/get-string-width.d.ts.map +1 -0
  230. package/dist/src/render/get-string-width.js +61 -0
  231. package/dist/src/render/get-string-width.js.map +1 -0
  232. package/dist/src/render/index.d.ts +2 -0
  233. package/dist/src/render/index.d.ts.map +1 -0
  234. package/dist/src/render/index.js +2 -0
  235. package/dist/src/render/index.js.map +1 -0
  236. package/dist/src/render/node-context.d.ts +5 -0
  237. package/dist/src/render/node-context.d.ts.map +1 -0
  238. package/dist/src/render/node-context.js +7 -0
  239. package/dist/src/render/node-context.js.map +1 -0
  240. package/dist/src/render/node.d.ts +146 -0
  241. package/dist/src/render/node.d.ts.map +1 -0
  242. package/dist/src/render/node.js +386 -0
  243. package/dist/src/render/node.js.map +1 -0
  244. package/dist/src/render/printer-support.d.ts +50 -0
  245. package/dist/src/render/printer-support.d.ts.map +1 -0
  246. package/dist/src/render/printer-support.js +180 -0
  247. package/dist/src/render/printer-support.js.map +1 -0
  248. package/dist/src/render/printer.d.ts +35 -0
  249. package/dist/src/render/printer.d.ts.map +1 -0
  250. package/dist/src/render/printer.js +797 -0
  251. package/dist/src/render/printer.js.map +1 -0
  252. package/dist/src/render-error.d.ts +4 -0
  253. package/dist/src/render-error.d.ts.map +1 -0
  254. package/dist/src/render-error.js +79 -0
  255. package/dist/src/render-error.js.map +1 -0
  256. package/dist/src/render-output.d.ts +42 -0
  257. package/dist/src/render-output.d.ts.map +1 -0
  258. package/dist/src/render-output.js +209 -0
  259. package/dist/src/render-output.js.map +1 -0
  260. package/dist/src/runtime/component.d.ts +2 -2
  261. package/dist/src/runtime/component.d.ts.map +1 -1
  262. package/dist/src/runtime/create-intrinsic.d.ts +28 -0
  263. package/dist/src/runtime/create-intrinsic.d.ts.map +1 -0
  264. package/dist/src/runtime/create-intrinsic.js +53 -0
  265. package/dist/src/runtime/create-intrinsic.js.map +1 -0
  266. package/dist/src/runtime/fragment.d.ts +16 -0
  267. package/dist/src/runtime/fragment.d.ts.map +1 -0
  268. package/dist/src/runtime/fragment.js +21 -0
  269. package/dist/src/runtime/fragment.js.map +1 -0
  270. package/dist/src/runtime/index.d.ts +12 -0
  271. package/dist/src/runtime/index.d.ts.map +1 -0
  272. package/dist/src/runtime/index.js +13 -0
  273. package/dist/src/runtime/index.js.map +1 -0
  274. package/dist/src/runtime/insert.d.ts +29 -0
  275. package/dist/src/runtime/insert.d.ts.map +1 -0
  276. package/dist/src/runtime/insert.js +453 -0
  277. package/dist/src/runtime/insert.js.map +1 -0
  278. package/dist/src/runtime/intrinsic.d.ts +12 -29
  279. package/dist/src/runtime/intrinsic.d.ts.map +1 -1
  280. package/dist/src/runtime/intrinsic.js +1 -11
  281. package/dist/src/runtime/intrinsic.js.map +1 -1
  282. package/dist/src/scheduler.d.ts.map +1 -1
  283. package/dist/src/scheduler.js +38 -14
  284. package/dist/src/scheduler.js.map +1 -1
  285. package/dist/src/stc.d.ts.map +1 -1
  286. package/dist/src/stc.js +2 -0
  287. package/dist/src/stc.js.map +1 -1
  288. package/dist/src/sti.d.ts +7 -6
  289. package/dist/src/sti.d.ts.map +1 -1
  290. package/dist/src/sti.js +1 -1
  291. package/dist/src/sti.js.map +1 -1
  292. package/dist/src/symbols/symbol-slot.test.js +1 -1
  293. package/dist/src/symbols/symbol-slot.test.js.map +1 -1
  294. package/dist/src/test-render.d.ts +31 -0
  295. package/dist/src/test-render.d.ts.map +1 -0
  296. package/dist/src/test-render.js +78 -0
  297. package/dist/src/test-render.js.map +1 -0
  298. package/dist/src/utils.d.ts +1 -1
  299. package/dist/src/utils.d.ts.map +1 -1
  300. package/dist/src/utils.js +40 -28
  301. package/dist/src/utils.js.map +1 -1
  302. package/dist/src/write-output.d.ts +1 -1
  303. package/dist/src/write-output.d.ts.map +1 -1
  304. package/dist/test/babel-e2e.test.d.ts +13 -0
  305. package/dist/test/babel-e2e.test.d.ts.map +1 -0
  306. package/dist/test/babel-e2e.test.js +218 -0
  307. package/dist/test/babel-e2e.test.js.map +1 -0
  308. package/dist/test/browser-build.test.js +70 -9
  309. package/dist/test/browser-build.test.js.map +1 -1
  310. package/dist/test/components/block.test.js +1 -1
  311. package/dist/test/components/block.test.js.map +1 -1
  312. package/dist/test/components/copy-file.test.d.ts.map +1 -1
  313. package/dist/test/components/copy-file.test.js +1 -1
  314. package/dist/test/components/copy-file.test.js.map +1 -1
  315. package/dist/test/components/update-file.test.js +1 -1
  316. package/dist/test/components/update-file.test.js.map +1 -1
  317. package/dist/test/components/wrap.test.js +1 -1
  318. package/dist/test/components/wrap.test.js.map +1 -1
  319. package/dist/test/control-flow/match.test.js +1 -1
  320. package/dist/test/control-flow/match.test.js.map +1 -1
  321. package/dist/test/control-flow/show.test.js +1 -1
  322. package/dist/test/control-flow/show.test.js.map +1 -1
  323. package/dist/test/lazy-isempty.test.js +6 -6
  324. package/dist/test/lazy-isempty.test.js.map +1 -1
  325. package/dist/test/node.test.d.ts +2 -0
  326. package/dist/test/node.test.d.ts.map +1 -0
  327. package/dist/test/node.test.js +80 -0
  328. package/dist/test/node.test.js.map +1 -0
  329. package/dist/test/output-e2e.test.d.ts +13 -0
  330. package/dist/test/output-e2e.test.d.ts.map +1 -0
  331. package/dist/test/output-e2e.test.js +194 -0
  332. package/dist/test/output-e2e.test.js.map +1 -0
  333. package/dist/test/reactivity/circular-reactives.test.js +1 -1
  334. package/dist/test/reactivity/circular-reactives.test.js.map +1 -1
  335. package/dist/test/reactivity/cleanup.test.js +1 -1
  336. package/dist/test/reactivity/cleanup.test.js.map +1 -1
  337. package/dist/test/rendering/memoization.test.js +6 -1
  338. package/dist/test/rendering/memoization.test.js.map +1 -1
  339. package/dist/test/rendering/render-output-diagnostics.test.d.ts +2 -0
  340. package/dist/test/rendering/render-output-diagnostics.test.d.ts.map +1 -0
  341. package/dist/test/rendering/render-output-diagnostics.test.js +82 -0
  342. package/dist/test/rendering/render-output-diagnostics.test.js.map +1 -0
  343. package/dist/test/runtime.test.d.ts +11 -0
  344. package/dist/test/runtime.test.d.ts.map +1 -0
  345. package/dist/test/runtime.test.js +385 -0
  346. package/dist/test/runtime.test.js.map +1 -0
  347. package/dist/test/tree-test-utils.d.ts +3 -0
  348. package/dist/test/tree-test-utils.d.ts.map +1 -0
  349. package/dist/test/tree-test-utils.js +16 -0
  350. package/dist/test/tree-test-utils.js.map +1 -0
  351. package/dist/test/utils.test.js +1 -1
  352. package/dist/test/utils.test.js.map +1 -1
  353. package/dist/testing/devtools-utils.d.ts.map +1 -1
  354. package/dist/testing/devtools-utils.js +1 -1
  355. package/dist/testing/devtools-utils.js.map +1 -1
  356. package/dist/testing/extend-expect.d.ts.map +1 -1
  357. package/dist/testing/extend-expect.js +7 -33
  358. package/dist/testing/extend-expect.js.map +1 -1
  359. package/dist/testing/render.d.ts +7 -9
  360. package/dist/testing/render.d.ts.map +1 -1
  361. package/dist/testing/render.js +7 -17
  362. package/dist/testing/render.js.map +1 -1
  363. package/dist/tsconfig.tsbuildinfo +1 -1
  364. package/docs/api/components/Output.md +0 -3
  365. package/docs/api/components/SourceFile.md +0 -3
  366. package/docs/api/functions/createComment.md +18 -0
  367. package/docs/api/functions/createElement.md +19 -0
  368. package/docs/api/functions/createFragment.md +17 -0
  369. package/docs/api/functions/createTextNode.md +18 -0
  370. package/docs/api/functions/emitDiagnosticForTree.md +19 -0
  371. package/docs/api/functions/ensureIsEmpty.md +1 -1
  372. package/docs/api/functions/getContextForNode.md +18 -0
  373. package/docs/api/functions/getContextForRenderNode.md +4 -4
  374. package/docs/api/functions/getDiagnosticsForTree.md +7 -5
  375. package/docs/api/functions/getRegisteredDiagnosticsForTree.md +18 -0
  376. package/docs/api/functions/index.md +17 -12
  377. package/docs/api/functions/isCustomContext.md +4 -4
  378. package/docs/api/functions/notifyContentState.md +6 -0
  379. package/docs/api/functions/printTree.md +6 -16
  380. package/docs/api/functions/registerDiagnosticsForTree.md +19 -0
  381. package/docs/api/functions/render.md +1 -2
  382. package/docs/api/functions/renderAsync.md +1 -2
  383. package/docs/api/functions/renderTree.md +8 -5
  384. package/docs/api/functions/reportDiagnosticsForTree.md +18 -0
  385. package/docs/api/functions/runInContext.md +28 -0
  386. package/docs/api/functions/sourceFilesForTree.md +6 -16
  387. package/docs/api/index.md +3 -3
  388. package/docs/api/testing/functions/index.md +1 -1
  389. package/docs/api/testing/functions/renderToString.md +1 -1
  390. package/docs/api/types/AlloyNode.md +22 -0
  391. package/docs/api/types/Child.md +1 -1
  392. package/docs/api/types/CommentNode.md +15 -0
  393. package/docs/api/types/Context.md +13 -15
  394. package/docs/api/types/ElementNode.md +18 -0
  395. package/docs/api/types/FragmentNode.md +12 -0
  396. package/docs/api/types/Insertable.md +7 -0
  397. package/docs/api/types/NodeType.md +5 -0
  398. package/docs/api/types/OutputDirectory.md +0 -50
  399. package/docs/api/types/PrintTreeOptions.md +0 -1
  400. package/docs/api/types/RenderTreeOptions.md +7 -0
  401. package/docs/api/types/StiComponentCreator.md +4 -4
  402. package/docs/api/types/StiSignature.md +1 -1
  403. package/docs/api/types/TextNode.md +16 -0
  404. package/docs/api/types/index.md +10 -28
  405. package/docs/api/variables/COMMENT_NODE.md +5 -0
  406. package/docs/api/variables/ELEMENT_NODE.md +11 -0
  407. package/docs/api/variables/FRAGMENT_NODE.md +5 -0
  408. package/docs/api/variables/TEXT_NODE.md +5 -0
  409. package/docs/api/variables/index.md +4 -2
  410. package/docs/formatting.md +1 -1
  411. package/docs/rendering.md +4 -4
  412. package/package.json +11 -7
  413. package/src/components/AccessExpression.test.tsx +1 -1
  414. package/src/components/Output.tsx +2 -1
  415. package/src/components/SourceFile.tsx +1 -1
  416. package/src/content-slot.test.tsx +1 -1
  417. package/src/context/format-options.ts +1 -1
  418. package/src/context.ts +37 -4
  419. package/src/debug/cli.browser.ts +17 -0
  420. package/src/debug/diagnostics.test.tsx +1 -1
  421. package/src/debug/effects.test.tsx +1 -1
  422. package/src/debug/file-streaming.ts +115 -0
  423. package/src/debug/files.test.tsx +15 -11
  424. package/src/debug/index.ts +11 -11
  425. package/src/debug/message-format.test.tsx +32 -19
  426. package/src/debug/render-tree-orphans.test.tsx +10 -19
  427. package/src/debug/render.test.tsx +206 -78
  428. package/src/debug/render.ts +642 -495
  429. package/src/debug/trace-db.browser.ts +12 -0
  430. package/src/debug/trace-db.ts +42 -0
  431. package/src/debug/trace-writer.ts +173 -41
  432. package/src/debug/trace.ts +0 -20
  433. package/src/devtools/devtools-protocol.ts +43 -0
  434. package/src/devtools/devtools-server.ts +57 -32
  435. package/src/devtools-entry.browser.ts +5 -0
  436. package/src/devtools-entry.ts +5 -0
  437. package/src/diagnostics.ts +31 -0
  438. package/src/index.ts +66 -2
  439. package/src/jsx-runtime.ts +16 -14
  440. package/src/output-types.ts +47 -0
  441. package/src/reactivity.ts +186 -40
  442. package/src/render/get-string-width.ts +201 -0
  443. package/src/render/index.ts +1 -0
  444. package/src/render/node-context.ts +14 -0
  445. package/src/render/node.ts +442 -0
  446. package/src/render/printer-support.ts +209 -0
  447. package/src/render/printer.ts +817 -0
  448. package/src/render-error.ts +98 -0
  449. package/src/render-output.ts +243 -0
  450. package/src/runtime/component.ts +2 -2
  451. package/src/runtime/create-intrinsic.ts +56 -0
  452. package/src/runtime/fragment.ts +22 -0
  453. package/src/runtime/index.ts +12 -0
  454. package/src/runtime/insert.ts +569 -0
  455. package/src/runtime/intrinsic.ts +14 -70
  456. package/src/scheduler.ts +40 -25
  457. package/src/stc.ts +3 -0
  458. package/src/sti.ts +17 -20
  459. package/src/symbols/symbol-slot.test.tsx +1 -1
  460. package/src/test-render.ts +103 -0
  461. package/src/utils.tsx +55 -37
  462. package/src/write-output.ts +1 -1
  463. package/temp/api-testing.json +390 -14
  464. package/temp/api.json +4320 -4144
  465. package/test/babel-e2e.test.ts +224 -0
  466. package/test/browser-build.test.ts +81 -9
  467. package/test/components/block.test.tsx +1 -1
  468. package/test/components/copy-file.test.tsx +2 -1
  469. package/test/components/update-file.test.tsx +1 -1
  470. package/test/components/wrap.test.tsx +1 -1
  471. package/test/control-flow/match.test.tsx +1 -1
  472. package/test/control-flow/show.test.tsx +1 -1
  473. package/test/lazy-isempty.test.tsx +6 -6
  474. package/test/node.test.ts +90 -0
  475. package/test/output-e2e.test.ts +198 -0
  476. package/test/reactivity/circular-reactives.test.tsx +1 -1
  477. package/test/reactivity/cleanup.test.tsx +1 -1
  478. package/test/rendering/memoization.test.tsx +6 -1
  479. package/test/rendering/render-output-diagnostics.test.tsx +120 -0
  480. package/test/runtime.test.ts +448 -0
  481. package/test/tree-test-utils.ts +23 -0
  482. package/test/utils.test.tsx +1 -1
  483. package/testing/devtools-utils.ts +2 -0
  484. package/testing/extend-expect.ts +8 -46
  485. package/testing/render.ts +17 -21
  486. package/dist/dev/src/print-hook.js +0 -10
  487. package/dist/dev/src/print-hook.js.map +0 -1
  488. package/dist/dev/src/render.js +0 -872
  489. package/dist/dev/src/render.js.map +0 -1
  490. package/dist/src/print-hook.d.ts +0 -14
  491. package/dist/src/print-hook.d.ts.map +0 -1
  492. package/dist/src/print-hook.js +0 -10
  493. package/dist/src/print-hook.js.map +0 -1
  494. package/dist/src/render.d.ts +0 -155
  495. package/dist/src/render.d.ts.map +0 -1
  496. package/dist/src/render.js +0 -872
  497. package/dist/src/render.js.map +0 -1
  498. package/docs/api/functions/createIntrinsic.md +0 -19
  499. package/docs/api/functions/createRenderTreeHook.md +0 -19
  500. package/docs/api/functions/getElementCache.md +0 -17
  501. package/docs/api/functions/isIntrinsicElement.md +0 -18
  502. package/docs/api/functions/isPrintHook.md +0 -18
  503. package/docs/api/types/AlignIntrinsicElement.md +0 -5
  504. package/docs/api/types/BrIntrinsicElement.md +0 -5
  505. package/docs/api/types/BreakParentIntrinsicElement.md +0 -5
  506. package/docs/api/types/DedentIntrinsicElement.md +0 -5
  507. package/docs/api/types/DedentToRootIntrinsicElement.md +0 -5
  508. package/docs/api/types/ElementCache.md +0 -5
  509. package/docs/api/types/ElementCacheKey.md +0 -5
  510. package/docs/api/types/FillIntrinsicElement.md +0 -5
  511. package/docs/api/types/GroupIntrinsicElement.md +0 -5
  512. package/docs/api/types/HardlineIntrinsicElement.md +0 -5
  513. package/docs/api/types/HbrIntrinsicElement.md +0 -5
  514. package/docs/api/types/IfBreakIntrinsicElement.md +0 -5
  515. package/docs/api/types/IndentIfBreakIntrinsicElement.md +0 -5
  516. package/docs/api/types/IndentIntrinsicElement.md +0 -5
  517. package/docs/api/types/IntrinsicElement.md +0 -5
  518. package/docs/api/types/IntrinsicElementBase.md +0 -9
  519. package/docs/api/types/LbrIntrinsicElement.md +0 -5
  520. package/docs/api/types/LineIntrinsicElement.md +0 -5
  521. package/docs/api/types/LineSuffixBoundaryIntrinsicElement.md +0 -5
  522. package/docs/api/types/LineSuffixIntrinsicElement.md +0 -5
  523. package/docs/api/types/LiterallineIntrinsicElement.md +0 -5
  524. package/docs/api/types/MarkAsRootIntrinsicElement.md +0 -5
  525. package/docs/api/types/PrintHook.md +0 -10
  526. package/docs/api/types/RenderedTextTree.md +0 -5
  527. package/docs/api/types/SbrIntrinsicElement.md +0 -5
  528. package/docs/api/types/SoftlineIntrinsicElement.md +0 -5
  529. package/docs/api/variables/intrinsicElementKey.md +0 -5
  530. package/docs/api/variables/printHookTag.md +0 -7
  531. package/src/print-hook.ts +0 -22
  532. package/src/render.ts +0 -1154
@@ -1,355 +1,507 @@
1
+ /**
2
+ * Debug-render module — bridges the AlloyNode render tree to the
3
+ * trace-writer SQLite DB and the devtools WebSocket protocol.
4
+ *
5
+ * # Tree shape
6
+ *
7
+ * The trace tree mirrors the real AlloyNode tree. Component invocations
8
+ * are recorded separately as canonical metadata (`component_instances`
9
+ * and `component_roots`) so devtools can derive presentation groupings
10
+ * without storing UI artifacts as render nodes.
11
+ *
12
+ * Real AlloyNodes are exposed as:
13
+ *
14
+ * - `TextNode` → `kind: "text"`, with `value: data`
15
+ * - `ElementNode` with a marker `localName` (`alloy:source-file`,
16
+ * `alloy:directory`, `alloy:copy-file`) → `kind` set to the marker
17
+ * - any other `ElementNode` → `kind: "intrinsic"` with `name: localName`
18
+ * - `FragmentNode` → `kind: "fragment"`
19
+ * - `CommentNode` (slot/ctx markers) → not exposed (skipped)
20
+ *
21
+ * # Hook surface
22
+ *
23
+ * Mutation hooks:
24
+ * - `nodeAttached(node, parent, before)` — called from
25
+ * `render/node.ts::insertBefore`. Emits a `node_added` event for
26
+ * `node` (and any descendants it brings with it, e.g. a previously
27
+ * built subtree being moved or a fragment splice).
28
+ * - `nodeDetached(node, parent)` — called from
29
+ * `render/node.ts::detach`. Emits `node_removed` for `node` and all
30
+ * descendants.
31
+ *
32
+ * Lifecycle hooks:
33
+ * - `initialize(root)` — called at the start of each `render` /
34
+ * `renderAsync`. Resets module state and emits `render:reset`.
35
+ * - `complete()` — emits `render:complete`.
36
+ * - `flushJobsComplete()` — emits `flushJobs:complete`.
37
+ * - `error(info, stack)` — emits `render:error` and writes a
38
+ * `render_errors` row.
39
+ *
40
+ * Component hooks:
41
+ * - `beginComponent(opts)` — records a component instance and captures
42
+ * the real top-level AlloyNodes it emits.
43
+ *
44
+ * Each hook short-circuits when neither devtools nor the trace DB
45
+ * are enabled.
46
+ */
47
+
1
48
  import { watch } from "@vue/reactivity";
2
49
  import * as devalue from "devalue";
3
50
  import { isDevtoolsEnabled, registerDevtoolsMessageHandler } from "../devtools/devtools-server.js";
4
- import { isPrintHook } from "../print-hook.js";
5
51
  import { getContext, untrack } from "../reactivity.js";
52
+ import { getContextForNode } from "../render/node-context.js";
53
+ import { AlloyNode, CommentNode, ELEMENT_NODE, FRAGMENT_NODE, setMutationListener, TEXT_NODE } from "../render/node.js";
6
54
  import { flushJobsAsync } from "../scheduler.js";
55
+ import { flushAllDirtyFiles, markFileDirtyForNode, reset as resetFileStreaming } from "./file-streaming.js";
7
56
  import { sanitizeRecord } from "./serialize.js";
8
57
  import { resolveComponentSource } from "./source-map.js";
9
- import { deleteDirectory, deleteOutputFile, insertDirectory, insertOutputFile, insertRenderError, insertRenderNode, isTraceEnabled, notifyFlushComplete, notifyRenderComplete, notifyRenderReset, deleteRenderNode as traceDeleteRenderNode, updateRenderNodeProps as traceUpdateRenderNodeProps, updateEffectComponentByContext, updateRenderNodeContext } from "./trace-writer.js";
58
+ import { deleteComponentInstance, deleteComponentRoot, insertComponentInstance, insertComponentRoot, insertDirectory, insertOutputFile, insertRenderError, isTraceEnabled, notifyFlushComplete, notifyRenderComplete, notifyRenderReset, deleteRenderNode as traceDeleteRenderNode, insertRenderNode as traceInsertRenderNode, updateComponentInstanceProps, updateEffectComponentByContext } from "./trace-writer.js";
10
59
  import { isDebugEnabled, logDevtoolsMessage } from "./trace.js";
11
60
 
61
+ // #region Public debug types used by runtime and devtools integration
62
+
12
63
  /** The kind discriminant for render tree nodes. */
13
64
 
14
65
  /** Information about a render tree node, used when recording nodes to devtools. */
15
66
 
16
- /** Any node tracked by the devtools render tree. */
67
+ export function isRerenderEnabled() {
68
+ return isDevtoolsEnabled();
69
+ }
70
+ // #endregion
17
71
 
18
- // ─────────────────────────────────────────────────────────────────────────────
19
- // Module state — reset in initialize()
20
- // ─────────────────────────────────────────────────────────────────────────────
72
+ // #region Module state
21
73
 
74
+ /** Map AlloyNode → trace node id (assigned when first emitted). */
22
75
  let nodeIds = new WeakMap();
23
- let idToNode = new Map();
24
- let entryIds = new WeakMap();
25
- let nodeKinds = new WeakMap();
76
+ /** AlloyNodes that have been emitted to the trace tree. */
77
+ let tracked = new WeakSet();
78
+ /** Component owner captured while a subtree is built before being rooted. */
79
+ let pendingOwnerComponent = new WeakMap();
80
+ /** Component roots captured while a subtree is built before being rooted. */
81
+ let pendingRootComponents = new WeakMap();
82
+ /** Sidecar metadata per node id — kind + name + source for cleanup re-emit. */
83
+ let nodeKinds = new Map();
84
+ /** Sidecar: nodes that own a file/directory entry in the trace DB. */
26
85
  let fileNodes = new Map();
27
86
  let directoryNodes = new Map();
87
+ /** Latest props-serialized value per id (for de-duplicated updates). */
28
88
  let nodeProps = new Map();
89
+ /** Devtools-side rerender bindings keyed by render-tree node id. */
29
90
  let rerenderActions = new Map();
30
- let nextId = 1;
31
- let handlerRegistered = false;
91
+ let componentStack = [];
92
+ let componentsById = new Map();
93
+ let componentByContextId = new Map();
94
+ let ownerComponentByNodeId = new Map();
95
+ let childComponentsById = new Map();
96
+ let rootComponentsByNodeId = new Map();
32
97
 
33
- // ─────────────────────────────────────────────────────────────────────────────
34
- // Props serialization
35
- // ─────────────────────────────────────────────────────────────────────────────
36
-
37
- function serializeRenderTreeProps(input) {
38
- return untrack(() => {
39
- if (!input) return undefined;
40
- const {
41
- children: _children,
42
- ...rest
43
- } = input;
44
- const sanitized = sanitizeRecord(rest);
45
- if (!sanitized) return undefined;
46
- try {
47
- return devalue.stringify(sanitized);
48
- } catch {
49
- return undefined;
98
+ /**
99
+ * Reverse index: parent render-tree id → set of currently-emitted child
100
+ * render-tree ids. Maintained by every `insertRenderNode` call in this
101
+ * module, and used by `emitRemoved` to cascade-remove descendants whose
102
+ * lifetime is bound to the removed parent.
103
+ */
104
+ let renderChildIds = new Map();
105
+ function insertRenderNode(id, parentId, kind, name, props, sourceFile, sourceLine, sourceCol, contextId, value) {
106
+ if (parentId !== null) {
107
+ let set = renderChildIds.get(parentId);
108
+ if (!set) {
109
+ set = new Set();
110
+ renderChildIds.set(parentId, set);
50
111
  }
51
- });
112
+ set.add(id);
113
+ }
114
+ traceInsertRenderNode(id, parentId, kind, name, props, sourceFile, sourceLine, sourceCol, contextId, value);
52
115
  }
116
+ let nextId = 1;
117
+ let nextErrorId = 1;
118
+ let handlerRegistered = false;
53
119
 
54
- // ─────────────────────────────────────────────────────────────────────────────
55
- // Node ID management & tree structure
56
- // ─────────────────────────────────────────────────────────────────────────────
120
+ // #endregion
57
121
 
58
- function emitNodeRemoved(parentId, id) {
59
- clearRenderTreeChildrenForId(id);
60
- traceDeleteRenderNode(id);
61
- rerenderActions.delete(id);
62
- nodeProps.delete(id);
63
- idToNode.delete(id);
64
- const fileInfo = fileNodes.get(id);
65
- if (fileInfo) {
66
- deleteOutputFile(fileInfo.path);
67
- fileNodes.delete(id);
122
+ // #region Lifecycle
123
+
124
+ export function initialize(root) {
125
+ for (const frame of componentsById.values()) {
126
+ frame.stopWatch?.();
68
127
  }
69
- const dirInfo = directoryNodes.get(id);
70
- if (dirInfo) {
71
- deleteDirectory(dirInfo.path);
72
- directoryNodes.delete(id);
128
+ if (!isDebugEnabled()) {
129
+ setMutationListener(null);
130
+ return;
73
131
  }
132
+ ensureDevtoolsHandler();
133
+ nodeIds = new WeakMap();
134
+ tracked = new WeakSet();
135
+ pendingOwnerComponent = new WeakMap();
136
+ pendingRootComponents = new WeakMap();
137
+ renderChildIds = new Map();
138
+ nodeKinds = new Map();
139
+ fileNodes = new Map();
140
+ directoryNodes = new Map();
141
+ nodeProps = new Map();
142
+ rerenderActions = new Map();
143
+ componentStack = [];
144
+ componentsById = new Map();
145
+ componentByContextId = new Map();
146
+ ownerComponentByNodeId = new Map();
147
+ childComponentsById = new Map();
148
+ rootComponentsByNodeId = new Map();
149
+ nextId = 1;
150
+ resetFileStreaming();
151
+ setMutationListener({
152
+ attached: nodeAttached,
153
+ detached: nodeDetached
154
+ });
155
+ notifyRenderReset();
156
+ const rootId = getOrCreateNodeId(root);
157
+ tracked.add(root);
158
+ nodeKinds.set(rootId, {
159
+ kind: "root"
160
+ });
161
+ insertRenderNode(rootId, null, "root", undefined, undefined, undefined, undefined, undefined, null, undefined);
74
162
  }
75
- function getEntryList(parent) {
76
- let list = entryIds.get(parent);
77
- if (!list) {
78
- list = [];
79
- entryIds.set(parent, list);
80
- }
81
- return list;
163
+ export function complete() {
164
+ flushAllDirtyFiles();
165
+ logDevtoolsMessage({
166
+ type: "render:complete"
167
+ });
168
+ notifyRenderComplete();
169
+ }
170
+ export function flushJobsComplete() {
171
+ logDevtoolsMessage({
172
+ type: "flushJobs:complete"
173
+ });
174
+ notifyFlushComplete();
82
175
  }
176
+
177
+ // #endregion
178
+
179
+ // #region Node-id management
180
+
83
181
  function getOrCreateNodeId(node) {
84
182
  const existing = nodeIds.get(node);
85
- if (existing) {
86
- // Restore reverse mapping — emitNodeRemoved deletes idToNode but nodeIds
87
- // (WeakMap) survives. Without this, clearRenderTreeChildrenForId can't
88
- // find the node on the next cleanup, leaving orphaned children in the DB.
89
- idToNode.set(existing, node);
90
- return existing;
91
- }
183
+ if (existing !== undefined) return existing;
92
184
  const id = nextId++;
93
185
  nodeIds.set(node, id);
94
- idToNode.set(id, node);
95
186
  return id;
96
187
  }
97
188
  export function getRenderNodeId(node) {
98
189
  if (!isDebugEnabled()) return undefined;
99
- return getOrCreateNodeId(node);
190
+ if (!(node instanceof AlloyNode)) return undefined;
191
+ return nodeIds.get(node);
192
+ }
193
+
194
+ // #endregion
195
+
196
+ // #region Kind classification
197
+
198
+ const SKIPPED_COMMENT_DATAS = new Set(["slot:start", "slot:end", "slot:item:start", "slot:item:end", "ctx:start", "ctx:end", "component:start", "component:end"]);
199
+ function shouldExposeNode(node) {
200
+ if (node instanceof CommentNode) {
201
+ // Bookkeeping comments are not part of the render tree.
202
+ return !SKIPPED_COMMENT_DATAS.has(node.data);
203
+ }
204
+ return true;
100
205
  }
101
- function setEntryId(parent, index, id) {
102
- const list = getEntryList(parent);
103
- list[index] = id;
206
+ function classifyNode(node) {
207
+ const t = node.nodeType;
208
+ if (t === TEXT_NODE) {
209
+ return {
210
+ kind: "text",
211
+ value: node.data
212
+ };
213
+ }
214
+ if (t === FRAGMENT_NODE) {
215
+ return {
216
+ kind: "fragment"
217
+ };
218
+ }
219
+ if (t === ELEMENT_NODE) {
220
+ const ln = node.localName;
221
+ if (ln === "alloy:source-file" || ln === "alloy:directory" || ln === "alloy:copy-file") {
222
+ return {
223
+ kind: ln.slice("alloy:".length),
224
+ name: ln
225
+ };
226
+ }
227
+ return {
228
+ kind: "intrinsic",
229
+ name: ln
230
+ };
231
+ }
232
+ // CommentNode that's exposed — generic "comment" kind. Marker
233
+ // comments are filtered out by `shouldExposeNode`, so this is rare.
234
+ return {
235
+ kind: "comment",
236
+ value: node.data
237
+ };
104
238
  }
105
- export function initialize(root) {
106
- if (!isDebugEnabled()) return;
107
- ensureDevtoolsHandler();
108
- nodeIds = new WeakMap();
109
- idToNode = new Map();
110
- entryIds = new WeakMap();
111
- nodeKinds = new WeakMap();
112
- fileNodes = new Map();
113
- directoryNodes = new Map();
114
- nodeProps = new Map();
115
- rerenderActions = new Map();
116
- nextId = 1;
117
- notifyRenderReset();
118
- const rootId = getOrCreateNodeId(root);
119
- insertRenderNode(rootId, null, "root", undefined, undefined, undefined, undefined, undefined, null, undefined);
239
+
240
+ // #endregion
241
+
242
+ // #region Component ownership resolution
243
+
244
+ function currentComponentFrame() {
245
+ return componentStack[componentStack.length - 1];
120
246
  }
121
- export function registerRenderNodeActions(node, actions) {
122
- if (!isDebugEnabled()) return;
123
- const id = getOrCreateNodeId(node);
124
- rerenderActions.set(id, actions);
247
+ function currentContextComponentFrame() {
248
+ const ctx = getContext();
249
+ return ctx ? componentByContextId.get(ctx.id) : undefined;
125
250
  }
126
- export function unregisterRenderNodeActions(node) {
127
- if (!isDebugEnabled()) return;
128
- const id = nodeIds.get(node);
129
- if (id !== undefined) {
130
- rerenderActions.delete(id);
251
+ function findRootComponentsForAttach(parent) {
252
+ const frames = [];
253
+ for (let i = componentStack.length - 1; i >= 0; i--) {
254
+ const frame = componentStack[i];
255
+ if (frame.hostParent === parent) frames.unshift(frame);
131
256
  }
257
+ return frames;
132
258
  }
133
- function ensureDevtoolsHandler() {
134
- if (handlerRegistered || !isDevtoolsEnabled()) return;
135
- handlerRegistered = true;
136
- registerDevtoolsMessageHandler(message => {
137
- if (message.type !== "render:rerender" && message.type !== "render:rerenderAndBreak") {
138
- return;
259
+ function ownerFrameForAttach(parentId, inheritedOwner) {
260
+ if (inheritedOwner) return inheritedOwner;
261
+ const active = currentComponentFrame();
262
+ if (active) return active;
263
+ const contextFrame = currentContextComponentFrame();
264
+ if (contextFrame) return contextFrame;
265
+ if (parentId !== null) {
266
+ const parentOwner = ownerComponentByNodeId.get(parentId);
267
+ if (parentOwner !== undefined) return componentsById.get(parentOwner);
268
+ }
269
+ return undefined;
270
+ }
271
+ function recordComponentRoot(frame, renderNodeId) {
272
+ if (frame.rootSet.has(renderNodeId)) return;
273
+ frame.rootSet.add(renderNodeId);
274
+ const ordinal = frame.roots.length;
275
+ frame.roots.push(renderNodeId);
276
+ let components = rootComponentsByNodeId.get(renderNodeId);
277
+ if (!components) {
278
+ components = new Set();
279
+ rootComponentsByNodeId.set(renderNodeId, components);
280
+ }
281
+ components.add(frame.id);
282
+ insertComponentRoot(frame.id, renderNodeId, ordinal);
283
+ if (ordinal === 0) {
284
+ if (frame.file) {
285
+ fileNodes.set(renderNodeId, frame.file);
286
+ insertOutputFile(frame.file.path, frame.file.filetype, renderNodeId);
139
287
  }
140
- const rawId = message.id;
141
- if (typeof rawId !== "number" && typeof rawId !== "string") return;
142
- const id = Number(rawId);
143
- if (!Number.isFinite(id)) return;
144
- const actions = rerenderActions.get(id);
145
- if (!actions) return;
146
- if (message.type === "render:rerender") {
147
- actions.rerender();
148
- } else {
149
- actions.rerenderAndBreak();
288
+ if (frame.directory) {
289
+ directoryNodes.set(renderNodeId, frame.directory);
150
290
  }
151
- void flushJobsAsync();
152
- });
153
- }
154
- export function recordTextNode(parent, index, value) {
155
- if (!isDebugEnabled()) return;
156
- const id = nextId++;
157
- setEntryId(parent, index, id);
158
- insertRenderNode(id, getOrCreateNodeId(parent), "text", undefined, undefined, undefined, undefined, undefined, null, value);
291
+ }
292
+ if (frame.actions) rerenderActions.set(renderNodeId, frame.actions);
159
293
  }
160
- function recordNodeAdded(parent, index, node, info) {
161
- if (!isDebugEnabled()) return;
162
- const id = getOrCreateNodeId(node);
163
- if (info.propsSerialized !== undefined) {
164
- nodeProps.set(id, info.propsSerialized);
165
- }
166
- // Remember the kind and source so cached re-adds preserve them
167
- nodeKinds.set(node, {
168
- kind: info.kind,
169
- name: info.name,
170
- source: info.source
171
- });
172
- setEntryId(parent, index, id);
173
- insertRenderNode(id, getOrCreateNodeId(parent), info.kind, info.name, info.propsSerialized, info.source?.fileName, info.source?.lineNumber, info.source?.columnNumber, null, undefined);
294
+ function removeComponentRoot(frame, renderNodeId, deleteWhenEmpty = true) {
295
+ if (!frame.rootSet.delete(renderNodeId)) return;
296
+ frame.roots = frame.roots.filter(id => id !== renderNodeId);
297
+ const components = rootComponentsByNodeId.get(renderNodeId);
298
+ if (components) {
299
+ components.delete(frame.id);
300
+ if (components.size === 0) rootComponentsByNodeId.delete(renderNodeId);
301
+ }
302
+ deleteComponentRoot(frame.id, renderNodeId);
303
+ if (deleteWhenEmpty && frame.rootSet.size === 0) {
304
+ deleteComponentFrame(frame);
305
+ }
174
306
  }
175
- function recordSubtreeAdded(parentNode, subtree, info = {
176
- kind: "fragment"
177
- }) {
178
- if (!isDebugEnabled()) return;
179
- const parentId = getOrCreateNodeId(parentNode);
180
- // Check if this node was previously rendered (cached) by seeing if it already has an ID
181
- const existingId = nodeIds.get(subtree);
182
- const isCached = existingId !== undefined;
183
- const id = isCached ? existingId : getOrCreateNodeId(subtree);
184
- // Merge source from previously-saved nodeKinds if the caller didn't provide one
185
- const savedKind = nodeKinds.get(subtree);
186
- const source = info.source ?? savedKind?.source;
187
- // Remember the kind and source so cached re-adds preserve them
188
- nodeKinds.set(subtree, {
189
- kind: info.kind,
190
- name: info.name,
191
- source
192
- });
193
- // Track in entryIds so clearRenderTreeChildren can find and remove it
194
- if (Array.isArray(parentNode)) {
195
- const list = getEntryList(parentNode);
196
- list.push(id);
307
+ function deleteComponentFrame(frame) {
308
+ if (!componentsById.delete(frame.id)) return;
309
+ const children = childComponentsById.get(frame.id);
310
+ if (children) {
311
+ childComponentsById.delete(frame.id);
312
+ for (const childId of [...children]) {
313
+ const child = componentsById.get(childId);
314
+ if (child) deleteComponentFrame(child);
315
+ }
197
316
  }
198
- insertRenderNode(id, parentId, info.kind, info.name, info.propsSerialized, source?.fileName, source?.lineNumber, source?.columnNumber, null, undefined);
199
-
200
- // For cached nodes, we need to recursively re-add all their children since
201
- // clearRenderTreeChildren removed them when the parent re-rendered
202
- if (isCached) {
203
- recordCachedSubtreeChildrenRecursively(subtree);
317
+ for (const rootId of [...frame.roots]) {
318
+ removeComponentRoot(frame, rootId, false);
319
+ }
320
+ if (frame.parentComponentId !== null) {
321
+ const siblings = childComponentsById.get(frame.parentComponentId);
322
+ siblings?.delete(frame.id);
323
+ }
324
+ if (frame.contextId !== null && componentByContextId.get(frame.contextId)?.id === frame.id) {
325
+ componentByContextId.delete(frame.contextId);
204
326
  }
327
+ nodeProps.delete(frame.id);
328
+ frame.stopWatch?.();
329
+ deleteComponentInstance(frame.id);
205
330
  }
206
331
 
207
332
  /**
208
- * Recursively re-adds all children of a cached render tree node to devtools.
209
- * This is needed because clearRenderTreeChildren recursively removes all
210
- * descendants, but cached nodes aren't re-rendered so their children need
211
- * to be explicitly re-added.
333
+ * Decide whether `attachedParent` is currently part of the live trace
334
+ * tree (rooted at the initialized root), and if so which trace node id
335
+ * should be the new node's parent.
336
+ *
337
+ * Returns `undefined` when `attachedParent` isn't tracked — the caller
338
+ * should defer emission until the subtree is later attached at a
339
+ * tracked location.
212
340
  */
213
- function recordCachedSubtreeChildrenRecursively(node) {
214
- if (!isDebugEnabled()) return;
215
- const parentId = getOrCreateNodeId(node);
216
-
217
- // Clear any previously-recorded children from the DB before re-adding.
218
- // The in-memory tree may have changed since the last cached re-add
219
- // (e.g., a memo inside the cached subtree re-ran), so old DB children
220
- // that are no longer in the tree would become orphans.
221
- clearRenderTreeChildren(node);
222
-
223
- // Rebuild the entryIds for this node
224
- const list = getEntryList(node);
225
- list.length = 0;
226
- for (let i = 0; i < node.length; i++) {
227
- const child = node[i];
228
- if (typeof child === "string") {
229
- // Text nodes - re-record them with new IDs
230
- if (child !== "") {
231
- const id = nextId++;
232
- list.push(id);
233
- idToNode.set(id, child);
234
- insertRenderNode(id, parentId, "text", undefined, undefined, undefined, undefined, undefined, null, child);
235
- }
236
- } else if (Array.isArray(child)) {
237
- // Nested RenderedTextTree - record and recurse, preserving original kind and source
238
- const id = getOrCreateNodeId(child);
239
- list.push(id);
240
- const savedKind = nodeKinds.get(child);
241
- insertRenderNode(id, parentId, savedKind?.kind ?? "fragment", savedKind?.name, undefined, savedKind?.source?.fileName, savedKind?.source?.lineNumber, savedKind?.source?.columnNumber, null, undefined);
242
- recordCachedSubtreeChildrenRecursively(child);
243
- } else if (isPrintHook(child)) {
244
- // PrintHook - record and recurse into subtree
245
- const id = getOrCreateNodeId(child);
246
- list.push(id);
247
- insertRenderNode(id, parentId, "printHook", child.name ?? "hook", undefined, undefined, undefined, undefined, null, undefined);
248
- if (child.subtree) {
249
- const subtreeId = getOrCreateNodeId(child.subtree);
250
- const hookList = getEntryList(child);
251
- hookList.length = 0;
252
- hookList.push(subtreeId);
253
- insertRenderNode(subtreeId, id, "fragment", undefined, undefined, undefined, undefined, undefined, null, undefined);
254
- recordCachedSubtreeChildrenRecursively(child.subtree);
255
- }
256
- }
341
+ function resolveParentId(node, attachedParent) {
342
+ if (tracked.has(attachedParent)) {
343
+ const id = nodeIds.get(attachedParent);
344
+ return id === undefined ? null : id;
257
345
  }
346
+ return undefined;
258
347
  }
259
- function recordNodePropsUpdated(node, propsSerialized) {
260
- if (!isDebugEnabled()) return;
261
- const id = getOrCreateNodeId(node);
262
- const previous = nodeProps.get(id);
263
- if (previous === propsSerialized) return;
264
- nodeProps.set(id, propsSerialized);
265
- traceUpdateRenderNodeProps(id, propsSerialized);
266
- }
267
- function clearRenderTreeChildren(parent) {
348
+
349
+ // #endregion
350
+
351
+ // #region Tree-mutation hooks
352
+
353
+ /**
354
+ * Called after `node` is attached as a child of `parent`. Emits an
355
+ * `added` event for `node` itself (if exposed) and recursively for any
356
+ * descendants it brought with it (move / fragment splice / cached subtree).
357
+ *
358
+ * If `parent` isn't part of the live tree yet, stamps the active component
359
+ * ownership onto `node` and defers emission until the subtree finally attaches.
360
+ */
361
+ export function nodeAttached(node, parent) {
268
362
  if (!isDebugEnabled()) return;
269
- const list = entryIds.get(parent);
270
- if (!list || list.length === 0) return;
271
- const parentId = getOrCreateNodeId(parent);
272
- for (const id of list) {
273
- if (id !== undefined) {
274
- emitNodeRemoved(parentId, id);
275
- }
363
+ markFileDirtyForNode(parent);
364
+ const parentId = resolveParentId(node, parent);
365
+ const ownerFrame = currentComponentFrame() ?? currentContextComponentFrame();
366
+ let rootFrames = findRootComponentsForAttach(parent);
367
+ if (rootFrames.length === 0 && ownerFrame !== undefined && parentId !== undefined && (parentId === null || ownerComponentByNodeId.get(parentId) !== ownerFrame.id)) {
368
+ rootFrames = [ownerFrame];
276
369
  }
277
- entryIds.set(parent, []);
370
+ if (parentId === undefined) {
371
+ if (ownerFrame) pendingOwnerComponent.set(node, ownerFrame);
372
+ if (rootFrames.length > 0) pendingRootComponents.set(node, rootFrames);
373
+ return;
374
+ }
375
+ attachWithSelf(node, parentId, ownerFrame, rootFrames);
278
376
  }
279
- function clearRenderTreeChildrenForId(id) {
280
- const node = idToNode.get(id);
281
- if (!node) return;
282
- if (Array.isArray(node)) {
283
- clearRenderTreeChildren(node);
377
+ function attachWithSelf(node, parentId, inheritedOwner, inheritedRoots) {
378
+ const pendingOwner = pendingOwnerComponent.get(node);
379
+ if (pendingOwner !== undefined) {
380
+ pendingOwnerComponent.delete(node);
381
+ }
382
+ const pendingRoots = pendingRootComponents.get(node);
383
+ if (pendingRoots !== undefined) {
384
+ pendingRootComponents.delete(node);
385
+ }
386
+ const ownerFrame = ownerFrameForAttach(parentId, pendingOwner ?? inheritedOwner);
387
+ const rootFrames = pendingRoots ?? inheritedRoots;
388
+ if (!shouldExposeNode(node)) {
389
+ for (let c = node.firstChild; c !== null; c = c.nextSibling) {
390
+ attachWithSelf(c, parentId, ownerFrame, rootFrames);
391
+ }
284
392
  return;
285
393
  }
286
- // For PrintHook nodes: clear the subtree's children, then remove
287
- // the subtree node itself (which is a child of this hook).
288
- const subtree = node.subtree;
289
- if (subtree && Array.isArray(subtree)) {
290
- clearRenderTreeChildren(subtree);
291
- const subtreeId = nodeIds.get(subtree);
292
- if (subtreeId !== undefined) {
293
- emitNodeRemoved(id, subtreeId);
394
+ if (tracked.has(node)) {
395
+ // Already eagerly emitted (e.g. an alloy:* wrapper pre-emitted via
396
+ // ensureWrapperHostTracked while inside a thunk body). Don't re-emit;
397
+ // just walk newly-attached children that may not have been seen yet.
398
+ const existingId = nodeIds.get(node);
399
+ for (let c = node.firstChild; c !== null; c = c.nextSibling) {
400
+ if (!tracked.has(c)) {
401
+ attachWithSelf(c, existingId, ownerFrame, []);
402
+ }
294
403
  }
404
+ return;
295
405
  }
296
- }
297
-
298
- // ─────────────────────────────────────────────────────────────────────────────
299
- // File / directory node tracking
300
- // ─────────────────────────────────────────────────────────────────────────────
301
-
302
- function recordDirectoryNode(node, path) {
303
- if (!isDebugEnabled()) return;
304
406
  const id = getOrCreateNodeId(node);
305
- if (directoryNodes.has(id)) return;
306
- directoryNodes.set(id, {
307
- path
308
- });
309
- insertDirectory(path);
407
+ emitAdded(node, id, parentId);
408
+ tracked.add(node);
409
+ if (ownerFrame !== undefined) {
410
+ ownerComponentByNodeId.set(id, ownerFrame.id);
411
+ }
412
+ for (const rootFrame of rootFrames) {
413
+ recordComponentRoot(rootFrame, id);
414
+ }
415
+ for (let c = node.firstChild; c !== null; c = c.nextSibling) {
416
+ if (!tracked.has(c)) attachWithSelf(c, id, ownerFrame, []);
417
+ }
310
418
  }
311
- function recordFileNode(node, path, filetype) {
312
- if (!isDebugEnabled()) return;
313
- const id = getOrCreateNodeId(node);
314
- if (fileNodes.has(id)) return;
315
- fileNodes.set(id, {
316
- path,
317
- filetype
318
- });
319
- insertOutputFile(path, filetype, id);
419
+ function emitAdded(node, id, parentId) {
420
+ const cls = classifyNode(node);
421
+ // Stamp metadata so cleanup re-emit (and `error()` stack resolution)
422
+ // can recover identity.
423
+ let entry = nodeKinds.get(id);
424
+ if (!entry) {
425
+ entry = {
426
+ kind: cls.kind,
427
+ name: cls.name
428
+ };
429
+ nodeKinds.set(id, entry);
430
+ } else {
431
+ entry.kind = cls.kind;
432
+ if (cls.name !== undefined) entry.name = cls.name;
433
+ }
434
+ const props = nodeProps.get(id);
435
+ insertRenderNode(id, parentId, cls.kind, cls.name, props, entry.source?.fileName, entry.source?.lineNumber, entry.source?.columnNumber, getContextForNode(node)?.id ?? null, cls.value);
320
436
  }
321
- function removeFileEntriesForNode(node) {
437
+
438
+ /**
439
+ * Called after `node` has been detached. Emits `node_removed` for
440
+ * `node` and all of its still-attached descendants in post-order.
441
+ */
442
+ export function nodeDetached(node, formerParent) {
322
443
  if (!isDebugEnabled()) return;
444
+ markFileDirtyForNode(formerParent);
445
+ detachRecursive(node);
446
+ }
447
+ function detachRecursive(node) {
448
+ for (let c = node.firstChild; c !== null; c = c.nextSibling) {
449
+ detachRecursive(c);
450
+ }
451
+ if (!tracked.has(node)) return;
452
+ tracked.delete(node);
453
+ if (!shouldExposeNode(node)) return;
323
454
  const id = nodeIds.get(node);
324
455
  if (id === undefined) return;
325
- const fileInfo = fileNodes.get(id);
326
- if (fileInfo) {
327
- deleteOutputFile(fileInfo.path);
328
- fileNodes.delete(id);
456
+ emitRemoved(id);
457
+ }
458
+ function emitRemoved(id) {
459
+ const componentIds = rootComponentsByNodeId.get(id);
460
+ if (componentIds) {
461
+ for (const componentId of [...componentIds]) {
462
+ const component = componentsById.get(componentId);
463
+ if (component) removeComponentRoot(component, id);
464
+ }
329
465
  }
330
- const dirInfo = directoryNodes.get(id);
331
- if (dirInfo) {
332
- deleteDirectory(dirInfo.path);
333
- directoryNodes.delete(id);
466
+ traceDeleteRenderNode(id);
467
+ rerenderActions.delete(id);
468
+ nodeProps.delete(id);
469
+ nodeKinds.delete(id);
470
+ // Files & directories owned by this node.
471
+ fileNodes.delete(id);
472
+ directoryNodes.delete(id);
473
+ ownerComponentByNodeId.delete(id);
474
+ // Cascade to any descendants currently registered as children of this id.
475
+ const children = renderChildIds.get(id);
476
+ if (children !== undefined) {
477
+ renderChildIds.delete(id);
478
+ for (const childId of children) {
479
+ emitRemoved(childId);
480
+ }
334
481
  }
335
482
  }
336
483
 
337
- // ─────────────────────────────────────────────────────────────────────────────
338
- // Public API — called from render.ts via the debug object
339
- // ─────────────────────────────────────────────────────────────────────────────
484
+ // #endregion
340
485
 
341
- /** Begin tracking a component render. Returns a session to record files/dirs and dispose watchers. */
486
+ // #region Component lifecycle
487
+
488
+ function serializeRenderTreeProps(input) {
489
+ return untrack(() => {
490
+ if (!input) return undefined;
491
+ const {
492
+ children: _children,
493
+ ...rest
494
+ } = input;
495
+ const sanitized = sanitizeRecord(rest);
496
+ if (!sanitized) return undefined;
497
+ try {
498
+ return devalue.stringify(sanitized);
499
+ } catch {
500
+ return undefined;
501
+ }
502
+ });
503
+ }
342
504
  export function beginComponent(options) {
343
- const {
344
- parent,
345
- index,
346
- node,
347
- component,
348
- propsSource,
349
- source,
350
- isExisting,
351
- actions
352
- } = options;
353
505
  if (!isDebugEnabled()) {
354
506
  return {
355
507
  recordDirectory() {},
@@ -357,6 +509,13 @@ export function beginComponent(options) {
357
509
  dispose() {}
358
510
  };
359
511
  }
512
+ const {
513
+ component,
514
+ propsSource,
515
+ source,
516
+ parent,
517
+ actions
518
+ } = options;
360
519
  return untrack(() => {
361
520
  let componentName = component.component.name;
362
521
  if (componentName === "Provider") {
@@ -367,86 +526,114 @@ export function beginComponent(options) {
367
526
  }
368
527
  const propsSerialized = serializeRenderTreeProps(propsSource);
369
528
  const resolvedSource = resolveComponentSource(source);
370
- if (isExisting) {
371
- clearRenderTreeChildren(node);
372
- } else {
373
- recordNodeAdded(parent, index, node, {
374
- kind: "component",
375
- name: componentName,
376
- propsSerialized,
377
- source: resolvedSource
378
- });
379
- }
380
- if (isTraceEnabled()) {
381
- const ctx = getContext();
382
- if (ctx) {
383
- updateRenderNodeContext(getOrCreateNodeId(node), ctx.id);
384
- updateEffectComponentByContext(ctx.id, componentName);
529
+ const id = nextId++;
530
+ const ctx = getContext();
531
+ const parentComponent = componentStack[componentStack.length - 1] ?? (ctx?.owner ? componentByContextId.get(ctx.owner.id) : undefined);
532
+ const frame = {
533
+ id,
534
+ parentComponentId: parentComponent?.id ?? null,
535
+ hostParent: parent,
536
+ name: componentName,
537
+ propsSerialized,
538
+ source: resolvedSource,
539
+ contextId: ctx?.id ?? null,
540
+ roots: [],
541
+ rootSet: new Set(),
542
+ actions
543
+ };
544
+ componentsById.set(id, frame);
545
+ if (frame.parentComponentId !== null) {
546
+ let children = childComponentsById.get(frame.parentComponentId);
547
+ if (!children) {
548
+ children = new Set();
549
+ childComponentsById.set(frame.parentComponentId, children);
385
550
  }
551
+ children.add(id);
552
+ }
553
+ componentStack.push(frame);
554
+ if (ctx) componentByContextId.set(ctx.id, frame);
555
+ if (propsSerialized !== undefined) nodeProps.set(id, propsSerialized);
556
+ insertComponentInstance(id, frame.parentComponentId, componentName, propsSerialized, resolvedSource?.fileName, resolvedSource?.lineNumber, resolvedSource?.columnNumber, frame.contextId);
557
+ if (isTraceEnabled() && ctx) {
558
+ updateEffectComponentByContext(ctx.id, componentName);
386
559
  }
387
- recordNodePropsUpdated(node, propsSerialized);
388
- registerRenderNodeActions(node, actions);
560
+
561
+ // Watch reactive props and re-emit on change.
389
562
  let stopWatch;
390
563
  if (propsSource) {
391
- const propKeys = Object.keys(propsSource).filter(key => key !== "children");
564
+ const propKeys = Object.keys(propsSource).filter(k => k !== "children");
392
565
  if (propKeys.length > 0) {
393
- stopWatch = watch(() => propKeys.map(key => propsSource[key]), () => {
394
- const nextSerialized = serializeRenderTreeProps(propsSource);
395
- recordNodePropsUpdated(node, nextSerialized);
566
+ stopWatch = watch(() => propKeys.map(k => propsSource[k]), () => {
567
+ const next = serializeRenderTreeProps(propsSource);
568
+ const previous = nodeProps.get(id);
569
+ if (previous === next) return;
570
+ nodeProps.set(id, next);
571
+ updateComponentInstanceProps(id, next);
396
572
  });
397
573
  }
398
574
  }
575
+ frame.stopWatch = stopWatch;
576
+ let disposed = false;
399
577
  return {
400
578
  recordDirectory(path) {
401
- recordDirectoryNode(node, path);
579
+ if (frame.directory) return;
580
+ frame.directory = {
581
+ path
582
+ };
583
+ insertDirectory(path);
402
584
  },
403
585
  recordFile(path, filetype) {
404
- recordFileNode(node, path, filetype);
586
+ if (frame.file) return;
587
+ frame.file = {
588
+ path,
589
+ filetype
590
+ };
405
591
  },
406
592
  dispose() {
407
- stopWatch?.();
408
- removeFileEntriesForNode(node);
409
- unregisterRenderNodeActions(node);
593
+ if (disposed) return;
594
+ disposed = true;
595
+ for (let i = componentStack.length - 1; i >= 0; i--) {
596
+ if (componentStack[i].id === id) {
597
+ componentStack.splice(i, 1);
598
+ break;
599
+ }
600
+ }
410
601
  }
411
602
  };
412
603
  });
413
604
  }
414
- export function appendCustomContext(parent, node) {
415
- recordSubtreeAdded(parent, node, {
416
- kind: "customContext"
417
- });
418
- }
419
- export function appendPrintHook(parent, index, hook, name, subtree) {
420
- recordNodeAdded(parent, index, hook, {
421
- kind: "printHook",
422
- name
423
- });
424
- if (subtree) {
425
- recordSubtreeAdded(hook, subtree);
426
- }
427
- }
428
- export function appendFragmentChild(parent, child) {
429
- recordSubtreeAdded(parent, child, {
430
- kind: "fragment"
431
- });
432
- }
433
- export function appendTextNode(parent, index, value) {
434
- recordTextNode(parent, index, value);
435
- }
436
- export function prepareMemoNode(parent, node, isExisting) {
437
- if (isExisting) {
438
- clearRenderTreeChildren(node);
439
- return;
440
- }
441
- recordSubtreeAdded(parent, node, {
442
- kind: "memo"
605
+
606
+ // #endregion
607
+
608
+ // #region Devtools rerender bridge
609
+
610
+ function ensureDevtoolsHandler() {
611
+ if (handlerRegistered || !isDevtoolsEnabled()) return;
612
+ handlerRegistered = true;
613
+ registerDevtoolsMessageHandler(message => {
614
+ if (message.type !== "render:rerender" && message.type !== "render:rerenderAndBreak") {
615
+ return;
616
+ }
617
+ const rawId = message.id;
618
+ if (typeof rawId !== "number" && typeof rawId !== "string") return;
619
+ const id = Number(rawId);
620
+ if (!Number.isFinite(id)) return;
621
+ const actions = rerenderActions.get(id);
622
+ if (!actions) return;
623
+ if (message.type === "render:rerender") {
624
+ actions.rerender();
625
+ } else {
626
+ actions.rerenderAndBreak();
627
+ }
628
+ void flushJobsAsync();
443
629
  });
444
630
  }
445
- let nextErrorId = 1;
446
631
 
447
- /** Render error stack entry with optional runtime props (extends protocol type). */
632
+ // #endregion
448
633
 
449
- export function error(error, componentStack) {
634
+ // #region Errors
635
+
636
+ export function error(err, componentStack) {
450
637
  if (!isDebugEnabled()) return;
451
638
  const serializedStack = untrack(() => componentStack.map(entry => ({
452
639
  name: entry.name,
@@ -457,23 +644,13 @@ export function error(error, componentStack) {
457
644
  logDevtoolsMessage({
458
645
  type: "render:error",
459
646
  id: nextErrorId++,
460
- name: error.name,
461
- message: error.message,
462
- stack: error.stack,
647
+ name: err.name,
648
+ message: err.message,
649
+ stack: err.stack,
463
650
  componentStack: serializedStack
464
651
  });
465
- insertRenderError(error.name, error.message, error.stack, JSON.stringify(serializedStack));
466
- }
467
- export function complete() {
468
- logDevtoolsMessage({
469
- type: "render:complete"
470
- });
471
- notifyRenderComplete();
472
- }
473
- export function flushJobsComplete() {
474
- logDevtoolsMessage({
475
- type: "flushJobs:complete"
476
- });
477
- notifyFlushComplete();
652
+ insertRenderError(err.name, err.message, err.stack, JSON.stringify(serializedStack));
478
653
  }
654
+
655
+ // #endregion
479
656
  //# sourceMappingURL=render.js.map