@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
@@ -0,0 +1,224 @@
1
+ /**
2
+ * End-to-end test: compile real JSX through the Alloy babel preset with
3
+ * then execute the compiled output against the new runtime.
4
+ *
5
+ * Validates that:
6
+ * - The preset routes runtime imports to `@alloy-js/core/jsx-runtime`.
7
+ * - The compiled output (using `_$createIntrinsic` / `_$createComponent`
8
+ * / `_$memo` / `_$mergeProps`) executes correctly under the new
9
+ * runtime semantics (component thunks invoked via `runInContext`,
10
+ * intrinsics returning AlloyNodes eagerly).
11
+ */
12
+
13
+ // @ts-expect-error — @babel/core has no bundled types in this workspace
14
+ import { transformSync } from "@babel/core";
15
+ // @ts-expect-error — preset has no types
16
+ import alloyPreset from "@alloy-js/babel-preset";
17
+ // @ts-expect-error — preset-typescript has no types
18
+ import typescriptPreset from "@babel/preset-typescript";
19
+ import { describe, expect, it } from "vitest";
20
+ import { type AlloyNode } from "../src/render/index.js";
21
+ import { createElement } from "../src/render/node.js";
22
+ import { insert } from "../src/runtime/index.js";
23
+ import { flushJobs } from "../src/scheduler.js";
24
+ import { textContent } from "./tree-test-utils.js";
25
+
26
+ function compile(src: string): string {
27
+ const result = transformSync(src, {
28
+ filename: "test.tsx",
29
+ presets: [typescriptPreset, [alloyPreset]],
30
+ });
31
+ if (!result?.code) throw new Error("compile failed");
32
+ return result.code;
33
+ }
34
+
35
+ /**
36
+ * Build a function that evaluates the compiled module body with our
37
+ * jsx-runtime exports injected, and returns the named export.
38
+ */
39
+ async function evalCompiled(src: string, exportName: string): Promise<unknown> {
40
+ const code = compile(src);
41
+ // Replace the auto-imports with a destructure from a passed-in runtime.
42
+ const runtimeStub = `const __rt = arguments[0]; const __core = arguments[1];`;
43
+ // Strip all `import { ... } from "@alloy-js/core/jsx-runtime";` lines
44
+ // and replace them with destructuring from __rt.
45
+ const importRegex =
46
+ /import\s*\{\s*([^}]+)\s*\}\s*from\s*"@alloy-js\/core\/jsx-runtime";?/g;
47
+ const destructures: string[] = [];
48
+ let body = code.replace(importRegex, (_match, names: string) => {
49
+ // Convert `foo as _$foo` (import alias) → `foo: _$foo` (destructure alias).
50
+ const destructureNames = names.replace(/(\w+)\s+as\s+(\w+)/g, "$1: $2");
51
+ destructures.push(`const {${destructureNames}} = __rt;`);
52
+ return "";
53
+ });
54
+ // Bare @alloy-js/core imports (Show, Switch, Match, For, …) come from
55
+ // the second runtime argument.
56
+ const coreImportRegex =
57
+ /import\s*\{\s*([^}]+)\s*\}\s*from\s*"@alloy-js\/core";?/g;
58
+ body = body.replace(coreImportRegex, (_match, names: string) => {
59
+ const destructureNames = names.replace(/(\w+)\s+as\s+(\w+)/g, "$1: $2");
60
+ // Built-ins live in the runtime module; everything
61
+ // else comes from core. Split the names by what the runtime
62
+ // re-exports.
63
+ destructures.push(`const {${destructureNames}} = { ...__core, ...__rt };`);
64
+ return "";
65
+ });
66
+ // The compiled module uses ESM `export { App }`. Convert to a return.
67
+ body = body.replace(
68
+ /export\s*\{\s*([^}]+)\s*\}\s*;?/g,
69
+ (_, names: string) => {
70
+ const list = names.split(",").map((s) => s.trim());
71
+ return `return { ${list.join(",")} };`;
72
+ },
73
+ );
74
+ // import.meta.url isn't available; stub it.
75
+ body = body.replace(/import\.meta\.url/g, '"test://test.tsx"');
76
+
77
+ const wrapped = `${runtimeStub}\n${destructures.join("\n")}\n${body}`;
78
+ const fn = new Function(wrapped);
79
+ const runtime = await import("../src/runtime/index.js");
80
+ const core = await import("../src/index.js");
81
+ return fn(runtime, core)[exportName];
82
+ }
83
+
84
+ function renderToString(thunk: unknown): string {
85
+ const parent = createElement("group");
86
+ insert(parent, thunk);
87
+ flushJobs();
88
+ return textContent(parent);
89
+ }
90
+
91
+ function printNode(node: AlloyNode): string {
92
+ flushJobs();
93
+ return textContent(node);
94
+ }
95
+
96
+ describe("babel preset — end-to-end", () => {
97
+ it("compiles intrinsics and produces AlloyNode output", async () => {
98
+ const src = `
99
+ const App = () => <group>hello, world</group>;
100
+ export { App };
101
+ `;
102
+ const App = (await evalCompiled(src, "App")) as () => unknown;
103
+ // App is a plain function (no createComponent wrapper at the top).
104
+ const node = App() as AlloyNode;
105
+ expect(printNode(node)).toBe("hello, world");
106
+ });
107
+
108
+ it("compiles component invocations and threads props correctly", async () => {
109
+ const src = `
110
+ const Greet = (props) => <group>hello, {props.name}!</group>;
111
+ const App = () => <indent><Greet name="world" /></indent>;
112
+ export { App };
113
+ `;
114
+ const App = (await evalCompiled(src, "App")) as () => unknown;
115
+ const node = App() as AlloyNode;
116
+ expect(printNode(node)).toBe("hello, world!");
117
+ });
118
+
119
+ it("compiles fragments and arrays of children", async () => {
120
+ const src = `
121
+ const App = () => <><group>a</group>{"-"}<group>b</group></>;
122
+ export { App };
123
+ `;
124
+ const App = (await evalCompiled(src, "App")) as () => unknown;
125
+ // Top-level fragment: App() returns an array (Children) per plugin
126
+ // output. Insert into a parent and print.
127
+ expect(renderToString(App())).toBe("a-b");
128
+ });
129
+
130
+ it("compiles nested components composing through intrinsics", async () => {
131
+ const src = `
132
+ const Inner = (props) => <group>[{props.value}]</group>;
133
+ const Mid = (props) => <indent><Inner value={props.value} /></indent>;
134
+ const App = () => <group><Mid value="x" /></group>;
135
+ export { App };
136
+ `;
137
+ const App = (await evalCompiled(src, "App")) as () => unknown;
138
+ expect(printNode(App() as AlloyNode)).toBe("[x]");
139
+ });
140
+
141
+ it("Show built-in works with alloy preset", async () => {
142
+ const src = `
143
+ import { Show } from "@alloy-js/core";
144
+ const App = (props) => <group><Show when={props.cond} fallback="no">yes</Show></group>;
145
+ export { App };
146
+ `;
147
+ const App = (await evalCompiled(src, "App")) as (props: any) => unknown;
148
+ expect(printNode(App({ cond: true }) as AlloyNode)).toBe("yes");
149
+ expect(printNode(App({ cond: false }) as AlloyNode)).toBe("no");
150
+ });
151
+
152
+ it("Switch/Match built-ins work with alloy preset", async () => {
153
+ const src = `
154
+ import { Switch, Match } from "@alloy-js/core";
155
+ const App = (props) => (
156
+ <group>
157
+ <Switch>
158
+ <Match when={props.kind === "a"}>A!</Match>
159
+ <Match when={props.kind === "b"}>B!</Match>
160
+ <Match else>other</Match>
161
+ </Switch>
162
+ </group>
163
+ );
164
+ export { App };
165
+ `;
166
+ const App = (await evalCompiled(src, "App")) as (props: any) => unknown;
167
+ expect(printNode(App({ kind: "a" }) as AlloyNode)).toBe("A!");
168
+ expect(printNode(App({ kind: "b" }) as AlloyNode)).toBe("B!");
169
+ expect(printNode(App({ kind: "c" }) as AlloyNode)).toBe("other");
170
+ });
171
+
172
+ it("For built-in works with alloy preset", async () => {
173
+ const src = `
174
+ import { For } from "@alloy-js/core";
175
+ const App = (props) => (
176
+ <group>
177
+ <For each={props.items}>{(item) => <group>[{item}]</group>}</For>
178
+ </group>
179
+ );
180
+ export { App };
181
+ `;
182
+ const App = (await evalCompiled(src, "App")) as (props: any) => unknown;
183
+ expect(printNode(App({ items: ["a", "b", "c"] }) as AlloyNode)).toBe(
184
+ "[a][b][c]",
185
+ );
186
+ });
187
+
188
+ it("For with joiner with alloy preset", async () => {
189
+ const src = `
190
+ import { For } from "@alloy-js/core";
191
+ const App = (props) => (
192
+ <group>
193
+ <For each={props.items} joiner=",">{(item) => <group>{item}</group>}</For>
194
+ </group>
195
+ );
196
+ export { App };
197
+ `;
198
+ const App = (await evalCompiled(src, "App")) as (props: any) => unknown;
199
+ expect(printNode(App({ items: ["x", "y", "z"] }) as AlloyNode)).toBe(
200
+ "x,y,z",
201
+ );
202
+ expect(printNode(App({ items: [] }) as AlloyNode)).toBe("");
203
+ });
204
+
205
+ it("Context.Provider value flows to descendants with alloy preset", async () => {
206
+ const src = `
207
+ import { createContext, useContext } from "@alloy-js/core";
208
+ const Ctx = createContext();
209
+ const Reader = () => {
210
+ const v = useContext(Ctx);
211
+ return <group>v={v}</group>;
212
+ };
213
+ const App = () => (
214
+ <Ctx.Provider value="hello">
215
+ <group><Reader /></group>
216
+ </Ctx.Provider>
217
+ );
218
+ export { App };
219
+ `;
220
+ const App = (await evalCompiled(src, "App")) as () => unknown;
221
+ // Top-level Component yields a thunk; route through insert into a parent.
222
+ expect(renderToString(App())).toBe("v=hello");
223
+ });
224
+ });
@@ -1,29 +1,74 @@
1
1
  import { existsSync, mkdirSync, rmSync, writeFileSync } from "fs";
