@alloy-js/core 0.23.0-dev.12 → 0.23.0-dev.15

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 (521) hide show
  1. package/api-extractor.json +1 -8
  2. package/api-extractor.testing.json +19 -0
  3. package/dist/dev/src/binder.js +108 -1
  4. package/dist/dev/src/binder.js.map +1 -1
  5. package/dist/dev/src/components/Block.js +17 -5
  6. package/dist/dev/src/components/Block.js.map +1 -1
  7. package/dist/dev/src/components/List.js +1 -1
  8. package/dist/dev/src/components/List.js.map +1 -1
  9. package/dist/dev/src/components/MemberDeclaration.js +6 -6
  10. package/dist/dev/src/components/MemberName.js +7 -0
  11. package/dist/dev/src/components/MemberName.js.map +1 -1
  12. package/dist/dev/src/components/MemberScope.js +7 -2
  13. package/dist/dev/src/components/MemberScope.js.map +1 -1
  14. package/dist/dev/src/components/Output.js +4 -4
  15. package/dist/dev/src/components/Output.js.map +1 -1
  16. package/dist/dev/src/components/Scope.js +7 -1
  17. package/dist/dev/src/components/Scope.js.map +1 -1
  18. package/dist/dev/src/components/SourceFile.js +3 -3
  19. package/dist/dev/src/components/SourceFile.js.map +1 -1
  20. package/dist/dev/src/context/binder.js +5 -0
  21. package/dist/dev/src/context/binder.js.map +1 -1
  22. package/dist/dev/src/context/format-options.js +14 -1
  23. package/dist/dev/src/context/format-options.js.map +1 -1
  24. package/dist/dev/src/context/scope.js +5 -0
  25. package/dist/dev/src/context/scope.js.map +1 -1
  26. package/dist/dev/src/context/source-directory.js +9 -0
  27. package/dist/dev/src/context/source-directory.js.map +1 -1
  28. package/dist/dev/src/debug/cli.js +3 -2
  29. package/dist/dev/src/debug/cli.js.map +1 -1
  30. package/dist/dev/src/debug/source-map.browser.js +24 -0
  31. package/dist/dev/src/debug/source-map.browser.js.map +1 -0
  32. package/dist/dev/src/debug/trace.js +7 -6
  33. package/dist/dev/src/debug/trace.js.map +1 -1
  34. package/dist/dev/src/host/node-host.browser.js +21 -0
  35. package/dist/dev/src/host/node-host.browser.js.map +1 -0
  36. package/dist/dev/src/host/node-host.js +20 -0
  37. package/dist/dev/src/host/node-host.js.map +1 -0
  38. package/dist/dev/src/library-symbol-reference.js +54 -0
  39. package/dist/dev/src/library-symbol-reference.js.map +1 -1
  40. package/dist/dev/src/name-policy.js +27 -0
  41. package/dist/dev/src/name-policy.js.map +1 -1
  42. package/dist/dev/src/reactivity.js +16 -0
  43. package/dist/dev/src/reactivity.js.map +1 -1
  44. package/dist/dev/src/render-stack.js +4 -3
  45. package/dist/dev/src/render-stack.js.map +1 -1
  46. package/dist/dev/src/render.js.map +1 -1
  47. package/dist/dev/src/symbols/output-scope.js +34 -1
  48. package/dist/dev/src/symbols/output-scope.js.map +1 -1
  49. package/dist/dev/src/symbols/output-space.js +15 -0
  50. package/dist/dev/src/symbols/output-space.js.map +1 -1
  51. package/dist/dev/src/symbols/output-symbol.js +81 -11
  52. package/dist/dev/src/symbols/output-symbol.js.map +1 -1
  53. package/dist/dev/src/symbols/symbol-slot.js +7 -0
  54. package/dist/dev/src/symbols/symbol-slot.js.map +1 -1
  55. package/dist/dev/src/symbols/symbol-slot.test.js +27 -2
  56. package/dist/dev/src/symbols/symbol-slot.test.js.map +1 -1
  57. package/dist/dev/src/write-output.js +6 -5
  58. package/dist/dev/src/write-output.js.map +1 -1
  59. package/dist/dev/test/browser-build.test.js +67 -68
  60. package/dist/dev/test/browser-build.test.js.map +1 -1
  61. package/dist/dev/testing/create-test-wrapper.js +59 -5
  62. package/dist/dev/testing/create-test-wrapper.js.map +1 -1
  63. package/dist/dev/testing/extend-expect.js +20 -0
  64. package/dist/dev/testing/extend-expect.js.map +1 -1
  65. package/dist/dev/testing/index.js +1 -1
  66. package/dist/dev/testing/index.js.map +1 -1
  67. package/dist/dev/testing/render.js +11 -0
  68. package/dist/dev/testing/render.js.map +1 -1
  69. package/dist/src/binder.d.ts +107 -3
  70. package/dist/src/binder.d.ts.map +1 -1
  71. package/dist/src/binder.js +108 -1
  72. package/dist/src/binder.js.map +1 -1
  73. package/dist/src/components/Block.d.ts +12 -0
  74. package/dist/src/components/Block.d.ts.map +1 -1
  75. package/dist/src/components/Block.js +12 -0
  76. package/dist/src/components/Block.js.map +1 -1
  77. package/dist/src/components/List.d.ts +11 -1
  78. package/dist/src/components/List.d.ts.map +1 -1
  79. package/dist/src/components/List.js.map +1 -1
  80. package/dist/src/components/MemberDeclaration.d.ts +6 -6
  81. package/dist/src/components/MemberDeclaration.js +6 -6
  82. package/dist/src/components/MemberName.d.ts +6 -0
  83. package/dist/src/components/MemberName.d.ts.map +1 -1
  84. package/dist/src/components/MemberName.js +7 -0
  85. package/dist/src/components/MemberName.js.map +1 -1
  86. package/dist/src/components/MemberScope.d.ts +5 -0
  87. package/dist/src/components/MemberScope.d.ts.map +1 -1
  88. package/dist/src/components/MemberScope.js +5 -0
  89. package/dist/src/components/MemberScope.js.map +1 -1
  90. package/dist/src/components/Output.d.ts +4 -2
  91. package/dist/src/components/Output.d.ts.map +1 -1
  92. package/dist/src/components/Output.js.map +1 -1
  93. package/dist/src/components/Scope.d.ts +6 -0
  94. package/dist/src/components/Scope.d.ts.map +1 -1
  95. package/dist/src/components/Scope.js +6 -0
  96. package/dist/src/components/Scope.js.map +1 -1
  97. package/dist/src/components/SourceFile.d.ts +22 -2
  98. package/dist/src/components/SourceFile.d.ts.map +1 -1
  99. package/dist/src/components/SourceFile.js.map +1 -1
  100. package/dist/src/context/binder.d.ts +4 -0
  101. package/dist/src/context/binder.d.ts.map +1 -1
  102. package/dist/src/context/binder.js +5 -0
  103. package/dist/src/context/binder.js.map +1 -1
  104. package/dist/src/context/format-options.d.ts +14 -1
  105. package/dist/src/context/format-options.d.ts.map +1 -1
  106. package/dist/src/context/format-options.js +14 -1
  107. package/dist/src/context/format-options.js.map +1 -1
  108. package/dist/src/context/scope.d.ts +4 -0
  109. package/dist/src/context/scope.d.ts.map +1 -1
  110. package/dist/src/context/scope.js +5 -0
  111. package/dist/src/context/scope.js.map +1 -1
  112. package/dist/src/context/source-directory.d.ts +9 -0
  113. package/dist/src/context/source-directory.d.ts.map +1 -1
  114. package/dist/src/context/source-directory.js +9 -0
  115. package/dist/src/context/source-directory.js.map +1 -1
  116. package/dist/src/debug/cli.d.ts.map +1 -1
  117. package/dist/src/debug/cli.js +3 -2
  118. package/dist/src/debug/cli.js.map +1 -1
  119. package/dist/src/debug/source-map.browser.d.ts +16 -0
  120. package/dist/src/debug/source-map.browser.d.ts.map +1 -0
  121. package/dist/src/debug/source-map.browser.js +24 -0
  122. package/dist/src/debug/source-map.browser.js.map +1 -0
  123. package/dist/src/debug/trace.d.ts.map +1 -1
  124. package/dist/src/debug/trace.js +7 -6
  125. package/dist/src/debug/trace.js.map +1 -1
  126. package/dist/src/host/node-host.browser.d.ts +11 -0
  127. package/dist/src/host/node-host.browser.d.ts.map +1 -0
  128. package/dist/src/host/node-host.browser.js +21 -0
  129. package/dist/src/host/node-host.browser.js.map +1 -0
  130. package/dist/src/host/node-host.d.ts +11 -0
  131. package/dist/src/host/node-host.d.ts.map +1 -0
  132. package/dist/src/host/node-host.js +20 -0
  133. package/dist/src/host/node-host.js.map +1 -0
  134. package/dist/src/library-symbol-reference.d.ts +52 -0
  135. package/dist/src/library-symbol-reference.d.ts.map +1 -1
  136. package/dist/src/library-symbol-reference.js +54 -0
  137. package/dist/src/library-symbol-reference.js.map +1 -1
  138. package/dist/src/name-policy.d.ts +30 -3
  139. package/dist/src/name-policy.d.ts.map +1 -1
  140. package/dist/src/name-policy.js +27 -0
  141. package/dist/src/name-policy.js.map +1 -1
  142. package/dist/src/reactivity.d.ts +15 -0
  143. package/dist/src/reactivity.d.ts.map +1 -1
  144. package/dist/src/reactivity.js +16 -0
  145. package/dist/src/reactivity.js.map +1 -1
  146. package/dist/src/render-stack.d.ts.map +1 -1
  147. package/dist/src/render-stack.js +4 -3
  148. package/dist/src/render-stack.js.map +1 -1
  149. package/dist/src/render.d.ts +2 -0
  150. package/dist/src/render.d.ts.map +1 -1
  151. package/dist/src/render.js.map +1 -1
  152. package/dist/src/symbols/output-scope.d.ts +33 -1
  153. package/dist/src/symbols/output-scope.d.ts.map +1 -1
  154. package/dist/src/symbols/output-scope.js +34 -1
  155. package/dist/src/symbols/output-scope.js.map +1 -1
  156. package/dist/src/symbols/output-space.d.ts +12 -0
  157. package/dist/src/symbols/output-space.d.ts.map +1 -1
  158. package/dist/src/symbols/output-space.js +15 -0
  159. package/dist/src/symbols/output-space.js.map +1 -1
  160. package/dist/src/symbols/output-symbol.d.ts +93 -12
  161. package/dist/src/symbols/output-symbol.d.ts.map +1 -1
  162. package/dist/src/symbols/output-symbol.js +81 -11
  163. package/dist/src/symbols/output-symbol.js.map +1 -1
  164. package/dist/src/symbols/symbol-slot.d.ts.map +1 -1
  165. package/dist/src/symbols/symbol-slot.js +7 -0
  166. package/dist/src/symbols/symbol-slot.js.map +1 -1
  167. package/dist/src/symbols/symbol-slot.test.js +18 -1
  168. package/dist/src/symbols/symbol-slot.test.js.map +1 -1
  169. package/dist/src/write-output.d.ts.map +1 -1
  170. package/dist/src/write-output.js +6 -5
  171. package/dist/src/write-output.js.map +1 -1
  172. package/dist/test/browser-build.test.js +67 -68
  173. package/dist/test/browser-build.test.js.map +1 -1
  174. package/dist/testing/create-test-wrapper.d.ts +75 -2
  175. package/dist/testing/create-test-wrapper.d.ts.map +1 -1
  176. package/dist/testing/create-test-wrapper.js +55 -1
  177. package/dist/testing/create-test-wrapper.js.map +1 -1
  178. package/dist/testing/extend-expect.d.ts +26 -0
  179. package/dist/testing/extend-expect.d.ts.map +1 -1
  180. package/dist/testing/extend-expect.js +20 -0
  181. package/dist/testing/extend-expect.js.map +1 -1
  182. package/dist/testing/index.d.ts +1 -1
  183. package/dist/testing/index.d.ts.map +1 -1
  184. package/dist/testing/index.js +1 -1
  185. package/dist/testing/index.js.map +1 -1
  186. package/dist/testing/render.d.ts +9 -0
  187. package/dist/testing/render.d.ts.map +1 -1
  188. package/dist/testing/render.js +11 -0
  189. package/dist/testing/render.js.map +1 -1
  190. package/dist/tsconfig.tsbuildinfo +1 -1
  191. package/docs/api/components/AppendRegion.md +83 -0
  192. package/docs/api/components/Block.md +49 -0
  193. package/docs/api/components/CopyFile.md +26 -0
  194. package/docs/api/components/Declaration.md +85 -0
  195. package/docs/api/components/For.md +91 -0
  196. package/docs/api/components/Indent.md +40 -0
  197. package/docs/api/components/List.md +68 -0
  198. package/docs/api/components/MemberDeclaration.md +89 -0
  199. package/docs/api/components/MemberName.md +21 -0
  200. package/docs/api/components/MemberScope.md +81 -0
  201. package/docs/api/components/Name.md +19 -0
  202. package/docs/api/components/Output.md +62 -0
  203. package/docs/api/components/Prose.md +29 -0
  204. package/docs/api/components/ReferenceOrContent.md +28 -0
  205. package/docs/api/components/Scope.md +83 -0
  206. package/docs/api/components/Show.md +32 -0
  207. package/docs/api/components/SourceDirectory.md +28 -0
  208. package/docs/api/components/SourceFile.md +60 -0
  209. package/docs/api/components/StatementList.md +29 -0
  210. package/docs/api/components/Switch.md +42 -0
  211. package/docs/api/components/TemplateFile.md +71 -0
  212. package/docs/api/components/TemplateVariable.md +57 -0
  213. package/docs/api/components/UpdateFile.md +56 -0
  214. package/docs/api/components/Wrap.md +40 -0
  215. package/docs/api/components/createAccessExpression.md +55 -0
  216. package/docs/api/components/index.md +27 -0
  217. package/docs/api/contexts/Assignment-context.md +43 -0
  218. package/docs/api/contexts/Binder-context.md +22 -0
  219. package/docs/api/contexts/Declaration-context.md +15 -0
  220. package/docs/api/contexts/Member-context.md +17 -0
  221. package/docs/api/contexts/MemberDeclaration-context.md +24 -0
  222. package/docs/api/contexts/NamePolicy-context.md +18 -0
  223. package/docs/api/contexts/Scope-context.md +20 -0
  224. package/docs/api/contexts/SourceDirectory-context.md +26 -0
  225. package/docs/api/contexts/SourceFile-context.md +19 -0
  226. package/docs/api/contexts/index.md +11 -0
  227. package/docs/api/functions/attachDiagnosticsCollector.md +18 -0
  228. package/docs/api/functions/baseListPropsToMapJoinArgs.md +20 -0
  229. package/docs/api/functions/children.md +27 -0
  230. package/docs/api/functions/childrenArray.md +25 -0
  231. package/docs/api/functions/code.md +25 -0
  232. package/docs/api/functions/computed.md +18 -0
  233. package/docs/api/functions/createComponent.md +20 -0
  234. package/docs/api/functions/createContentSlot.md +33 -0
  235. package/docs/api/functions/createContext.md +19 -0
  236. package/docs/api/functions/createCustomContext.md +18 -0
  237. package/docs/api/functions/createDeclarationTap.md +20 -0
  238. package/docs/api/functions/createFileResource.md +35 -0
  239. package/docs/api/functions/createFormatOptionsContextFor.md +28 -0
  240. package/docs/api/functions/createIntrinsic.md +19 -0
  241. package/docs/api/functions/createMemberTap.md +20 -0
  242. package/docs/api/functions/createNamePolicy.md +37 -0
  243. package/docs/api/functions/createNamedContext.md +19 -0
  244. package/docs/api/functions/createOutputBinder.md +24 -0
  245. package/docs/api/functions/createRenderTreeHook.md +19 -0
  246. package/docs/api/functions/createResource.md +77 -0
  247. package/docs/api/functions/createScope.md +35 -0
  248. package/docs/api/functions/createScopeTap.md +20 -0
  249. package/docs/api/functions/createSourceFileTap.md +20 -0
  250. package/docs/api/functions/createSymbol.md +25 -0
  251. package/docs/api/functions/createSymbolSlot.md +19 -0
  252. package/docs/api/functions/createTap.md +55 -0
  253. package/docs/api/functions/decl.md +20 -0
  254. package/docs/api/functions/defaultProps.md +21 -0
  255. package/docs/api/functions/effect.md +26 -0
  256. package/docs/api/functions/emitDiagnostic.md +18 -0
  257. package/docs/api/functions/emitSymbol.md +18 -0
  258. package/docs/api/functions/ensureIsEmpty.md +20 -0
  259. package/docs/api/functions/findCurrentEffectId.md +19 -0
  260. package/docs/api/functions/findKeyedChild.md +19 -0
  261. package/docs/api/functions/findKeyedChildren.md +19 -0
  262. package/docs/api/functions/findUnkeyedChildren.md +18 -0
  263. package/docs/api/functions/formatReactivePropertyLabel.md +21 -0
  264. package/docs/api/functions/getAssignmentSymbol.md +19 -0
  265. package/docs/api/functions/getContext.md +17 -0
  266. package/docs/api/functions/getContextForRenderNode.md +18 -0
  267. package/docs/api/functions/getDiagnosticsForTree.md +18 -0
  268. package/docs/api/functions/getEffectDebugId.md +18 -0
  269. package/docs/api/functions/getElementCache.md +17 -0
  270. package/docs/api/functions/getReactiveCreationLocation.md +18 -0
  271. package/docs/api/functions/getSymbolCreator.md +18 -0
  272. package/docs/api/functions/getSymbolCreatorSymbol.md +17 -0
  273. package/docs/api/functions/index.md +105 -0
  274. package/docs/api/functions/inspectRefkey.md +18 -0
  275. package/docs/api/functions/instantiateTakenMembersTo.md +20 -0
  276. package/docs/api/functions/isComponentCreator.md +19 -0
  277. package/docs/api/functions/isCustomContext.md +18 -0
  278. package/docs/api/functions/isIntrinsicElement.md +18 -0
  279. package/docs/api/functions/isKeyedChild.md +18 -0
  280. package/docs/api/functions/isLibrarySymbolReference.md +18 -0
  281. package/docs/api/functions/isMemberRefkey.md +18 -0
  282. package/docs/api/functions/isNamekey.md +18 -0
  283. package/docs/api/functions/isPrintHook.md +18 -0
  284. package/docs/api/functions/isRefkey.md +18 -0
  285. package/docs/api/functions/isRefkeyable.md +18 -0
  286. package/docs/api/functions/isRenderableObject.md +20 -0
  287. package/docs/api/functions/isSymbolRefkey.md +18 -0
  288. package/docs/api/functions/join.md +33 -0
  289. package/docs/api/functions/mapJoin.md +106 -0
  290. package/docs/api/functions/memberRefkey.md +27 -0
  291. package/docs/api/functions/memo.md +29 -0
  292. package/docs/api/functions/mergeProps.md +64 -0
  293. package/docs/api/functions/moveTakenMembersTo.md +18 -0
  294. package/docs/api/functions/namekey.md +41 -0
  295. package/docs/api/functions/nextReactiveId.md +19 -0
  296. package/docs/api/functions/notifyContentState.md +17 -0
  297. package/docs/api/functions/onCleanup.md +26 -0
  298. package/docs/api/functions/printTree.md +31 -0
  299. package/docs/api/functions/reactivePropertyRefId.md +21 -0
  300. package/docs/api/functions/ref.md +21 -0
  301. package/docs/api/functions/refId.md +18 -0
  302. package/docs/api/functions/refkey.md +24 -0
  303. package/docs/api/functions/render.md +31 -0
  304. package/docs/api/functions/renderAsync.md +31 -0
  305. package/docs/api/functions/renderTree.md +18 -0
  306. package/docs/api/functions/reportDiagnostics.md +18 -0
  307. package/docs/api/functions/resetRefIdCounter.md +17 -0
  308. package/docs/api/functions/resolve.md +31 -0
  309. package/docs/api/functions/root.md +25 -0
  310. package/docs/api/functions/shallowReactive.md +18 -0
  311. package/docs/api/functions/shallowRef.md +21 -0
  312. package/docs/api/functions/sourceFilesForTree.md +31 -0
  313. package/docs/api/functions/splitProps.md +19 -0
  314. package/docs/api/functions/stc.md +18 -0
  315. package/docs/api/functions/sti.md +18 -0
  316. package/docs/api/functions/symbolForRefkey.md +24 -0
  317. package/docs/api/functions/taggedComponent.md +19 -0
  318. package/docs/api/functions/takeSymbols.md +18 -0
  319. package/docs/api/functions/text.md +19 -0
  320. package/docs/api/functions/toRef.md +20 -0
  321. package/docs/api/functions/toRefkey.md +18 -0
  322. package/docs/api/functions/toRefs.md +20 -0
  323. package/docs/api/functions/traverseOutput.md +21 -0
  324. package/docs/api/functions/unresolvedRefkey.md +18 -0
  325. package/docs/api/functions/untrack.md +18 -0
  326. package/docs/api/functions/useContext.md +18 -0
  327. package/docs/api/functions/useFormatOptions.md +18 -0
  328. package/docs/api/functions/useMemberContext.md +17 -0
  329. package/docs/api/functions/useMemberScope.md +17 -0
  330. package/docs/api/functions/writeOutput.md +21 -0
  331. package/docs/api/index.md +9 -0
  332. package/docs/api/testing/functions/createTestWrapper.md +70 -0
  333. package/docs/api/testing/functions/d.md +21 -0
  334. package/docs/api/testing/functions/dedent.md +18 -0
  335. package/docs/api/testing/functions/index.md +6 -0
  336. package/docs/api/testing/functions/renderToString.md +20 -0
  337. package/docs/api/testing/index.md +4 -0
  338. package/docs/api/testing/types/TestWrapper.md +10 -0
  339. package/docs/api/testing/types/ToRenderToOptions.md +24 -0
  340. package/docs/api/testing/types/index.md +4 -0
  341. package/docs/api/types/AlignIntrinsicElement.md +5 -0
  342. package/docs/api/types/AppendRegionProps.md +5 -0
  343. package/docs/api/types/BaseListProps.md +21 -0
  344. package/docs/api/types/BasePartProps.md +10 -0
  345. package/docs/api/types/BasicScope.md +15 -0
  346. package/docs/api/types/BasicSymbol.md +18 -0
  347. package/docs/api/types/Binder.md +18 -0
  348. package/docs/api/types/BinderOptions.md +7 -0
  349. package/docs/api/types/BrIntrinsicElement.md +5 -0
  350. package/docs/api/types/BreakParentIntrinsicElement.md +5 -0
  351. package/docs/api/types/Child.md +5 -0
  352. package/docs/api/types/Children.md +5 -0
  353. package/docs/api/types/ChildrenOptions.md +7 -0
  354. package/docs/api/types/CommonFormatOptions.md +8 -0
  355. package/docs/api/types/Component.md +8 -0
  356. package/docs/api/types/ComponentContext.md +11 -0
  357. package/docs/api/types/ComponentCreator.md +11 -0
  358. package/docs/api/types/ComponentDefinition.md +7 -0
  359. package/docs/api/types/ContentOutputFile.md +10 -0
  360. package/docs/api/types/ContentSlot.md +12 -0
  361. package/docs/api/types/Context.md +19 -0
  362. package/docs/api/types/ContextProviderProps.md +8 -0
  363. package/docs/api/types/CopyFileContext.md +8 -0
  364. package/docs/api/types/CopyOutputFile.md +9 -0
  365. package/docs/api/types/CustomContext.md +10 -0
  366. package/docs/api/types/CustomContextChildrenCallback.md +5 -0
  367. package/docs/api/types/DeclarationProps.md +5 -0
  368. package/docs/api/types/DedentIntrinsicElement.md +5 -0
  369. package/docs/api/types/DedentToRootIntrinsicElement.md +5 -0
  370. package/docs/api/types/Diagnostic.md +11 -0
  371. package/docs/api/types/DiagnosticHandle.md +7 -0
  372. package/docs/api/types/DiagnosticInput.md +10 -0
  373. package/docs/api/types/DiagnosticSeverity.md +5 -0
  374. package/docs/api/types/DiagnosticStackEntry.md +9 -0
  375. package/docs/api/types/DiagnosticsCollector.md +8 -0
  376. package/docs/api/types/Disposable_2.md +7 -0
  377. package/docs/api/types/EffectDebugOptions.md +8 -0
  378. package/docs/api/types/EffectOptions.md +7 -0
  379. package/docs/api/types/ElementCache.md +5 -0
  380. package/docs/api/types/ElementCacheKey.md +5 -0
  381. package/docs/api/types/FillIntrinsicElement.md +5 -0
  382. package/docs/api/types/ForCallbackArgs.md +5 -0
  383. package/docs/api/types/ForSupportedCollections.md +5 -0
  384. package/docs/api/types/GroupIntrinsicElement.md +5 -0
  385. package/docs/api/types/HardlineIntrinsicElement.md +5 -0
  386. package/docs/api/types/HbrIntrinsicElement.md +5 -0
  387. package/docs/api/types/IfBreakIntrinsicElement.md +5 -0
  388. package/docs/api/types/IndentIfBreakIntrinsicElement.md +5 -0
  389. package/docs/api/types/IndentIntrinsicElement.md +5 -0
  390. package/docs/api/types/IntrinsicElement.md +5 -0
  391. package/docs/api/types/IntrinsicElementBase.md +9 -0
  392. package/docs/api/types/IntrinsicElements.md +26 -0
  393. package/docs/api/types/JoinOptions.md +9 -0
  394. package/docs/api/types/LbrIntrinsicElement.md +5 -0
  395. package/docs/api/types/LibrarySymbolReference.md +13 -0
  396. package/docs/api/types/LineIntrinsicElement.md +5 -0
  397. package/docs/api/types/LineSuffixBoundaryIntrinsicElement.md +5 -0
  398. package/docs/api/types/LineSuffixIntrinsicElement.md +5 -0
  399. package/docs/api/types/LiterallineIntrinsicElement.md +5 -0
  400. package/docs/api/types/MakeChildrenOptional.md +7 -0
  401. package/docs/api/types/MarkAsRootIntrinsicElement.md +5 -0
  402. package/docs/api/types/MatchProps.md +9 -0
  403. package/docs/api/types/MemberDeclarationProps.md +5 -0
  404. package/docs/api/types/MemberDescriptor.md +10 -0
  405. package/docs/api/types/MemberRefkey.md +10 -0
  406. package/docs/api/types/MemberResolutionContext.md +10 -0
  407. package/docs/api/types/MemberResolver.md +32 -0
  408. package/docs/api/types/MemberScopeProps.md +5 -0
  409. package/docs/api/types/Metadata.md +5 -0
  410. package/docs/api/types/NameConflictResolver.md +27 -0
  411. package/docs/api/types/NamePolicy.md +8 -0
  412. package/docs/api/types/NamePolicyGetter.md +9 -0
  413. package/docs/api/types/Namekey.md +10 -0
  414. package/docs/api/types/NamekeyOptions.md +8 -0
  415. package/docs/api/types/OnReactiveSetAddCallback.md +5 -0
  416. package/docs/api/types/OnReactiveSetDeleteCallback.md +5 -0
  417. package/docs/api/types/OutputDeclarationSpace.md +13 -0
  418. package/docs/api/types/OutputDirectory.md +59 -0
  419. package/docs/api/types/OutputFile.md +5 -0
  420. package/docs/api/types/OutputFileBase.md +8 -0
  421. package/docs/api/types/OutputMemberSpace.md +13 -0
  422. package/docs/api/types/OutputScope.md +33 -0
  423. package/docs/api/types/OutputScopeOptions.md +9 -0
  424. package/docs/api/types/OutputSpace.md +7 -0
  425. package/docs/api/types/OutputSymbol.md +76 -0
  426. package/docs/api/types/OutputSymbolOptions.md +16 -0
  427. package/docs/api/types/OutputVisitor.md +10 -0
  428. package/docs/api/types/PrintHook.md +10 -0
  429. package/docs/api/types/PrintTreeOptions.md +11 -0
  430. package/docs/api/types/Props.md +5 -0
  431. package/docs/api/types/ReactiveUnionSet.md +20 -0
  432. package/docs/api/types/ReactiveUnionSetOptions.md +8 -0
  433. package/docs/api/types/Refkey.md +5 -0
  434. package/docs/api/types/Refkeyable.md +5 -0
  435. package/docs/api/types/RefkeyableObject.md +7 -0
  436. package/docs/api/types/RenderableObject.md +9 -0
  437. package/docs/api/types/RenderedTextTree.md +5 -0
  438. package/docs/api/types/ResolutionResult.md +39 -0
  439. package/docs/api/types/ResolveDeclarationByKeyOptions.md +7 -0
  440. package/docs/api/types/Resource.md +11 -0
  441. package/docs/api/types/RootOptions.md +7 -0
  442. package/docs/api/types/SbrIntrinsicElement.md +5 -0
  443. package/docs/api/types/ScopeProps.md +5 -0
  444. package/docs/api/types/SoftlineIntrinsicElement.md +5 -0
  445. package/docs/api/types/SourceLocation.md +9 -0
  446. package/docs/api/types/SplitProps.md +12 -0
  447. package/docs/api/types/StcComponentCreator.md +9 -0
  448. package/docs/api/types/StcSignature.md +5 -0
  449. package/docs/api/types/StiComponentCreator.md +9 -0
  450. package/docs/api/types/StiSignature.md +7 -0
  451. package/docs/api/types/SymbolCreator.md +15 -0
  452. package/docs/api/types/SymbolRefkey.md +9 -0
  453. package/docs/api/types/SymbolSlot.md +12 -0
  454. package/docs/api/types/SymbolTable.md +15 -0
  455. package/docs/api/types/TakeSymbolCallback.md +7 -0
  456. package/docs/api/types/TakeSymbolsCallback.md +7 -0
  457. package/docs/api/types/Tap.md +11 -0
  458. package/docs/api/types/TapHandler.md +9 -0
  459. package/docs/api/types/Tapper.md +9 -0
  460. package/docs/api/types/TemplateVariableProps.md +5 -0
  461. package/docs/api/types/index.md +122 -0
  462. package/docs/api/variables/FormatOptions.md +5 -0
  463. package/docs/api/variables/Match.md +7 -0
  464. package/docs/api/variables/REFKEYABLE.md +5 -0
  465. package/docs/api/variables/RENDERABLE.md +5 -0
  466. package/docs/api/variables/TO_SYMBOL.md +39 -0
  467. package/docs/api/variables/contextsByKey.md +5 -0
  468. package/docs/api/variables/index.md +11 -0
  469. package/docs/api/variables/intrinsicElementKey.md +5 -0
  470. package/docs/api/variables/matchTag.md +5 -0
  471. package/docs/api/variables/printHookTag.md +7 -0
  472. package/docs/components.md +97 -0
  473. package/docs/context.md +67 -0
  474. package/docs/control-flow.md +5 -0
  475. package/docs/debugging.md +105 -0
  476. package/docs/formatting.md +99 -0
  477. package/docs/guides/language-package-guide.md +593 -0
  478. package/docs/guides/references-and-refkeys.md +210 -0
  479. package/docs/guides/style-guide.md +244 -0
  480. package/docs/index.md +22 -0
  481. package/docs/reactivity.md +68 -0
  482. package/docs/rendering.md +41 -0
  483. package/docs/symbols-and-scopes.md +180 -0
  484. package/package.json +8 -4
  485. package/src/binder.ts +107 -3
  486. package/src/components/Block.tsx +12 -0
  487. package/src/components/List.tsx +11 -1
  488. package/src/components/MemberDeclaration.tsx +6 -6
  489. package/src/components/MemberName.tsx +6 -0
  490. package/src/components/MemberScope.tsx +5 -0
  491. package/src/components/Output.tsx +4 -1
  492. package/src/components/Scope.tsx +6 -0
  493. package/src/components/SourceFile.tsx +22 -2
  494. package/src/context/binder.ts +4 -0
  495. package/src/context/format-options.ts +14 -1
  496. package/src/context/scope.ts +4 -0
  497. package/src/context/source-directory.ts +9 -0
  498. package/src/debug/cli.ts +3 -2
  499. package/src/debug/source-map.browser.ts +30 -0
  500. package/src/debug/trace.ts +7 -6
  501. package/src/host/node-host.browser.ts +23 -0
  502. package/src/host/node-host.ts +22 -0
  503. package/src/library-symbol-reference.ts +52 -0
  504. package/src/name-policy.ts +30 -3
  505. package/src/reactivity.ts +15 -0
  506. package/src/render-stack.ts +4 -3
  507. package/src/render.ts +2 -0
  508. package/src/symbols/output-scope.ts +33 -1
  509. package/src/symbols/output-space.ts +13 -0
  510. package/src/symbols/output-symbol.ts +93 -12
  511. package/src/symbols/symbol-slot.test.tsx +28 -1
  512. package/src/symbols/symbol-slot.tsx +8 -0
  513. package/src/write-output.ts +6 -5
  514. package/temp/api-testing.json +673 -0
  515. package/temp/api.json +48 -47
  516. package/test/browser-build.test.ts +71 -78
  517. package/testing/create-test-wrapper.tsx +81 -2
  518. package/testing/extend-expect.ts +22 -1
  519. package/testing/index.ts +1 -1
  520. package/testing/render.ts +9 -0
  521. package/testing/vitest.d.ts +3 -8
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import type { ServerToClientMessage } from "../devtools/devtools-protocol.js";
5
5
  import { isDevtoolsEnabled } from "../devtools/devtools-server.js";
