@alloy-js/core 0.24.0-dev.2 → 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 (506) 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/diagnostics.test.js +1 -1
  12. package/dist/dev/src/debug/diagnostics.test.js.map +1 -1
  13. package/dist/dev/src/debug/effects.test.js +1 -1
  14. package/dist/dev/src/debug/effects.test.js.map +1 -1
  15. package/dist/dev/src/debug/file-streaming.js +103 -0
  16. package/dist/dev/src/debug/file-streaming.js.map +1 -0
  17. package/dist/dev/src/debug/files.test.js +4 -5
  18. package/dist/dev/src/debug/files.test.js.map +1 -1
  19. package/dist/dev/src/debug/index.js +4 -6
  20. package/dist/dev/src/debug/index.js.map +1 -1
  21. package/dist/dev/src/debug/message-format.test.js +50 -52
  22. package/dist/dev/src/debug/message-format.test.js.map +1 -1
  23. package/dist/dev/src/debug/render-tree-orphans.test.js +13 -23
  24. package/dist/dev/src/debug/render-tree-orphans.test.js.map +1 -1
  25. package/dist/dev/src/debug/render.js +529 -352
  26. package/dist/dev/src/debug/render.js.map +1 -1
  27. package/dist/dev/src/debug/render.test.js +171 -92
  28. package/dist/dev/src/debug/render.test.js.map +1 -1
  29. package/dist/dev/src/debug/trace-writer.js +127 -15
  30. package/dist/dev/src/debug/trace-writer.js.map +1 -1
  31. package/dist/dev/src/debug/trace.js +0 -36
  32. package/dist/dev/src/debug/trace.js.map +1 -1
  33. package/dist/dev/src/devtools/devtools-server.js +55 -32
  34. package/dist/dev/src/devtools/devtools-server.js.map +1 -1
  35. package/dist/dev/src/devtools-entry.browser.js.map +1 -1
  36. package/dist/dev/src/devtools-entry.js.map +1 -1
  37. package/dist/dev/src/diagnostics.js +19 -1
  38. package/dist/dev/src/diagnostics.js.map +1 -1
  39. package/dist/dev/src/index.js +5 -2
  40. package/dist/dev/src/index.js.map +1 -1
  41. package/dist/dev/src/jsx-runtime.js +14 -8
  42. package/dist/dev/src/jsx-runtime.js.map +1 -1
  43. package/dist/dev/src/output-types.js +2 -0
  44. package/dist/dev/src/output-types.js.map +1 -0
  45. package/dist/dev/src/reactivity.js +155 -13
  46. package/dist/dev/src/reactivity.js.map +1 -1
  47. package/dist/dev/src/render/get-string-width.js +61 -0
  48. package/dist/dev/src/render/get-string-width.js.map +1 -0
  49. package/dist/dev/src/render/index.js +2 -0
  50. package/dist/dev/src/render/index.js.map +1 -0
  51. package/dist/dev/src/render/node-context.js +7 -0
  52. package/dist/dev/src/render/node-context.js.map +1 -0
  53. package/dist/dev/src/render/node.js +386 -0
  54. package/dist/dev/src/render/node.js.map +1 -0
  55. package/dist/dev/src/render/printer-support.js +180 -0
  56. package/dist/dev/src/render/printer-support.js.map +1 -0
  57. package/dist/dev/src/render/printer.js +797 -0
  58. package/dist/dev/src/render/printer.js.map +1 -0
  59. package/dist/dev/src/render-error.js +79 -0
  60. package/dist/dev/src/render-error.js.map +1 -0
  61. package/dist/dev/src/render-output.js +209 -0
  62. package/dist/dev/src/render-output.js.map +1 -0
  63. package/dist/dev/src/runtime/create-intrinsic.js +53 -0
  64. package/dist/dev/src/runtime/create-intrinsic.js.map +1 -0
  65. package/dist/dev/src/runtime/fragment.js +21 -0
  66. package/dist/dev/src/runtime/fragment.js.map +1 -0
  67. package/dist/dev/src/runtime/index.js +13 -0
  68. package/dist/dev/src/runtime/index.js.map +1 -0
  69. package/dist/dev/src/runtime/insert.js +453 -0
  70. package/dist/dev/src/runtime/insert.js.map +1 -0
  71. package/dist/dev/src/runtime/intrinsic.js +1 -11
  72. package/dist/dev/src/runtime/intrinsic.js.map +1 -1
  73. package/dist/dev/src/scheduler.js +38 -14
  74. package/dist/dev/src/scheduler.js.map +1 -1
  75. package/dist/dev/src/stc.js +2 -0
  76. package/dist/dev/src/stc.js.map +1 -1
  77. package/dist/dev/src/sti.js +1 -1
  78. package/dist/dev/src/sti.js.map +1 -1
  79. package/dist/dev/src/symbols/symbol-slot.test.js +1 -1
  80. package/dist/dev/src/symbols/symbol-slot.test.js.map +1 -1
  81. package/dist/dev/src/test-render.js +78 -0
  82. package/dist/dev/src/test-render.js.map +1 -0
  83. package/dist/dev/src/utils.js +47 -35
  84. package/dist/dev/src/utils.js.map +1 -1
  85. package/dist/dev/test/babel-e2e.test.js +218 -0
  86. package/dist/dev/test/babel-e2e.test.js.map +1 -0
  87. package/dist/dev/test/components/block.test.js +1 -1
  88. package/dist/dev/test/components/block.test.js.map +1 -1
  89. package/dist/dev/test/components/copy-file.test.js +7 -7
  90. package/dist/dev/test/components/copy-file.test.js.map +1 -1
  91. package/dist/dev/test/components/update-file.test.js +1 -1
  92. package/dist/dev/test/components/update-file.test.js.map +1 -1
  93. package/dist/dev/test/components/wrap.test.js +1 -1
  94. package/dist/dev/test/components/wrap.test.js.map +1 -1
  95. package/dist/dev/test/control-flow/match.test.js +1 -1
  96. package/dist/dev/test/control-flow/match.test.js.map +1 -1
  97. package/dist/dev/test/control-flow/show.test.js +1 -1
  98. package/dist/dev/test/control-flow/show.test.js.map +1 -1
  99. package/dist/dev/test/lazy-isempty.test.js +6 -6
  100. package/dist/dev/test/lazy-isempty.test.js.map +1 -1
  101. package/dist/dev/test/node.test.js +80 -0
  102. package/dist/dev/test/node.test.js.map +1 -0
  103. package/dist/dev/test/output-e2e.test.js +194 -0
  104. package/dist/dev/test/output-e2e.test.js.map +1 -0
  105. package/dist/dev/test/reactivity/circular-reactives.test.js +1 -1
  106. package/dist/dev/test/reactivity/circular-reactives.test.js.map +1 -1
  107. package/dist/dev/test/reactivity/cleanup.test.js +1 -1
  108. package/dist/dev/test/reactivity/cleanup.test.js.map +1 -1
  109. package/dist/dev/test/rendering/memoization.test.js +6 -1
  110. package/dist/dev/test/rendering/memoization.test.js.map +1 -1
  111. package/dist/dev/test/rendering/render-output-diagnostics.test.js +102 -0
  112. package/dist/dev/test/rendering/render-output-diagnostics.test.js.map +1 -0
  113. package/dist/dev/test/runtime.test.js +385 -0
  114. package/dist/dev/test/runtime.test.js.map +1 -0
  115. package/dist/dev/test/tree-test-utils.js +16 -0
  116. package/dist/dev/test/tree-test-utils.js.map +1 -0
  117. package/dist/dev/test/utils.test.js +1 -1
  118. package/dist/dev/test/utils.test.js.map +1 -1
  119. package/dist/dev/testing/devtools-utils.js +1 -1
  120. package/dist/dev/testing/devtools-utils.js.map +1 -1
  121. package/dist/dev/testing/extend-expect.js +7 -33
  122. package/dist/dev/testing/extend-expect.js.map +1 -1
  123. package/dist/dev/testing/render.js +7 -17
  124. package/dist/dev/testing/render.js.map +1 -1
  125. package/dist/devtools/index.html +17 -17
  126. package/dist/src/components/AccessExpression.test.js +1 -1
  127. package/dist/src/components/AccessExpression.test.js.map +1 -1
  128. package/dist/src/components/Output.d.ts +1 -1
  129. package/dist/src/components/Output.d.ts.map +1 -1
  130. package/dist/src/components/Output.js +2 -1
  131. package/dist/src/components/Output.js.map +1 -1
  132. package/dist/src/components/ReferenceOrContent.d.ts +1 -1
  133. package/dist/src/components/ReferenceOrContent.d.ts.map +1 -1
  134. package/dist/src/components/SourceFile.d.ts +1 -1
  135. package/dist/src/components/SourceFile.d.ts.map +1 -1
  136. package/dist/src/components/SourceFile.js.map +1 -1
  137. package/dist/src/content-slot.test.js +1 -1
  138. package/dist/src/content-slot.test.js.map +1 -1
  139. package/dist/src/context/format-options.d.ts +1 -1
  140. package/dist/src/context/format-options.d.ts.map +1 -1
  141. package/dist/src/context.d.ts +9 -1
  142. package/dist/src/context.d.ts.map +1 -1
  143. package/dist/src/context.js +30 -3
  144. package/dist/src/context.js.map +1 -1
  145. package/dist/src/debug/diagnostics.test.js +1 -1
  146. package/dist/src/debug/diagnostics.test.js.map +1 -1
  147. package/dist/src/debug/effects.test.js +1 -1
  148. package/dist/src/debug/effects.test.js.map +1 -1
  149. package/dist/src/debug/file-streaming.d.ts +22 -0
  150. package/dist/src/debug/file-streaming.d.ts.map +1 -0
  151. package/dist/src/debug/file-streaming.js +103 -0
  152. package/dist/src/debug/file-streaming.js.map +1 -0
  153. package/dist/src/debug/files.test.js +4 -5
  154. package/dist/src/debug/files.test.js.map +1 -1
  155. package/dist/src/debug/index.d.ts +5 -7
  156. package/dist/src/debug/index.d.ts.map +1 -1
  157. package/dist/src/debug/index.js +4 -6
  158. package/dist/src/debug/index.js.map +1 -1
  159. package/dist/src/debug/message-format.test.js +16 -18
  160. package/dist/src/debug/message-format.test.js.map +1 -1
  161. package/dist/src/debug/render-tree-orphans.test.js +8 -18
  162. package/dist/src/debug/render-tree-orphans.test.js.map +1 -1
  163. package/dist/src/debug/render.d.ts +71 -21
  164. package/dist/src/debug/render.d.ts.map +1 -1
  165. package/dist/src/debug/render.js +529 -352
  166. package/dist/src/debug/render.js.map +1 -1
  167. package/dist/src/debug/render.test.js +137 -74
  168. package/dist/src/debug/render.test.js.map +1 -1
  169. package/dist/src/debug/trace-writer.d.ts +6 -1
  170. package/dist/src/debug/trace-writer.d.ts.map +1 -1
  171. package/dist/src/debug/trace-writer.js +127 -15
  172. package/dist/src/debug/trace-writer.js.map +1 -1
  173. package/dist/src/debug/trace.d.ts +0 -36
  174. package/dist/src/debug/trace.d.ts.map +1 -1
  175. package/dist/src/debug/trace.js +0 -36
  176. package/dist/src/debug/trace.js.map +1 -1
  177. package/dist/src/devtools/devtools-protocol.d.ts +34 -1
  178. package/dist/src/devtools/devtools-protocol.d.ts.map +1 -1
  179. package/dist/src/devtools/devtools-server.d.ts.map +1 -1
  180. package/dist/src/devtools/devtools-server.js +55 -32
  181. package/dist/src/devtools/devtools-server.js.map +1 -1
  182. package/dist/src/devtools-entry.browser.d.ts +1 -1
  183. package/dist/src/devtools-entry.browser.d.ts.map +1 -1
  184. package/dist/src/devtools-entry.browser.js.map +1 -1
  185. package/dist/src/devtools-entry.d.ts +1 -1
  186. package/dist/src/devtools-entry.d.ts.map +1 -1
  187. package/dist/src/devtools-entry.js.map +1 -1
  188. package/dist/src/diagnostics.d.ts +4 -0
  189. package/dist/src/diagnostics.d.ts.map +1 -1
  190. package/dist/src/diagnostics.js +19 -1
  191. package/dist/src/diagnostics.js.map +1 -1
  192. package/dist/src/index.d.ts +5 -2
  193. package/dist/src/index.d.ts.map +1 -1
  194. package/dist/src/index.js +5 -2
  195. package/dist/src/index.js.map +1 -1
  196. package/dist/src/jsx-runtime.d.ts +13 -4
  197. package/dist/src/jsx-runtime.d.ts.map +1 -1
  198. package/dist/src/jsx-runtime.js +14 -8
  199. package/dist/src/jsx-runtime.js.map +1 -1
  200. package/dist/src/output-types.d.ts +40 -0
  201. package/dist/src/output-types.d.ts.map +1 -0
  202. package/dist/src/output-types.js +2 -0
  203. package/dist/src/output-types.js.map +1 -0
  204. package/dist/src/reactivity.d.ts +49 -18
  205. package/dist/src/reactivity.d.ts.map +1 -1
  206. package/dist/src/reactivity.js +155 -13
  207. package/dist/src/reactivity.js.map +1 -1
  208. package/dist/src/render/get-string-width.d.ts +19 -0
  209. package/dist/src/render/get-string-width.d.ts.map +1 -0
  210. package/dist/src/render/get-string-width.js +61 -0
  211. package/dist/src/render/get-string-width.js.map +1 -0
  212. package/dist/src/render/index.d.ts +2 -0
  213. package/dist/src/render/index.d.ts.map +1 -0
  214. package/dist/src/render/index.js +2 -0
  215. package/dist/src/render/index.js.map +1 -0
  216. package/dist/src/render/node-context.d.ts +5 -0
  217. package/dist/src/render/node-context.d.ts.map +1 -0
  218. package/dist/src/render/node-context.js +7 -0
  219. package/dist/src/render/node-context.js.map +1 -0
  220. package/dist/src/render/node.d.ts +146 -0
  221. package/dist/src/render/node.d.ts.map +1 -0
  222. package/dist/src/render/node.js +386 -0
  223. package/dist/src/render/node.js.map +1 -0
  224. package/dist/src/render/printer-support.d.ts +50 -0
  225. package/dist/src/render/printer-support.d.ts.map +1 -0
  226. package/dist/src/render/printer-support.js +180 -0
  227. package/dist/src/render/printer-support.js.map +1 -0
  228. package/dist/src/render/printer.d.ts +35 -0
  229. package/dist/src/render/printer.d.ts.map +1 -0
  230. package/dist/src/render/printer.js +797 -0
  231. package/dist/src/render/printer.js.map +1 -0
  232. package/dist/src/render-error.d.ts +4 -0
  233. package/dist/src/render-error.d.ts.map +1 -0
  234. package/dist/src/render-error.js +79 -0
  235. package/dist/src/render-error.js.map +1 -0
  236. package/dist/src/render-output.d.ts +42 -0
  237. package/dist/src/render-output.d.ts.map +1 -0
  238. package/dist/src/render-output.js +209 -0
  239. package/dist/src/render-output.js.map +1 -0
  240. package/dist/src/runtime/component.d.ts +2 -2
  241. package/dist/src/runtime/component.d.ts.map +1 -1
  242. package/dist/src/runtime/create-intrinsic.d.ts +28 -0
  243. package/dist/src/runtime/create-intrinsic.d.ts.map +1 -0
  244. package/dist/src/runtime/create-intrinsic.js +53 -0
  245. package/dist/src/runtime/create-intrinsic.js.map +1 -0
  246. package/dist/src/runtime/fragment.d.ts +16 -0
  247. package/dist/src/runtime/fragment.d.ts.map +1 -0
  248. package/dist/src/runtime/fragment.js +21 -0
  249. package/dist/src/runtime/fragment.js.map +1 -0
  250. package/dist/src/runtime/index.d.ts +12 -0
  251. package/dist/src/runtime/index.d.ts.map +1 -0
  252. package/dist/src/runtime/index.js +13 -0
  253. package/dist/src/runtime/index.js.map +1 -0
  254. package/dist/src/runtime/insert.d.ts +29 -0
  255. package/dist/src/runtime/insert.d.ts.map +1 -0
  256. package/dist/src/runtime/insert.js +453 -0
  257. package/dist/src/runtime/insert.js.map +1 -0
  258. package/dist/src/runtime/intrinsic.d.ts +12 -29
  259. package/dist/src/runtime/intrinsic.d.ts.map +1 -1
  260. package/dist/src/runtime/intrinsic.js +1 -11
  261. package/dist/src/runtime/intrinsic.js.map +1 -1
  262. package/dist/src/scheduler.d.ts.map +1 -1
  263. package/dist/src/scheduler.js +38 -14
  264. package/dist/src/scheduler.js.map +1 -1
  265. package/dist/src/stc.d.ts.map +1 -1
  266. package/dist/src/stc.js +2 -0
  267. package/dist/src/stc.js.map +1 -1
  268. package/dist/src/sti.d.ts +7 -6
  269. package/dist/src/sti.d.ts.map +1 -1
  270. package/dist/src/sti.js +1 -1
  271. package/dist/src/sti.js.map +1 -1
  272. package/dist/src/symbols/symbol-slot.test.js +1 -1
  273. package/dist/src/symbols/symbol-slot.test.js.map +1 -1
  274. package/dist/src/test-render.d.ts +31 -0
  275. package/dist/src/test-render.d.ts.map +1 -0
  276. package/dist/src/test-render.js +78 -0
  277. package/dist/src/test-render.js.map +1 -0
  278. package/dist/src/utils.d.ts +1 -1
  279. package/dist/src/utils.d.ts.map +1 -1
  280. package/dist/src/utils.js +40 -28
  281. package/dist/src/utils.js.map +1 -1
  282. package/dist/src/write-output.d.ts +1 -1
  283. package/dist/src/write-output.d.ts.map +1 -1
  284. package/dist/test/babel-e2e.test.d.ts +13 -0
  285. package/dist/test/babel-e2e.test.d.ts.map +1 -0
  286. package/dist/test/babel-e2e.test.js +218 -0
  287. package/dist/test/babel-e2e.test.js.map +1 -0
  288. package/dist/test/components/block.test.js +1 -1
  289. package/dist/test/components/block.test.js.map +1 -1
  290. package/dist/test/components/copy-file.test.d.ts.map +1 -1
  291. package/dist/test/components/copy-file.test.js +1 -1
  292. package/dist/test/components/copy-file.test.js.map +1 -1
  293. package/dist/test/components/update-file.test.js +1 -1
  294. package/dist/test/components/update-file.test.js.map +1 -1
  295. package/dist/test/components/wrap.test.js +1 -1
  296. package/dist/test/components/wrap.test.js.map +1 -1
  297. package/dist/test/control-flow/match.test.js +1 -1
  298. package/dist/test/control-flow/match.test.js.map +1 -1
  299. package/dist/test/control-flow/show.test.js +1 -1
  300. package/dist/test/control-flow/show.test.js.map +1 -1
  301. package/dist/test/lazy-isempty.test.js +6 -6
  302. package/dist/test/lazy-isempty.test.js.map +1 -1
  303. package/dist/test/node.test.d.ts +2 -0
  304. package/dist/test/node.test.d.ts.map +1 -0
  305. package/dist/test/node.test.js +80 -0
  306. package/dist/test/node.test.js.map +1 -0
  307. package/dist/test/output-e2e.test.d.ts +13 -0
  308. package/dist/test/output-e2e.test.d.ts.map +1 -0
  309. package/dist/test/output-e2e.test.js +194 -0
  310. package/dist/test/output-e2e.test.js.map +1 -0
  311. package/dist/test/reactivity/circular-reactives.test.js +1 -1
  312. package/dist/test/reactivity/circular-reactives.test.js.map +1 -1
  313. package/dist/test/reactivity/cleanup.test.js +1 -1
  314. package/dist/test/reactivity/cleanup.test.js.map +1 -1
  315. package/dist/test/rendering/memoization.test.js +6 -1
  316. package/dist/test/rendering/memoization.test.js.map +1 -1
  317. package/dist/test/rendering/render-output-diagnostics.test.d.ts +2 -0
  318. package/dist/test/rendering/render-output-diagnostics.test.d.ts.map +1 -0
  319. package/dist/test/rendering/render-output-diagnostics.test.js +82 -0
  320. package/dist/test/rendering/render-output-diagnostics.test.js.map +1 -0
  321. package/dist/test/runtime.test.d.ts +11 -0
  322. package/dist/test/runtime.test.d.ts.map +1 -0
  323. package/dist/test/runtime.test.js +385 -0
  324. package/dist/test/runtime.test.js.map +1 -0
  325. package/dist/test/tree-test-utils.d.ts +3 -0
  326. package/dist/test/tree-test-utils.d.ts.map +1 -0
  327. package/dist/test/tree-test-utils.js +16 -0
  328. package/dist/test/tree-test-utils.js.map +1 -0
  329. package/dist/test/utils.test.js +1 -1
  330. package/dist/test/utils.test.js.map +1 -1
  331. package/dist/testing/devtools-utils.d.ts.map +1 -1
  332. package/dist/testing/devtools-utils.js +1 -1
  333. package/dist/testing/devtools-utils.js.map +1 -1
  334. package/dist/testing/extend-expect.d.ts.map +1 -1
  335. package/dist/testing/extend-expect.js +7 -33
  336. package/dist/testing/extend-expect.js.map +1 -1
  337. package/dist/testing/render.d.ts +7 -9
  338. package/dist/testing/render.d.ts.map +1 -1
  339. package/dist/testing/render.js +7 -17
  340. package/dist/testing/render.js.map +1 -1
  341. package/dist/tsconfig.tsbuildinfo +1 -1
  342. package/docs/api/components/Output.md +0 -3
  343. package/docs/api/components/SourceFile.md +0 -3
  344. package/docs/api/functions/createComment.md +18 -0
  345. package/docs/api/functions/createElement.md +19 -0
  346. package/docs/api/functions/createFragment.md +17 -0
  347. package/docs/api/functions/createTextNode.md +18 -0
  348. package/docs/api/functions/emitDiagnosticForTree.md +19 -0
  349. package/docs/api/functions/ensureIsEmpty.md +1 -1
  350. package/docs/api/functions/getContextForNode.md +18 -0
  351. package/docs/api/functions/getContextForRenderNode.md +4 -4
  352. package/docs/api/functions/getDiagnosticsForTree.md +7 -5
  353. package/docs/api/functions/getRegisteredDiagnosticsForTree.md +18 -0
  354. package/docs/api/functions/index.md +17 -12
  355. package/docs/api/functions/isCustomContext.md +4 -4
  356. package/docs/api/functions/notifyContentState.md +6 -0
  357. package/docs/api/functions/printTree.md +6 -16
  358. package/docs/api/functions/registerDiagnosticsForTree.md +19 -0
  359. package/docs/api/functions/render.md +1 -2
  360. package/docs/api/functions/renderAsync.md +1 -2
  361. package/docs/api/functions/renderTree.md +8 -5
  362. package/docs/api/functions/reportDiagnosticsForTree.md +18 -0
  363. package/docs/api/functions/runInContext.md +28 -0
  364. package/docs/api/functions/sourceFilesForTree.md +6 -16
  365. package/docs/api/index.md +3 -3
  366. package/docs/api/testing/functions/index.md +1 -1
  367. package/docs/api/testing/functions/renderToString.md +1 -1
  368. package/docs/api/types/AlloyNode.md +22 -0
  369. package/docs/api/types/Child.md +1 -1
  370. package/docs/api/types/CommentNode.md +15 -0
  371. package/docs/api/types/Context.md +13 -15
  372. package/docs/api/types/ElementNode.md +18 -0
  373. package/docs/api/types/FragmentNode.md +12 -0
  374. package/docs/api/types/Insertable.md +7 -0
  375. package/docs/api/types/NodeType.md +5 -0
  376. package/docs/api/types/OutputDirectory.md +0 -50
  377. package/docs/api/types/PrintTreeOptions.md +0 -1
  378. package/docs/api/types/RenderTreeOptions.md +7 -0
  379. package/docs/api/types/StiComponentCreator.md +4 -4
  380. package/docs/api/types/StiSignature.md +1 -1
  381. package/docs/api/types/TextNode.md +16 -0
  382. package/docs/api/types/index.md +10 -28
  383. package/docs/api/variables/COMMENT_NODE.md +5 -0
  384. package/docs/api/variables/ELEMENT_NODE.md +11 -0
  385. package/docs/api/variables/FRAGMENT_NODE.md +5 -0
  386. package/docs/api/variables/TEXT_NODE.md +5 -0
  387. package/docs/api/variables/index.md +4 -2
  388. package/docs/formatting.md +1 -1
  389. package/docs/rendering.md +4 -4
  390. package/package.json +6 -6
  391. package/src/components/AccessExpression.test.tsx +1 -1
  392. package/src/components/Output.tsx +2 -1
  393. package/src/components/SourceFile.tsx +1 -1
  394. package/src/content-slot.test.tsx +1 -1
  395. package/src/context/format-options.ts +1 -1
  396. package/src/context.ts +37 -4
  397. package/src/debug/diagnostics.test.tsx +1 -1
  398. package/src/debug/effects.test.tsx +1 -1
  399. package/src/debug/file-streaming.ts +115 -0
  400. package/src/debug/files.test.tsx +15 -11
  401. package/src/debug/index.ts +11 -11
  402. package/src/debug/message-format.test.tsx +32 -19
  403. package/src/debug/render-tree-orphans.test.tsx +10 -19
  404. package/src/debug/render.test.tsx +206 -78
  405. package/src/debug/render.ts +642 -495
  406. package/src/debug/trace-writer.ts +168 -14
  407. package/src/debug/trace.ts +0 -20
  408. package/src/devtools/devtools-protocol.ts +43 -0
  409. package/src/devtools/devtools-server.ts +57 -32
  410. package/src/devtools-entry.browser.ts +5 -0
  411. package/src/devtools-entry.ts +5 -0
  412. package/src/diagnostics.ts +31 -0
  413. package/src/index.ts +66 -2
  414. package/src/jsx-runtime.ts +16 -14
  415. package/src/output-types.ts +47 -0
  416. package/src/reactivity.ts +186 -40
  417. package/src/render/get-string-width.ts +201 -0
  418. package/src/render/index.ts +1 -0
  419. package/src/render/node-context.ts +14 -0
  420. package/src/render/node.ts +442 -0
  421. package/src/render/printer-support.ts +209 -0
  422. package/src/render/printer.ts +817 -0
  423. package/src/render-error.ts +98 -0
  424. package/src/render-output.ts +243 -0
  425. package/src/runtime/component.ts +2 -2
  426. package/src/runtime/create-intrinsic.ts +56 -0
  427. package/src/runtime/fragment.ts +22 -0
  428. package/src/runtime/index.ts +12 -0
  429. package/src/runtime/insert.ts +569 -0
  430. package/src/runtime/intrinsic.ts +14 -70
  431. package/src/scheduler.ts +40 -25
  432. package/src/stc.ts +3 -0
  433. package/src/sti.ts +17 -20
  434. package/src/symbols/symbol-slot.test.tsx +1 -1
  435. package/src/test-render.ts +103 -0
  436. package/src/utils.tsx +55 -37
  437. package/src/write-output.ts +1 -1
  438. package/temp/api-testing.json +390 -14
  439. package/temp/api.json +4320 -4144
  440. package/test/babel-e2e.test.ts +224 -0
  441. package/test/components/block.test.tsx +1 -1
  442. package/test/components/copy-file.test.tsx +2 -1
  443. package/test/components/update-file.test.tsx +1 -1
  444. package/test/components/wrap.test.tsx +1 -1
  445. package/test/control-flow/match.test.tsx +1 -1
  446. package/test/control-flow/show.test.tsx +1 -1
  447. package/test/lazy-isempty.test.tsx +6 -6
  448. package/test/node.test.ts +90 -0
  449. package/test/output-e2e.test.ts +198 -0
  450. package/test/reactivity/circular-reactives.test.tsx +1 -1
  451. package/test/reactivity/cleanup.test.tsx +1 -1
  452. package/test/rendering/memoization.test.tsx +6 -1
  453. package/test/rendering/render-output-diagnostics.test.tsx +120 -0
  454. package/test/runtime.test.ts +448 -0
  455. package/test/tree-test-utils.ts +23 -0
  456. package/test/utils.test.tsx +1 -1
  457. package/testing/devtools-utils.ts +2 -0
  458. package/testing/extend-expect.ts +8 -46
  459. package/testing/render.ts +17 -21
  460. package/dist/dev/src/print-hook.js +0 -10
  461. package/dist/dev/src/print-hook.js.map +0 -1
  462. package/dist/dev/src/render.js +0 -872
  463. package/dist/dev/src/render.js.map +0 -1
  464. package/dist/src/print-hook.d.ts +0 -14
  465. package/dist/src/print-hook.d.ts.map +0 -1
  466. package/dist/src/print-hook.js +0 -10
  467. package/dist/src/print-hook.js.map +0 -1
  468. package/dist/src/render.d.ts +0 -155
  469. package/dist/src/render.d.ts.map +0 -1
  470. package/dist/src/render.js +0 -872
  471. package/dist/src/render.js.map +0 -1
  472. package/docs/api/functions/createIntrinsic.md +0 -19
  473. package/docs/api/functions/createRenderTreeHook.md +0 -19
  474. package/docs/api/functions/getElementCache.md +0 -17
  475. package/docs/api/functions/isIntrinsicElement.md +0 -18
  476. package/docs/api/functions/isPrintHook.md +0 -18
  477. package/docs/api/types/AlignIntrinsicElement.md +0 -5
  478. package/docs/api/types/BrIntrinsicElement.md +0 -5
  479. package/docs/api/types/BreakParentIntrinsicElement.md +0 -5
  480. package/docs/api/types/DedentIntrinsicElement.md +0 -5
  481. package/docs/api/types/DedentToRootIntrinsicElement.md +0 -5
  482. package/docs/api/types/ElementCache.md +0 -5
  483. package/docs/api/types/ElementCacheKey.md +0 -5
  484. package/docs/api/types/FillIntrinsicElement.md +0 -5
  485. package/docs/api/types/GroupIntrinsicElement.md +0 -5
  486. package/docs/api/types/HardlineIntrinsicElement.md +0 -5
  487. package/docs/api/types/HbrIntrinsicElement.md +0 -5
  488. package/docs/api/types/IfBreakIntrinsicElement.md +0 -5
  489. package/docs/api/types/IndentIfBreakIntrinsicElement.md +0 -5
  490. package/docs/api/types/IndentIntrinsicElement.md +0 -5
  491. package/docs/api/types/IntrinsicElement.md +0 -5
  492. package/docs/api/types/IntrinsicElementBase.md +0 -9
  493. package/docs/api/types/LbrIntrinsicElement.md +0 -5
  494. package/docs/api/types/LineIntrinsicElement.md +0 -5
  495. package/docs/api/types/LineSuffixBoundaryIntrinsicElement.md +0 -5
  496. package/docs/api/types/LineSuffixIntrinsicElement.md +0 -5
  497. package/docs/api/types/LiterallineIntrinsicElement.md +0 -5
  498. package/docs/api/types/MarkAsRootIntrinsicElement.md +0 -5
  499. package/docs/api/types/PrintHook.md +0 -10
  500. package/docs/api/types/RenderedTextTree.md +0 -5
  501. package/docs/api/types/SbrIntrinsicElement.md +0 -5
  502. package/docs/api/types/SoftlineIntrinsicElement.md +0 -5
  503. package/docs/api/variables/intrinsicElementKey.md +0 -5
  504. package/docs/api/variables/printHookTag.md +0 -7
  505. package/src/print-hook.ts +0 -22
  506. package/src/render.ts +0 -1154