2
- import { join } from "path";
2
+ import { join, resolve } from "path";
3
3
  import { build, type Rolldown } from "vite";
4
4
  import { afterAll, beforeAll, describe, expect, it } from "vitest";
5
5
 
6
6
  const tempDir = join(__dirname, ".temp", "browser-build-test");
7
7
  const entryFile = join(tempDir, "entry.js");
8
8
 
9
+ // Absolute path to the compiled browser entry point.
10
+ const corePkgDir = resolve(__dirname, "..");
11
+ const browserEntry = resolve(corePkgDir, "dist/src/index.browser.js");
12
+
9
13
  /**
10
14
  * Bundles `@alloy-js/core` for the browser using Vite and returns
11
- * the concatenated output code.
15
+ * the concatenated output code and any warnings emitted during the build.
12
16
  *
13
- * Uses the `browser` export condition from the package exports map,
14
- * which resolves to the compiled browser entry. This requires the
15
- * package to be built first (the CI pipeline and `pnpm build` handle
16
- * this automatically).
17
+ * Uses a custom resolveId plugin to force the browser entry point,
18
+ * because vitest's `resolve.conditions: ["source"]` leaks into the
19
+ * Vite build() call even with `configFile: false`, causing the test
20
+ * to resolve TypeScript source files instead of compiled dist.
17
21
  */