6
+ import { env, sourceMapsEnabled } from "../host/node-host.js";
6
7
  import { untrack } from "../reactivity.js";
7
8
  import { initTrace, isTraceEnabled } from "./trace-writer.js";
8
9
 
@@ -21,12 +22,12 @@ export function isDebugEnabled(): boolean {
21
22
  // Environment configuration
22
23
  // ─────────────────────────────────────────────────────────────────────────────
23
24
 
24
- const traceEnv = process.env.ALLOY_TRACE ?? "";
25
+ const traceEnv = env("ALLOY_TRACE") ?? "";
25
26
  const tracePhases = new Set<string>(
26
27
  traceEnv === "" ? [] : traceEnv.split(",").map((t) => t.trim()),
27
28
  );
28
29
 
29
- const debuggerIdsEnv = process.env.ALLOY_BREAK_ON_DID ?? "";
30
+ const debuggerIdsEnv = env("ALLOY_BREAK_ON_DID") ?? "";
30
31
  const debuggerIds = new Set<number>();
31
32
  debuggerIdsEnv.split(",").forEach((id) => {
32
33
  const num = parseInt(id, 10);
@@ -37,9 +38,9 @@ debuggerIdsEnv.split(",").forEach((id) => {
37
38
 
38
39
  /** Parse the ALLOY_BREAK_ON_DID environment variable into a set of IDs. */
39
40
  export function parseBreakOnIds(): Set<number> {
40
- const env = process.env.ALLOY_BREAK_ON_DID ?? "";
41
+ const raw = env("ALLOY_BREAK_ON_DID") ?? "";
41
42
  const ids = new Set<number>();
42
- env.split(",").forEach((id) => {
43
+ raw.split(",").forEach((id) => {
43
44
  const num = parseInt(id, 10);
44
45
  if (!isNaN(num)) {
45
46
  ids.add(num);
@@ -65,7 +66,7 @@ if (tracePhases.size > 0) {
65
66
  }
66
67
 
67
68
  // Initialize SQLite trace writer if ALLOY_DEBUG_TRACE is set
68
- const traceDbEnv = process.env.ALLOY_DEBUG_TRACE;
69
+ const traceDbEnv = env("ALLOY_DEBUG_TRACE");
69
70
  if (traceDbEnv) {
70
71
  const traceDbPath =
71
72
  traceDbEnv === "1" || traceDbEnv === "true" ? "alloy-trace.db" : traceDbEnv;
@@ -82,7 +83,7 @@ if (traceDbEnv) {
82
83
  if (import.meta.url.includes("/dist/dev/")) {
83
84
  // eslint-disable-next-line no-console
84
85
  console.log("Alloy debug build loaded.");
85
- if (process.sourceMapsEnabled) {
86
+ if (sourceMapsEnabled()) {
86
87
  // eslint-disable-next-line no-console
87
88
  console.log(" Source maps enabled.");
88
89
  } else {
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Browser stub for Node.js host APIs.
3
+ *
4
+ * Replaces `node-host.ts` in browser builds so that no Node.js globals
5
+ * (`process`, etc.) are referenced.
6
+ */
7
+
8
+ export function env(_key: string): string | undefined {
9
+ return undefined;
10
+ }
11
+
12
+ export function cwd(): string {
13
+ return "";
14
+ }
15
+
16
+ export function stdoutWrite(text: string): void {
17
+ // eslint-disable-next-line no-console
18
+ console.log(text);
19
+ }
20
+
21
+ export function sourceMapsEnabled(): boolean {
22
+ return false;
23
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Node.js host APIs.
3
+ *
4
+ * Provides access to Node.js-specific process APIs. In browser builds this
5
+ * module is replaced by `node-host.browser.ts` which returns safe defaults.
6
+ */
7
+
8
+ export function env(key: string): string | undefined {
9
+ return process.env[key];
10
+ }
11
+
12
+ export function cwd(): string {
13
+ return process.cwd();
14
+ }
15
+
16
+ export function stdoutWrite(text: string): void {
17
+ process.stdout.write(text);
18
+ }
19
+
20
+ export function sourceMapsEnabled(): boolean {
21
+ return !!(process as any).sourceMapsEnabled;
22
+ }
@@ -1,10 +1,62 @@
1
1
  import { RefkeyableObject } from "./refkey.js";
2
2
  import { OutputSymbol } from "./symbols/output-symbol.js";
3
3
 
4
+ /**
5
+ * Well-known symbol for the lazy-symbol-creation protocol used by external
6
+ * library descriptors. Objects implementing `[TO_SYMBOL]()` are recognized as
7
+ * {@link LibrarySymbolReference} values that can be passed anywhere a refkey
8
+ * is accepted.
9
+ *
10
+ * @remarks
11
+ *
12
+ * Implement `[TO_SYMBOL]()` on a descriptor object to register it as a
13
+ * referenceable library symbol. Inside the method:
14
+ *
15
+ * 1. Call {@link useBinder} to get the current binder context.
16
+ * 2. Look up (or create) the symbol for that binder in a
17
+ * `WeakMap<object, OutputSymbol>` (use a sentinel object for the
18
+ * no-binder case, since `WeakMap` keys must be objects).
19
+ * 3. On first creation, construct the symbol and register it into the
20
+ * appropriate space for your library, passing `{ binder }`
21
+ * (see {@link OutputSymbolOptions.binder}).
22
+ *
23
+ * The method is called by language package code each time the descriptor is
24
+ * used as a reference (e.g. inside `ref()`). It is NOT called by the binder
25
+ * itself.
26
+ *
27
+ * @example
28
+ *
29
+ * ```ts
30
+ * const defaultKey = {};
31
+ * const symbols = new WeakMap<object, MySymbol>();
32
+ * const descriptor: LibrarySymbolReference = {
33
+ * [REFKEYABLE]() {
34
+ * return descriptor[TO_SYMBOL]().refkeys[0];
35
+ * },
36
+ * [TO_SYMBOL]() {
37
+ * const binder = useBinder();
38
+ * const key = binder ?? defaultKey;
39
+ * let sym = symbols.get(key);
40
+ * if (!sym) {
41
+ * sym = new MySymbol("SomeType", space, { binder });
42
+ * symbols.set(key, sym);
43
+ * }
44
+ * return sym;
45
+ * },
46
+ * };
47
+ * ```
48
+ */
4
49
  export const TO_SYMBOL: unique symbol = Symbol(
5
50
  "Alloy.RefkeyableObject.TO_SYMBOL",
6
51
  );
7
52
 
53
+ /**
54
+ * An object that acts as a lazy reference to an external library symbol.
55
+ * Implements {@link REFKEYABLE} and `[TO_SYMBOL]()`.
56
+ *
57
+ * Use {@link isLibrarySymbolReference} to test whether an unknown value is a
58
+ * library symbol reference.
59
+ */
8
60
  export interface LibrarySymbolReference extends RefkeyableObject {
9
61
  [TO_SYMBOL](): OutputSymbol;
10
62
  }
@@ -1,20 +1,47 @@
1
+ /**
2
+ * A function that transforms a name according to a naming policy for a
3
+ * specific element kind. Obtained from {@link NamePolicy.for}.
4
+ */
1
5
  export interface NamePolicyGetter {
2
6
  (originalName: string): string;
3
7
  }
4
8
  export interface NamePolicy<TElements extends string> {
5
9
  /**
6
- * Apply the language policy to the provided name for the provided element
7
- * type.
10
+ * Apply the language policy to the provided name for the provided element type.
11
+ * When `element` is `undefined`, returns `originalName` unchanged.
8
12
  */
9
13
  getName(originalName: string, element: TElements | undefined): string;
10
14
  /**
11
15
  * Get a function that takes a name and applies the naming policy to it.
16
+ * When `element` is `undefined`, returns an identity function.
12
17
  */
13
18
  for(element: TElements | undefined): NamePolicyGetter;
14
19
  }
15
20
 
21
+ /**
22
+ * Creates a name policy that transforms symbol names based on element kind.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const policy = createNamePolicy((name, element) => {
27
+ * if (element === "value") return toCamelCase(name);
28
+ * if (element === "type") return toPascalCase(name);
29
+ * return name;
30
+ * });
31
+ * <Output namePolicy={policy}>...</Output>
32
+ * ```
33
+ *
34
+ * @remarks
35
+ * `element` identifies the kind of declaration (e.g., `"value"`, `"type"`).
36
+ * The set of valid element strings is defined by the language package.
37
+ *
38
+ * When `element` is `undefined` (outside a declaration context), {@link NamePolicy.getName}
39
+ * and {@link NamePolicy.for} short-circuit and return the original name unchanged — the
40
+ * namer callback is **not** invoked. The namer therefore always receives a defined `T`.
41
+ * This means names outside a declaration context cannot be transformed by the policy.
42
+ */
16
43
  export function createNamePolicy<T extends string>(
17
- namer: (name: string, elements: T) => string,
44
+ namer: (name: string, element: T) => string,
18
45
  ): NamePolicy<T> {
19
46
  const forCache = new Map<string, NamePolicyGetter>();
20
47
  const noopGetter = (name: string) => name;
package/src/reactivity.ts CHANGED
@@ -200,6 +200,21 @@ export function findCurrentEffectId(): number | undefined {
200
200
  return undefined;
201
201
  }
202
202
 
203
+ /**
204
+ * Returns a getter caching the result of `fn`. Re-evaluates when reactive
205
+ * dependencies change. See the [Reactivity docs](../../reactivity.md) for details.
206
+ *
207
+ * @param fn - Function to memoize.
208
+ * @param equal - Skip updates when value is unchanged.
209
+ * @param name - Debug label for traces.
210
+ * @returns A zero-argument getter returning the cached value.
211
+ *
212
+ * @example
213
+ * ```ts
214
+ * const fullName = memo(() => `${first.value} ${last.value}`);
215
+ * fullName(); // cached; re-evaluates when first or last changes
216
+ * ```
217
+ */
203
218
  export function memo<T>(fn: () => T, equal?: boolean, name?: string): () => T {
204
219
  const memoLabel = name ? `memo:${name}` : "memo";
205
220
  const o = shallowRef<T>(undefined as T, {
@@ -2,6 +2,7 @@ import pc from "picocolors";
2
2
  import { contextsByKey } from "./context.js";
3
3
  import { SourceDirectoryContext } from "./context/source-directory.js";
4
4
  import { SourceFileContext } from "./context/source-file.js";
5
+ import { cwd } from "./host/node-host.js";
5
6
  import { Context, getContext } from "./reactivity.js";
6
7
  import { Component, Props, SourceLocation } from "./runtime/component.js";
7
8
 
@@ -125,12 +126,12 @@ function formatValue(value: unknown): string {
125
126
  }
126
127
 
127
128
  function formatSourceLocation(source: SourceLocation): string {
128
- const cwd = process.cwd();
129
+ const currentCwd = cwd();
129
130
  let filePath = source.fileName;
130
131
 
131
132
  // Convert to relative path if under cwd
132
- if (filePath.startsWith(cwd)) {
133
- filePath = filePath.slice(cwd.length + 1); // +1 to remove leading slash
133
+ if (currentCwd && filePath.startsWith(currentCwd)) {
134
+ filePath = filePath.slice(currentCwd.length + 1); // +1 to remove leading slash
134
135
  }
135
136
 
136
137
  return `${filePath}:${source.lineNumber}:${source.columnNumber}`;
package/src/render.ts CHANGED
@@ -282,12 +282,14 @@ const {
282
282
 
283
283
  export interface OutputDirectory {
284
284
  kind: "directory";
285
+ /** Full path from the output root, e.g. `"generated-client/src"`. Do not prepend parent directory paths when walking the tree. */
285
286
  path: string;
286
287
  contents: (OutputDirectory | OutputFile)[];
287
288
  }
288
289
 
289
290
  export interface OutputFileBase {
290
291
  kind: "file";
292
+ /** Full path from the output root, e.g. `"generated-client/src/models.ext"`. Do not prepend parent directory paths when walking the tree. */
291
293
  path: string;
292
294
  }
293
295
 
@@ -54,6 +54,11 @@ export interface OutputScopeOptions {
54
54
  * within a reactive context.
55
55
  */
56
56
  export abstract class OutputScope {
57
+ /**
58
+ * The declaration space keys for this scope type. Subclasses override this
59
+ * to declare which declaration spaces are created on construction (e.g.,
60
+ * `["types", "values"]`).
61
+ */
57
62
  static readonly declarationSpaces: Readonly<string[]> = [] as const;
58
63
 
59
64
  #name: string;
@@ -125,7 +130,8 @@ export abstract class OutputScope {
125
130
  #spaces: Record<string, OutputDeclarationSpace>;
126
131
 
127
132
  /**
128
- * Get the declaration space for the given key.
133
+ * Get the declaration space for the given key (e.g., `"types"`, `"values"`).
134
+ * Returns `undefined` when no space with that key exists on this scope.
129
135
  */
130
136
  spaceFor(key: string): OutputSpace | undefined {
131
137
  return this.#spaces[key];
@@ -153,6 +159,32 @@ export abstract class OutputScope {
153
159
 
154
160
  [ReactiveFlags.SKIP] = true;
155
161
 
162
+ /**
163
+ * Subclasses must forward all three positional arguments to `super`. See
164
+ * {@link createScope} for the preferred instantiation path.
165
+ *
166
+ * @param name - A descriptive name for this scope (used in debugging and
167
+ * diagnostics).
168
+ * @param parentScope - The parent scope in the scope tree, or `undefined`
169
+ * for root scopes. Inside a component, obtain this via `useScope()`.
170
+ * @param options - Additional scope options; see {@link OutputScopeOptions}.
171
+ *
172
+ * @example
173
+ * ```ts
174
+ * class MyScope extends OutputScope {
175
+ * constructor(
176
+ * name: string,
177
+ * parent: OutputScope | undefined,
178
+ * options?: OutputScopeOptions,
179
+ * ) {
180
+ * super(name, parent, options);
181
+ * }
182
+ * }
183
+ *
184
+ * // Inside a component:
185
+ * const scope = createScope(MyScope, "my-scope", useScope());
186
+ * ```
187
+ */
156
188
  constructor(
157
189
  name: string,
158
190
  parentScope: OutputScope | undefined,
@@ -5,7 +5,16 @@ import { OutputScope } from "./output-scope.js";
5
5
  import { OutputSymbol } from "./output-symbol.js";
6
6
  import { SymbolTable } from "./symbol-table.js";
7
7
 
8
+ /**
9
+ * A symbol table that belongs to either a scope (declaration space) or a symbol
10
+ * (member space).
11
+ */
8
12
  export type OutputSpace = OutputDeclarationSpace | OutputMemberSpace;
13
+
14
+ /**
15
+ * A symbol table attached to an {@link OutputScope}. Holds lexical declarations
16
+ * visible within that scope (e.g., "types" or "values" in a TypeScript module).
17
+ */
9
18
  export class OutputDeclarationSpace extends SymbolTable {
10
19
  constructor(scope: OutputScope, key: string, binder?: Binder) {
11
20
  super(key, binder);
@@ -27,6 +36,10 @@ export class OutputDeclarationSpace extends SymbolTable {
27
36
  }
28
37
  }
29
38
 
39
+ /**
40
+ * A symbol table attached to an {@link OutputSymbol}. Holds member declarations
41
+ * belonging to that symbol (e.g., "static" or "instance" members of a class).
42
+ */
30
43
  export class OutputMemberSpace extends SymbolTable {
31
44
  constructor(symbol: OutputSymbol, key: string, binder?: Binder) {
32
45
  super(key, binder);
@@ -37,6 +37,12 @@ export interface OutputSymbolOptions {
37
37
  * will be reported to this binder. This binder will be able to find this
38
38
  * symbol via its refkey and other means. Without a binder, this symbol will
39
39
  * be unbound, which means it cannot be referenced by refkey.
40
+ *
41
+ * @remarks
42
+ *
43
+ * When constructing an external library symbol, pass `{ binder }` here to
44
+ * ensure the symbol is registered with the binder. See {@link TO_SYMBOL} for
45
+ * the full implementation protocol.
40
46
  */
41
47
  binder?: Binder;
42
48
 
@@ -97,7 +103,15 @@ export interface OutputSymbolOptions {
97
103
  ignoreNameConflict?: boolean;
98
104
 
99
105
  /**
100
- * Provide a function which lazy-initializes members when an enumeration of members are needed.
106
+ * Provide a function which lazy-initializes members the first time
107
+ * `resolveMemberByName()` is called on this symbol. Called at most once.
108
+ *
109
+ * @remarks
110
+ *
111
+ * Only `resolveMemberByName()` triggers this callback — iterating
112
+ * `OutputMemberSpace` directly does not. The callback fires regardless of
113
+ * whether the symbol belongs to any scope, so it is safe to use on scopeless
114
+ * external library symbols.
101
115
  */
102
116
  lazyMemberInitializer?: () => void;
103
117
  }
@@ -110,11 +124,47 @@ let symbolCount = 0;
110
124
  *
111
125
  * @remarks
112
126
  *
113
- * This class is the base implementation of symbol. Most languages will have
114
- * subtypes that provide additional metadata. Symbols are reactive values, so
115
- * you can observe changes to their properties in a reactive context.
127
+ * This is an abstract base class. Language packages must subclass it and
128
+ * implement the abstract {@link OutputSymbol.copy | copy()} method, which
129
+ * creates a clone that tracks the original's name and flags.
130
+ *
131
+ * Subtypes typically add language-specific properties (e.g., accessibility,
132
+ * static/abstract flags). Symbols are reactive values, so you can observe
133
+ * changes to their properties in a reactive context.
134
+ *
135
+ * To construct a scopeless external library symbol — one that resolves via
136
+ * refkey but does not appear in any declaration space — pass `undefined` as
137
+ * the `spaces` constructor argument and supply `{ binder }` in `options`.
138
+ * See {@link OutputSymbolOptions} (`binder` option) and {@link TO_SYMBOL}.
139
+ *
140
+ * @example
141
+ *
142
+ * ```ts
143
+ * import { createSymbol, OutputSymbol, OutputSpace } from "@alloy-js/core";
144
+ *
145
+ * class MySymbol extends OutputSymbol {
146
+ * copy() {
147
+ * // getCopyOptions() already includes binder
148
+ * const opts = this.getCopyOptions();
149
+ * const sym = createSymbol(MySymbol, this.name, undefined, opts);
150
+ * this.initializeCopy(sym);
151
+ * return sym;
152
+ * }
153
+ * }
154
+ *
155
+ * // name: string | Namekey; spaces: OutputSpace | OutputSpace[] | undefined; options: OutputSymbolOptions
156
+ * const sym = createSymbol(MySymbol, namekey, scope.symbols, { binder });
157
+ *
158
+ * // Construct a scopeless external library symbol (resolves via refkey only):
159
+ * const extSym = createSymbol(MySymbol, namekey, undefined, { binder });
160
+ * ```
116
161
  */
117
162
  export abstract class OutputSymbol {
163
+ /**
164
+ * The member space keys for this symbol type. Subclasses override this to
165
+ * declare which member spaces are created on construction (e.g.,
166
+ * `["static", "instance"]`).
167
+ */
118
168
  public static readonly memberSpaces: Readonly<string[]> = [];
119
169
 
120
170
  #originalName: string;
@@ -131,7 +181,8 @@ export abstract class OutputSymbol {
131
181
  // this field is set by calling the name accessor.
132
182
  #name!: string;
133
183
  /**
134
- * The name of this symbol.
184
+ * The name of this symbol. Assigning to this property applies the active
185
+ * name policy (unless `ignoreNamePolicy` is true) before storing the value.
135
186
  *
136
187
  * @reactive
137
188
  */
@@ -338,6 +389,13 @@ export abstract class OutputSymbol {
338
389
  return this.#metadata;
339
390
  }
340
391
 
392
+ /**
393
+ * Copy this symbol into the given space. Calls {@link OutputSymbol.copy} and places
394
+ * the result in `space`, then returns the copy.
395
+ *
396
+ * @param space - The space to place the copy in.
397
+ * @returns The copy of this symbol, now belonging to `space`.
398
+ */
341
399
  copyToSpace(space: OutputSpace) {
342
400
  const copy = this.copy();
343
401
  copy.spaces = space;
@@ -507,6 +565,14 @@ export abstract class OutputSymbol {
507
565
  // proxy.
508
566
  [ReactiveFlags.SKIP] = true;
509
567
 
568
+ /**
569
+ * @param name - The symbol name, or a {@link Namekey} carrying name and
570
+ * options (e.g., `ignoreNamePolicy`).
571
+ * @param spaces - The declaration or member space(s) this symbol belongs to.
572
+ * Pass `undefined` for scopeless external library symbols (see `binder` option).
573
+ * @param options - Additional symbol options (binder, refkeys, metadata,
574
+ * type, name policy, etc.).
575
+ */
510
576
  constructor(
511
577
  name: string | Namekey,
512
578
  spaces: OutputSpace[] | OutputSpace | undefined,
@@ -631,17 +697,19 @@ export abstract class OutputSymbol {
631
697
  }
632
698
 
633
699
  /**
634
- * Makes a copy of this symbol which will update the name and flags
635
- * of the clone when the original symbol is updated.
700
+ * Create a clone of this symbol whose name and flags reactively track the
701
+ * original.
636
702
  *
637
703
  * @remarks
638
704
  *
639
- * This is used to create a symbol that is a copy of this symbol, but
640
- * with a different scope. Changes to the copy will not affect the
641
- * original symbol, and changes to the original symbol's name and flags
642
- * will overwrite the copy's name and flags.
705
+ * Called by `SymbolTable.copyTo` during scope/space transfers.
706
+ * Subclasses implement cloning logic and call `getCopyOptions` for
707
+ * base options and `initializeCopy` to wire up member copying and
708
+ * name tracking.
643
709
  *
644
- * @param newScope - The scope to use for the copy.
710
+ * **Space registration contract:** The returned clone must not be registered
711
+ * in any space on exit. `copyToSpace()` calls this method and assigns the
712
+ * space afterward.
645
713
  */
646
714
  abstract copy(): OutputSymbol;
647
715
 
@@ -654,6 +722,19 @@ export abstract class OutputSymbol {
654
722
  };
655
723
  }
656
724
 
725
+ /**
726
+ * Wires up reactive member-space copying and name tracking from this symbol
727
+ * to its `copy`.
728
+ *
729
+ * @remarks
730
+ *
731
+ * Iterates each member space and calls `copyTo` on the corresponding space
732
+ * on `copy`. Then installs a reactive watcher so that any future change to
733
+ * `this.name` is immediately mirrored onto `copy.name`.
734
+ *
735
+ * **Must be called by every `copy()` override** before the override returns.
736
+ * Pair with `getCopyOptions` to supply the base constructor options.
737
+ */
657
738
  protected initializeCopy(copy: OutputSymbol) {
658
739
  for (const sourceSpace of this.memberSpaces) {
659
740
  const targetSpace = copy.memberSpaceFor(sourceSpace.key);
@@ -1,6 +1,6 @@
1
1
  import { shallowRef } from "@vue/reactivity";
2
2
  import { expect, it } from "vitest";
3
- import { renderTree } from "../render.js";
3
+ import { getDiagnosticsForTree, renderTree } from "../render.js";
4
4
  import { flushJobs } from "../scheduler.js";
5
5
  import { BasicSymbol } from "./basic-symbol.js";
6
6
  import { emitSymbol } from "./symbol-flow.js";
@@ -21,6 +21,33 @@ it("captures firstSymbol", async () => {
21
21
  expect(Slot.firstSymbol.value!.name).toBe("a");
22
22
  });
23
23
 
24
+ it("emits error diagnostic when rendered more than once", async () => {
25
+ const Slot = createSymbolSlot();
26
+
27
+ const tree = renderTree(
28
+ <>
29
+ <Slot>
30
+ {() => {
31
+ emitSymbol(new BasicSymbol("a", undefined));
32
+ }}
33
+ </Slot>
34
+ <Slot>
35
+ {() => {
36
+ emitSymbol(new BasicSymbol("b", undefined));
37
+ }}
38
+ </Slot>
39
+ </>,
40
+ );
41
+ await flushJobs();
42
+
43
+ const diagnostics = getDiagnosticsForTree(tree);
44
+ expect(diagnostics.length).toBe(1);
45
+ expect(diagnostics[0].severity).toBe("error");
46
+ expect(diagnostics[0].message).toContain(
47
+ "SymbolSlot rendered more than once",
48
+ );
49
+ });
50
+
24
51
  it("captures firstSymbol when emitting a ref to a symbol", async () => {
25
52
  const Slot = createSymbolSlot();
26
53
  const symref = shallowRef<BasicSymbol | undefined>();
@@ -1,4 +1,5 @@
1
1
  import { Ref, ShallowReactive, shallowRef } from "@vue/reactivity";
2
+ import { emitDiagnostic } from "../diagnostics.js";
2
3
  import { effect, onCleanup } from "../reactivity.js";
3
4
  import type { Children, Component } from "../runtime/component.js";
4
5
  import { OutputSymbol } from "./output-symbol.js";
@@ -35,6 +36,13 @@ export function createSymbolSlot(): SymbolSlot {
35
36
  const symbolSlotRef: Ref<ShallowReactive<Set<OutputSymbol>> | undefined> =
36
37
  shallowRef();
37
38
  function SymbolSlot(props: { children: Children }) {
39
+ if (symbolSlotRef.value !== undefined) {
40
+ emitDiagnostic({
41
+ message:
42
+ "SymbolSlot rendered more than once. The second render will overwrite symbols captured by the first render.",
43
+ severity: "error",
44
+ });
45
+ }
38
46
  const set = takeSymbols();
39
47
  symbolSlotRef.value = set;
40
48
 
@@ -1,5 +1,6 @@
1
1
  import { dirname, relative, resolve } from "pathe";
2
2
  import { AlloyHost } from "./host/alloy-host.js";
3
+ import { cwd } from "./host/node-host.js";
3
4
  import { OutputDirectory } from "./render.js";
4
5
  import { traverseOutput } from "./utils.js";
5
6
  /**
@@ -17,7 +18,7 @@ export async function writeOutput(
17
18
  return;
18
19
  }
19
20
  // eslint-disable-next-line no-console
20
- console.log("create", relative(process.cwd(), path));
21
+ console.log("create", relative(cwd(), path));
21
22
  await AlloyHost.mkdir(path);
22
23
  },
23
24
  async visitFile(file) {
@@ -25,10 +26,10 @@ export async function writeOutput(
25
26
  const path = resolve(basePath, file.path);
26
27
  if (await AlloyHost.exists(path)) {
27
28
  // eslint-disable-next-line no-console
28
- console.log("overwrite", relative(process.cwd(), path));
29
+ console.log("overwrite", relative(cwd(), path));
29
30
  } else {
30
31
  // eslint-disable-next-line no-console
31
- console.log("create", relative(process.cwd(), path));
32
+ console.log("create", relative(cwd(), path));
32
33
  }
33
34
 
34
35
  await AlloyHost.write(path, file.contents);
@@ -38,10 +39,10 @@ export async function writeOutput(
38
39
  const target = resolve(basePath, file.path);
39
40
  if (await AlloyHost.exists(target)) {
40
41
  // eslint-disable-next-line no-console
41
- console.log("copy over", relative(process.cwd(), target));
42
+ console.log("copy over", relative(cwd(), target));
42
43
  } else {
43
44
  // eslint-disable-next-line no-console
44
- console.log("copy", relative(process.cwd(), target));
45
+ console.log("copy", relative(cwd(), target));
45
46
  }
46
47
  await AlloyHost.mkdir(dirname(target));
47
48
  await AlloyHost.write(target, AlloyHost.read(source).stream());