@llui/compiler 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/LICENSE +21 -0
  2. package/dist/accessor-resolver.d.ts +58 -0
  3. package/dist/accessor-resolver.d.ts.map +1 -0
  4. package/dist/accessor-resolver.js +119 -0
  5. package/dist/accessor-resolver.js.map +1 -0
  6. package/dist/binding-descriptors.d.ts +105 -0
  7. package/dist/binding-descriptors.d.ts.map +1 -0
  8. package/dist/binding-descriptors.js +340 -0
  9. package/dist/binding-descriptors.js.map +1 -0
  10. package/dist/collect-deps.d.ts +49 -0
  11. package/dist/collect-deps.d.ts.map +1 -0
  12. package/dist/collect-deps.js +444 -0
  13. package/dist/collect-deps.js.map +1 -0
  14. package/dist/compiler-cache.d.ts +20 -0
  15. package/dist/compiler-cache.d.ts.map +1 -0
  16. package/dist/compiler-cache.js +20 -0
  17. package/dist/compiler-cache.js.map +1 -0
  18. package/dist/cross-file-resolver.d.ts +109 -0
  19. package/dist/cross-file-resolver.d.ts.map +1 -0
  20. package/dist/cross-file-resolver.js +530 -0
  21. package/dist/cross-file-resolver.js.map +1 -0
  22. package/dist/cross-file-walker.d.ts +63 -0
  23. package/dist/cross-file-walker.d.ts.map +1 -0
  24. package/dist/cross-file-walker.js +516 -0
  25. package/dist/cross-file-walker.js.map +1 -0
  26. package/dist/diagnostic.d.ts +76 -0
  27. package/dist/diagnostic.d.ts.map +1 -0
  28. package/dist/diagnostic.js +59 -0
  29. package/dist/diagnostic.js.map +1 -0
  30. package/dist/index.d.ts +27 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +37 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/introspection-factory.d.ts +54 -0
  35. package/dist/introspection-factory.d.ts.map +1 -0
  36. package/dist/introspection-factory.js +46 -0
  37. package/dist/introspection-factory.js.map +1 -0
  38. package/dist/manifest.d.ts +144 -0
  39. package/dist/manifest.d.ts.map +1 -0
  40. package/dist/manifest.js +209 -0
  41. package/dist/manifest.js.map +1 -0
  42. package/dist/module.d.ts +222 -0
  43. package/dist/module.d.ts.map +1 -0
  44. package/dist/module.js +256 -0
  45. package/dist/module.js.map +1 -0
  46. package/dist/modules/_element-helpers.d.ts +4 -0
  47. package/dist/modules/_element-helpers.d.ts.map +1 -0
  48. package/dist/modules/_element-helpers.js +138 -0
  49. package/dist/modules/_element-helpers.js.map +1 -0
  50. package/dist/modules/_msg-variants.d.ts +10 -0
  51. package/dist/modules/_msg-variants.d.ts.map +1 -0
  52. package/dist/modules/_msg-variants.js +97 -0
  53. package/dist/modules/_msg-variants.js.map +1 -0
  54. package/dist/modules/_shared.d.ts +16 -0
  55. package/dist/modules/_shared.d.ts.map +1 -0
  56. package/dist/modules/_shared.js +30 -0
  57. package/dist/modules/_shared.js.map +1 -0
  58. package/dist/modules/accessibility.d.ts +3 -0
  59. package/dist/modules/accessibility.d.ts.map +1 -0
  60. package/dist/modules/accessibility.js +82 -0
  61. package/dist/modules/accessibility.js.map +1 -0
  62. package/dist/modules/accessor-side-effect.d.ts +3 -0
  63. package/dist/modules/accessor-side-effect.d.ts.map +1 -0
  64. package/dist/modules/accessor-side-effect.js +113 -0
  65. package/dist/modules/accessor-side-effect.js.map +1 -0
  66. package/dist/modules/agent-emits-drift.d.ts +3 -0
  67. package/dist/modules/agent-emits-drift.d.ts.map +1 -0
  68. package/dist/modules/agent-emits-drift.js +158 -0
  69. package/dist/modules/agent-emits-drift.js.map +1 -0
  70. package/dist/modules/agent-example-on-payload.d.ts +3 -0
  71. package/dist/modules/agent-example-on-payload.d.ts.map +1 -0
  72. package/dist/modules/agent-example-on-payload.js +53 -0
  73. package/dist/modules/agent-example-on-payload.js.map +1 -0
  74. package/dist/modules/agent-exclusive-annotations.d.ts +3 -0
  75. package/dist/modules/agent-exclusive-annotations.d.ts.map +1 -0
  76. package/dist/modules/agent-exclusive-annotations.js +68 -0
  77. package/dist/modules/agent-exclusive-annotations.js.map +1 -0
  78. package/dist/modules/agent-missing-intent.d.ts +3 -0
  79. package/dist/modules/agent-missing-intent.d.ts.map +1 -0
  80. package/dist/modules/agent-missing-intent.js +47 -0
  81. package/dist/modules/agent-missing-intent.js.map +1 -0
  82. package/dist/modules/agent-msg-resolvable.d.ts +3 -0
  83. package/dist/modules/agent-msg-resolvable.d.ts.map +1 -0
  84. package/dist/modules/agent-msg-resolvable.js +161 -0
  85. package/dist/modules/agent-msg-resolvable.js.map +1 -0
  86. package/dist/modules/agent-nonextractable-handler.d.ts +3 -0
  87. package/dist/modules/agent-nonextractable-handler.d.ts.map +1 -0
  88. package/dist/modules/agent-nonextractable-handler.js +127 -0
  89. package/dist/modules/agent-nonextractable-handler.js.map +1 -0
  90. package/dist/modules/agent-optional-field-undocumented.d.ts +3 -0
  91. package/dist/modules/agent-optional-field-undocumented.d.ts.map +1 -0
  92. package/dist/modules/agent-optional-field-undocumented.js +67 -0
  93. package/dist/modules/agent-optional-field-undocumented.js.map +1 -0
  94. package/dist/modules/agent-tagsend-translator-missing.d.ts +3 -0
  95. package/dist/modules/agent-tagsend-translator-missing.d.ts.map +1 -0
  96. package/dist/modules/agent-tagsend-translator-missing.js +58 -0
  97. package/dist/modules/agent-tagsend-translator-missing.js.map +1 -0
  98. package/dist/modules/agent-warning-on-confirm.d.ts +3 -0
  99. package/dist/modules/agent-warning-on-confirm.d.ts.map +1 -0
  100. package/dist/modules/agent-warning-on-confirm.js +46 -0
  101. package/dist/modules/agent-warning-on-confirm.js.map +1 -0
  102. package/dist/modules/async-update.d.ts +3 -0
  103. package/dist/modules/async-update.d.ts.map +1 -0
  104. package/dist/modules/async-update.js +86 -0
  105. package/dist/modules/async-update.js.map +1 -0
  106. package/dist/modules/binding-descriptors.d.ts +4 -0
  107. package/dist/modules/binding-descriptors.d.ts.map +1 -0
  108. package/dist/modules/binding-descriptors.js +48 -0
  109. package/dist/modules/binding-descriptors.js.map +1 -0
  110. package/dist/modules/bitmask-overflow.d.ts +3 -0
  111. package/dist/modules/bitmask-overflow.d.ts.map +1 -0
  112. package/dist/modules/bitmask-overflow.js +152 -0
  113. package/dist/modules/bitmask-overflow.js.map +1 -0
  114. package/dist/modules/compiler-stamp.d.ts +3 -0
  115. package/dist/modules/compiler-stamp.d.ts.map +1 -0
  116. package/dist/modules/compiler-stamp.js +44 -0
  117. package/dist/modules/compiler-stamp.js.map +1 -0
  118. package/dist/modules/component-meta.d.ts +3 -0
  119. package/dist/modules/component-meta.d.ts.map +1 -0
  120. package/dist/modules/component-meta.js +44 -0
  121. package/dist/modules/component-meta.js.map +1 -0
  122. package/dist/modules/controlled-input.d.ts +3 -0
  123. package/dist/modules/controlled-input.d.ts.map +1 -0
  124. package/dist/modules/controlled-input.js +68 -0
  125. package/dist/modules/controlled-input.js.map +1 -0
  126. package/dist/modules/core-synthesis.d.ts +18 -0
  127. package/dist/modules/core-synthesis.d.ts.map +1 -0
  128. package/dist/modules/core-synthesis.js +748 -0
  129. package/dist/modules/core-synthesis.js.map +1 -0
  130. package/dist/modules/direct-state-in-view.d.ts +3 -0
  131. package/dist/modules/direct-state-in-view.d.ts.map +1 -0
  132. package/dist/modules/direct-state-in-view.js +103 -0
  133. package/dist/modules/direct-state-in-view.js.map +1 -0
  134. package/dist/modules/each-closure-violation.d.ts +3 -0
  135. package/dist/modules/each-closure-violation.d.ts.map +1 -0
  136. package/dist/modules/each-closure-violation.js +255 -0
  137. package/dist/modules/each-closure-violation.js.map +1 -0
  138. package/dist/modules/each-memo.d.ts +15 -0
  139. package/dist/modules/each-memo.d.ts.map +1 -0
  140. package/dist/modules/each-memo.js +115 -0
  141. package/dist/modules/each-memo.js.map +1 -0
  142. package/dist/modules/effect-without-handler.d.ts +3 -0
  143. package/dist/modules/effect-without-handler.d.ts.map +1 -0
  144. package/dist/modules/effect-without-handler.js +92 -0
  145. package/dist/modules/effect-without-handler.js.map +1 -0
  146. package/dist/modules/element-rewrite.d.ts +22 -0
  147. package/dist/modules/element-rewrite.d.ts.map +1 -0
  148. package/dist/modules/element-rewrite.js +1017 -0
  149. package/dist/modules/element-rewrite.js.map +1 -0
  150. package/dist/modules/empty-props.d.ts +3 -0
  151. package/dist/modules/empty-props.d.ts.map +1 -0
  152. package/dist/modules/empty-props.js +50 -0
  153. package/dist/modules/empty-props.js.map +1 -0
  154. package/dist/modules/exhaustive-effect-handling.d.ts +3 -0
  155. package/dist/modules/exhaustive-effect-handling.d.ts.map +1 -0
  156. package/dist/modules/exhaustive-effect-handling.js +61 -0
  157. package/dist/modules/exhaustive-effect-handling.js.map +1 -0
  158. package/dist/modules/exhaustive-update.d.ts +3 -0
  159. package/dist/modules/exhaustive-update.d.ts.map +1 -0
  160. package/dist/modules/exhaustive-update.js +146 -0
  161. package/dist/modules/exhaustive-update.js.map +1 -0
  162. package/dist/modules/forgotten-spread.d.ts +3 -0
  163. package/dist/modules/forgotten-spread.d.ts.map +1 -0
  164. package/dist/modules/forgotten-spread.js +51 -0
  165. package/dist/modules/forgotten-spread.js.map +1 -0
  166. package/dist/modules/form-boilerplate.d.ts +3 -0
  167. package/dist/modules/form-boilerplate.d.ts.map +1 -0
  168. package/dist/modules/form-boilerplate.js +101 -0
  169. package/dist/modules/form-boilerplate.js.map +1 -0
  170. package/dist/modules/imperative-dom-in-view.d.ts +3 -0
  171. package/dist/modules/imperative-dom-in-view.d.ts.map +1 -0
  172. package/dist/modules/imperative-dom-in-view.js +123 -0
  173. package/dist/modules/imperative-dom-in-view.js.map +1 -0
  174. package/dist/modules/item-dedup.d.ts +7 -0
  175. package/dist/modules/item-dedup.d.ts.map +1 -0
  176. package/dist/modules/item-dedup.js +204 -0
  177. package/dist/modules/item-dedup.js.map +1 -0
  178. package/dist/modules/map-on-state-array.d.ts +3 -0
  179. package/dist/modules/map-on-state-array.d.ts.map +1 -0
  180. package/dist/modules/map-on-state-array.js +84 -0
  181. package/dist/modules/map-on-state-array.js.map +1 -0
  182. package/dist/modules/mask-legend.d.ts +10 -0
  183. package/dist/modules/mask-legend.d.ts.map +1 -0
  184. package/dist/modules/mask-legend.js +50 -0
  185. package/dist/modules/mask-legend.js.map +1 -0
  186. package/dist/modules/missing-memo.d.ts +3 -0
  187. package/dist/modules/missing-memo.d.ts.map +1 -0
  188. package/dist/modules/missing-memo.js +114 -0
  189. package/dist/modules/missing-memo.js.map +1 -0
  190. package/dist/modules/msg-annotations.d.ts +9 -0
  191. package/dist/modules/msg-annotations.d.ts.map +1 -0
  192. package/dist/modules/msg-annotations.js +54 -0
  193. package/dist/modules/msg-annotations.js.map +1 -0
  194. package/dist/modules/msg-schema.d.ts +10 -0
  195. package/dist/modules/msg-schema.d.ts.map +1 -0
  196. package/dist/modules/msg-schema.js +70 -0
  197. package/dist/modules/msg-schema.js.map +1 -0
  198. package/dist/modules/namespace-import.d.ts +3 -0
  199. package/dist/modules/namespace-import.d.ts.map +1 -0
  200. package/dist/modules/namespace-import.js +80 -0
  201. package/dist/modules/namespace-import.js.map +1 -0
  202. package/dist/modules/nested-send-in-update.d.ts +3 -0
  203. package/dist/modules/nested-send-in-update.d.ts.map +1 -0
  204. package/dist/modules/nested-send-in-update.js +77 -0
  205. package/dist/modules/nested-send-in-update.js.map +1 -0
  206. package/dist/modules/no-barrel-import-when-subpath-exists.d.ts +3 -0
  207. package/dist/modules/no-barrel-import-when-subpath-exists.d.ts.map +1 -0
  208. package/dist/modules/no-barrel-import-when-subpath-exists.js +100 -0
  209. package/dist/modules/no-barrel-import-when-subpath-exists.js.map +1 -0
  210. package/dist/modules/no-eager-item-accessor.d.ts +3 -0
  211. package/dist/modules/no-eager-item-accessor.d.ts.map +1 -0
  212. package/dist/modules/no-eager-item-accessor.js +74 -0
  213. package/dist/modules/no-eager-item-accessor.js.map +1 -0
  214. package/dist/modules/no-let-reactive-accessor.d.ts +3 -0
  215. package/dist/modules/no-let-reactive-accessor.d.ts.map +1 -0
  216. package/dist/modules/no-let-reactive-accessor.js +227 -0
  217. package/dist/modules/no-let-reactive-accessor.js.map +1 -0
  218. package/dist/modules/no-list-render-in-sample.d.ts +3 -0
  219. package/dist/modules/no-list-render-in-sample.d.ts.map +1 -0
  220. package/dist/modules/no-list-render-in-sample.js +89 -0
  221. package/dist/modules/no-list-render-in-sample.js.map +1 -0
  222. package/dist/modules/no-sample-in-accessor.d.ts +3 -0
  223. package/dist/modules/no-sample-in-accessor.d.ts.map +1 -0
  224. package/dist/modules/no-sample-in-accessor.js +141 -0
  225. package/dist/modules/no-sample-in-accessor.js.map +1 -0
  226. package/dist/modules/no-sample-in-reactive-position.d.ts +3 -0
  227. package/dist/modules/no-sample-in-reactive-position.d.ts.map +1 -0
  228. package/dist/modules/no-sample-in-reactive-position.js +72 -0
  229. package/dist/modules/no-sample-in-reactive-position.js.map +1 -0
  230. package/dist/modules/pure-update-function.d.ts +3 -0
  231. package/dist/modules/pure-update-function.d.ts.map +1 -0
  232. package/dist/modules/pure-update-function.js +127 -0
  233. package/dist/modules/pure-update-function.js.map +1 -0
  234. package/dist/modules/reactive-paths.d.ts +3 -0
  235. package/dist/modules/reactive-paths.d.ts.map +1 -0
  236. package/dist/modules/reactive-paths.js +77 -0
  237. package/dist/modules/reactive-paths.js.map +1 -0
  238. package/dist/modules/row-factory.d.ts +12 -0
  239. package/dist/modules/row-factory.d.ts.map +1 -0
  240. package/dist/modules/row-factory.js +385 -0
  241. package/dist/modules/row-factory.js.map +1 -0
  242. package/dist/modules/schema-hash.d.ts +15 -0
  243. package/dist/modules/schema-hash.d.ts.map +1 -0
  244. package/dist/modules/schema-hash.js +70 -0
  245. package/dist/modules/schema-hash.js.map +1 -0
  246. package/dist/modules/spread-in-children.d.ts +3 -0
  247. package/dist/modules/spread-in-children.d.ts.map +1 -0
  248. package/dist/modules/spread-in-children.js +144 -0
  249. package/dist/modules/spread-in-children.js.map +1 -0
  250. package/dist/modules/state-mutation.d.ts +3 -0
  251. package/dist/modules/state-mutation.d.ts.map +1 -0
  252. package/dist/modules/state-mutation.js +138 -0
  253. package/dist/modules/state-mutation.js.map +1 -0
  254. package/dist/modules/state-schema.d.ts +8 -0
  255. package/dist/modules/state-schema.d.ts.map +1 -0
  256. package/dist/modules/state-schema.js +55 -0
  257. package/dist/modules/state-schema.js.map +1 -0
  258. package/dist/modules/static-items.d.ts +3 -0
  259. package/dist/modules/static-items.d.ts.map +1 -0
  260. package/dist/modules/static-items.js +125 -0
  261. package/dist/modules/static-items.js.map +1 -0
  262. package/dist/modules/static-on.d.ts +3 -0
  263. package/dist/modules/static-on.d.ts.map +1 -0
  264. package/dist/modules/static-on.js +100 -0
  265. package/dist/modules/static-on.js.map +1 -0
  266. package/dist/modules/string-effect-callback.d.ts +3 -0
  267. package/dist/modules/string-effect-callback.d.ts.map +1 -0
  268. package/dist/modules/string-effect-callback.js +50 -0
  269. package/dist/modules/string-effect-callback.js.map +1 -0
  270. package/dist/modules/structural-mask.d.ts +8 -0
  271. package/dist/modules/structural-mask.d.ts.map +1 -0
  272. package/dist/modules/structural-mask.js +76 -0
  273. package/dist/modules/structural-mask.js.map +1 -0
  274. package/dist/modules/subapp-requires-reason.d.ts +3 -0
  275. package/dist/modules/subapp-requires-reason.d.ts.map +1 -0
  276. package/dist/modules/subapp-requires-reason.js +129 -0
  277. package/dist/modules/subapp-requires-reason.js.map +1 -0
  278. package/dist/modules/text-mask.d.ts +12 -0
  279. package/dist/modules/text-mask.d.ts.map +1 -0
  280. package/dist/modules/text-mask.js +63 -0
  281. package/dist/modules/text-mask.js.map +1 -0
  282. package/dist/modules/view-bag-import.d.ts +3 -0
  283. package/dist/modules/view-bag-import.d.ts.map +1 -0
  284. package/dist/modules/view-bag-import.js +80 -0
  285. package/dist/modules/view-bag-import.js.map +1 -0
  286. package/dist/msg-annotations.d.ts +104 -0
  287. package/dist/msg-annotations.d.ts.map +1 -0
  288. package/dist/msg-annotations.js +242 -0
  289. package/dist/msg-annotations.js.map +1 -0
  290. package/dist/msg-schema.d.ts +130 -0
  291. package/dist/msg-schema.d.ts.map +1 -0
  292. package/dist/msg-schema.js +770 -0
  293. package/dist/msg-schema.js.map +1 -0
  294. package/dist/schema-hash.d.ts +16 -0
  295. package/dist/schema-hash.d.ts.map +1 -0
  296. package/dist/schema-hash.js +31 -0
  297. package/dist/schema-hash.js.map +1 -0
  298. package/dist/state-schema.d.ts +41 -0
  299. package/dist/state-schema.d.ts.map +1 -0
  300. package/dist/state-schema.js +156 -0
  301. package/dist/state-schema.js.map +1 -0
  302. package/dist/transform.d.ts +109 -0
  303. package/dist/transform.d.ts.map +1 -0
  304. package/dist/transform.js +1390 -0
  305. package/dist/transform.js.map +1 -0
  306. package/dist/version.d.ts +11 -0
  307. package/dist/version.d.ts.map +1 -0
  308. package/dist/version.js +11 -0
  309. package/dist/version.js.map +1 -0
  310. package/package.json +47 -0
