@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.
- package/LICENSE +21 -0
- package/dist/accessor-resolver.d.ts +58 -0
- package/dist/accessor-resolver.d.ts.map +1 -0
- package/dist/accessor-resolver.js +119 -0
- package/dist/accessor-resolver.js.map +1 -0
- package/dist/binding-descriptors.d.ts +105 -0
- package/dist/binding-descriptors.d.ts.map +1 -0
- package/dist/binding-descriptors.js +340 -0
- package/dist/binding-descriptors.js.map +1 -0
- package/dist/collect-deps.d.ts +49 -0
- package/dist/collect-deps.d.ts.map +1 -0
- package/dist/collect-deps.js +444 -0
- package/dist/collect-deps.js.map +1 -0
- package/dist/compiler-cache.d.ts +20 -0
- package/dist/compiler-cache.d.ts.map +1 -0
- package/dist/compiler-cache.js +20 -0
- package/dist/compiler-cache.js.map +1 -0
- package/dist/cross-file-resolver.d.ts +109 -0
- package/dist/cross-file-resolver.d.ts.map +1 -0
- package/dist/cross-file-resolver.js +530 -0
- package/dist/cross-file-resolver.js.map +1 -0
- package/dist/cross-file-walker.d.ts +63 -0
- package/dist/cross-file-walker.d.ts.map +1 -0
- package/dist/cross-file-walker.js +516 -0
- package/dist/cross-file-walker.js.map +1 -0
- package/dist/diagnostic.d.ts +76 -0
- package/dist/diagnostic.d.ts.map +1 -0
- package/dist/diagnostic.js +59 -0
- package/dist/diagnostic.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/introspection-factory.d.ts +54 -0
- package/dist/introspection-factory.d.ts.map +1 -0
- package/dist/introspection-factory.js +46 -0
- package/dist/introspection-factory.js.map +1 -0
- package/dist/manifest.d.ts +144 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +209 -0
- package/dist/manifest.js.map +1 -0
- package/dist/module.d.ts +222 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +256 -0
- package/dist/module.js.map +1 -0
- package/dist/modules/_element-helpers.d.ts +4 -0
- package/dist/modules/_element-helpers.d.ts.map +1 -0
- package/dist/modules/_element-helpers.js +138 -0
- package/dist/modules/_element-helpers.js.map +1 -0
- package/dist/modules/_msg-variants.d.ts +10 -0
- package/dist/modules/_msg-variants.d.ts.map +1 -0
- package/dist/modules/_msg-variants.js +97 -0
- package/dist/modules/_msg-variants.js.map +1 -0
- package/dist/modules/_shared.d.ts +16 -0
- package/dist/modules/_shared.d.ts.map +1 -0
- package/dist/modules/_shared.js +30 -0
- package/dist/modules/_shared.js.map +1 -0
- package/dist/modules/accessibility.d.ts +3 -0
- package/dist/modules/accessibility.d.ts.map +1 -0
- package/dist/modules/accessibility.js +82 -0
- package/dist/modules/accessibility.js.map +1 -0
- package/dist/modules/accessor-side-effect.d.ts +3 -0
- package/dist/modules/accessor-side-effect.d.ts.map +1 -0
- package/dist/modules/accessor-side-effect.js +113 -0
- package/dist/modules/accessor-side-effect.js.map +1 -0
- package/dist/modules/agent-emits-drift.d.ts +3 -0
- package/dist/modules/agent-emits-drift.d.ts.map +1 -0
- package/dist/modules/agent-emits-drift.js +158 -0
- package/dist/modules/agent-emits-drift.js.map +1 -0
- package/dist/modules/agent-example-on-payload.d.ts +3 -0
- package/dist/modules/agent-example-on-payload.d.ts.map +1 -0
- package/dist/modules/agent-example-on-payload.js +53 -0
- package/dist/modules/agent-example-on-payload.js.map +1 -0
- package/dist/modules/agent-exclusive-annotations.d.ts +3 -0
- package/dist/modules/agent-exclusive-annotations.d.ts.map +1 -0
- package/dist/modules/agent-exclusive-annotations.js +68 -0
- package/dist/modules/agent-exclusive-annotations.js.map +1 -0
- package/dist/modules/agent-missing-intent.d.ts +3 -0
- package/dist/modules/agent-missing-intent.d.ts.map +1 -0
- package/dist/modules/agent-missing-intent.js +47 -0
- package/dist/modules/agent-missing-intent.js.map +1 -0
- package/dist/modules/agent-msg-resolvable.d.ts +3 -0
- package/dist/modules/agent-msg-resolvable.d.ts.map +1 -0
- package/dist/modules/agent-msg-resolvable.js +161 -0
- package/dist/modules/agent-msg-resolvable.js.map +1 -0
- package/dist/modules/agent-nonextractable-handler.d.ts +3 -0
- package/dist/modules/agent-nonextractable-handler.d.ts.map +1 -0
- package/dist/modules/agent-nonextractable-handler.js +127 -0
- package/dist/modules/agent-nonextractable-handler.js.map +1 -0
- package/dist/modules/agent-optional-field-undocumented.d.ts +3 -0
- package/dist/modules/agent-optional-field-undocumented.d.ts.map +1 -0
- package/dist/modules/agent-optional-field-undocumented.js +67 -0
- package/dist/modules/agent-optional-field-undocumented.js.map +1 -0
- package/dist/modules/agent-tagsend-translator-missing.d.ts +3 -0
- package/dist/modules/agent-tagsend-translator-missing.d.ts.map +1 -0
- package/dist/modules/agent-tagsend-translator-missing.js +58 -0
- package/dist/modules/agent-tagsend-translator-missing.js.map +1 -0
- package/dist/modules/agent-warning-on-confirm.d.ts +3 -0
- package/dist/modules/agent-warning-on-confirm.d.ts.map +1 -0
- package/dist/modules/agent-warning-on-confirm.js +46 -0
- package/dist/modules/agent-warning-on-confirm.js.map +1 -0
- package/dist/modules/async-update.d.ts +3 -0
- package/dist/modules/async-update.d.ts.map +1 -0
- package/dist/modules/async-update.js +86 -0
- package/dist/modules/async-update.js.map +1 -0
- package/dist/modules/binding-descriptors.d.ts +4 -0
- package/dist/modules/binding-descriptors.d.ts.map +1 -0
- package/dist/modules/binding-descriptors.js +48 -0
- package/dist/modules/binding-descriptors.js.map +1 -0
- package/dist/modules/bitmask-overflow.d.ts +3 -0
- package/dist/modules/bitmask-overflow.d.ts.map +1 -0
- package/dist/modules/bitmask-overflow.js +152 -0
- package/dist/modules/bitmask-overflow.js.map +1 -0
- package/dist/modules/compiler-stamp.d.ts +3 -0
- package/dist/modules/compiler-stamp.d.ts.map +1 -0
- package/dist/modules/compiler-stamp.js +44 -0
- package/dist/modules/compiler-stamp.js.map +1 -0
- package/dist/modules/component-meta.d.ts +3 -0
- package/dist/modules/component-meta.d.ts.map +1 -0
- package/dist/modules/component-meta.js +44 -0
- package/dist/modules/component-meta.js.map +1 -0
- package/dist/modules/controlled-input.d.ts +3 -0
- package/dist/modules/controlled-input.d.ts.map +1 -0
- package/dist/modules/controlled-input.js +68 -0
- package/dist/modules/controlled-input.js.map +1 -0
- package/dist/modules/core-synthesis.d.ts +18 -0
- package/dist/modules/core-synthesis.d.ts.map +1 -0
- package/dist/modules/core-synthesis.js +748 -0
- package/dist/modules/core-synthesis.js.map +1 -0
- package/dist/modules/direct-state-in-view.d.ts +3 -0
- package/dist/modules/direct-state-in-view.d.ts.map +1 -0
- package/dist/modules/direct-state-in-view.js +103 -0
- package/dist/modules/direct-state-in-view.js.map +1 -0
- package/dist/modules/each-closure-violation.d.ts +3 -0
- package/dist/modules/each-closure-violation.d.ts.map +1 -0
- package/dist/modules/each-closure-violation.js +255 -0
- package/dist/modules/each-closure-violation.js.map +1 -0
- package/dist/modules/each-memo.d.ts +15 -0
- package/dist/modules/each-memo.d.ts.map +1 -0
- package/dist/modules/each-memo.js +115 -0
- package/dist/modules/each-memo.js.map +1 -0
- package/dist/modules/effect-without-handler.d.ts +3 -0
- package/dist/modules/effect-without-handler.d.ts.map +1 -0
- package/dist/modules/effect-without-handler.js +92 -0
- package/dist/modules/effect-without-handler.js.map +1 -0
- package/dist/modules/element-rewrite.d.ts +22 -0
- package/dist/modules/element-rewrite.d.ts.map +1 -0
- package/dist/modules/element-rewrite.js +1017 -0
- package/dist/modules/element-rewrite.js.map +1 -0
- package/dist/modules/empty-props.d.ts +3 -0
- package/dist/modules/empty-props.d.ts.map +1 -0
- package/dist/modules/empty-props.js +50 -0
- package/dist/modules/empty-props.js.map +1 -0
- package/dist/modules/exhaustive-effect-handling.d.ts +3 -0
- package/dist/modules/exhaustive-effect-handling.d.ts.map +1 -0
- package/dist/modules/exhaustive-effect-handling.js +61 -0
- package/dist/modules/exhaustive-effect-handling.js.map +1 -0
- package/dist/modules/exhaustive-update.d.ts +3 -0
- package/dist/modules/exhaustive-update.d.ts.map +1 -0
- package/dist/modules/exhaustive-update.js +146 -0
- package/dist/modules/exhaustive-update.js.map +1 -0
- package/dist/modules/forgotten-spread.d.ts +3 -0
- package/dist/modules/forgotten-spread.d.ts.map +1 -0
- package/dist/modules/forgotten-spread.js +51 -0
- package/dist/modules/forgotten-spread.js.map +1 -0
- package/dist/modules/form-boilerplate.d.ts +3 -0
- package/dist/modules/form-boilerplate.d.ts.map +1 -0
- package/dist/modules/form-boilerplate.js +101 -0
- package/dist/modules/form-boilerplate.js.map +1 -0
- package/dist/modules/imperative-dom-in-view.d.ts +3 -0
- package/dist/modules/imperative-dom-in-view.d.ts.map +1 -0
- package/dist/modules/imperative-dom-in-view.js +123 -0
- package/dist/modules/imperative-dom-in-view.js.map +1 -0
- package/dist/modules/item-dedup.d.ts +7 -0
- package/dist/modules/item-dedup.d.ts.map +1 -0
- package/dist/modules/item-dedup.js +204 -0
- package/dist/modules/item-dedup.js.map +1 -0
- package/dist/modules/map-on-state-array.d.ts +3 -0
- package/dist/modules/map-on-state-array.d.ts.map +1 -0
- package/dist/modules/map-on-state-array.js +84 -0
- package/dist/modules/map-on-state-array.js.map +1 -0
- package/dist/modules/mask-legend.d.ts +10 -0
- package/dist/modules/mask-legend.d.ts.map +1 -0
- package/dist/modules/mask-legend.js +50 -0
- package/dist/modules/mask-legend.js.map +1 -0
- package/dist/modules/missing-memo.d.ts +3 -0
- package/dist/modules/missing-memo.d.ts.map +1 -0
- package/dist/modules/missing-memo.js +114 -0
- package/dist/modules/missing-memo.js.map +1 -0
- package/dist/modules/msg-annotations.d.ts +9 -0
- package/dist/modules/msg-annotations.d.ts.map +1 -0
- package/dist/modules/msg-annotations.js +54 -0
- package/dist/modules/msg-annotations.js.map +1 -0
- package/dist/modules/msg-schema.d.ts +10 -0
- package/dist/modules/msg-schema.d.ts.map +1 -0
- package/dist/modules/msg-schema.js +70 -0
- package/dist/modules/msg-schema.js.map +1 -0
- package/dist/modules/namespace-import.d.ts +3 -0
- package/dist/modules/namespace-import.d.ts.map +1 -0
- package/dist/modules/namespace-import.js +80 -0
- package/dist/modules/namespace-import.js.map +1 -0
- package/dist/modules/nested-send-in-update.d.ts +3 -0
- package/dist/modules/nested-send-in-update.d.ts.map +1 -0
- package/dist/modules/nested-send-in-update.js +77 -0
- package/dist/modules/nested-send-in-update.js.map +1 -0
- package/dist/modules/no-barrel-import-when-subpath-exists.d.ts +3 -0
- package/dist/modules/no-barrel-import-when-subpath-exists.d.ts.map +1 -0
- package/dist/modules/no-barrel-import-when-subpath-exists.js +100 -0
- package/dist/modules/no-barrel-import-when-subpath-exists.js.map +1 -0
- package/dist/modules/no-eager-item-accessor.d.ts +3 -0
- package/dist/modules/no-eager-item-accessor.d.ts.map +1 -0
- package/dist/modules/no-eager-item-accessor.js +74 -0
- package/dist/modules/no-eager-item-accessor.js.map +1 -0
- package/dist/modules/no-let-reactive-accessor.d.ts +3 -0
- package/dist/modules/no-let-reactive-accessor.d.ts.map +1 -0
- package/dist/modules/no-let-reactive-accessor.js +227 -0
- package/dist/modules/no-let-reactive-accessor.js.map +1 -0
- package/dist/modules/no-list-render-in-sample.d.ts +3 -0
- package/dist/modules/no-list-render-in-sample.d.ts.map +1 -0
- package/dist/modules/no-list-render-in-sample.js +89 -0
- package/dist/modules/no-list-render-in-sample.js.map +1 -0
- package/dist/modules/no-sample-in-accessor.d.ts +3 -0
- package/dist/modules/no-sample-in-accessor.d.ts.map +1 -0
- package/dist/modules/no-sample-in-accessor.js +141 -0
- package/dist/modules/no-sample-in-accessor.js.map +1 -0
- package/dist/modules/no-sample-in-reactive-position.d.ts +3 -0
- package/dist/modules/no-sample-in-reactive-position.d.ts.map +1 -0
- package/dist/modules/no-sample-in-reactive-position.js +72 -0
- package/dist/modules/no-sample-in-reactive-position.js.map +1 -0
- package/dist/modules/pure-update-function.d.ts +3 -0
- package/dist/modules/pure-update-function.d.ts.map +1 -0
- package/dist/modules/pure-update-function.js +127 -0
- package/dist/modules/pure-update-function.js.map +1 -0
- package/dist/modules/reactive-paths.d.ts +3 -0
- package/dist/modules/reactive-paths.d.ts.map +1 -0
- package/dist/modules/reactive-paths.js +77 -0
- package/dist/modules/reactive-paths.js.map +1 -0
- package/dist/modules/row-factory.d.ts +12 -0
- package/dist/modules/row-factory.d.ts.map +1 -0
- package/dist/modules/row-factory.js +385 -0
- package/dist/modules/row-factory.js.map +1 -0
- package/dist/modules/schema-hash.d.ts +15 -0
- package/dist/modules/schema-hash.d.ts.map +1 -0
- package/dist/modules/schema-hash.js +70 -0
- package/dist/modules/schema-hash.js.map +1 -0
- package/dist/modules/spread-in-children.d.ts +3 -0
- package/dist/modules/spread-in-children.d.ts.map +1 -0
- package/dist/modules/spread-in-children.js +144 -0
- package/dist/modules/spread-in-children.js.map +1 -0
- package/dist/modules/state-mutation.d.ts +3 -0
- package/dist/modules/state-mutation.d.ts.map +1 -0
- package/dist/modules/state-mutation.js +138 -0
- package/dist/modules/state-mutation.js.map +1 -0
- package/dist/modules/state-schema.d.ts +8 -0
- package/dist/modules/state-schema.d.ts.map +1 -0
- package/dist/modules/state-schema.js +55 -0
- package/dist/modules/state-schema.js.map +1 -0
- package/dist/modules/static-items.d.ts +3 -0
- package/dist/modules/static-items.d.ts.map +1 -0
- package/dist/modules/static-items.js +125 -0
- package/dist/modules/static-items.js.map +1 -0
- package/dist/modules/static-on.d.ts +3 -0
- package/dist/modules/static-on.d.ts.map +1 -0
- package/dist/modules/static-on.js +100 -0
- package/dist/modules/static-on.js.map +1 -0
- package/dist/modules/string-effect-callback.d.ts +3 -0
- package/dist/modules/string-effect-callback.d.ts.map +1 -0
- package/dist/modules/string-effect-callback.js +50 -0
- package/dist/modules/string-effect-callback.js.map +1 -0
- package/dist/modules/structural-mask.d.ts +8 -0
- package/dist/modules/structural-mask.d.ts.map +1 -0
- package/dist/modules/structural-mask.js +76 -0
- package/dist/modules/structural-mask.js.map +1 -0
- package/dist/modules/subapp-requires-reason.d.ts +3 -0
- package/dist/modules/subapp-requires-reason.d.ts.map +1 -0
- package/dist/modules/subapp-requires-reason.js +129 -0
- package/dist/modules/subapp-requires-reason.js.map +1 -0
- package/dist/modules/text-mask.d.ts +12 -0
- package/dist/modules/text-mask.d.ts.map +1 -0
- package/dist/modules/text-mask.js +63 -0
- package/dist/modules/text-mask.js.map +1 -0
- package/dist/modules/view-bag-import.d.ts +3 -0
- package/dist/modules/view-bag-import.d.ts.map +1 -0
- package/dist/modules/view-bag-import.js +80 -0
- package/dist/modules/view-bag-import.js.map +1 -0
- package/dist/msg-annotations.d.ts +104 -0
- package/dist/msg-annotations.d.ts.map +1 -0
- package/dist/msg-annotations.js +242 -0
- package/dist/msg-annotations.js.map +1 -0
- package/dist/msg-schema.d.ts +130 -0
- package/dist/msg-schema.d.ts.map +1 -0
- package/dist/msg-schema.js +770 -0
- package/dist/msg-schema.js.map +1 -0
- package/dist/schema-hash.d.ts +16 -0
- package/dist/schema-hash.d.ts.map +1 -0
- package/dist/schema-hash.js +31 -0
- package/dist/schema-hash.js.map +1 -0
- package/dist/state-schema.d.ts +41 -0
- package/dist/state-schema.d.ts.map +1 -0
- package/dist/state-schema.js +156 -0
- package/dist/state-schema.js.map +1 -0
- package/dist/transform.d.ts +109 -0
- package/dist/transform.d.ts.map +1 -0
- package/dist/transform.js +1390 -0
- package/dist/transform.js.map +1 -0
- package/dist/version.d.ts +11 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +11 -0
- package/dist/version.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binding-descriptors.js","sourceRoot":"","sources":["../src/binding-descriptors.ts"],"names":[],"mappings":"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","sourcesContent":["import ts from 'typescript'\n\n/**\n * Compiler passes that surface the Msg variants currently dispatchable\n * from rendered UI to the agent layer's `list_actions`. Two passes\n * cover two distinct dispatch shapes:\n *\n * 1. `tagEventHandlerSends` — tags event-handler arrow functions\n * (`onClick`, `onInput`, …) whose body contains literal\n * `<id>({type: 'X', …})` call sites. Wraps with\n * `Object.assign(arrow, { __lluiVariants: ['X', …] })`. The\n * runtime in `@llui/dom` `elements.ts` / `el-split.ts` reads the\n * metadata at bind time and registers the variants on the active\n * component instance for the lifetime of the binding's scope.\n *\n * 2. `injectScopeVariantRegistrations` — handles the\n * dispatch-translation case that pass (1) can't follow:\n * `<bag>.connect(get, sendFn, …)` where `sendFn` is a user-\n * defined function that translates library Msgs into app Msgs via\n * `dispatch({type: 'X', …})`. Static analysis of the library's\n * internal onClick can't see across this hop. The pass detects the\n * `*.connect(get, sendFn, …)` syntactic pattern, follows `sendFn`\n * to its declaration, scans the body for literal dispatches, and\n * inserts a runtime `__registerScopeVariants(['X', …])` call\n * immediately before the connect call. Lifetime semantics fall\n * out of the render context: the call's active scope is whatever\n * `each(...)` / `branch(...)` / root scope happens to be live when\n * the view evaluates that statement.\n *\n * Both passes are gated on `devMode || emitAgentMetadata` in\n * `transform.ts`. Production bundles without agent integration get\n * neither the per-handler `Object.assign` cost nor the registration\n * statements.\n *\n * False positives are deliberate. The alternative — proving the\n * callee resolves to the destructured `send` from a `View` bag, or\n * tracing function calls across files — would require full scope\n * tracking the compiler doesn't do. In practice the patterns\n * `<id>({type:'X',…})` and `*.connect(get, fn, …)` are reliable\n * shape-level signals; an extra entry in the live descriptor\n * registry just means the agent sees one more \"affordable variant\"\n * than necessary — never a wrong dispatch, never a runtime error.\n *\n * False negatives stay where they were: non-literal `type` values\n * (`send({ type: nextStep })`), and dispatch translators bound via\n * patterns other than `*.connect(get, fn, …)`. Apps that hit those\n * cases declare `agentAffordances` on the component def — the\n * documented escape hatch.\n *\n * @see agent spec §5.2, §12.2\n * @see @llui/dom binding-descriptors.ts (runtime registry + helper)\n */\n\n// ── Pass 1: dispatch-handler tagger (universal) ─────────────────────\n\n/**\n * Walks every `ArrowFunction` and `FunctionExpression` in the source\n * and wraps any whose body contains literal `<id>({type:'X', …})`\n * dispatches with `Object.assign(fn, {__lluiVariants: ['X', …]})`.\n *\n * The runtime (in `@llui/dom` `elements.ts` / `el-split.ts`) reads\n * `__lluiVariants` from event-handler bindings only — so tags placed\n * on functions in non-handler positions (a const declared but never\n * bound, an arrow passed to `Array.filter`, a view function whose\n * body has nested handlers with dispatches) are runtime-inert. The\n * compiler tags generously; the runtime registers selectively.\n *\n * Universal scope means three concrete patterns all surface their\n * variants without the app author having to think about it:\n *\n * 1. **Inline event-handler arrows** —\n * `onClick: () => send({type:'X'})` (the original Pass 1 case).\n * 2. **Const-bound translator functions** —\n * `const sendMenu = (m) => dispatch({type:'Y'})` paired with\n * `*.connect(get, sendMenu, …)` (the original Pass 3 case). The\n * tag travels with the function reference; library connect impls\n * use `tagSend(send, libVariants, fn)` to propagate it onto\n * returned handlers.\n * 3. **Positional-arg handlers** —\n * `helper(label, () => send({type:'Z'}))` where `helper` is an\n * app-defined wrapper like `navButton(label, onClick)` that\n * eventually binds the function as an event listener. The arrow\n * is still tagged at its declaration site, and the runtime reads\n * the tag when the wrapper binds it.\n *\n * False positives are deliberate. The alternative — proving that a\n * tagged arrow actually reaches an event-handler binding — would\n * require cross-function, cross-file flow analysis the compiler\n * doesn't do. In practice the cost of an over-tagged arrow is bytes,\n * not behavior: the runtime never reads the tag from non-handler\n * bindings.\n *\n * Pass 2's `collectLocalFns` resolves identifiers to their original\n * arrow/function initializers; this pass replaces those initializers\n * with `Object.assign(arrow, {…})` wrappers. Run Pass 2 BEFORE Pass 1\n * so the resolver still sees raw arrows.\n *\n * Already-wrapped functions (CallExpressions, including user-applied\n * `tagSend(...)` or this pass's own prior output) are skipped — the\n * pass only fires on bare arrow/function expressions.\n */\nexport function tagDispatchHandlers(node: ts.SourceFile, f: ts.NodeFactory): ts.SourceFile {\n const transformer: ts.TransformerFactory<ts.SourceFile> = (ctx) => {\n const visit: ts.Visitor = (n) => {\n if (ts.isArrowFunction(n) || ts.isFunctionExpression(n)) {\n // Visit children first so nested arrows are tagged before\n // their parents see them. The parent's\n // `collectLiteralSendVariants` walks the original (unwrapped)\n // body — the recursive collect doesn't descend into nested\n // function bodies (that would cause an outer arrow to inherit\n // every dispatch from every closure within it, which is too\n // permissive).\n const inner = ts.visitEachChild(n, visit, ctx) as ts.ArrowFunction | ts.FunctionExpression\n const variants = collectLiteralSendVariants(inner.body)\n if (variants.length > 0) {\n return wrapWithVariants(inner, variants, f)\n }\n return inner\n }\n return ts.visitEachChild(n, visit, ctx)\n }\n return (sf) => ts.visitEachChild(sf, visit, ctx) as ts.SourceFile\n }\n const result = ts.transform(node, [transformer])\n const out = result.transformed[0] as ts.SourceFile\n result.dispose()\n return out\n}\n\nfunction wrapWithVariants(\n arrow: ts.ArrowFunction | ts.FunctionExpression,\n variants: readonly string[],\n f: ts.NodeFactory,\n): ts.CallExpression {\n return f.createCallExpression(\n f.createPropertyAccessExpression(f.createIdentifier('Object'), 'assign'),\n undefined,\n [\n arrow,\n f.createObjectLiteralExpression(\n [\n f.createPropertyAssignment(\n '__lluiVariants',\n f.createArrayLiteralExpression(\n variants.map((v) => f.createStringLiteral(v)),\n false,\n ),\n ),\n ],\n false,\n ),\n ],\n )\n}\n\n// ── Pass 2: connect-pattern registration injector ────────────────\n\nexport interface InjectResult {\n sf: ts.SourceFile\n /** True when at least one `__registerScopeVariants(...)` call was inserted. */\n injected: boolean\n}\n\nexport function injectScopeVariantRegistrations(\n node: ts.SourceFile,\n f: ts.NodeFactory,\n): InjectResult {\n let injected = false\n\n const transformer: ts.TransformerFactory<ts.SourceFile> = (ctx) => {\n /**\n * Tracks whether we're inside a function body. Top-level\n * (module-scope) connect calls are skipped — there's no render\n * context active when module code runs, so the registration\n * would silently no-op anyway, and emitting it adds noise. Apps\n * with module-scope translators (a single shared `parts` re-used\n * across views) declare `agentAffordances` instead.\n */\n let inFunction = 0\n\n function rewriteBlock<B extends ts.Block | ts.SourceFile>(block: B): B {\n const stmts = (block as ts.Block | ts.SourceFile).statements\n const localFns = collectLocalFns(stmts)\n const out: ts.Statement[] = []\n for (const stmt of stmts) {\n const visited = ts.visitNode(stmt, (n) => visitNode(n, localFns)) as ts.Statement\n out.push(visited)\n }\n if (ts.isSourceFile(block)) {\n return f.updateSourceFile(block, out) as B\n }\n return f.updateBlock(block, out) as B\n }\n\n function visitNode(\n n: ts.Node,\n localFns: Map<string, ts.ArrowFunction | ts.FunctionExpression>,\n ): ts.Node {\n if (ts.isBlock(n)) {\n return rewriteBlock(n)\n }\n // Track function-body nesting so we know whether the current\n // call site can plausibly run within a render context. Arrow\n // functions and function expressions/declarations both qualify.\n if (\n ts.isArrowFunction(n) ||\n ts.isFunctionExpression(n) ||\n ts.isFunctionDeclaration(n) ||\n ts.isMethodDeclaration(n)\n ) {\n inFunction++\n const r = ts.visitEachChild(n, (c) => visitNode(c, localFns), ctx)\n inFunction--\n return r\n }\n if (ts.isCallExpression(n) && inFunction > 0 && isConnectCallShape(n)) {\n const sendArg = n.arguments[1]!\n const sendFn = resolveSendFn(sendArg, localFns)\n if (sendFn) {\n const variants = collectLiteralSendVariants(sendFn.body)\n if (variants.length > 0) {\n // Replace the call expression with a comma expression:\n // (__registerScopeVariants([...]), originalCall)\n // The comma keeps the call's value position intact (so\n // `const parts = popover.connect(...)` still binds the\n // original return), and ensures the registration fires\n // *before* the call returns. This positions correctly\n // regardless of the surrounding function context: view\n // body, render callback inside `each(...)`, or any\n // nested helper called from within a view.\n injected = true\n const inner = ts.visitEachChild(\n n,\n (c) => visitNode(c, localFns),\n ctx,\n ) as ts.CallExpression\n return f.createParenthesizedExpression(\n f.createBinaryExpression(\n emitRegisterCall(variants, f),\n f.createToken(ts.SyntaxKind.CommaToken),\n inner,\n ),\n )\n }\n }\n }\n return ts.visitEachChild(n, (c) => visitNode(c, localFns), ctx)\n }\n\n return (sf) => rewriteBlock(sf)\n }\n\n const result = ts.transform(node, [transformer])\n const out = result.transformed[0] as ts.SourceFile\n result.dispose()\n return { sf: out, injected }\n}\n\n/**\n * Collect `const fn = (m) => { … }` / `const fn = function(m){ … }`\n * declarations in `stmts` so an identifier passed to a connect call\n * later in the same scope can resolve to its body. Conservative —\n * only direct function-valued initializers count; aliasing\n * (`const a = b`) is not followed.\n */\nfunction collectLocalFns(\n stmts: ts.NodeArray<ts.Statement>,\n): Map<string, ts.ArrowFunction | ts.FunctionExpression> {\n const out = new Map<string, ts.ArrowFunction | ts.FunctionExpression>()\n for (const stmt of stmts) {\n if (!ts.isVariableStatement(stmt)) continue\n for (const decl of stmt.declarationList.declarations) {\n if (!ts.isIdentifier(decl.name)) continue\n const init = decl.initializer\n if (init && (ts.isArrowFunction(init) || ts.isFunctionExpression(init))) {\n out.set(decl.name.text, init)\n }\n }\n }\n return out\n}\n\nfunction isConnectCallShape(node: ts.CallExpression): boolean {\n if (!ts.isPropertyAccessExpression(node.expression)) return false\n if (node.expression.name.text !== 'connect') return false\n return node.arguments.length >= 2\n}\n\nfunction resolveSendFn(\n arg: ts.Expression,\n localFns: Map<string, ts.ArrowFunction | ts.FunctionExpression>,\n): ts.ArrowFunction | ts.FunctionExpression | null {\n if (ts.isArrowFunction(arg) || ts.isFunctionExpression(arg)) return arg\n if (ts.isIdentifier(arg)) return localFns.get(arg.text) ?? null\n return null\n}\n\nfunction emitRegisterCall(variants: readonly string[], f: ts.NodeFactory): ts.CallExpression {\n return f.createCallExpression(f.createIdentifier('__registerScopeVariants'), undefined, [\n f.createArrayLiteralExpression(\n variants.map((v) => f.createStringLiteral(v)),\n false,\n ),\n ])\n}\n\n// ── Shared: literal-send variant collection ──────────────────────────\n\n/**\n * Walk `node`, collecting every literal type string from\n * `<id>({ type: 'literal', … })` call sites. De-dupes while preserving\n * first-seen order so the emitted array reads naturally for anyone\n * inspecting the compiled output.\n *\n * The walk stops at nested function/arrow boundaries — every function\n * \"owns\" its own dispatches, and the universal tagger visits each\n * function separately. Without this guard, an outer arrow whose body\n * includes a nested onClick arrow would be tagged with the inner\n * arrow's variants too: a parent view tagged with every dispatch in\n * every child handler. The runtime only reads the tag from event-\n * handler bindings, so functionally that's harmless — but it bloats\n * the wrapped output and obscures intent.\n */\nfunction collectLiteralSendVariants(body: ts.Node): string[] {\n const seen = new Set<string>()\n const out: string[] = []\n function visit(n: ts.Node): void {\n // Stop at every nested function/arrow boundary — those functions\n // own their own variants and are tagged independently. An outer\n // arrow whose body contains `setTimeout(() => send(...), 100)`\n // doesn't dispatch directly when invoked; the inner arrow does\n // when the timer fires. Counting the inner's variants on the\n // outer would be too permissive.\n if (\n ts.isArrowFunction(n) ||\n ts.isFunctionExpression(n) ||\n ts.isFunctionDeclaration(n) ||\n ts.isMethodDeclaration(n)\n ) {\n return\n }\n if (ts.isCallExpression(n)) {\n const callee = n.expression\n const first = n.arguments[0]\n if (\n callee &&\n ts.isIdentifier(callee) &&\n isDispatcherName(callee.text) &&\n first &&\n ts.isObjectLiteralExpression(first)\n ) {\n const variant = readTypeLiteral(first)\n if (variant !== null && !seen.has(variant)) {\n seen.add(variant)\n out.push(variant)\n }\n }\n }\n ts.forEachChild(n, visit)\n }\n visit(body)\n return out\n}\n\n/**\n * Recognize a callee as a dispatcher by name. The convention in LLui\n * apps is `send` (the framework-provided dispatch) or `dispatch` (a\n * common app-level alias), plus `send*` / `dispatch*` prefixes for\n * named translators (`sendMenu`, `dispatchMenu`).\n *\n * Without this filter, the tagger would treat element-helper calls\n * like `button({type: 'button'})` and `input({type: 'email'})` as\n * dispatch sites — they syntactically match `<Identifier>({type:\n * literal})`, but they construct DOM, not Msgs. Phantom variants\n * like `button` and `email` would then leak into the binding-\n * descriptor registry and surface as agent affordances. Filtering\n * by name keeps the convention narrow enough that false positives\n * are nearly zero while leaving room for translator naming.\n *\n * Apps that use unconventional dispatcher names (`forward`,\n * `tellMenu`) need to either rename to the convention or wrap their\n * handlers with the runtime `tagSend`/`tagVariants` helpers\n * explicitly — the same escape hatch library code already uses.\n */\nfunction isDispatcherName(name: string): boolean {\n return /^(send|dispatch)/i.test(name)\n}\n\nfunction readTypeLiteral(obj: ts.ObjectLiteralExpression): string | null {\n for (const prop of obj.properties) {\n if (!ts.isPropertyAssignment(prop)) continue\n if (!prop.name) continue\n const nameOk =\n (ts.isIdentifier(prop.name) && prop.name.text === 'type') ||\n (ts.isStringLiteral(prop.name) && prop.name.text === 'type')\n if (!nameOk) continue\n const init = prop.initializer\n if (ts.isStringLiteral(init)) return init.text\n if (ts.isNoSubstitutionTemplateLiteral(init)) return init.text\n }\n return null\n}\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Walk the AST and collect every unique state access path referenced by
|
|
4
|
+
* a reactive accessor. A reactive accessor is one of:
|
|
5
|
+
*
|
|
6
|
+
* - An inline arrow / function expression at a reactive position
|
|
7
|
+
* (`text(s => s.count)`, `div({ title: s => s.title })`,
|
|
8
|
+
* `show({ when: s => s.gated })`, etc.).
|
|
9
|
+
* - An Identifier at a reactive position that resolves to a callable
|
|
10
|
+
* in this file — a const-bound arrow / function expression,
|
|
11
|
+
* a hoisted function declaration, or `const x = memo(arrow)`.
|
|
12
|
+
*
|
|
13
|
+
* The second case lets authors refactor a literal arrow into a named
|
|
14
|
+
* helper without losing the reactive-mask optimization (a precise mask
|
|
15
|
+
* for `__dirty` and structural-primitive `__mask`). Without it, the
|
|
16
|
+
* runtime falls back to FULL_MASK — correct, but every binding fires
|
|
17
|
+
* on every state change.
|
|
18
|
+
*
|
|
19
|
+
* Shared by the bit-assignment path (`collectDeps`, below) and the
|
|
20
|
+
* `diagnostics.ts` bitmask-overflow warning.
|
|
21
|
+
*/
|
|
22
|
+
export declare function collectStatePathsFromSource(sourceFile: ts.SourceFile): Set<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Per-accessor path sets — one entry per reactive arrow/function. Used
|
|
25
|
+
* by the bitmask-overflow diagnostic to find clusters of paths that
|
|
26
|
+
* always fire together (co-occurrence analysis).
|
|
27
|
+
*/
|
|
28
|
+
export declare function collectAccessorPathSets(sourceFile: ts.SourceFile): Set<string>[];
|
|
29
|
+
/**
|
|
30
|
+
* Pre-scan a source file to collect all unique state access paths
|
|
31
|
+
* referenced by reactive accessors (arrow functions in props and text() calls).
|
|
32
|
+
*
|
|
33
|
+
* Returns a pair of maps:
|
|
34
|
+
* - `lo`: paths at bit positions 0..30, with value `1 << position`
|
|
35
|
+
* - `hi`: paths at bit positions 31..61, with value `1 << (position - 31)`
|
|
36
|
+
*
|
|
37
|
+
* Bit positions past 61 collapse to `-1` (FULL_MASK) in the `lo` map and
|
|
38
|
+
* cause every binding reading them to re-evaluate on every cycle. The
|
|
39
|
+
* `bitmask-overflow` lint rule warns the user to restructure state.
|
|
40
|
+
*
|
|
41
|
+
* Components with ≤31 paths see an empty `hi` map; the compiler skips
|
|
42
|
+
* all high-word emit so the generated code is byte-identical to the
|
|
43
|
+
* pre-multi-word baseline.
|
|
44
|
+
*/
|
|
45
|
+
export declare function collectDeps(source: string, extraPaths?: ReadonlySet<string>): {
|
|
46
|
+
lo: Map<string, number>;
|
|
47
|
+
hi: Map<string, number>;
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=collect-deps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-deps.d.ts","sourceRoot":"","sources":["../src/collect-deps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAyG3B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAuBlF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAwBhF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAC/B;IACD,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvB,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACxB,CAsCA"}
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { resolveAccessorBody } from './accessor-resolver.js';
|
|
3
|
+
/**
|
|
4
|
+
* Names whose first arg is itself a reactive accessor (the existing
|
|
5
|
+
* arrow walker handles them) or which are explicitly excluded
|
|
6
|
+
* (sample/item read state imperatively / per-row, not as state
|
|
7
|
+
* accessors). When a delegating accessor's body contains a call to one
|
|
8
|
+
* of these, we don't follow it — recursion is reserved for "this is
|
|
9
|
+
* just a thin wrapper that hands the state to another local helper."
|
|
10
|
+
*/
|
|
11
|
+
const NON_DELEGATION_HELPERS = new Set(['sample', 'item', 'memo', 'text', 'unsafeHtml']);
|
|
12
|
+
/**
|
|
13
|
+
* Walk a delegating accessor's body looking for calls to OTHER local
|
|
14
|
+
* functions that take the state param verbatim — `helper(s)` where
|
|
15
|
+
* `s` matches the outer accessor's param name. For each, hand the
|
|
16
|
+
* resolved declaration back so the caller can recurse into its body.
|
|
17
|
+
*
|
|
18
|
+
* Skips:
|
|
19
|
+
* - Framework helpers (`memo`, `text`, etc.) — their arrow args are
|
|
20
|
+
* visited by the top-level arrow walker; we'd double-count.
|
|
21
|
+
* - Method calls (`s.items.filter(...)`) — the callee is a builtin,
|
|
22
|
+
* not a local function we can resolve.
|
|
23
|
+
* - Nested function bodies — params inside a `(item) => …` shadow
|
|
24
|
+
* ours, so a `helper(s)` deep in there isn't (necessarily)
|
|
25
|
+
* handing OUR state in. Conservative: don't recurse through
|
|
26
|
+
* lambda boundaries.
|
|
27
|
+
*/
|
|
28
|
+
function visitTopLevelDelegations(body, stateParamName, follow) {
|
|
29
|
+
function visit(node) {
|
|
30
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
|
|
31
|
+
const name = node.expression.text;
|
|
32
|
+
if (!NON_DELEGATION_HELPERS.has(name)) {
|
|
33
|
+
const arg0 = node.arguments[0];
|
|
34
|
+
if (arg0 && ts.isIdentifier(arg0) && arg0.text === stateParamName) {
|
|
35
|
+
const resolved = resolveAccessorBody(node.expression);
|
|
36
|
+
if (resolved)
|
|
37
|
+
follow(resolved);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Don't descend into nested function bodies — their params shadow
|
|
42
|
+
// ours, and any call inside them isn't unambiguously delegating
|
|
43
|
+
// our state.
|
|
44
|
+
if (ts.isArrowFunction(node) ||
|
|
45
|
+
ts.isFunctionExpression(node) ||
|
|
46
|
+
ts.isFunctionDeclaration(node)) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
ts.forEachChild(node, visit);
|
|
50
|
+
}
|
|
51
|
+
// If the body itself is a function, there's nothing at the top
|
|
52
|
+
// level to inspect — its own body is a separate scope.
|
|
53
|
+
if (ts.isArrowFunction(body) || ts.isFunctionExpression(body) || ts.isFunctionDeclaration(body)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
visit(body);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Extract paths from a callable accessor (arrow / fn-expr / fn-decl)
|
|
60
|
+
* into the given set. Recurses through call-delegations to other local
|
|
61
|
+
* helpers so that `(s) => filtered(s)` / `(s) => { void s.x; return
|
|
62
|
+
* inner(s) }` correctly contribute the helper's state-path reads.
|
|
63
|
+
* Without recursion the precise mask under-counts — fields read only
|
|
64
|
+
* via the helper drop off the bitmask, and any sibling reactive
|
|
65
|
+
* accessor that reads them produces a non-zero `dirty` that AND'd with
|
|
66
|
+
* the narrow each.__mask is zero, silently skipping the reconcile.
|
|
67
|
+
*
|
|
68
|
+
* `visited` breaks cycles on mutually-recursive helpers — terminates
|
|
69
|
+
* the walk; doesn't try to be precise about what such helpers read.
|
|
70
|
+
*/
|
|
71
|
+
function extractAccessorPaths(accessor, paths, visited = new Set()) {
|
|
72
|
+
if (visited.has(accessor))
|
|
73
|
+
return false;
|
|
74
|
+
visited.add(accessor);
|
|
75
|
+
const params = accessor.parameters;
|
|
76
|
+
if (params.length !== 1)
|
|
77
|
+
return false;
|
|
78
|
+
const paramName = params[0].name;
|
|
79
|
+
if (!ts.isIdentifier(paramName))
|
|
80
|
+
return false;
|
|
81
|
+
if (!accessor.body)
|
|
82
|
+
return false;
|
|
83
|
+
const before = paths.size;
|
|
84
|
+
extractPaths(accessor.body, paramName.text, '', paths);
|
|
85
|
+
// Follow delegations: `(s) => helper(s)` — extract `helper`'s body's
|
|
86
|
+
// state paths too. Reuses the `visited` set across the recursion
|
|
87
|
+
// chain so cycles terminate.
|
|
88
|
+
visitTopLevelDelegations(accessor.body, paramName.text, (resolved) => {
|
|
89
|
+
extractAccessorPaths(resolved, paths, visited);
|
|
90
|
+
});
|
|
91
|
+
return paths.size > before;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Walk the AST and collect every unique state access path referenced by
|
|
95
|
+
* a reactive accessor. A reactive accessor is one of:
|
|
96
|
+
*
|
|
97
|
+
* - An inline arrow / function expression at a reactive position
|
|
98
|
+
* (`text(s => s.count)`, `div({ title: s => s.title })`,
|
|
99
|
+
* `show({ when: s => s.gated })`, etc.).
|
|
100
|
+
* - An Identifier at a reactive position that resolves to a callable
|
|
101
|
+
* in this file — a const-bound arrow / function expression,
|
|
102
|
+
* a hoisted function declaration, or `const x = memo(arrow)`.
|
|
103
|
+
*
|
|
104
|
+
* The second case lets authors refactor a literal arrow into a named
|
|
105
|
+
* helper without losing the reactive-mask optimization (a precise mask
|
|
106
|
+
* for `__dirty` and structural-primitive `__mask`). Without it, the
|
|
107
|
+
* runtime falls back to FULL_MASK — correct, but every binding fires
|
|
108
|
+
* on every state change.
|
|
109
|
+
*
|
|
110
|
+
* Shared by the bit-assignment path (`collectDeps`, below) and the
|
|
111
|
+
* `diagnostics.ts` bitmask-overflow warning.
|
|
112
|
+
*/
|
|
113
|
+
export function collectStatePathsFromSource(sourceFile) {
|
|
114
|
+
const paths = new Set();
|
|
115
|
+
function visit(node) {
|
|
116
|
+
// Inline arrow / function expression at a reactive position.
|
|
117
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
|
|
118
|
+
if (isReactiveAccessor(node))
|
|
119
|
+
extractAccessorPaths(node, paths);
|
|
120
|
+
}
|
|
121
|
+
// Identifier at a reactive position — resolve to its declaration
|
|
122
|
+
// and extract paths from the resolved body. Skip identifiers
|
|
123
|
+
// imported from elsewhere (resolver returns null) — there's no
|
|
124
|
+
// body to scan, runtime falls back to FULL_MASK.
|
|
125
|
+
if (ts.isIdentifier(node) && isReactiveAccessor(node)) {
|
|
126
|
+
const resolved = resolveAccessorBody(node);
|
|
127
|
+
if (resolved)
|
|
128
|
+
extractAccessorPaths(resolved, paths);
|
|
129
|
+
}
|
|
130
|
+
ts.forEachChild(node, visit);
|
|
131
|
+
}
|
|
132
|
+
visit(sourceFile);
|
|
133
|
+
return paths;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Per-accessor path sets — one entry per reactive arrow/function. Used
|
|
137
|
+
* by the bitmask-overflow diagnostic to find clusters of paths that
|
|
138
|
+
* always fire together (co-occurrence analysis).
|
|
139
|
+
*/
|
|
140
|
+
export function collectAccessorPathSets(sourceFile) {
|
|
141
|
+
const sets = [];
|
|
142
|
+
function visit(node) {
|
|
143
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
|
|
144
|
+
if (isReactiveAccessor(node)) {
|
|
145
|
+
const set = new Set();
|
|
146
|
+
if (extractAccessorPaths(node, set))
|
|
147
|
+
sets.push(set);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (ts.isIdentifier(node) && isReactiveAccessor(node)) {
|
|
151
|
+
const resolved = resolveAccessorBody(node);
|
|
152
|
+
if (resolved) {
|
|
153
|
+
const set = new Set();
|
|
154
|
+
if (extractAccessorPaths(resolved, set))
|
|
155
|
+
sets.push(set);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
ts.forEachChild(node, visit);
|
|
159
|
+
}
|
|
160
|
+
visit(sourceFile);
|
|
161
|
+
return sets;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Pre-scan a source file to collect all unique state access paths
|
|
165
|
+
* referenced by reactive accessors (arrow functions in props and text() calls).
|
|
166
|
+
*
|
|
167
|
+
* Returns a pair of maps:
|
|
168
|
+
* - `lo`: paths at bit positions 0..30, with value `1 << position`
|
|
169
|
+
* - `hi`: paths at bit positions 31..61, with value `1 << (position - 31)`
|
|
170
|
+
*
|
|
171
|
+
* Bit positions past 61 collapse to `-1` (FULL_MASK) in the `lo` map and
|
|
172
|
+
* cause every binding reading them to re-evaluate on every cycle. The
|
|
173
|
+
* `bitmask-overflow` lint rule warns the user to restructure state.
|
|
174
|
+
*
|
|
175
|
+
* Components with ≤31 paths see an empty `hi` map; the compiler skips
|
|
176
|
+
* all high-word emit so the generated code is byte-identical to the
|
|
177
|
+
* pre-multi-word baseline.
|
|
178
|
+
*/
|
|
179
|
+
export function collectDeps(source, extraPaths) {
|
|
180
|
+
const sourceFile = ts.createSourceFile('input.ts', source, ts.ScriptTarget.Latest, true);
|
|
181
|
+
// Check if file imports from @llui/dom
|
|
182
|
+
if (!hasLluiImport(sourceFile)) {
|
|
183
|
+
return { lo: new Map(), hi: new Map() };
|
|
184
|
+
}
|
|
185
|
+
const paths = collectStatePathsFromSource(sourceFile);
|
|
186
|
+
// Cross-file extension (v2c pipeline integration): the host adapter may
|
|
187
|
+
// pass paths discovered by `crossFileAccessorPaths()` — paths read
|
|
188
|
+
// through in-repo view-helpers in *other* files. Union them with the
|
|
189
|
+
// file-local set before bit assignment. Without this merge the
|
|
190
|
+
// sentinel-`show()` workaround from v2b §1 remains necessary; with
|
|
191
|
+
// it, helpers in other files contribute to the consumer's __prefixes
|
|
192
|
+
// table automatically.
|
|
193
|
+
if (extraPaths) {
|
|
194
|
+
for (const p of extraPaths)
|
|
195
|
+
paths.add(p);
|
|
196
|
+
}
|
|
197
|
+
const lo = new Map();
|
|
198
|
+
const hi = new Map();
|
|
199
|
+
let index = 0;
|
|
200
|
+
for (const path of paths) {
|
|
201
|
+
if (index < 31) {
|
|
202
|
+
lo.set(path, 1 << index);
|
|
203
|
+
}
|
|
204
|
+
else if (index < 62) {
|
|
205
|
+
hi.set(path, 1 << (index - 31));
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
// Past 61 paths — graceful FULL_MASK fallback in the low word.
|
|
209
|
+
// Realistic LLui components shouldn't hit this; the lint rule
|
|
210
|
+
// fires well before.
|
|
211
|
+
lo.set(path, -1);
|
|
212
|
+
}
|
|
213
|
+
index++;
|
|
214
|
+
}
|
|
215
|
+
return { lo, hi };
|
|
216
|
+
}
|
|
217
|
+
function hasLluiImport(sourceFile) {
|
|
218
|
+
for (const stmt of sourceFile.statements) {
|
|
219
|
+
if (ts.isImportDeclaration(stmt) &&
|
|
220
|
+
ts.isStringLiteral(stmt.moduleSpecifier) &&
|
|
221
|
+
stmt.moduleSpecifier.text === '@llui/dom') {
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Determines if a node is at a reactive-accessor position — either an
|
|
229
|
+
* inline arrow / function expression OR an identifier that's about to
|
|
230
|
+
* be resolved to one. The check is identity-based on `parent.arguments[0]`
|
|
231
|
+
* etc., so the same logic works for both shapes.
|
|
232
|
+
*/
|
|
233
|
+
function isReactiveAccessor(node) {
|
|
234
|
+
const parent = node.parent;
|
|
235
|
+
// text(s => s.count) — first arg to a call
|
|
236
|
+
if (ts.isCallExpression(parent) && parent.arguments[0] === node) {
|
|
237
|
+
// Skip item(t => t.id) — per-item selectors inside each() render.
|
|
238
|
+
// Skip sample(s => s.x) — imperative one-shot read, no binding created
|
|
239
|
+
// (both the top-level import and the destructured-from-h form).
|
|
240
|
+
if (ts.isIdentifier(parent.expression)) {
|
|
241
|
+
if (parent.expression.text === 'item' || parent.expression.text === 'sample') {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// Skip array method callbacks: .filter(t => ...), .map(t => ...), .some(t => ...), etc.
|
|
246
|
+
// Allow view-helper primitive calls: h.text(s => ...), h.memo(s => ...)
|
|
247
|
+
if (ts.isPropertyAccessExpression(parent.expression)) {
|
|
248
|
+
const methodName = parent.expression.name.text;
|
|
249
|
+
if (methodName === 'text' || methodName === 'memo') {
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
// div({ title: s => s.title }) — value in a property assignment inside an object literal.
|
|
257
|
+
// Only treat as reactive if the containing call is a known framework API whose
|
|
258
|
+
// properties are reactive accessors. Otherwise user-land helpers like
|
|
259
|
+
// sliceHandler({ narrow: (m) => m.type === ... }) would pollute the path set.
|
|
260
|
+
if (ts.isPropertyAssignment(parent)) {
|
|
261
|
+
const key = parent.name;
|
|
262
|
+
if (ts.isIdentifier(key)) {
|
|
263
|
+
// Skip event handlers (onClick, onInput, etc.)
|
|
264
|
+
if (/^on[A-Z]/.test(key.text))
|
|
265
|
+
return false;
|
|
266
|
+
// Skip each() key function and other non-reactive props
|
|
267
|
+
if (key.text === 'key' || key.text === 'name')
|
|
268
|
+
return false;
|
|
269
|
+
// Walk up to find the enclosing call expression
|
|
270
|
+
let ancestor = parent.parent; // ObjectLiteralExpression
|
|
271
|
+
while (ancestor && !ts.isCallExpression(ancestor)) {
|
|
272
|
+
ancestor = ancestor.parent;
|
|
273
|
+
}
|
|
274
|
+
if (!ancestor)
|
|
275
|
+
return false;
|
|
276
|
+
const callExpr = ancestor;
|
|
277
|
+
if (!ts.isIdentifier(callExpr.expression))
|
|
278
|
+
return false;
|
|
279
|
+
return REACTIVE_API_NAMES.has(callExpr.expression.text);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
// Framework APIs whose object-literal arguments contain reactive accessors.
|
|
285
|
+
// Arrow functions in property values of these calls are state-tracked.
|
|
286
|
+
const REACTIVE_API_NAMES = new Set([
|
|
287
|
+
// Element helpers (see ELEMENT_HELPERS in transform.ts — we keep a superset here)
|
|
288
|
+
...[
|
|
289
|
+
'a',
|
|
290
|
+
'abbr',
|
|
291
|
+
'article',
|
|
292
|
+
'aside',
|
|
293
|
+
'b',
|
|
294
|
+
'blockquote',
|
|
295
|
+
'br',
|
|
296
|
+
'button',
|
|
297
|
+
'canvas',
|
|
298
|
+
'code',
|
|
299
|
+
'dd',
|
|
300
|
+
'details',
|
|
301
|
+
'dialog',
|
|
302
|
+
'div',
|
|
303
|
+
'dl',
|
|
304
|
+
'dt',
|
|
305
|
+
'em',
|
|
306
|
+
'fieldset',
|
|
307
|
+
'figcaption',
|
|
308
|
+
'figure',
|
|
309
|
+
'footer',
|
|
310
|
+
'form',
|
|
311
|
+
'h1',
|
|
312
|
+
'h2',
|
|
313
|
+
'h3',
|
|
314
|
+
'h4',
|
|
315
|
+
'h5',
|
|
316
|
+
'h6',
|
|
317
|
+
'header',
|
|
318
|
+
'hr',
|
|
319
|
+
'i',
|
|
320
|
+
'iframe',
|
|
321
|
+
'img',
|
|
322
|
+
'input',
|
|
323
|
+
'label',
|
|
324
|
+
'legend',
|
|
325
|
+
'li',
|
|
326
|
+
'main',
|
|
327
|
+
'mark',
|
|
328
|
+
'nav',
|
|
329
|
+
'ol',
|
|
330
|
+
'optgroup',
|
|
331
|
+
'option',
|
|
332
|
+
'output',
|
|
333
|
+
'p',
|
|
334
|
+
'pre',
|
|
335
|
+
'progress',
|
|
336
|
+
'section',
|
|
337
|
+
'select',
|
|
338
|
+
'small',
|
|
339
|
+
'span',
|
|
340
|
+
'strong',
|
|
341
|
+
'sub',
|
|
342
|
+
'summary',
|
|
343
|
+
'sup',
|
|
344
|
+
'table',
|
|
345
|
+
'tbody',
|
|
346
|
+
'td',
|
|
347
|
+
'textarea',
|
|
348
|
+
'tfoot',
|
|
349
|
+
'th',
|
|
350
|
+
'thead',
|
|
351
|
+
'time',
|
|
352
|
+
'tr',
|
|
353
|
+
'ul',
|
|
354
|
+
'video',
|
|
355
|
+
],
|
|
356
|
+
// Structural primitives
|
|
357
|
+
'each',
|
|
358
|
+
'branch',
|
|
359
|
+
'scope',
|
|
360
|
+
'show',
|
|
361
|
+
'memo',
|
|
362
|
+
'portal',
|
|
363
|
+
'foreign',
|
|
364
|
+
'child',
|
|
365
|
+
'errorBoundary',
|
|
366
|
+
// track({ deps: (s) => [...] }) — explicit reactivity declaration for
|
|
367
|
+
// paths static analysis can't infer. The compiler treats `deps` as a
|
|
368
|
+
// reactive accessor so its paths fold into the host component's
|
|
369
|
+
// __prefixes; the call expression is then stripped from emission
|
|
370
|
+
// (see transform.ts). v2b §3.
|
|
371
|
+
'track',
|
|
372
|
+
]);
|
|
373
|
+
/**
|
|
374
|
+
* Extract state access paths from an expression body.
|
|
375
|
+
* Handles:
|
|
376
|
+
* - Direct property access: param.field, param.field.subfield
|
|
377
|
+
* - Bracket notation with string literal: param['field']
|
|
378
|
+
*/
|
|
379
|
+
function extractPaths(node, paramName, _prefix, paths) {
|
|
380
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
381
|
+
// Skip if this is an intermediate in a deeper chain
|
|
382
|
+
if (ts.isPropertyAccessExpression(node.parent)) {
|
|
383
|
+
// handled when the leaf is visited
|
|
384
|
+
}
|
|
385
|
+
// Skip if this is the callee of a method call: s.todos.filter(...)
|
|
386
|
+
else if (ts.isCallExpression(node.parent) && node.parent.expression === node) {
|
|
387
|
+
// It's a method call — record the object, not the method
|
|
388
|
+
// e.g. s.todos.filter(...) → record 'todos', not 'todos.filter'
|
|
389
|
+
if (ts.isPropertyAccessExpression(node.expression)) {
|
|
390
|
+
const chain = resolvePropertyChain(node.expression, paramName);
|
|
391
|
+
if (chain)
|
|
392
|
+
paths.add(chain);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
const chain = resolvePropertyChain(node, paramName);
|
|
397
|
+
if (chain) {
|
|
398
|
+
paths.add(chain);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
if (ts.isElementAccessExpression(node)) {
|
|
403
|
+
const chain = resolveElementAccess(node, paramName);
|
|
404
|
+
if (chain) {
|
|
405
|
+
paths.add(chain);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
ts.forEachChild(node, (child) => extractPaths(child, paramName, _prefix, paths));
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Resolve a property access chain like s.user.name to "user.name".
|
|
412
|
+
* Returns null if the chain doesn't start with the state parameter.
|
|
413
|
+
* Stops at depth 2.
|
|
414
|
+
*/
|
|
415
|
+
function resolvePropertyChain(node, paramName) {
|
|
416
|
+
const parts = [];
|
|
417
|
+
let current = node;
|
|
418
|
+
while (ts.isPropertyAccessExpression(current)) {
|
|
419
|
+
parts.unshift(current.name.text);
|
|
420
|
+
current = current.expression;
|
|
421
|
+
}
|
|
422
|
+
// The root must be the state parameter
|
|
423
|
+
if (!ts.isIdentifier(current) || current.text !== paramName) {
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
// Limit to depth 2
|
|
427
|
+
if (parts.length > 2) {
|
|
428
|
+
return parts.slice(0, 2).join('.');
|
|
429
|
+
}
|
|
430
|
+
return parts.join('.');
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Resolve bracket access with string literal: s['count'] → "count"
|
|
434
|
+
*/
|
|
435
|
+
function resolveElementAccess(node, paramName) {
|
|
436
|
+
if (!ts.isIdentifier(node.expression) || node.expression.text !== paramName) {
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
439
|
+
if (ts.isStringLiteral(node.argumentExpression)) {
|
|
440
|
+
return node.argumentExpression.text;
|
|
441
|
+
}
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
//# sourceMappingURL=collect-deps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-deps.js","sourceRoot":"","sources":["../src/collect-deps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAE5D;;;;;;;GAOG;AACH,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAA;AAExF;;;;;;;;;;;;;;;GAeG;AACH,SAAS,wBAAwB,CAC/B,IAAa,EACb,cAAsB,EACtB,MAA6F;IAE7F,SAAS,KAAK,CAAC,IAAa;QAC1B,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAClE,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAA;YACjC,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;gBAC9B,IAAI,IAAI,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;oBAClE,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;oBACrD,IAAI,QAAQ;wBAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;gBAChC,CAAC;YACH,CAAC;QACH,CAAC;QACD,kEAAkE;QAClE,gEAAgE;QAChE,aAAa;QACb,IACE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;YACxB,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC;YAC7B,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAC9B,CAAC;YACD,OAAM;QACR,CAAC;QACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC9B,CAAC;IACD,+DAA+D;IAC/D,uDAAuD;IACvD,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC;QAChG,OAAM;IACR,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,CAAA;AACb,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,oBAAoB,CAC3B,QAA2E,EAC3E,KAAkB,EAClB,UAAwB,IAAI,GAAG,EAAE;IAEjC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAA;IACvC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAErB,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAA;IAClC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACrC,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC,IAAI,CAAA;IACjC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAA;IAC7C,IAAI,CAAC,QAAQ,CAAC,IAAI;QAAE,OAAO,KAAK,CAAA;IAChC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAA;IAEzB,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,CAAA;IAEtD,qEAAqE;IACrE,iEAAiE;IACjE,6BAA6B;IAC7B,wBAAwB,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE;QACnE,oBAAoB,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,OAAO,KAAK,CAAC,IAAI,GAAG,MAAM,CAAA;AAC5B,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,2BAA2B,CAAC,UAAyB;IACnE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAA;IAE/B,SAAS,KAAK,CAAC,IAAa;QAC1B,6DAA6D;QAC7D,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9D,IAAI,kBAAkB,CAAC,IAAI,CAAC;gBAAE,oBAAoB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QACjE,CAAC;QAED,iEAAiE;QACjE,6DAA6D;QAC7D,+DAA+D;QAC/D,iDAAiD;QACjD,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;YACtD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAA;YAC1C,IAAI,QAAQ;gBAAE,oBAAoB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;QACrD,CAAC;QAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,CAAA;IACjB,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAyB;IAC/D,MAAM,IAAI,GAAkB,EAAE,CAAA;IAE9B,SAAS,KAAK,CAAC,IAAa;QAC1B,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9D,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7B,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAA;gBAC7B,IAAI,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC;oBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACrD,CAAC;QACH,CAAC;QAED,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;YACtD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAA;YAC1C,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAA;gBAC7B,IAAI,oBAAoB,CAAC,QAAQ,EAAE,GAAG,CAAC;oBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACzD,CAAC;QACH,CAAC;QAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,CAAA;IACjB,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,WAAW,CACzB,MAAc,EACd,UAAgC;IAKhC,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IAExF,uCAAuC;IACvC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,EAAE,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,GAAG,EAAE,EAAE,CAAA;IACzC,CAAC;IAED,MAAM,KAAK,GAAG,2BAA2B,CAAC,UAAU,CAAC,CAAA;IACrD,wEAAwE;IACxE,mEAAmE;IACnE,qEAAqE;IACrE,+DAA+D;IAC/D,mEAAmE;IACnE,qEAAqE;IACrE,uBAAuB;IACvB,IAAI,UAAU,EAAE,CAAC;QACf,KAAK,MAAM,CAAC,IAAI,UAAU;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAC1C,CAAC;IAED,MAAM,EAAE,GAAG,IAAI,GAAG,EAAkB,CAAA;IACpC,MAAM,EAAE,GAAG,IAAI,GAAG,EAAkB,CAAA;IACpC,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;YACf,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,CAAC,CAAA;QAC1B,CAAC;aAAM,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;YACtB,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAA;QACjC,CAAC;aAAM,CAAC;YACN,+DAA+D;YAC/D,8DAA8D;YAC9D,qBAAqB;YACrB,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QAClB,CAAC;QACD,KAAK,EAAE,CAAA;IACT,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,CAAA;AACnB,CAAC;AAED,SAAS,aAAa,CAAC,UAAyB;IAC9C,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;QACzC,IACE,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC;YAC5B,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,eAAe,CAAC;YACxC,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,WAAW,EACzC,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAS,kBAAkB,CAAC,IAAa;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;IAE1B,2CAA2C;IAC3C,IAAI,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAChE,kEAAkE;QAClE,uEAAuE;QACvE,gEAAgE;QAChE,IAAI,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACvC,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7E,OAAO,KAAK,CAAA;YACd,CAAC;QACH,CAAC;QACD,wFAAwF;QACxF,wEAAwE;QACxE,IAAI,EAAE,CAAC,0BAA0B,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACrD,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAA;YAC9C,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;gBACnD,OAAO,IAAI,CAAA;YACb,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,0FAA0F;IAC1F,+EAA+E;IAC/E,sEAAsE;IACtE,8EAA8E;IAC9E,IAAI,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QACpC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAA;QACvB,IAAI,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,+CAA+C;YAC/C,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,OAAO,KAAK,CAAA;YAC3C,wDAAwD;YACxD,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;gBAAE,OAAO,KAAK,CAAA;YAC3D,gDAAgD;YAChD,IAAI,QAAQ,GAAwB,MAAM,CAAC,MAAM,CAAA,CAAC,0BAA0B;YAC5E,OAAO,QAAQ,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClD,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAA;YAC5B,CAAC;YACD,IAAI,CAAC,QAAQ;gBAAE,OAAO,KAAK,CAAA;YAC3B,MAAM,QAAQ,GAAG,QAA6B,CAAA;YAC9C,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC;gBAAE,OAAO,KAAK,CAAA;YACvD,OAAO,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;QACzD,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,4EAA4E;AAC5E,uEAAuE;AACvE,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,kFAAkF;IAClF,GAAG;QACD,GAAG;QACH,MAAM;QACN,SAAS;QACT,OAAO;QACP,GAAG;QACH,YAAY;QACZ,IAAI;QACJ,QAAQ;QACR,QAAQ;QACR,MAAM;QACN,IAAI;QACJ,SAAS;QACT,QAAQ;QACR,KAAK;QACL,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,UAAU;QACV,YAAY;QACZ,QAAQ;QACR,QAAQ;QACR,MAAM;QACN,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,QAAQ;QACR,IAAI;QACJ,GAAG;QACH,QAAQ;QACR,KAAK;QACL,OAAO;QACP,OAAO;QACP,QAAQ;QACR,IAAI;QACJ,MAAM;QACN,MAAM;QACN,KAAK;QACL,IAAI;QACJ,UAAU;QACV,QAAQ;QACR,QAAQ;QACR,GAAG;QACH,KAAK;QACL,UAAU;QACV,SAAS;QACT,QAAQ;QACR,OAAO;QACP,MAAM;QACN,QAAQ;QACR,KAAK;QACL,SAAS;QACT,KAAK;QACL,OAAO;QACP,OAAO;QACP,IAAI;QACJ,UAAU;QACV,OAAO;QACP,IAAI;QACJ,OAAO;QACP,MAAM;QACN,IAAI;QACJ,IAAI;QACJ,OAAO;KACR;IACD,wBAAwB;IACxB,MAAM;IACN,QAAQ;IACR,OAAO;IACP,MAAM;IACN,MAAM;IACN,QAAQ;IACR,SAAS;IACT,OAAO;IACP,eAAe;IACf,sEAAsE;IACtE,qEAAqE;IACrE,gEAAgE;IAChE,iEAAiE;IACjE,8BAA8B;IAC9B,OAAO;CACR,CAAC,CAAA;AAEF;;;;;GAKG;AACH,SAAS,YAAY,CAAC,IAAa,EAAE,SAAiB,EAAE,OAAe,EAAE,KAAkB;IACzF,IAAI,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,oDAAoD;QACpD,IAAI,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/C,mCAAmC;QACrC,CAAC;QACD,mEAAmE;aAC9D,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YAC7E,yDAAyD;YACzD,gEAAgE;YAChE,IAAI,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBACnD,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;gBAC9D,IAAI,KAAK;oBAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YAC7B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;YACnD,IAAI,KAAK,EAAE,CAAC;gBACV,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;QACnD,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAClB,CAAC;IACH,CAAC;IAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAA;AAClF,CAAC;AAED;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,IAAiC,EAAE,SAAiB;IAChF,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,OAAO,GAAkB,IAAI,CAAA;IAEjC,OAAO,EAAE,CAAC,0BAA0B,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAChC,OAAO,GAAG,OAAO,CAAC,UAAU,CAAA;IAC9B,CAAC;IAED,uCAAuC;IACvC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC5D,OAAO,IAAI,CAAA;IACb,CAAC;IAED,mBAAmB;IACnB,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACpC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,IAAgC,EAAE,SAAiB;IAC/E,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC5E,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAA;IACrC,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import ts from 'typescript'\nimport { resolveAccessorBody } from './accessor-resolver.js'\n\n/**\n * Names whose first arg is itself a reactive accessor (the existing\n * arrow walker handles them) or which are explicitly excluded\n * (sample/item read state imperatively / per-row, not as state\n * accessors). When a delegating accessor's body contains a call to one\n * of these, we don't follow it — recursion is reserved for \"this is\n * just a thin wrapper that hands the state to another local helper.\"\n */\nconst NON_DELEGATION_HELPERS = new Set(['sample', 'item', 'memo', 'text', 'unsafeHtml'])\n\n/**\n * Walk a delegating accessor's body looking for calls to OTHER local\n * functions that take the state param verbatim — `helper(s)` where\n * `s` matches the outer accessor's param name. For each, hand the\n * resolved declaration back so the caller can recurse into its body.\n *\n * Skips:\n * - Framework helpers (`memo`, `text`, etc.) — their arrow args are\n * visited by the top-level arrow walker; we'd double-count.\n * - Method calls (`s.items.filter(...)`) — the callee is a builtin,\n * not a local function we can resolve.\n * - Nested function bodies — params inside a `(item) => …` shadow\n * ours, so a `helper(s)` deep in there isn't (necessarily)\n * handing OUR state in. Conservative: don't recurse through\n * lambda boundaries.\n */\nfunction visitTopLevelDelegations(\n body: ts.Node,\n stateParamName: string,\n follow: (resolved: ts.ArrowFunction | ts.FunctionExpression | ts.FunctionDeclaration) => void,\n): void {\n function visit(node: ts.Node): void {\n if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {\n const name = node.expression.text\n if (!NON_DELEGATION_HELPERS.has(name)) {\n const arg0 = node.arguments[0]\n if (arg0 && ts.isIdentifier(arg0) && arg0.text === stateParamName) {\n const resolved = resolveAccessorBody(node.expression)\n if (resolved) follow(resolved)\n }\n }\n }\n // Don't descend into nested function bodies — their params shadow\n // ours, and any call inside them isn't unambiguously delegating\n // our state.\n if (\n ts.isArrowFunction(node) ||\n ts.isFunctionExpression(node) ||\n ts.isFunctionDeclaration(node)\n ) {\n return\n }\n ts.forEachChild(node, visit)\n }\n // If the body itself is a function, there's nothing at the top\n // level to inspect — its own body is a separate scope.\n if (ts.isArrowFunction(body) || ts.isFunctionExpression(body) || ts.isFunctionDeclaration(body)) {\n return\n }\n visit(body)\n}\n\n/**\n * Extract paths from a callable accessor (arrow / fn-expr / fn-decl)\n * into the given set. Recurses through call-delegations to other local\n * helpers so that `(s) => filtered(s)` / `(s) => { void s.x; return\n * inner(s) }` correctly contribute the helper's state-path reads.\n * Without recursion the precise mask under-counts — fields read only\n * via the helper drop off the bitmask, and any sibling reactive\n * accessor that reads them produces a non-zero `dirty` that AND'd with\n * the narrow each.__mask is zero, silently skipping the reconcile.\n *\n * `visited` breaks cycles on mutually-recursive helpers — terminates\n * the walk; doesn't try to be precise about what such helpers read.\n */\nfunction extractAccessorPaths(\n accessor: ts.ArrowFunction | ts.FunctionExpression | ts.FunctionDeclaration,\n paths: Set<string>,\n visited: Set<ts.Node> = new Set(),\n): boolean {\n if (visited.has(accessor)) return false\n visited.add(accessor)\n\n const params = accessor.parameters\n if (params.length !== 1) return false\n const paramName = params[0]!.name\n if (!ts.isIdentifier(paramName)) return false\n if (!accessor.body) return false\n const before = paths.size\n\n extractPaths(accessor.body, paramName.text, '', paths)\n\n // Follow delegations: `(s) => helper(s)` — extract `helper`'s body's\n // state paths too. Reuses the `visited` set across the recursion\n // chain so cycles terminate.\n visitTopLevelDelegations(accessor.body, paramName.text, (resolved) => {\n extractAccessorPaths(resolved, paths, visited)\n })\n\n return paths.size > before\n}\n\n/**\n * Walk the AST and collect every unique state access path referenced by\n * a reactive accessor. A reactive accessor is one of:\n *\n * - An inline arrow / function expression at a reactive position\n * (`text(s => s.count)`, `div({ title: s => s.title })`,\n * `show({ when: s => s.gated })`, etc.).\n * - An Identifier at a reactive position that resolves to a callable\n * in this file — a const-bound arrow / function expression,\n * a hoisted function declaration, or `const x = memo(arrow)`.\n *\n * The second case lets authors refactor a literal arrow into a named\n * helper without losing the reactive-mask optimization (a precise mask\n * for `__dirty` and structural-primitive `__mask`). Without it, the\n * runtime falls back to FULL_MASK — correct, but every binding fires\n * on every state change.\n *\n * Shared by the bit-assignment path (`collectDeps`, below) and the\n * `diagnostics.ts` bitmask-overflow warning.\n */\nexport function collectStatePathsFromSource(sourceFile: ts.SourceFile): Set<string> {\n const paths = new Set<string>()\n\n function visit(node: ts.Node): void {\n // Inline arrow / function expression at a reactive position.\n if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {\n if (isReactiveAccessor(node)) extractAccessorPaths(node, paths)\n }\n\n // Identifier at a reactive position — resolve to its declaration\n // and extract paths from the resolved body. Skip identifiers\n // imported from elsewhere (resolver returns null) — there's no\n // body to scan, runtime falls back to FULL_MASK.\n if (ts.isIdentifier(node) && isReactiveAccessor(node)) {\n const resolved = resolveAccessorBody(node)\n if (resolved) extractAccessorPaths(resolved, paths)\n }\n\n ts.forEachChild(node, visit)\n }\n\n visit(sourceFile)\n return paths\n}\n\n/**\n * Per-accessor path sets — one entry per reactive arrow/function. Used\n * by the bitmask-overflow diagnostic to find clusters of paths that\n * always fire together (co-occurrence analysis).\n */\nexport function collectAccessorPathSets(sourceFile: ts.SourceFile): Set<string>[] {\n const sets: Set<string>[] = []\n\n function visit(node: ts.Node): void {\n if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {\n if (isReactiveAccessor(node)) {\n const set = new Set<string>()\n if (extractAccessorPaths(node, set)) sets.push(set)\n }\n }\n\n if (ts.isIdentifier(node) && isReactiveAccessor(node)) {\n const resolved = resolveAccessorBody(node)\n if (resolved) {\n const set = new Set<string>()\n if (extractAccessorPaths(resolved, set)) sets.push(set)\n }\n }\n\n ts.forEachChild(node, visit)\n }\n\n visit(sourceFile)\n return sets\n}\n\n/**\n * Pre-scan a source file to collect all unique state access paths\n * referenced by reactive accessors (arrow functions in props and text() calls).\n *\n * Returns a pair of maps:\n * - `lo`: paths at bit positions 0..30, with value `1 << position`\n * - `hi`: paths at bit positions 31..61, with value `1 << (position - 31)`\n *\n * Bit positions past 61 collapse to `-1` (FULL_MASK) in the `lo` map and\n * cause every binding reading them to re-evaluate on every cycle. The\n * `bitmask-overflow` lint rule warns the user to restructure state.\n *\n * Components with ≤31 paths see an empty `hi` map; the compiler skips\n * all high-word emit so the generated code is byte-identical to the\n * pre-multi-word baseline.\n */\nexport function collectDeps(\n source: string,\n extraPaths?: ReadonlySet<string>,\n): {\n lo: Map<string, number>\n hi: Map<string, number>\n} {\n const sourceFile = ts.createSourceFile('input.ts', source, ts.ScriptTarget.Latest, true)\n\n // Check if file imports from @llui/dom\n if (!hasLluiImport(sourceFile)) {\n return { lo: new Map(), hi: new Map() }\n }\n\n const paths = collectStatePathsFromSource(sourceFile)\n // Cross-file extension (v2c pipeline integration): the host adapter may\n // pass paths discovered by `crossFileAccessorPaths()` — paths read\n // through in-repo view-helpers in *other* files. Union them with the\n // file-local set before bit assignment. Without this merge the\n // sentinel-`show()` workaround from v2b §1 remains necessary; with\n // it, helpers in other files contribute to the consumer's __prefixes\n // table automatically.\n if (extraPaths) {\n for (const p of extraPaths) paths.add(p)\n }\n\n const lo = new Map<string, number>()\n const hi = new Map<string, number>()\n let index = 0\n for (const path of paths) {\n if (index < 31) {\n lo.set(path, 1 << index)\n } else if (index < 62) {\n hi.set(path, 1 << (index - 31))\n } else {\n // Past 61 paths — graceful FULL_MASK fallback in the low word.\n // Realistic LLui components shouldn't hit this; the lint rule\n // fires well before.\n lo.set(path, -1)\n }\n index++\n }\n\n return { lo, hi }\n}\n\nfunction hasLluiImport(sourceFile: ts.SourceFile): boolean {\n for (const stmt of sourceFile.statements) {\n if (\n ts.isImportDeclaration(stmt) &&\n ts.isStringLiteral(stmt.moduleSpecifier) &&\n stmt.moduleSpecifier.text === '@llui/dom'\n ) {\n return true\n }\n }\n return false\n}\n\n/**\n * Determines if a node is at a reactive-accessor position — either an\n * inline arrow / function expression OR an identifier that's about to\n * be resolved to one. The check is identity-based on `parent.arguments[0]`\n * etc., so the same logic works for both shapes.\n */\nfunction isReactiveAccessor(node: ts.Node): boolean {\n const parent = node.parent\n\n // text(s => s.count) — first arg to a call\n if (ts.isCallExpression(parent) && parent.arguments[0] === node) {\n // Skip item(t => t.id) — per-item selectors inside each() render.\n // Skip sample(s => s.x) — imperative one-shot read, no binding created\n // (both the top-level import and the destructured-from-h form).\n if (ts.isIdentifier(parent.expression)) {\n if (parent.expression.text === 'item' || parent.expression.text === 'sample') {\n return false\n }\n }\n // Skip array method callbacks: .filter(t => ...), .map(t => ...), .some(t => ...), etc.\n // Allow view-helper primitive calls: h.text(s => ...), h.memo(s => ...)\n if (ts.isPropertyAccessExpression(parent.expression)) {\n const methodName = parent.expression.name.text\n if (methodName === 'text' || methodName === 'memo') {\n return true\n }\n return false\n }\n return true\n }\n\n // div({ title: s => s.title }) — value in a property assignment inside an object literal.\n // Only treat as reactive if the containing call is a known framework API whose\n // properties are reactive accessors. Otherwise user-land helpers like\n // sliceHandler({ narrow: (m) => m.type === ... }) would pollute the path set.\n if (ts.isPropertyAssignment(parent)) {\n const key = parent.name\n if (ts.isIdentifier(key)) {\n // Skip event handlers (onClick, onInput, etc.)\n if (/^on[A-Z]/.test(key.text)) return false\n // Skip each() key function and other non-reactive props\n if (key.text === 'key' || key.text === 'name') return false\n // Walk up to find the enclosing call expression\n let ancestor: ts.Node | undefined = parent.parent // ObjectLiteralExpression\n while (ancestor && !ts.isCallExpression(ancestor)) {\n ancestor = ancestor.parent\n }\n if (!ancestor) return false\n const callExpr = ancestor as ts.CallExpression\n if (!ts.isIdentifier(callExpr.expression)) return false\n return REACTIVE_API_NAMES.has(callExpr.expression.text)\n }\n }\n\n return false\n}\n\n// Framework APIs whose object-literal arguments contain reactive accessors.\n// Arrow functions in property values of these calls are state-tracked.\nconst REACTIVE_API_NAMES = new Set([\n // Element helpers (see ELEMENT_HELPERS in transform.ts — we keep a superset here)\n ...[\n 'a',\n 'abbr',\n 'article',\n 'aside',\n 'b',\n 'blockquote',\n 'br',\n 'button',\n 'canvas',\n 'code',\n 'dd',\n 'details',\n 'dialog',\n 'div',\n 'dl',\n 'dt',\n 'em',\n 'fieldset',\n 'figcaption',\n 'figure',\n 'footer',\n 'form',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'header',\n 'hr',\n 'i',\n 'iframe',\n 'img',\n 'input',\n 'label',\n 'legend',\n 'li',\n 'main',\n 'mark',\n 'nav',\n 'ol',\n 'optgroup',\n 'option',\n 'output',\n 'p',\n 'pre',\n 'progress',\n 'section',\n 'select',\n 'small',\n 'span',\n 'strong',\n 'sub',\n 'summary',\n 'sup',\n 'table',\n 'tbody',\n 'td',\n 'textarea',\n 'tfoot',\n 'th',\n 'thead',\n 'time',\n 'tr',\n 'ul',\n 'video',\n ],\n // Structural primitives\n 'each',\n 'branch',\n 'scope',\n 'show',\n 'memo',\n 'portal',\n 'foreign',\n 'child',\n 'errorBoundary',\n // track({ deps: (s) => [...] }) — explicit reactivity declaration for\n // paths static analysis can't infer. The compiler treats `deps` as a\n // reactive accessor so its paths fold into the host component's\n // __prefixes; the call expression is then stripped from emission\n // (see transform.ts). v2b §3.\n 'track',\n])\n\n/**\n * Extract state access paths from an expression body.\n * Handles:\n * - Direct property access: param.field, param.field.subfield\n * - Bracket notation with string literal: param['field']\n */\nfunction extractPaths(node: ts.Node, paramName: string, _prefix: string, paths: Set<string>): void {\n if (ts.isPropertyAccessExpression(node)) {\n // Skip if this is an intermediate in a deeper chain\n if (ts.isPropertyAccessExpression(node.parent)) {\n // handled when the leaf is visited\n }\n // Skip if this is the callee of a method call: s.todos.filter(...)\n else if (ts.isCallExpression(node.parent) && node.parent.expression === node) {\n // It's a method call — record the object, not the method\n // e.g. s.todos.filter(...) → record 'todos', not 'todos.filter'\n if (ts.isPropertyAccessExpression(node.expression)) {\n const chain = resolvePropertyChain(node.expression, paramName)\n if (chain) paths.add(chain)\n }\n } else {\n const chain = resolvePropertyChain(node, paramName)\n if (chain) {\n paths.add(chain)\n }\n }\n }\n\n if (ts.isElementAccessExpression(node)) {\n const chain = resolveElementAccess(node, paramName)\n if (chain) {\n paths.add(chain)\n }\n }\n\n ts.forEachChild(node, (child) => extractPaths(child, paramName, _prefix, paths))\n}\n\n/**\n * Resolve a property access chain like s.user.name to \"user.name\".\n * Returns null if the chain doesn't start with the state parameter.\n * Stops at depth 2.\n */\nfunction resolvePropertyChain(node: ts.PropertyAccessExpression, paramName: string): string | null {\n const parts: string[] = []\n let current: ts.Expression = node\n\n while (ts.isPropertyAccessExpression(current)) {\n parts.unshift(current.name.text)\n current = current.expression\n }\n\n // The root must be the state parameter\n if (!ts.isIdentifier(current) || current.text !== paramName) {\n return null\n }\n\n // Limit to depth 2\n if (parts.length > 2) {\n return parts.slice(0, 2).join('.')\n }\n\n return parts.join('.')\n}\n\n/**\n * Resolve bracket access with string literal: s['count'] → \"count\"\n */\nfunction resolveElementAccess(node: ts.ElementAccessExpression, paramName: string): string | null {\n if (!ts.isIdentifier(node.expression) || node.expression.text !== paramName) {\n return null\n }\n\n if (ts.isStringLiteral(node.argumentExpression)) {\n return node.argumentExpression.text\n }\n\n return null\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface BindingSourceEntry {
|
|
2
|
+
bindingIndex: number;
|
|
3
|
+
file: string;
|
|
4
|
+
line: number;
|
|
5
|
+
column: number;
|
|
6
|
+
}
|
|
7
|
+
export interface CompilerCacheEntry {
|
|
8
|
+
preSource: string;
|
|
9
|
+
postSource: string;
|
|
10
|
+
msgMaskMap: Record<string, number>;
|
|
11
|
+
bindingSources: BindingSourceEntry[];
|
|
12
|
+
}
|
|
13
|
+
export declare class CompilerCache {
|
|
14
|
+
private readonly cache;
|
|
15
|
+
set(componentName: string, entry: CompilerCacheEntry): void;
|
|
16
|
+
get(componentName: string): CompilerCacheEntry | undefined;
|
|
17
|
+
has(componentName: string): boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare const compilerCache: CompilerCache;
|
|
20
|
+
//# sourceMappingURL=compiler-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compiler-cache.d.ts","sourceRoot":"","sources":["../src/compiler-cache.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,cAAc,EAAE,kBAAkB,EAAE,CAAA;CACrC;AAID,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwC;IAE9D,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAQ3D,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAI1D,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;CAGpC;AAED,eAAO,MAAM,aAAa,eAAsB,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const MAX_ENTRIES = 50;
|
|
2
|
+
export class CompilerCache {
|
|
3
|
+
cache = new Map();
|
|
4
|
+
set(componentName, entry) {
|
|
5
|
+
if (this.cache.has(componentName))
|
|
6
|
+
this.cache.delete(componentName);
|
|
7
|
+
this.cache.set(componentName, entry);
|
|
8
|
+
if (this.cache.size > MAX_ENTRIES) {
|
|
9
|
+
this.cache.delete(this.cache.keys().next().value);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
get(componentName) {
|
|
13
|
+
return this.cache.get(componentName);
|
|
14
|
+
}
|
|
15
|
+
has(componentName) {
|
|
16
|
+
return this.cache.has(componentName);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export const compilerCache = new CompilerCache();
|
|
20
|
+
//# sourceMappingURL=compiler-cache.js.map
|