package/src/scheduler.ts CHANGED
@@ -13,8 +13,21 @@ import { getEffectDebugId } from "./reactivity.js";
13
13
  export interface QueueJob {
14
14
  run(): void;
15
15
  }
16
- const immediateQueue = new Set<QueueJob>();
17
- const queue = new Set<QueueJob>();
16
+ // Dedup membership set + ordered drain array with a moving head pointer.
17
+ // Using `Set.values().next().value` per takeJob (the prior impl) allocated
18
+ // a fresh iterator + result object on every pop, which dominated CPU and
19
+ // GC for scenarios with many queued effects (~31% of CPU on render-imports).
20
+ // The hybrid below keeps O(1) dedup via the Set while making takeJob
21
+ // allocation-free in the steady state.
22
+ const inQueueSet = new Set<QueueJob>();
23
+ const immediateArr: QueueJob[] = [];
24
+ let immediateHead = 0;
25
+ const queueArr: QueueJob[] = [];
26
+ let queueHead = 0;
27
+
28
+ function queueSize(): number {
29
+ return immediateArr.length - immediateHead + (queueArr.length - queueHead);
30
+ }
18
31
 
19
32
  function isJobActive(job: QueueJob): boolean {
20
33
  // ReactiveEffect uses bit 0 (flags & 1) as the ACTIVE flag.
@@ -63,21 +76,18 @@ export function queueJob(job: QueueJob | (() => void), immediate = false) {
63
76
  if (typeof job === "function") {
64
77
  job = { run: job };
65
78
  }
79
+ if (inQueueSet.has(job)) return;
80
+ inQueueSet.add(job);
66
81
  if (immediate) {
67
- immediateQueue.add(job);
82
+ immediateArr.push(job);
68
83
  } else {
69
- queue.add(job);
84
+ queueArr.push(job);
70
85
  }
71
86
 
72
87
  if (isTraceEnabled()) {
73
88
  const effectId = getEffectDebugId(job as object);
74
89
  if (effectId !== undefined) {
75
- insertSchedulerJob(
76
- "queue",
77
- effectId,
78
- immediate,
79
- immediateQueue.size + queue.size,
80
- );
90
+ insertSchedulerJob("queue", effectId, immediate, queueSize());
81
91
  }
82
92
  }
83
93
 
@@ -108,12 +118,7 @@ export function flushJobs() {
108
118
  if (isTraceEnabled()) {
109
119
  const effectId = getEffectDebugId(job as object);
110
120
  if (effectId !== undefined) {
111
- insertSchedulerJob(
112
- "run",
113
- effectId,
114
- false,
115
- immediateQueue.size + queue.size,
116
- );
121
+ insertSchedulerJob("run", effectId, false, queueSize());
117
122
  }
118
123
  }
119
124
  if (!isJobActive(job)) {
@@ -267,17 +272,27 @@ export async function flushJobsAsync() {
267
272
  debug.render.flushJobsComplete();
268
273
  }
269
274
 
270
- function takeJob() {
271
- if (immediateQueue.size > 0) {
272
- // return first item in immediateQueue
273
- const job = immediateQueue.values().next().value!;
274
- immediateQueue.delete(job);
275
+ function takeJob(): QueueJob | null {
276
+ if (immediateHead < immediateArr.length) {
277
+ const job = immediateArr[immediateHead];
278
+ immediateArr[immediateHead] = undefined as any; // release ref for GC
279
+ immediateHead++;
280
+ inQueueSet.delete(job);
281
+ if (immediateHead === immediateArr.length) {
282
+ immediateArr.length = 0;
283
+ immediateHead = 0;
284
+ }
275
285
  return job;
276
286
  }
277
- if (queue.size > 0) {
278
- // return first item in queue
279
- const job = queue.values().next().value!;
280
- queue.delete(job);
287
+ if (queueHead < queueArr.length) {
288
+ const job = queueArr[queueHead];
289
+ queueArr[queueHead] = undefined as any;
290
+ queueHead++;
291
+ inQueueSet.delete(job);
292
+ if (queueHead === queueArr.length) {
293
+ queueArr.length = 0;
294
+ queueHead = 0;
295
+ }
281
296
  return job;
282
297
  }
283
298
  return null;
package/src/stc.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { code, text } from "./code.js";
2
+ import { _registerStcImpl } from "./context.js";
2
3
  import {
3
4
  Children,
4
5
  ComponentCreator,
@@ -72,3 +73,5 @@ export function stc<T extends {}>(
72
73
  return fn;
73
74
  };
74
75
  }
76
+
77
+ _registerStcImpl(stc);
package/src/sti.ts CHANGED
@@ -1,37 +1,34 @@
1
1
  import { code, text } from "./code.js";
2
+ import type { ElementNode } from "./render/node.js";
2
3
  import { Children } from "./runtime/component.js";
3
- import {
4
- createIntrinsic,
5
- IntrinsicElementBase,
6
- IntrinsicElements,
7
- } from "./runtime/intrinsic.js";
4
+ import { createIntrinsic } from "./runtime/create-intrinsic.js";
5
+ import { IntrinsicElements } from "./runtime/intrinsic.js";
8
6
 
9
7
  export type StiSignature<T extends keyof IntrinsicElements> = (
10
8
  ...args: unknown extends T ? []
11
9
  : {} extends Omit<IntrinsicElements[T], "children"> ?
12
10
  [props?: IntrinsicElements[T]]
13
11
  : [props: IntrinsicElements[T]]
14
- ) => StiComponentCreator<T>;
15
-
16
- export type StiComponentCreator<T extends keyof IntrinsicElements> =
17
- (() => IntrinsicElementBase<T>) & {
18
- code(
19
- template: TemplateStringsArray,
20
- ...substitutions: Children[]
21
- ): () => IntrinsicElementBase<T>;
22
- text(
23
- template: TemplateStringsArray,
24
- ...substitutions: Children[]
25
- ): () => IntrinsicElementBase<T>;
26
- children(...children: Children[]): () => IntrinsicElementBase<T>;
27
- };
12
+ ) => StiComponentCreator;
13
+
14
+ export type StiComponentCreator = (() => ElementNode) & {
15
+ code(
16
+ template: TemplateStringsArray,
17
+ ...substitutions: Children[]
18
+ ): () => ElementNode;
19
+ text(
20
+ template: TemplateStringsArray,
21
+ ...substitutions: Children[]
22
+ ): () => ElementNode;
23
+ children(...children: Children[]): () => ElementNode;
24
+ };
28
25
 
29
26
  export function sti<T extends keyof IntrinsicElements>(
30
27
  name: T,
31
28
  ): StiSignature<T> {
32
29
  return (...args) => {
33
30
  const props: IntrinsicElements[T] | undefined = args[0];
34
- const fn: StiComponentCreator<T> = () => createIntrinsic(name, props!);
31
+ const fn: StiComponentCreator = () => createIntrinsic(name, props);
35
32
  fn.children = (...children: Children[]) => {
36
33
  const propsWithChildren = {
37
34
  ...(props ?? {}),
@@ -1,7 +1,7 @@
1
1
  import { shallowRef } from "@vue/reactivity";
2
2
  import { expect, it } from "vitest";
3
- import { getDiagnosticsForTree, renderTree } from "../render.js";
4
3
  import { flushJobs } from "../scheduler.js";
4
+ import { getDiagnosticsForTree, renderTree } from "../test-render.js";
5
5
  import { BasicSymbol } from "./basic-symbol.js";
6
6
  import { emitSymbol } from "./symbol-flow.js";
7
7
  import { createSymbolSlot } from "./symbol-slot.jsx";
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Direct AlloyNode-tree rendering helpers.
3
+ *
4
+ * `renderTree` produces an `ElementNode` root for assertions that need
5
+ * to inspect tree shape directly (used by component-level tests that
6
+ * don't go through `<SourceFile>`); `printTree` formats the tree with
7
+ * Alloy's direct printer. These are the lower-level entry points behind
8
+ * `render`/`renderAsync` and the testing matchers.
9
+ */
10
+
11
+ import {
12
+ attachDiagnosticsCollector,
13
+ DiagnosticsCollector,
14
+ getRegisteredDiagnosticsForTree,
15
+ registerDiagnosticsForTree,
16
+ type Diagnostic,
17
+ } from "./diagnostics.js";
18
+ import type { PrintTreeOptions } from "./output-types.js";
19
+ import { root, runInContext } from "./reactivity.js";
20
+ import { printNode } from "./render-output.js";
21
+ import { getContextForNode } from "./render/node-context.js";
22
+ import { AlloyNode, createElement, ElementNode } from "./render/node.js";
23
+ import type { Children } from "./runtime/component.js";
24
+ import { insert } from "./runtime/insert.js";
25
+ import { flushJobs } from "./scheduler.js";
26
+
27
+ export interface RenderTreeOptions {
28
+ noFlush?: boolean;
29
+ }
30
+
31
+ /** Render `children` into a fresh root AlloyNode. */
32
+ export function renderTree(
33
+ children: Children,
34
+ opts?: RenderTreeOptions,
35
+ ): ElementNode {
36
+ const rootNode = createElement("alloy:root");
37
+ const collector = new DiagnosticsCollector();
38
+ root(() => {
39
+ runInContext(() => {
40
+ attachDiagnosticsCollector(collector);
41
+ insert(rootNode, children);
42
+ });
43
+ });
44
+ if (!opts?.noFlush) flushJobs();
45
+ registerDiagnosticsForTree(rootNode, collector);
46
+ return rootNode;
47
+ }
48
+
49
+ /** Print an AlloyNode tree to a string. */
50
+ export function printTree(
51
+ node: AlloyNode,
52
+ opts?: PrintTreeOptions & RenderTreeOptions,
53
+ ): string {
54
+ if (!opts?.noFlush) flushJobs();
55
+ return printNode(node, opts);
56
+ }
57
+
58
+ /** Diagnostics collected during the render of `rootNode`. */
59
+ export function getDiagnosticsForTree(rootNode: AlloyNode): Diagnostic[] {
60
+ return getRegisteredDiagnosticsForTree(rootNode);
61
+ }
62
+
63
+ /**
64
+ * Collect source files from an AlloyNode tree as a `path → contents`
65
+ * map. If no `<SourceFile>` markers are found, returns the printed
66
+ * string of the whole tree. Used by the `toRenderTo` matcher; unlike
67
+ * `sourceFilesForTree`, this does NOT default `insertFinalNewLine`,
68
+ * preserving the raw printed body for test assertions.
69
+ */
70
+ export function getFilesFromTree(
71
+ rootNode: AlloyNode,
72
+ opts?: PrintTreeOptions & RenderTreeOptions,
73
+ ): string | Record<string, string> {
74
+ const files: Record<string, string> = {};
75
+ visit(rootNode);
76
+ if (Object.keys(files).length === 0) {
77
+ return printTree(rootNode, opts);
78
+ }
79
+ return files;
80
+
81
+ function visit(node: AlloyNode): void {
82
+ if (node instanceof ElementNode && node.localName === "alloy:source-file") {
83
+ const ctx = getContextForNode(node);
84
+ const sf = ctx?.meta?.sourceFile as { path: string } | undefined;
85
+ if (sf) {
86
+ const printOpts = ctx!.meta!.printOptions as
87
+ | PrintTreeOptions
88
+ | undefined;
89
+ files[sf.path] = printTree(node, {
90
+ printWidth: opts?.printWidth ?? printOpts?.printWidth,
91
+ tabWidth: opts?.tabWidth ?? printOpts?.tabWidth,
92
+ useTabs: opts?.useTabs ?? printOpts?.useTabs,
93
+ insertFinalNewLine:
94
+ opts?.insertFinalNewLine ?? printOpts?.insertFinalNewLine,
95
+ noFlush: true,
96
+ });
97
+ }
98
+ }
99
+ for (let c = node.firstChild; c !== null; c = c.nextSibling) {
100
+ visit(c);
101
+ }
102
+ }
103
+ }
package/src/utils.tsx CHANGED
@@ -1,20 +1,19 @@
1
1
  import { Ref, toRaw } from "@vue/reactivity";
2
2
  import { BaseListProps } from "./components/List.jsx";
3
+ import { OutputDirectory, OutputFile } from "./output-types.js";
3
4
  import {
4
5
  createCustomContext,
5
6
  CustomContext,
6
7
  Disposable,
7
- effect,
8
- ensureIsEmpty,
9
8
  getContext,
10
9
  memo,
11
10
  onCleanup,
12
11
  ref,
13
12
  root,
13
+ setContextEmptyChangeListener,
14
14
  untrack,
15
15
  } from "./reactivity.js";
16
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
17
- import { OutputDirectory, OutputFile, render } from "./render.js";
16
+ import { AlloyNode, FRAGMENT_NODE } from "./render/node.js";
18
17
  import {
19
18
  Children,
20
19
  ComponentCreator,
@@ -118,14 +117,25 @@ export function mapJoin<T, U, V>(
118
117
  item?: MapJoinItem;
119
118
  disposer?: Disposable;
120
119
  joiner?: Ref<Children | undefined>;
121
- isEmpty: Ref<boolean>;
120
+ /**
121
+ * Mirror of the slot's nested-context empty state, kept as a plain
122
+ * primitive. Written by:
123
+ * 1. The empty-change callback installed on the nested context
124
+ * (on real content transitions while the slot is live).
125
+ * 2. The outer thunk's recycle/truncate paths, which manually
126
+ * reset to `true` before disposing the old slot.
127
+ * Read inside the outer thunk's `untrack` region. No Ref/Dep
128
+ * tracking required — replaces what was previously a `Ref<boolean>`
129
+ * plus a per-slot `effect()`.
130
+ */
131
+ empty: boolean;
122
132
  }
123
133
  const itemSlots: MapJoinSlot[] = [];
124
134
 
125
135
  function getOrCreateSlot(index: number): MapJoinSlot {
126
136
  let slot = itemSlots[index];
127
137
  if (!slot) {
128
- slot = { isEmpty: ref(true) };
138
+ slot = { empty: true };
129
139
  itemSlots[index] = slot;
130
140
  }
131
141
  return slot;
@@ -177,7 +187,7 @@ export function mapJoin<T, U, V>(
177
187
  const shouldShow =
178
188
  previousNonEmpty !== -1 &&
179
189
  rightSlot !== undefined &&
180
- rightSlot.isEmpty.value === false;
190
+ rightSlot.empty === false;
181
191
 
182
192
  const newValue = shouldShow ? options.joiner : undefined;
183
193
  if (joinerRef.value !== newValue) {
@@ -189,7 +199,7 @@ export function mapJoin<T, U, V>(
189
199
  function findNextNonEmpty(from: number) {
190
200
  for (let i = Math.max(from, 0); i < itemSlots.length; i++) {
191
201
  const slot = itemSlots[i];
192
- if (slot && slot.isEmpty.value === false) {
202
+ if (slot && slot.empty === false) {
193
203
  return i;
194
204
  }
195
205
  }
@@ -200,7 +210,7 @@ export function mapJoin<T, U, V>(
200
210
  function findPrevNonEmpty(from: number) {
201
211
  for (let i = Math.min(from, itemSlots.length - 1); i >= 0; i--) {
202
212
  const slot = itemSlots[i];
203
- if (slot && slot.isEmpty.value === false) {
213
+ if (slot && slot.empty === false) {
204
214
  return i;
205
215
  }
206
216
  }
@@ -309,14 +319,13 @@ export function mapJoin<T, U, V>(
309
319
  for (; startIndex < itemsLen; startIndex++) {
310
320
  const slot = getOrCreateSlot(startIndex);
311
321
  slot.item = items[startIndex];
312
- const emptyFlag = slot.isEmpty;
313
322
 
314
323
  if (slot.disposer) {
315
- if (emptyFlag.value === false) {
324
+ if (slot.empty === false) {
316
325
  if (context) {
317
326
  context.childrenWithContent--;
318
327
  }
319
- emptyFlag.value = true;
328
+ slot.empty = true;
320
329
  applyEmptyStateChange(startIndex, true, false);
321
330
  }
322
331
  slot.disposer();
@@ -327,32 +336,25 @@ export function mapJoin<T, U, V>(
327
336
  mapped[startIndex * 2] = createCustomContext((cb) => {
328
337
  return root((disposer) => {
329
338
  const nestedContext = getContext()!;
330
- const isEmptyFlag = ensureIsEmpty(nestedContext);
331
339
 
332
340
  slot.disposer = disposer;
333
341
  disposer();
334
- effect(
335
- (prev?: boolean) => {
336
- const isEmpty = isEmptyFlag.value;
337
- return untrack(() => {
338
- if (slot.isEmpty.value !== isEmpty) {
339
- slot.isEmpty.value = isEmpty;
340
- }
341
- const wasEmpty = prev ?? true;
342
-
343
- applyEmptyStateChange(cleanupIndex, isEmpty, wasEmpty);
344
-
345
- return isEmpty;
346
- });
347
- },
348
- undefined,
349
- {
350
- debug: {
351
- name: `list:slotEmpty:${cleanupIndex}`,
352
- type: "list",
353
- },
354
- },
355
- );
342
+
343
+ // Single-subscriber callback: fires synchronously on every
344
+ // empty↔non-empty transition of this slot's nested context.
345
+ // No Ref/effect allocation per slot; cleared via
346
+ // `onCleanup` so a recycled slot's old context can never
347
+ // mutate the new slot's bookkeeping.
348
+ setContextEmptyChangeListener(nestedContext, (isEmpty) => {
349
+ const wasEmpty = slot.empty;
350
+ if (wasEmpty === isEmpty) return;
351
+ slot.empty = isEmpty;
352
+ applyEmptyStateChange(cleanupIndex, isEmpty, wasEmpty);
353
+ });
354
+ onCleanup(() => {
355
+ setContextEmptyChangeListener(nestedContext, undefined);
356
+ });
357
+
356
358
  cb(mapper(items[cleanupIndex], cleanupIndex));
357
359
  });
358
360
  });
@@ -378,11 +380,11 @@ export function mapJoin<T, U, V>(
378
380
  }
379
381
 
380
382
  slot.disposer?.();
381
- if (slot.isEmpty.value === false) {
383
+ if (slot.empty === false) {
382
384
  if (context) {
383
385
  context.childrenWithContent--;
384
386
  }
385
- slot.isEmpty.value = true;
387
+ slot.empty = true;
386
388
  applyEmptyStateChange(startIndex, true, false);
387
389
  }
388
390
  }
@@ -502,6 +504,22 @@ export function children(
502
504
  !isComponentCreator(children)
503
505
  ) {
504
506
  return collectChildren(children());
507
+ } else if (children instanceof AlloyNode) {
508
+ // A FragmentNode is the AlloyNode equivalent of an array — flatten
509
+ // by walking its sibling list. Other node kinds are opaque leaves.
510
+ if (children.nodeType === FRAGMENT_NODE) {
511
+ const out: Children[] = [];
512
+ for (let n = children.firstChild; n !== null; n = n.nextSibling) {
513
+ const collected = collectChildren(n);
514
+ if (Array.isArray(collected)) {
515
+ out.push(...collected);
516
+ } else {
517
+ out.push(collected);
518
+ }
519
+ }
520
+ return out;
521
+ }
522
+ return children;
505
523
  } else {
506
524
  return children;
507
525
  }
@@ -1,7 +1,7 @@
1
1
  import { dirname, relative, resolve } from "pathe";
2
2
  import { AlloyHost } from "./host/alloy-host.js";
3
3
  import { cwd } from "./host/node-host.js";
4
- import { OutputDirectory } from "./render.js";
4
+ import { OutputDirectory } from "./output-types.js";
5
5
  import { traverseOutput } from "./utils.js";
6
6
  /**
7
7
  * Write the output from {@link render} to the file system.