@@ -0,0 +1,209 @@
1
+ // __llui_deps.json — v2b library-boundary manifest (§4.2).
2
+ //
3
+ // Every published @llui/* package (and any third-party package that wants
4
+ // compiler-level integration) emits a manifest declaring each exported
5
+ // helper's reactive footprint: paths read directly, paths reached through
6
+ // accessor parameters, and context-provider keys consumed.
7
+ //
8
+ // The schema is the result of validating against the real @llui/components
9
+ // surface — every shape here is needed by some real helper. New shapes
10
+ // require a schema-version bump + a worked example in §4.3.
11
+ //
12
+ // The substitution algorithm (`substituteHelperCall`) consumes a manifest
13
+ // entry plus a call-site's argument expressions and computes the set of
14
+ // host-state paths the call contributes to the consumer's __prefixes.
15
+ import ts from 'typescript';
16
+ const MAX_SUBSTITUTION_DEPTH = 8;
17
+ /**
18
+ * Substitute a manifest helper call against its call-site arguments.
19
+ *
20
+ * Given a helper's manifest entry and the argument expressions at one call
21
+ * site, returns the set of host-state paths the call contributes to the
22
+ * consumer's __prefixes table.
23
+ *
24
+ * §4.4 substitution rules:
25
+ * 1. For each ViaParams entry, resolve the call-site argument.
26
+ * 2. `shape: 'accessor'` parameters are walked via `extractPaths`.
27
+ * 3. `shape: 'options-bag'` parameters are unpacked field-by-field
28
+ * against the call site's object-literal argument.
29
+ * 4. `innerReads` are composed against the resolved accessors:
30
+ * - rooted: helper-local, contributed verbatim
31
+ * - param-result: paths from param N's body
32
+ * - param-result-path: lift + sub-path composition
33
+ * 5. `readsThroughResultOf: N` — param's body operates on param N's
34
+ * result; substitution composes through N's accessor.
35
+ * 6. `contextReads` — resolved against `providers`; provider.accessor +
36
+ * subPaths compose to host-state paths.
37
+ * 7. Depth bounded at 8; cycles caught by `(helper-symbol, param-index)`
38
+ * visited set.
39
+ */
40
+ export function substituteHelperCall(entry, callArgs, ctx, helperKey = 'anonymous', visited = new Set(), depth = 0) {
41
+ const out = { paths: [], diagnostics: [], fullMask: false };
42
+ if (depth > MAX_SUBSTITUTION_DEPTH) {
43
+ out.diagnostics.push({
44
+ id: 'llui/substitution-depth-exceeded',
45
+ message: `Substitution depth exceeded 8 at helper "${helperKey}" (likely deep helper chain); contributing FULL_MASK at this call site.`,
46
+ });
47
+ out.fullMask = true;
48
+ return out;
49
+ }
50
+ // 1. Helper-local paths — rare; contributed verbatim. Reserved for the
51
+ // case where the helper's "host state shape" equals the consumer's
52
+ // (e.g. trivial passthrough helpers).
53
+ for (const p of entry.helperLocalPaths)
54
+ out.paths.push(p);
55
+ // 2. Per-parameter resolution.
56
+ for (const param of entry.viaParams) {
57
+ const arg = callArgs[param.index];
58
+ if (param.shape === 'send' || param.shape === 'opaque') {
59
+ // No path contribution — send is a Send<M> ref, opaque is intentional.
60
+ continue;
61
+ }
62
+ if (param.shape === 'thunk-returning-nodes') {
63
+ // The call site provides a `() => Node[]` thunk that closes over
64
+ // consumer-scope accessors. The substitution layer can't see inside
65
+ // the closure without re-walking the consumer's view source — that
66
+ // walk happens at the consumer's compile step, not here. We mark
67
+ // this param's contribution as "must be walked by consumer", which
68
+ // the cross-file walker handles by recursing into the thunk body
69
+ // directly. The manifest substitution itself contributes no paths.
70
+ continue;
71
+ }
72
+ if (param.shape === 'options-bag') {
73
+ if (!arg || !ts.isObjectLiteralExpression(arg)) {
74
+ // Non-literal options bag (variable reference, spread, etc.) is
75
+ // FULL_MASK at this call site. Real-world consumers do sometimes
76
+ // pre-build the options bag; we accept the cost and warn.
77
+ out.diagnostics.push({
78
+ id: 'llui/opaque-options-bag',
79
+ message: `Options-bag argument at index ${param.index} of "${helperKey}" is not an object literal; contributing FULL_MASK.`,
80
+ });
81
+ out.fullMask = true;
82
+ continue;
83
+ }
84
+ // Unpack: each field listed in `fields` is matched against the
85
+ // call-site object literal's property.
86
+ for (const [fieldName, fieldSpec] of Object.entries(param.fields)) {
87
+ const prop = arg.properties.find((p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === fieldName);
88
+ if (!prop || !ts.isPropertyAssignment(prop))
89
+ continue;
90
+ const fieldExpr = prop.initializer;
91
+ substituteField(fieldSpec, fieldExpr, ctx, helperKey, visited, depth, out, entry);
92
+ }
93
+ continue;
94
+ }
95
+ // shape: 'accessor'
96
+ // Compose helper's innerReads. Each `kind: 'param-result*'` reads
97
+ // through `callArgs[from]`'s accessor — which may be a different
98
+ // parameter (the readsThroughResultOf case). Hence the resolver
99
+ // takes `from` per innerRead, not the enclosing `param.index`.
100
+ for (const ir of param.innerReads) {
101
+ if (ir.kind === 'rooted') {
102
+ out.paths.push(ir.path);
103
+ continue;
104
+ }
105
+ const liftPaths = liftPathsForArg(callArgs[ir.from], ctx);
106
+ if (ir.kind === 'param-result') {
107
+ for (const p of liftPaths)
108
+ out.paths.push(p);
109
+ }
110
+ else if (ir.kind === 'param-result-path') {
111
+ for (const lift of liftPaths) {
112
+ out.paths.push(lift ? `${lift}.${ir.path}` : ir.path);
113
+ }
114
+ }
115
+ }
116
+ }
117
+ // 6. Context-provider reads.
118
+ if (entry.contextReads) {
119
+ for (const cr of entry.contextReads) {
120
+ const provider = ctx.providers.get(cr.context);
121
+ if (!provider) {
122
+ out.diagnostics.push({
123
+ id: 'llui/missing-context-provider',
124
+ message: `Helper "${helperKey}" reads from context "${cr.context}" but no matching provide(${cr.context}, ...) call was found in the consumer. The reads will fall back to FULL_MASK; add a provider or wrap the helper's call site in one.`,
125
+ });
126
+ out.fullMask = true;
127
+ continue;
128
+ }
129
+ if (!provider.accessor)
130
+ continue;
131
+ const rootParamName = getFirstParamName(provider.accessor);
132
+ if (!rootParamName)
133
+ continue;
134
+ const liftPaths = ctx.extractPaths(provider.accessor, rootParamName);
135
+ for (const lift of liftPaths) {
136
+ for (const sub of cr.subPaths) {
137
+ out.paths.push(lift ? `${lift}.${sub}` : sub);
138
+ }
139
+ }
140
+ }
141
+ }
142
+ // Dedup. Use a Set roundtrip — order is incidental for __prefixes.
143
+ out.paths = [...new Set(out.paths)];
144
+ return out;
145
+ }
146
+ function substituteField(fieldSpec, fieldExpr, ctx, helperKey, visited, depth, out, entry) {
147
+ if (fieldSpec.shape === 'send' || fieldSpec.shape === 'opaque')
148
+ return;
149
+ if (fieldSpec.shape === 'thunk-returning-nodes')
150
+ return; // consumer's view walker handles this
151
+ // shape: 'accessor' — field's innerReads compose against the field
152
+ // expression's accessor (depth-1 within the options bag).
153
+ const liftPaths = liftPathsForArg(fieldExpr, ctx);
154
+ for (const ir of fieldSpec.innerReads) {
155
+ if (ir.kind === 'rooted') {
156
+ out.paths.push(ir.path);
157
+ }
158
+ else if (ir.kind === 'param-result') {
159
+ for (const p of liftPaths)
160
+ out.paths.push(p);
161
+ }
162
+ else if (ir.kind === 'param-result-path') {
163
+ for (const lift of liftPaths) {
164
+ out.paths.push(lift ? `${lift}.${ir.path}` : ir.path);
165
+ }
166
+ }
167
+ }
168
+ // Silence the unused `entry`/`visited`/`helperKey`/`depth` — kept in
169
+ // the signature to mirror substituteHelperCall and ease the eventual
170
+ // recursive substitution Phase 3 lands.
171
+ void entry;
172
+ void visited;
173
+ void helperKey;
174
+ void depth;
175
+ }
176
+ /**
177
+ * Walk the call-site argument (or options-bag field) as an accessor and
178
+ * return its dotted path reads. Returns [] when the arg is not an arrow/
179
+ * function expression — substitution falls through to no contribution.
180
+ */
181
+ function liftPathsForArg(arg, ctx) {
182
+ if (!arg)
183
+ return [];
184
+ const accessor = unwrapAccessorArg(arg);
185
+ if (!accessor)
186
+ return [];
187
+ const rootParamName = getFirstParamName(accessor);
188
+ if (!rootParamName)
189
+ return [];
190
+ return ctx.extractPaths(accessor, rootParamName);
191
+ }
192
+ /**
193
+ * Unwrap a call-site argument into the accessor function expression, if any.
194
+ * Accepts inline arrows, function expressions, and identifiers that
195
+ * resolve to a local const initializer (one level — Phase 3's walker
196
+ * generalizes this via the existing `resolveAccessorBody`).
197
+ */
198
+ function unwrapAccessorArg(arg) {
199
+ if (ts.isArrowFunction(arg) || ts.isFunctionExpression(arg))
200
+ return arg;
201
+ return null;
202
+ }
203
+ function getFirstParamName(fn) {
204
+ const p0 = fn.parameters[0];
205
+ if (!p0 || !ts.isIdentifier(p0.name))
206
+ return undefined;
207
+ return p0.name.text;
208
+ }
209
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,EAAE;AACF,0EAA0E;AAC1E,uEAAuE;AACvE,0EAA0E;AAC1E,2DAA2D;AAC3D,EAAE;AACF,2EAA2E;AAC3E,uEAAuE;AACvE,4DAA4D;AAC5D,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,sEAAsE;AAEtE,OAAO,EAAE,MAAM,YAAY,CAAA;AAqH3B,MAAM,sBAAsB,GAAG,CAAC,CAAA;AAEhC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAkB,EAClB,QAAsC,EACtC,GAAwB,EACxB,SAAS,GAAG,WAAW,EACvB,UAAU,IAAI,GAAG,EAAU,EAC3B,KAAK,GAAG,CAAC;IAET,MAAM,GAAG,GAAuB,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;IAE/E,IAAI,KAAK,GAAG,sBAAsB,EAAE,CAAC;QACnC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC;YACnB,EAAE,EAAE,kCAAkC;YACtC,OAAO,EAAE,4CAA4C,SAAS,yEAAyE;SACxI,CAAC,CAAA;QACF,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAA;QACnB,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,uEAAuE;IACvE,sEAAsE;IACtE,yCAAyC;IACzC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,gBAAgB;QAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAEzD,+BAA+B;IAC/B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACpC,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAEjC,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvD,uEAAuE;YACvE,SAAQ;QACV,CAAC;QAED,IAAI,KAAK,CAAC,KAAK,KAAK,uBAAuB,EAAE,CAAC;YAC5C,iEAAiE;YACjE,oEAAoE;YACpE,mEAAmE;YACnE,iEAAiE;YACjE,mEAAmE;YACnE,iEAAiE;YACjE,mEAAmE;YACnE,SAAQ;QACV,CAAC;QAED,IAAI,KAAK,CAAC,KAAK,KAAK,aAAa,EAAE,CAAC;YAClC,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,yBAAyB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/C,gEAAgE;gBAChE,iEAAiE;gBACjE,0DAA0D;gBAC1D,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC;oBACnB,EAAE,EAAE,yBAAyB;oBAC7B,OAAO,EAAE,iCAAiC,KAAK,CAAC,KAAK,QAAQ,SAAS,qDAAqD;iBAC5H,CAAC,CAAA;gBACF,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAA;gBACnB,SAAQ;YACV,CAAC;YACD,+DAA+D;YAC/D,uCAAuC;YACvC,KAAK,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClE,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAC9B,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAC1F,CAAA;gBACD,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC;oBAAE,SAAQ;gBACrD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAA;gBAClC,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;YACnF,CAAC;YACD,SAAQ;QACV,CAAC;QAED,oBAAoB;QACpB,kEAAkE;QAClE,iEAAiE;QACjE,gEAAgE;QAChE,+DAA+D;QAC/D,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YAClC,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACzB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAA;gBACvB,SAAQ;YACV,CAAC;YACD,MAAM,SAAS,GAAG,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;YACzD,IAAI,EAAE,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;gBAC/B,KAAK,MAAM,CAAC,IAAI,SAAS;oBAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAC9C,CAAC;iBAAM,IAAI,EAAE,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;gBAC3C,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;oBAC7B,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAA;gBACvD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,CAAA;YAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC;oBACnB,EAAE,EAAE,+BAA+B;oBACnC,OAAO,EAAE,WAAW,SAAS,yBAAyB,EAAE,CAAC,OAAO,6BAA6B,EAAE,CAAC,OAAO,qIAAqI;iBAC7O,CAAC,CAAA;gBACF,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAA;gBACnB,SAAQ;YACV,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,QAAQ;gBAAE,SAAQ;YAChC,MAAM,aAAa,GAAG,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;YAC1D,IAAI,CAAC,aAAa;gBAAE,SAAQ;YAC5B,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;YACpE,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,KAAK,MAAM,GAAG,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;oBAC9B,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;gBAC/C,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;IACnC,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,eAAe,CACtB,SAAoB,EACpB,SAAwB,EACxB,GAAwB,EACxB,SAAiB,EACjB,OAAoB,EACpB,KAAa,EACb,GAAuB,EACvB,KAAkB;IAElB,IAAI,SAAS,CAAC,KAAK,KAAK,MAAM,IAAI,SAAS,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAM;IACtE,IAAI,SAAS,CAAC,KAAK,KAAK,uBAAuB;QAAE,OAAM,CAAC,sCAAsC;IAE9F,mEAAmE;IACnE,0DAA0D;IAC1D,MAAM,SAAS,GAAG,eAAe,CAAC,SAAS,EAAE,GAAG,CAAC,CAAA;IACjD,KAAK,MAAM,EAAE,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;QACtC,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACzB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAA;QACzB,CAAC;aAAM,IAAI,EAAE,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACtC,KAAK,MAAM,CAAC,IAAI,SAAS;gBAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC9C,CAAC;aAAM,IAAI,EAAE,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;YAC3C,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAA;YACvD,CAAC;QACH,CAAC;IACH,CAAC;IACD,qEAAqE;IACrE,qEAAqE;IACrE,wCAAwC;IACxC,KAAK,KAAK,CAAA;IACV,KAAK,OAAO,CAAA;IACZ,KAAK,SAAS,CAAA;IACd,KAAK,KAAK,CAAA;AACZ,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,GAA8B,EAAE,GAAwB;IAC/E,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAA;IACnB,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAA;IACvC,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAA;IACxB,MAAM,aAAa,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACjD,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,CAAA;IAC7B,OAAO,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;AAClD,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CAAC,GAAkB;IAC3C,IAAI,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,oBAAoB,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAA;IACvE,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,iBAAiB,CAAC,EAA4C;IACrE,MAAM,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;IAC3B,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAA;IACtD,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAA;AACrB,CAAC","sourcesContent":["// __llui_deps.json — v2b library-boundary manifest (§4.2).\n//\n// Every published @llui/* package (and any third-party package that wants\n// compiler-level integration) emits a manifest declaring each exported\n// helper's reactive footprint: paths read directly, paths reached through\n// accessor parameters, and context-provider keys consumed.\n//\n// The schema is the result of validating against the real @llui/components\n// surface — every shape here is needed by some real helper. New shapes\n// require a schema-version bump + a worked example in §4.3.\n//\n// The substitution algorithm (`substituteHelperCall`) consumes a manifest\n// entry plus a call-site's argument expressions and computes the set of\n// host-state paths the call contributes to the consumer's __prefixes.\n\nimport ts from 'typescript'\n\n// ── Schema ──────────────────────────────────────────────────────────\n\nexport interface Manifest {\n /** Schema version. Frozen at 1 in v2b. */\n version: 1\n /** Compiler version that emitted this manifest. */\n compilerVersion: string\n /** Exported helpers keyed by name. */\n helpers: Record<string, HelperEntry>\n /** Exported components keyed by name (for completeness; not used in v2b's substitution). */\n components: Record<string, ComponentEntry>\n}\n\nexport interface HelperEntry {\n /**\n * `'view-helper'` — the call returns Node[]-like and is resolved once per\n * call site.\n * `'parts-helper'` — the call returns a *parts bag* (a record of accessor\n * thunks). The bag is later spread into element calls by the consumer;\n * every spread contributes the same read set.\n */\n kind: 'view-helper' | 'parts-helper'\n /** Paths the helper reads from its OWN state shape (rare; usually empty). */\n helperLocalPaths: string[]\n /** Per-parameter substitution metadata. Index N corresponds to the helper's Nth declared parameter. */\n viaParams: ParamSpec[]\n /** Context-provider keys this helper consumes. Resolved against the consumer's provide() call sites. */\n contextReads?: ContextRead[]\n}\n\nexport interface ComponentEntry {\n /** Reserved for v2b's read-everything-the-component-reads escape hatch. Unused at v2b ship. */\n name: string\n}\n\nexport type ParamSpec =\n | { index: number; shape: 'accessor'; innerReads: InnerRead[] }\n | {\n index: number\n shape: 'accessor'\n /** This parameter's body operates on the result of parameter N. */\n readsThroughResultOf: number\n innerReads: InnerRead[]\n }\n | { index: number; shape: 'options-bag'; fields: Record<string, FieldSpec> }\n | { index: number; shape: 'send' }\n | { index: number; shape: 'thunk-returning-nodes' }\n | { index: number; shape: 'opaque' }\n\nexport type FieldSpec =\n | { shape: 'accessor'; innerReads: InnerRead[] }\n | {\n shape: 'accessor'\n readsThroughResultOf: number\n innerReads: InnerRead[]\n }\n | { shape: 'send' }\n | { shape: 'thunk-returning-nodes' }\n | { shape: 'opaque' }\n\nexport type InnerRead =\n /** Helper-local read — rare; the helper sees state directly. */\n | { kind: 'rooted'; path: string }\n /** The entire result of parameter N. */\n | { kind: 'param-result'; from: number }\n /** A sub-path within parameter N's accessor result. The dominant kind across @llui/components. */\n | { kind: 'param-result-path'; from: number; path: string }\n\nexport interface ContextRead {\n /** Canonical id: `<package-name>#<export-name>`. */\n context: string\n /** Sub-paths within the context value the helper reads. */\n subPaths: string[]\n}\n\n// ── Substitution algorithm (§4.4) ───────────────────────────────────\n\nexport interface ContextProvider {\n context: string\n /** Source AST for the consumer's `provide(LocaleContext, (s) => s.i18n, ...)` accessor. */\n accessor: ts.ArrowFunction | ts.FunctionExpression | undefined\n}\n\nexport interface SubstitutionContext {\n /** Maps canonical context ids to the consumer's matching provide(...) accessor. */\n providers: Map<string, ContextProvider>\n /**\n * Path-extraction hook. Walks an arrow body and returns the dotted paths\n * it reads. The cross-file walker injects its `extractAccessorPaths`\n * here; tests can stub with a simpler walker.\n */\n extractPaths: (\n accessor: ts.ArrowFunction | ts.FunctionExpression,\n rootParamName: string,\n ) => string[]\n}\n\nexport interface SubstitutionResult {\n /** Host-state paths contributed by this call site, e.g. `['carousel.paused', 'carousel.current']`. */\n paths: string[]\n /** Diagnostics emitted by the substitution. */\n diagnostics: SubstitutionDiagnostic[]\n /** Whether the call site fell back to FULL_MASK (e.g. unrecognized options-bag shape). */\n fullMask: boolean\n}\n\nexport interface SubstitutionDiagnostic {\n id:\n | 'llui/opaque-options-bag'\n | 'llui/missing-context-provider'\n | 'llui/substitution-depth-exceeded'\n | 'llui/substitution-cycle'\n message: string\n}\n\nconst MAX_SUBSTITUTION_DEPTH = 8\n\n/**\n * Substitute a manifest helper call against its call-site arguments.\n *\n * Given a helper's manifest entry and the argument expressions at one call\n * site, returns the set of host-state paths the call contributes to the\n * consumer's __prefixes table.\n *\n * §4.4 substitution rules:\n * 1. For each ViaParams entry, resolve the call-site argument.\n * 2. `shape: 'accessor'` parameters are walked via `extractPaths`.\n * 3. `shape: 'options-bag'` parameters are unpacked field-by-field\n * against the call site's object-literal argument.\n * 4. `innerReads` are composed against the resolved accessors:\n * - rooted: helper-local, contributed verbatim\n * - param-result: paths from param N's body\n * - param-result-path: lift + sub-path composition\n * 5. `readsThroughResultOf: N` — param's body operates on param N's\n * result; substitution composes through N's accessor.\n * 6. `contextReads` — resolved against `providers`; provider.accessor +\n * subPaths compose to host-state paths.\n * 7. Depth bounded at 8; cycles caught by `(helper-symbol, param-index)`\n * visited set.\n */\nexport function substituteHelperCall(\n entry: HelperEntry,\n callArgs: ReadonlyArray<ts.Expression>,\n ctx: SubstitutionContext,\n helperKey = 'anonymous',\n visited = new Set<string>(),\n depth = 0,\n): SubstitutionResult {\n const out: SubstitutionResult = { paths: [], diagnostics: [], fullMask: false }\n\n if (depth > MAX_SUBSTITUTION_DEPTH) {\n out.diagnostics.push({\n id: 'llui/substitution-depth-exceeded',\n message: `Substitution depth exceeded 8 at helper \"${helperKey}\" (likely deep helper chain); contributing FULL_MASK at this call site.`,\n })\n out.fullMask = true\n return out\n }\n\n // 1. Helper-local paths — rare; contributed verbatim. Reserved for the\n // case where the helper's \"host state shape\" equals the consumer's\n // (e.g. trivial passthrough helpers).\n for (const p of entry.helperLocalPaths) out.paths.push(p)\n\n // 2. Per-parameter resolution.\n for (const param of entry.viaParams) {\n const arg = callArgs[param.index]\n\n if (param.shape === 'send' || param.shape === 'opaque') {\n // No path contribution — send is a Send<M> ref, opaque is intentional.\n continue\n }\n\n if (param.shape === 'thunk-returning-nodes') {\n // The call site provides a `() => Node[]` thunk that closes over\n // consumer-scope accessors. The substitution layer can't see inside\n // the closure without re-walking the consumer's view source — that\n // walk happens at the consumer's compile step, not here. We mark\n // this param's contribution as \"must be walked by consumer\", which\n // the cross-file walker handles by recursing into the thunk body\n // directly. The manifest substitution itself contributes no paths.\n continue\n }\n\n if (param.shape === 'options-bag') {\n if (!arg || !ts.isObjectLiteralExpression(arg)) {\n // Non-literal options bag (variable reference, spread, etc.) is\n // FULL_MASK at this call site. Real-world consumers do sometimes\n // pre-build the options bag; we accept the cost and warn.\n out.diagnostics.push({\n id: 'llui/opaque-options-bag',\n message: `Options-bag argument at index ${param.index} of \"${helperKey}\" is not an object literal; contributing FULL_MASK.`,\n })\n out.fullMask = true\n continue\n }\n // Unpack: each field listed in `fields` is matched against the\n // call-site object literal's property.\n for (const [fieldName, fieldSpec] of Object.entries(param.fields)) {\n const prop = arg.properties.find(\n (p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === fieldName,\n )\n if (!prop || !ts.isPropertyAssignment(prop)) continue\n const fieldExpr = prop.initializer\n substituteField(fieldSpec, fieldExpr, ctx, helperKey, visited, depth, out, entry)\n }\n continue\n }\n\n // shape: 'accessor'\n // Compose helper's innerReads. Each `kind: 'param-result*'` reads\n // through `callArgs[from]`'s accessor — which may be a different\n // parameter (the readsThroughResultOf case). Hence the resolver\n // takes `from` per innerRead, not the enclosing `param.index`.\n for (const ir of param.innerReads) {\n if (ir.kind === 'rooted') {\n out.paths.push(ir.path)\n continue\n }\n const liftPaths = liftPathsForArg(callArgs[ir.from], ctx)\n if (ir.kind === 'param-result') {\n for (const p of liftPaths) out.paths.push(p)\n } else if (ir.kind === 'param-result-path') {\n for (const lift of liftPaths) {\n out.paths.push(lift ? `${lift}.${ir.path}` : ir.path)\n }\n }\n }\n }\n\n // 6. Context-provider reads.\n if (entry.contextReads) {\n for (const cr of entry.contextReads) {\n const provider = ctx.providers.get(cr.context)\n if (!provider) {\n out.diagnostics.push({\n id: 'llui/missing-context-provider',\n message: `Helper \"${helperKey}\" reads from context \"${cr.context}\" but no matching provide(${cr.context}, ...) call was found in the consumer. The reads will fall back to FULL_MASK; add a provider or wrap the helper's call site in one.`,\n })\n out.fullMask = true\n continue\n }\n if (!provider.accessor) continue\n const rootParamName = getFirstParamName(provider.accessor)\n if (!rootParamName) continue\n const liftPaths = ctx.extractPaths(provider.accessor, rootParamName)\n for (const lift of liftPaths) {\n for (const sub of cr.subPaths) {\n out.paths.push(lift ? `${lift}.${sub}` : sub)\n }\n }\n }\n }\n\n // Dedup. Use a Set roundtrip — order is incidental for __prefixes.\n out.paths = [...new Set(out.paths)]\n return out\n}\n\nfunction substituteField(\n fieldSpec: FieldSpec,\n fieldExpr: ts.Expression,\n ctx: SubstitutionContext,\n helperKey: string,\n visited: Set<string>,\n depth: number,\n out: SubstitutionResult,\n entry: HelperEntry,\n): void {\n if (fieldSpec.shape === 'send' || fieldSpec.shape === 'opaque') return\n if (fieldSpec.shape === 'thunk-returning-nodes') return // consumer's view walker handles this\n\n // shape: 'accessor' — field's innerReads compose against the field\n // expression's accessor (depth-1 within the options bag).\n const liftPaths = liftPathsForArg(fieldExpr, ctx)\n for (const ir of fieldSpec.innerReads) {\n if (ir.kind === 'rooted') {\n out.paths.push(ir.path)\n } else if (ir.kind === 'param-result') {\n for (const p of liftPaths) out.paths.push(p)\n } else if (ir.kind === 'param-result-path') {\n for (const lift of liftPaths) {\n out.paths.push(lift ? `${lift}.${ir.path}` : ir.path)\n }\n }\n }\n // Silence the unused `entry`/`visited`/`helperKey`/`depth` — kept in\n // the signature to mirror substituteHelperCall and ease the eventual\n // recursive substitution Phase 3 lands.\n void entry\n void visited\n void helperKey\n void depth\n}\n\n/**\n * Walk the call-site argument (or options-bag field) as an accessor and\n * return its dotted path reads. Returns [] when the arg is not an arrow/\n * function expression — substitution falls through to no contribution.\n */\nfunction liftPathsForArg(arg: ts.Expression | undefined, ctx: SubstitutionContext): string[] {\n if (!arg) return []\n const accessor = unwrapAccessorArg(arg)\n if (!accessor) return []\n const rootParamName = getFirstParamName(accessor)\n if (!rootParamName) return []\n return ctx.extractPaths(accessor, rootParamName)\n}\n\n/**\n * Unwrap a call-site argument into the accessor function expression, if any.\n * Accepts inline arrows, function expressions, and identifiers that\n * resolve to a local const initializer (one level — Phase 3's walker\n * generalizes this via the existing `resolveAccessorBody`).\n */\nfunction unwrapAccessorArg(arg: ts.Expression): ts.ArrowFunction | ts.FunctionExpression | null {\n if (ts.isArrowFunction(arg) || ts.isFunctionExpression(arg)) return arg\n return null\n}\n\nfunction getFirstParamName(fn: ts.ArrowFunction | ts.FunctionExpression): string | undefined {\n const p0 = fn.parameters[0]\n if (!p0 || !ts.isIdentifier(p0.name)) return undefined\n return p0.name.text\n}\n"]}
@@ -0,0 +1,222 @@
1
+ import ts from 'typescript';
2
+ import type { Diagnostic } from './diagnostic.js';
3
+ export interface DiagnosticDefinition {
4
+ /** Stable id, e.g. `llui/opaque-view-call`. Per v2c §3 §8.2. */
5
+ id: string;
6
+ /** One-line description; useful for adapter UIs that don't render the message. */
7
+ description: string;
8
+ }
9
+ /**
10
+ * Per-file analysis output. Modules accumulate findings here during
11
+ * visitor dispatch; emit consumes it. The shape is intentionally
12
+ * open-ended — modules name their own slots and the umbrella's
13
+ * orchestrator never inspects them, only forwards.
14
+ */
15
+ export interface FileAnalysis {
16
+ /** Source file the analysis ran over. */
17
+ sourceFile: ts.SourceFile;
18
+ /** Per-module accumulator buckets, keyed by module name. */
19
+ perModule: Map<string, unknown>;
20
+ /** Diagnostics emitted during the walk. */
21
+ diagnostics: Diagnostic[];
22
+ }
23
+ /**
24
+ * Context passed to every visitor invocation. Modules use it to record
25
+ * findings, emit diagnostics, and consult shared state (the TS
26
+ * Compiler-API checker, the project root, sibling-module findings if
27
+ * dependencies allow).
28
+ */
29
+ export interface AnalysisContext {
30
+ sourceFile: ts.SourceFile;
31
+ /** TS TypeChecker, when the host adapter has built a Program. May be undefined for AST-only paths. */
32
+ checker: ts.TypeChecker | undefined;
33
+ /**
34
+ * Get the named module's accumulator slot (creating it lazily). The
35
+ * slot is whatever shape the module wrote; type-safe access is the
36
+ * module author's responsibility — typically via a typed `get<T>()`
37
+ * wrapper exported alongside the module.
38
+ */
39
+ getSlot<T>(moduleName: string, init: () => T): T;
40
+ /** Record a diagnostic. The diagnostic's `id` should match one declared in `DiagnosticDefinition[]`. */
41
+ reportDiagnostic(d: Diagnostic): void;
42
+ }
43
+ export interface EmissionContribution {
44
+ /** Module emitting this contribution — used for conflict reporting. */
45
+ module: string;
46
+ /** Field name on the `ComponentDef` object literal (e.g. `__msgSchema`). */
47
+ field: string;
48
+ /** AST expression to assign. The umbrella merges into the component()'s config arg. */
49
+ value: ts.Expression;
50
+ /**
51
+ * Optional per-call target. When set, this contribution applies only
52
+ * to the named `component()` call expression; the umbrella's
53
+ * emission-merger writes the field into that call's config-arg
54
+ * object literal. When omitted, the contribution is *file-global*:
55
+ * the merger writes the field into every `component()` call in the
56
+ * file (the common case — `__msgSchema`, `__prefixes`, `__schemaHash`
57
+ * are file-shape-derived).
58
+ *
59
+ * Per-call target is needed for `__componentMeta` (file + line vary
60
+ * per call site) and any other field whose value depends on the
61
+ * specific `component()` call location.
62
+ *
63
+ * Conflict-detection runs per-(field, target) tuple — two modules
64
+ * may both contribute `__custom` if they target *different* call
65
+ * expressions; same target on the same field is still an error.
66
+ */
67
+ target?: ts.CallExpression;
68
+ }
69
+ export interface EmissionContext {
70
+ sourceFile: ts.SourceFile;
71
+ factory: ts.NodeFactory;
72
+ }
73
+ /**
74
+ * A compiler module declares:
75
+ * - identification (name, compilerVersion semver against the umbrella);
76
+ * - the diagnostics it can emit (stable IDs);
77
+ * - per-`SyntaxKind` visitor handlers (the walker dispatches each AST
78
+ * node once; every module with a handler for its kind sees it);
79
+ * - optionally, an `emit` function that contributes ComponentDef fields
80
+ * after the walk completes;
81
+ * - optionally, `runtimeImports` declaring which `@llui/dom` symbols
82
+ * its emissions reference.
83
+ */
84
+ export interface CompilerModule {
85
+ name: string;
86
+ /** Semver range against the compiler API. v2c §5. */
87
+ compilerVersion: string;
88
+ /** Modules this one depends on. The registry verifies presence at activation. */
89
+ dependsOn?: string[];
90
+ diagnostics: DiagnosticDefinition[];
91
+ /**
92
+ * Optional AST pre-transform. Called once per file BEFORE the
93
+ * visitor walk and emission phase. Returns a (possibly rewritten)
94
+ * SourceFile; the result is threaded through subsequent modules'
95
+ * pre-transforms (in declaration order) and then becomes the file
96
+ * the visitor walks. Use for AST mutations the visitor model can't
97
+ * cleanly express — adjacent statement insertion, wrapping arrow
98
+ * expressions, etc. The agent's connect-pattern pass and the
99
+ * universal handler-tagger are the canonical examples (MODULE-MAPPING.md
100
+ * binding-descriptors entry).
101
+ *
102
+ * Most modules do NOT need this. Visitor + emit is the preferred
103
+ * shape because it composes deterministically across modules without
104
+ * threading a mutable SourceFile through each one. preTransform
105
+ * exists for the cases where AST mutation is unavoidable.
106
+ *
107
+ * The §2.1 "walker runs once per file" invariant is preserved: the
108
+ * VISITOR walk runs once. preTransform passes are additional, but
109
+ * they're typically cheap (targeted call-site rewrites, not deep
110
+ * recursive walks) and execute before the single visitor walk.
111
+ */
112
+ preTransform?(ctx: PreTransformContext, sf: ts.SourceFile): ts.SourceFile;
113
+ visitors: {
114
+ [K in ts.SyntaxKind]?: (ctx: AnalysisContext, node: ts.Node) => void;
115
+ };
116
+ /**
117
+ * Optional per-call AST rewrite, BOTTOM-UP (after children visited).
118
+ * Called once per `CallExpression` during the post-visitor transform
119
+ * phase, AFTER analysis has accumulated findings in
120
+ * `analysis.perModule` AND after `ts.visitEachChild` has recursively
121
+ * rewritten the node's children. Returns either:
122
+ * - `null` — node unchanged; chain continues with the next module's
123
+ * transformCall (if any).
124
+ * - a new `ts.CallExpression` — node replaced; subsequent modules'
125
+ * transformCall hooks see the new node (composes in declaration
126
+ * order, just like preTransform).
127
+ *
128
+ * Use for rewrites that depend on the rewritten children — e.g.
129
+ * row-factory emission inspects the render body for an already-emitted
130
+ * `elTemplate(...)` call, so element rewrites that produce
131
+ * `elTemplate` MUST have fired first. Module authors should treat
132
+ * transformCall as a pure function of its inputs (the node + analysis
133
+ * findings).
134
+ */
135
+ transformCall?(ctx: TransformCallContext, node: ts.CallExpression): ts.CallExpression | null;
136
+ /**
137
+ * Optional per-call AST rewrite, TOP-DOWN (before children visited).
138
+ * Mirrors `transformCall` but fires BEFORE `ts.visitEachChild`
139
+ * recurses into the call's children. Use when the rewrite must happen
140
+ * before the children are visited — most commonly when the rewrite
141
+ * changes the call's argument shape and the children's visitor would
142
+ * misinterpret the original shape. Memo-wrapping the `items:`
143
+ * accessor of an `each()` call is the canonical example: the wrapped
144
+ * accessor is what subsequent passes (item-selector dedup, mask
145
+ * injection) read.
146
+ *
147
+ * Both `transformCallEnter` and `transformCall` may be declared by
148
+ * the same module; enter fires top-down before recursion, transformCall
149
+ * fires bottom-up after. Ordering within each direction is declaration
150
+ * order across modules; the two directions never interleave for a
151
+ * given node.
152
+ */
153
+ transformCallEnter?(ctx: TransformCallContext, node: ts.CallExpression): ts.CallExpression | null;
154
+ /** Called once per file after the visitor pass completes. Returns this module's emission contributions. */
155
+ emit?(ctx: EmissionContext, analysis: FileAnalysis): EmissionContribution[];
156
+ /** Runtime symbol names this module's emissions reference (from `@llui/dom`). */
157
+ runtimeImports?: string[];
158
+ }
159
+ export interface PreTransformContext {
160
+ factory: ts.NodeFactory;
161
+ /**
162
+ * Shared per-file findings accumulator. preTransform passes that
163
+ * need to communicate with their own emit step (e.g. "this file
164
+ * needed scope-variant registrations") use this slot map. The same
165
+ * `analysis.perModule` map is later passed to visitors and emit.
166
+ */
167
+ analysis: FileAnalysis;
168
+ }
169
+ /**
170
+ * Context passed to every `transformCall` invocation. Carries the
171
+ * factory for building new AST nodes and a read-only view of analysis
172
+ * findings (visitors have already completed and populated
173
+ * `analysis.perModule` by the time transformCall fires).
174
+ */
175
+ export interface TransformCallContext {
176
+ factory: ts.NodeFactory;
177
+ /** Read-only access to visitor-phase findings. */
178
+ analysis: FileAnalysis;
179
+ }
180
+ export interface RegistryRunResult {
181
+ analysis: FileAnalysis;
182
+ emissions: EmissionContribution[];
183
+ /** Union of runtime imports from every active module. */
184
+ runtimeImports: string[];
185
+ }
186
+ /**
187
+ * The visitor registry. Built once per compiler boot from the user's
188
+ * `llui.config.ts` `modules: [...]` array; the umbrella's per-file
189
+ * pipeline calls `run(sourceFile, checker)` to drive a complete pass.
190
+ */
191
+ export declare class ModuleRegistry {
192
+ private readonly modules;
193
+ /** Pre-indexed by SyntaxKind for O(1) dispatch. */
194
+ private readonly visitorsByKind;
195
+ constructor(modules: ReadonlyArray<CompilerModule>);
196
+ private verifyDependencies;
197
+ private buildVisitorIndex;
198
+ /**
199
+ * Run a full analysis + emission pass over `sourceFile`. Phases:
200
+ * 1. Pre-transform: each module's `preTransform?` fires in
201
+ * declaration order; the (possibly rewritten) SourceFile flows
202
+ * through subsequent passes.
203
+ * 2. Visitor walk: a single AST walk dispatches each node to every
204
+ * module's matching SyntaxKind handler. Read-only — visitors
205
+ * accumulate findings in `analysis.perModule` but cannot rewrite.
206
+ * 3. Transform: a `ts.transform`-style walk dispatches each
207
+ * `CallExpression` to every module's `transformCallEnter?`
208
+ * (top-down, before children recursion) and `transformCall?`
209
+ * (bottom-up, after children recursion) hooks in declaration
210
+ * order; each hook's return value (if non-null) feeds the next.
211
+ * Composes call-site rewrites without each module paying a
212
+ * whole-file walk cost.
213
+ * 4. Emission: each module's `emit?` fires; the registry merges
214
+ * contributions, detecting (field, target) conflicts.
215
+ */
216
+ run(sourceFile: ts.SourceFile, checker?: ts.TypeChecker): RegistryRunResult;
217
+ /** Module names in declaration order. Adapters surface this for debug logs / config diagnostics. */
218
+ listModules(): string[];
219
+ /** All diagnostic definitions across active modules. Used by adapters to enumerate stable IDs. */
220
+ listDiagnostics(): DiagnosticDefinition[];
221
+ }
222
+ //# sourceMappingURL=module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"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"}