18
- async function bundleForBrowser(): Promise<string> {
22
+ async function bundleForBrowser(): Promise<{
23
+ code: string;
24
+ warnings: string[];
25
+ }> {
26
+ const warnings: string[] = [];
19
27
  const result = await build({
20
28
  configFile: false,
21
29
  logLevel: "silent",
22
30
  resolve: {
23
31
  conditions: ["browser", "import"],
32
+ mainFields: ["browser", "module", "main"],
24
33
  },
25
34
  // Disable automatic process.env replacement so we can detect leaks
26
35
  define: {},
36
+ plugins: [
37
+ {
38
+ name: "force-browser-entry",
39
+ enforce: "pre",
40
+ resolveId(source) {
41
+ // Force @alloy-js/core to resolve to the compiled browser entry,
42
+ // bypassing vitest's "source" condition that would resolve to TS.
43
+ if (source === "@alloy-js/core") {
44
+ return browserEntry;
45
+ }
46
+ return null;
47
+ },
48
+ },
49
+ {
50
+ name: "capture-warnings",
51
+ enforce: "post",
52
+ buildStart() {
53
+ // Hook into Vite's warning channel via rollup options
54
+ },
55
+ },
56
+ ],
57
+ customLogger: {
58
+ info() {},
59
+ error() {},
60
+ clearScreen() {},
61
+ hasErrorLogged() {
62
+ return false;
63
+ },
64
+ hasWarned: false,
65
+ warnOnce(msg: string) {
66
+ warnings.push(msg);
67
+ },
68
+ warn(msg: string) {
69
+ warnings.push(msg);
70
+ },
71
+ },
27
72
  build: {
28
73
  write: false,
29
74
  minify: false,
@@ -41,6 +86,13 @@ async function bundleForBrowser(): Promise<string> {
41
86
  // Externalize third-party deps (vue, pathe, picocolors, …)
42
87
  return true;
43
88
  },
89
+ onwarn(warning) {
90
+ warnings.push(
91
+ typeof warning === "string" ? warning : (
92
+ (warning.message ?? String(warning))
93
+ ),
94
+ );
95
+ },
44
96
  },
45
97
  },
46
98
  });
@@ -52,7 +104,7 @@ async function bundleForBrowser(): Promise<string> {
52
104
  const chunks = output.output.filter(
53
105
  (o): o is Rolldown.OutputChunk => o.type === "chunk",
54
106
  );
55
- return chunks.map((c) => c.code).join("\n");
107
+ return { code: chunks.map((c) => c.code).join("\n"), warnings };
56
108
  }
57
109
 
58
110
  describe("browser build", () => {
@@ -71,7 +123,10 @@ describe("browser build", () => {
71
123
  });
72
124
 
73
125
  it("should bundle for browser without Node.js polyfills", async () => {
74
- const code = await bundleForBrowser();
126
+ const { code, warnings } = await bundleForBrowser();
127
+
128
+ // Sanity check: the bundle should not be empty
129
+ expect(code.length).toBeGreaterThan(0);
75
130
 
76
131
  // The browser bundle must not reference the Node.js `process` global.
77
132
  // If this fails, a file is using process.env / process.cwd / etc.
@@ -80,5 +135,22 @@ describe("browser build", () => {
80
135
 
81
136
  // Should not contain static require("node:…") calls
82
137
  expect(code).not.toMatch(/require\(\s*["']node:/);
138
+
139
+ // Should not contain dynamic import("node:…") calls — these are the
140
+ // ones esbuild and other browser bundlers reject (e.g. node:sqlite, node:fs).
141
+ expect(code).not.toMatch(/import\(\s*["']node:/);
142
+
143
+ // Vite silently externalizes node:* modules for browser builds via its
144
+ // built-in rolldown:vite-resolve plugin, which hides the issue from the
145
+ // code assertions above. Catch those by checking for externalization warnings.
146
+ const nodeExternalizationWarnings = warnings.filter(
147
+ (w) =>
148
+ w.includes("externalized for browser compatibility") ||
149
+ w.includes("node:"),
150
+ );
151
+ expect(
152
+ nodeExternalizationWarnings,
153
+ `Node.js modules were externalized for browser compatibility — missing browser shims:\n${nodeExternalizationWarnings.join("\n")}`,
154
+ ).toEqual([]);
83
155
  }, 30_000);
84
156
  });
@@ -1,7 +1,7 @@
1
1
  import { ref } from "@vue/reactivity";
2
2
  import { expect, it } from "vitest";
3
3
  import { Block } from "../../src/components/Block.jsx";
4
- import { printTree, renderTree } from "../../src/render.js";
4
+ import { printTree, renderTree } from "../../src/test-render.js";
5
5
  import "../../testing/extend-expect.js";
6
6
  it("renders properly with no children", () => {
7
7
  const template = (
@@ -4,7 +4,8 @@ import { join } from "path";
4
4
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
5
5
  import { CopyFile } from "../../src/components/CopyFile.jsx";
6
6
  import { SourceDirectory } from "../../src/components/SourceDirectory.jsx";
7
- import { CopyOutputFile, render } from "../../src/render.js";
7
+ import type { CopyOutputFile } from "../../src/output-types.js";
8
+ import { render } from "../../src/render-output.js";
8
9
  import { writeOutput } from "../../src/write-output.js";
9
10
  import "../../testing/extend-expect.js";
10
11
 
@@ -3,7 +3,7 @@ import { tmpdir } from "os";
3
3
  import { join } from "pathe";
4
4
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
5
5
  import { UpdateFile } from "../../src/components/UpdateFile.jsx";
6
- import { render } from "../../src/render.js";
6
+ import { render } from "../../src/render-output.js";
7
7
  import "../../testing/extend-expect.js";
8
8
  import { d } from "../../testing/render.js";
9
9
 
@@ -1,7 +1,7 @@
1
1
  import { ref } from "@vue/reactivity";
2
2
  import { expect, it } from "vitest";
3
3
  import { Wrap } from "../../src/components/Wrap.jsx";
4
- import { printTree, renderTree } from "../../src/render.js";
4
+ import { printTree, renderTree } from "../../src/test-render.js";
5
5
  import "../../testing/extend-expect.js";
6
6
 
7
7
  function Wrapper(props: any) {
@@ -2,7 +2,7 @@ import "@alloy-js/core/testing";
2
2
  import { ref } from "@vue/reactivity";
3
3
  import { expect, it } from "vitest";
4
4
  import { Match, Switch } from "../../src/components/Switch.jsx";
5
- import { printTree, renderTree } from "../../src/render.js";
5
+ import { printTree, renderTree } from "../../src/test-render.js";
6
6
 
7
7
  it("selects the true branch", () => {
8
8
  const template = (
@@ -2,7 +2,7 @@ import "@alloy-js/core/testing";
2
2
  import { ref } from "@vue/reactivity";
3
3
  import { expect, it } from "vitest";
4
4
  import { Show } from "../../src/components/Show.jsx";
5
- import { printTree, renderTree } from "../../src/render.js";
5
+ import { printTree, renderTree } from "../../src/test-render.js";
6
6
 
7
7
  it("selects the true branch", () => {
8
8
  const template = <Show when={true}>true</Show>;
@@ -3,10 +3,10 @@ import { describe, expect, it } from "vitest";
3
3
  import { Show } from "../src/components/Show.jsx";
4
4
  import { createContentSlot } from "../src/content-slot.jsx";
5
5
  import { Context, ensureIsEmpty, getContext } from "../src/reactivity.js";
6
- import { printTree, renderTree } from "../src/render.js";
6
+ import { printTree, renderTree } from "../src/test-render.js";
7
7
  import "../testing/extend-expect.js";
8
8
 
9
- describe("lazy isEmpty / _lastEmpty", () => {
9
+ describe("lazy isEmpty", () => {
10
10
  it("context starts without isEmpty ref allocated", () => {
11
11
  let ctx: Context | null = null;
12
12
 
@@ -20,7 +20,7 @@ describe("lazy isEmpty / _lastEmpty", () => {
20
20
  // The isEmpty ref should NOT be allocated unless someone observes it.
21
21
  expect(ctx).not.toBeNull();
22
22
  expect(ctx!.isEmpty).toBeUndefined();
23
- expect(ctx!._lastEmpty).toBe(false);
23
+ expect(ctx!.childrenWithContent).toBe(1);
24
24
  });
25
25
 
26
26
  it("ensureIsEmpty lazily allocates the isEmpty ref", () => {
@@ -39,7 +39,7 @@ describe("lazy isEmpty / _lastEmpty", () => {
39
39
  expect(isEmptyRef).toBe(ctx!.isEmpty);
40
40
  });
41
41
 
42
- it("_lastEmpty is true for empty component, false for non-empty", () => {
42
+ it("tracks content count for empty and non-empty components", () => {
43
43
  let emptyCtx: Context | null = null;
44
44
  let fullCtx: Context | null = null;
45
45
 
@@ -60,8 +60,8 @@ describe("lazy isEmpty / _lastEmpty", () => {
60
60
  </>,
61
61
  );
62
62
 
63
- expect(emptyCtx!._lastEmpty).toBe(true);
64
- expect(fullCtx!._lastEmpty).toBe(false);
63
+ expect(emptyCtx!.childrenWithContent).toBe(0);
64
+ expect(fullCtx!.childrenWithContent).toBe(1);
65
65
  });
66
66
 
67
67
  it("ContentSlot triggers ensureIsEmpty and tracks reactively", () => {
@@ -0,0 +1,90 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ createElement,
4
+ createFragment,
5
+ createTextNode,
6
+ } from "../src/render/index.js";
7
+ import { textContent } from "./tree-test-utils.js";
8
+
9
+ describe("Node tree", () => {
10
+ it("append/prepend/before/after build linked list correctly", () => {
11
+ const root = createElement("group");
12
+ const b = createTextNode("B");
13
+ const c = createTextNode("C");
14
+ root.append(b, c);
15
+ const a = createTextNode("A");
16
+ root.prepend(a);
17
+ const d = createTextNode("D");
18
+ c.after(d);
19
+ const between = createTextNode("X");
20
+ c.before(between);
21
+
22
+ expect(textContent(root)).toBe("ABXCD");
23
+ expect(root.firstChild).toBe(a);
24
+ expect(root.lastChild).toBe(d);
25
+ expect(a.nextSibling).toBe(b);
26
+ expect(d.previousSibling).toBe(c);
27
+ });
28
+
29
+ it("replaceWith / remove maintain links", () => {
30
+ const root = createElement("group");
31
+ const a = createTextNode("A");
32
+ const b = createTextNode("B");
33
+ const c = createTextNode("C");
34
+ root.append(a, b, c);
35
+ const x = createTextNode("X");
36
+ const y = createTextNode("Y");
37
+ b.replaceWith(x, y);
38
+ expect(textContent(root)).toBe("AXYC");
39
+ expect(b.parentNode).toBeNull();
40
+ a.remove();
41
+ expect(textContent(root)).toBe("XYC");
42
+ expect(root.firstChild).toBe(x);
43
+ });
44
+
45
+ it("Fragment splices children on insert and self-empties", () => {
46
+ const root = createElement("group");
47
+ const f = createFragment();
48
+ f.append("hello", " ", "world");
49
+ expect(f.firstChild).not.toBeNull();
50
+ root.append(f);
51
+ expect(f.firstChild).toBeNull();
52
+ expect(f.parentNode).toBeNull();
53
+ expect(textContent(root)).toBe("hello world");
54
+ });
55
+
56
+ it("indent element preserves nested text in tree order", () => {
57
+ const root = createElement("group");
58
+ const indent = createElement("indent");
59
+ indent.append("first\nsecond\nthird");
60
+ root.append("top\n", indent);
61
+ expect(textContent(root)).toBe("top\nfirst\nsecond\nthird");
62
+ expect(root.lastChild).toBe(indent);
63
+ });
64
+
65
+ it("moveBefore atomically relocates without disconnecting subtree", () => {
66
+ const root = createElement("group");
67
+ const a = createElement("group");
68
+ const b = createElement("group");
69
+ a.append("A-content");
70
+ b.append("B-content");
71
+ root.append(a, b);
72
+ expect(textContent(root)).toBe("A-contentB-content");
73
+ // Move a after b.
74
+ root.moveBefore(a, null);
75
+ expect(textContent(root)).toBe("B-contentA-content");
76
+ // Subtree of `a` is untouched.
77
+ expect(a.firstChild).not.toBeNull();
78
+ });
79
+
80
+ it("moveBefore is a no-op when already at target position", () => {
81
+ const root = createElement("group");
82
+ const a = createTextNode("A");
83
+ const b = createTextNode("B");
84
+ root.append(a, b);
85
+ const aPrev = a.previousSibling;
86
+ root.moveBefore(a, b);
87
+ expect(a.previousSibling).toBe(aPrev);
88
+ expect(textContent(root)).toBe("AB");
89
+ });
90
+ });