@fluixi/compiler 1.0.0-alpha.100

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 (303) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +131 -0
  3. package/dist/analyze/expr-shape.cjs +62 -0
  4. package/dist/analyze/expr-shape.d.cts +14 -0
  5. package/dist/analyze/expr-shape.d.ts +15 -0
  6. package/dist/analyze/expr-shape.d.ts.map +1 -0
  7. package/dist/analyze/expr-shape.js +37 -0
  8. package/dist/analyze/expr-shape.mjs +41 -0
  9. package/dist/analyze/intrinsics.cjs +112 -0
  10. package/dist/analyze/intrinsics.d.cts +80 -0
  11. package/dist/analyze/intrinsics.d.ts +81 -0
  12. package/dist/analyze/intrinsics.d.ts.map +1 -0
  13. package/dist/analyze/intrinsics.js +126 -0
  14. package/dist/analyze/intrinsics.mjs +91 -0
  15. package/dist/analyze/paren.cjs +134 -0
  16. package/dist/analyze/paren.d.cts +23 -0
  17. package/dist/analyze/paren.d.ts +24 -0
  18. package/dist/analyze/paren.d.ts.map +1 -0
  19. package/dist/analyze/paren.js +168 -0
  20. package/dist/analyze/paren.mjs +113 -0
  21. package/dist/analyze/props-destructure.cjs +226 -0
  22. package/dist/analyze/props-destructure.d.cts +83 -0
  23. package/dist/analyze/props-destructure.d.ts +84 -0
  24. package/dist/analyze/props-destructure.d.ts.map +1 -0
  25. package/dist/analyze/props-destructure.js +272 -0
  26. package/dist/analyze/props-destructure.mjs +205 -0
  27. package/dist/analyze/reactive-bindings.cjs +210 -0
  28. package/dist/analyze/reactive-bindings.d.cts +42 -0
  29. package/dist/analyze/reactive-bindings.d.ts +43 -0
  30. package/dist/analyze/reactive-bindings.d.ts.map +1 -0
  31. package/dist/analyze/reactive-bindings.js +191 -0
  32. package/dist/analyze/reactive-bindings.mjs +187 -0
  33. package/dist/analyze/reactive-expr.cjs +38 -0
  34. package/dist/analyze/reactive-expr.d.cts +38 -0
  35. package/dist/analyze/reactive-expr.d.ts +39 -0
  36. package/dist/analyze/reactive-expr.d.ts.map +1 -0
  37. package/dist/analyze/reactive-expr.js +31 -0
  38. package/dist/analyze/reactive-expr.mjs +17 -0
  39. package/dist/analyze/static-graph.cjs +831 -0
  40. package/dist/analyze/static-graph.d.cts +102 -0
  41. package/dist/analyze/static-graph.d.ts +103 -0
  42. package/dist/analyze/static-graph.d.ts.map +1 -0
  43. package/dist/analyze/static-graph.js +871 -0
  44. package/dist/analyze/static-graph.mjs +813 -0
  45. package/dist/babel-I6BUWUCU.mjs +636 -0
  46. package/dist/chunk-3AICWNF7.mjs +92 -0
  47. package/dist/chunk-6CWJWGE2.mjs +2170 -0
  48. package/dist/chunk-C3XPDB4Y.mjs +16 -0
  49. package/dist/chunk-GX5XV6Z7.mjs +190 -0
  50. package/dist/chunk-HXEXPWJ2.mjs +999 -0
  51. package/dist/chunk-NU3W67UZ.mjs +584 -0
  52. package/dist/chunk-SKAVY75W.mjs +11 -0
  53. package/dist/codegen/backend.cjs +18 -0
  54. package/dist/codegen/backend.d.cts +35 -0
  55. package/dist/codegen/backend.d.ts +36 -0
  56. package/dist/codegen/backend.d.ts.map +1 -0
  57. package/dist/codegen/backend.js +1 -0
  58. package/dist/codegen/backend.mjs +0 -0
  59. package/dist/codegen/backends/imperative.cjs +577 -0
  60. package/dist/codegen/backends/imperative.d.cts +11 -0
  61. package/dist/codegen/backends/imperative.d.ts +12 -0
  62. package/dist/codegen/backends/imperative.d.ts.map +1 -0
  63. package/dist/codegen/backends/imperative.js +362 -0
  64. package/dist/codegen/backends/imperative.mjs +554 -0
  65. package/dist/codegen/contract.cjs +52 -0
  66. package/dist/codegen/contract.d.cts +24 -0
  67. package/dist/codegen/contract.d.ts +25 -0
  68. package/dist/codegen/contract.d.ts.map +1 -0
  69. package/dist/codegen/contract.js +30 -0
  70. package/dist/codegen/contract.mjs +31 -0
  71. package/dist/codegen/partial-template.cjs +176 -0
  72. package/dist/codegen/partial-template.d.cts +61 -0
  73. package/dist/codegen/partial-template.d.ts +62 -0
  74. package/dist/codegen/partial-template.d.ts.map +1 -0
  75. package/dist/codegen/partial-template.js +0 -0
  76. package/dist/codegen/partial-template.mjs +153 -0
  77. package/dist/codegen/serialize-static.cjs +125 -0
  78. package/dist/codegen/serialize-static.d.cts +38 -0
  79. package/dist/codegen/serialize-static.d.ts +39 -0
  80. package/dist/codegen/serialize-static.d.ts.map +1 -0
  81. package/dist/codegen/serialize-static.js +165 -0
  82. package/dist/codegen/serialize-static.mjs +104 -0
  83. package/dist/frontend/babel/build-ir-lit.cjs +1933 -0
  84. package/dist/frontend/babel/build-ir-lit.d.cts +26 -0
  85. package/dist/frontend/babel/build-ir-lit.d.ts +27 -0
  86. package/dist/frontend/babel/build-ir-lit.d.ts.map +1 -0
  87. package/dist/frontend/babel/build-ir-lit.js +13 -0
  88. package/dist/frontend/babel/build-ir-lit.mjs +1902 -0
  89. package/dist/frontend/babel/build-ir.cjs +1948 -0
  90. package/dist/frontend/babel/build-ir.d.cts +35 -0
  91. package/dist/frontend/babel/build-ir.d.ts +36 -0
  92. package/dist/frontend/babel/build-ir.d.ts.map +1 -0
  93. package/dist/frontend/babel/build-ir.js +124 -0
  94. package/dist/frontend/babel/build-ir.mjs +1919 -0
  95. package/dist/frontend/babel/index.cjs +2610 -0
  96. package/dist/frontend/babel/index.d.cts +33 -0
  97. package/dist/frontend/babel/index.d.ts +34 -0
  98. package/dist/frontend/babel/index.d.ts.map +1 -0
  99. package/dist/frontend/babel/index.js +65 -0
  100. package/dist/frontend/babel/index.mjs +2580 -0
  101. package/dist/frontend/babel/lower-template.cjs +1931 -0
  102. package/dist/frontend/babel/lower-template.d.cts +23 -0
  103. package/dist/frontend/babel/lower-template.d.ts +24 -0
  104. package/dist/frontend/babel/lower-template.d.ts.map +1 -0
  105. package/dist/frontend/babel/lower-template.js +64 -0
  106. package/dist/frontend/babel/lower-template.mjs +1902 -0
  107. package/dist/frontend/babel/plugin.cjs +2556 -0
  108. package/dist/frontend/babel/plugin.d.cts +95 -0
  109. package/dist/frontend/babel/plugin.d.ts +96 -0
  110. package/dist/frontend/babel/plugin.d.ts.map +1 -0
  111. package/dist/frontend/babel/plugin.js +523 -0
  112. package/dist/frontend/babel/plugin.mjs +2527 -0
  113. package/dist/frontend/babel/server-functions.cjs +110 -0
  114. package/dist/frontend/babel/server-functions.d.cts +10 -0
  115. package/dist/frontend/babel/server-functions.d.ts +11 -0
  116. package/dist/frontend/babel/server-functions.d.ts.map +1 -0
  117. package/dist/frontend/babel/server-functions.js +81 -0
  118. package/dist/frontend/babel/server-functions.mjs +89 -0
  119. package/dist/frontend/babel/types.cjs +18 -0
  120. package/dist/frontend/babel/types.d.cts +33 -0
  121. package/dist/frontend/babel/types.d.ts +34 -0
  122. package/dist/frontend/babel/types.d.ts.map +1 -0
  123. package/dist/frontend/babel/types.js +1 -0
  124. package/dist/frontend/babel/types.mjs +0 -0
  125. package/dist/frontend/types.cjs +18 -0
  126. package/dist/frontend/types.d.cts +25 -0
  127. package/dist/frontend/types.d.ts +26 -0
  128. package/dist/frontend/types.d.ts.map +1 -0
  129. package/dist/frontend/types.js +1 -0
  130. package/dist/frontend/types.mjs +0 -0
  131. package/dist/frontend/vocabulary.cjs +98 -0
  132. package/dist/frontend/vocabulary.d.cts +79 -0
  133. package/dist/frontend/vocabulary.d.ts +80 -0
  134. package/dist/frontend/vocabulary.d.ts.map +1 -0
  135. package/dist/frontend/vocabulary.js +124 -0
  136. package/dist/frontend/vocabulary.mjs +77 -0
  137. package/dist/index.cjs +1957 -0
  138. package/dist/index.d.cts +27 -0
  139. package/dist/index.d.ts +28 -0
  140. package/dist/index.d.ts.map +1 -0
  141. package/dist/index.js +38 -0
  142. package/dist/index.mjs +1949 -0
  143. package/dist/integrations.cjs +5705 -0
  144. package/dist/integrations.d.cts +215 -0
  145. package/dist/integrations.d.ts +216 -0
  146. package/dist/integrations.d.ts.map +1 -0
  147. package/dist/integrations.js +566 -0
  148. package/dist/integrations.mjs +810 -0
  149. package/dist/ir/nodes.cjs +18 -0
  150. package/dist/ir/nodes.d.cts +168 -0
  151. package/dist/ir/nodes.d.ts +169 -0
  152. package/dist/ir/nodes.d.ts.map +1 -0
  153. package/dist/ir/nodes.js +1 -0
  154. package/dist/ir/nodes.mjs +0 -0
  155. package/dist/lower/compile-template.cjs +1670 -0
  156. package/dist/lower/compile-template.d.cts +82 -0
  157. package/dist/lower/compile-template.d.ts +83 -0
  158. package/dist/lower/compile-template.d.ts.map +1 -0
  159. package/dist/lower/compile-template.js +79 -0
  160. package/dist/lower/compile-template.mjs +1662 -0
  161. package/dist/lower/entities.cjs +288 -0
  162. package/dist/lower/entities.d.cts +1 -0
  163. package/dist/lower/entities.d.ts +2 -0
  164. package/dist/lower/entities.d.ts.map +1 -0
  165. package/dist/lower/entities.js +54 -0
  166. package/dist/lower/entities.mjs +267 -0
  167. package/dist/lower/jsx.cjs +1101 -0
  168. package/dist/lower/jsx.d.cts +33 -0
  169. package/dist/lower/jsx.d.ts +34 -0
  170. package/dist/lower/jsx.d.ts.map +1 -0
  171. package/dist/lower/jsx.js +414 -0
  172. package/dist/lower/jsx.mjs +1078 -0
  173. package/dist/lower/template.cjs +1354 -0
  174. package/dist/lower/template.d.cts +53 -0
  175. package/dist/lower/template.d.ts +54 -0
  176. package/dist/lower/template.d.ts.map +1 -0
  177. package/dist/lower/template.js +542 -0
  178. package/dist/lower/template.mjs +1335 -0
  179. package/dist/lower/text.cjs +42 -0
  180. package/dist/lower/text.d.cts +10 -0
  181. package/dist/lower/text.d.ts +11 -0
  182. package/dist/lower/text.d.ts.map +1 -0
  183. package/dist/lower/text.js +31 -0
  184. package/dist/lower/text.mjs +21 -0
  185. package/dist/optimize/analyze-static.cjs +112 -0
  186. package/dist/optimize/analyze-static.d.cts +39 -0
  187. package/dist/optimize/analyze-static.d.ts +40 -0
  188. package/dist/optimize/analyze-static.d.ts.map +1 -0
  189. package/dist/optimize/analyze-static.js +131 -0
  190. package/dist/optimize/analyze-static.mjs +91 -0
  191. package/dist/optimize/collapse-strategies.cjs +90 -0
  192. package/dist/optimize/collapse-strategies.d.cts +30 -0
  193. package/dist/optimize/collapse-strategies.d.ts +31 -0
  194. package/dist/optimize/collapse-strategies.d.ts.map +1 -0
  195. package/dist/optimize/collapse-strategies.js +33 -0
  196. package/dist/optimize/collapse-strategies.mjs +67 -0
  197. package/dist/options.cjs +33 -0
  198. package/dist/options.d.cts +39 -0
  199. package/dist/options.d.ts +40 -0
  200. package/dist/options.d.ts.map +1 -0
  201. package/dist/options.js +8 -0
  202. package/dist/options.mjs +12 -0
  203. package/dist/resolve/builtins.cjs +73 -0
  204. package/dist/resolve/builtins.d.cts +68 -0
  205. package/dist/resolve/builtins.d.ts +69 -0
  206. package/dist/resolve/builtins.d.ts.map +1 -0
  207. package/dist/resolve/builtins.js +64 -0
  208. package/dist/resolve/builtins.mjs +53 -0
  209. package/dist/resolve/component-globals.cjs +272 -0
  210. package/dist/resolve/component-globals.d.cts +88 -0
  211. package/dist/resolve/component-globals.d.ts +89 -0
  212. package/dist/resolve/component-globals.d.ts.map +1 -0
  213. package/dist/resolve/component-globals.js +160 -0
  214. package/dist/resolve/component-globals.mjs +249 -0
  215. package/dist/resolve/component-resolver.cjs +80 -0
  216. package/dist/resolve/component-resolver.d.cts +68 -0
  217. package/dist/resolve/component-resolver.d.ts +69 -0
  218. package/dist/resolve/component-resolver.d.ts.map +1 -0
  219. package/dist/resolve/component-resolver.js +95 -0
  220. package/dist/resolve/component-resolver.mjs +59 -0
  221. package/dist/resolve/load-directive.cjs +93 -0
  222. package/dist/resolve/load-directive.d.cts +53 -0
  223. package/dist/resolve/load-directive.d.ts +54 -0
  224. package/dist/resolve/load-directive.d.ts.map +1 -0
  225. package/dist/resolve/load-directive.js +93 -0
  226. package/dist/resolve/load-directive.mjs +72 -0
  227. package/dist/resolve/resolve-ir.cjs +108 -0
  228. package/dist/resolve/resolve-ir.d.cts +53 -0
  229. package/dist/resolve/resolve-ir.d.ts +54 -0
  230. package/dist/resolve/resolve-ir.d.ts.map +1 -0
  231. package/dist/resolve/resolve-ir.js +58 -0
  232. package/dist/resolve/resolve-ir.mjs +85 -0
  233. package/dist/resolve/write-globals.cjs +383 -0
  234. package/dist/resolve/write-globals.d.cts +36 -0
  235. package/dist/resolve/write-globals.d.ts +37 -0
  236. package/dist/resolve/write-globals.d.ts.map +1 -0
  237. package/dist/resolve/write-globals.js +169 -0
  238. package/dist/resolve/write-globals.mjs +362 -0
  239. package/dist/server-fns-VZLHMQTC.mjs +79 -0
  240. package/dist/server-functions-UAZKOLZW.mjs +82 -0
  241. package/dist/transform/bindings.cjs +71 -0
  242. package/dist/transform/bindings.d.cts +16 -0
  243. package/dist/transform/bindings.d.ts +17 -0
  244. package/dist/transform/bindings.d.ts.map +1 -0
  245. package/dist/transform/bindings.js +69 -0
  246. package/dist/transform/bindings.mjs +50 -0
  247. package/dist/transform/index.cjs +3837 -0
  248. package/dist/transform/index.d.cts +15 -0
  249. package/dist/transform/index.d.ts +16 -0
  250. package/dist/transform/index.d.ts.map +1 -0
  251. package/dist/transform/index.js +12 -0
  252. package/dist/transform/index.mjs +4882 -0
  253. package/dist/transform/intrinsics.cjs +261 -0
  254. package/dist/transform/intrinsics.d.cts +33 -0
  255. package/dist/transform/intrinsics.d.ts +34 -0
  256. package/dist/transform/intrinsics.d.ts.map +1 -0
  257. package/dist/transform/intrinsics.js +120 -0
  258. package/dist/transform/intrinsics.mjs +238 -0
  259. package/dist/transform/props.cjs +441 -0
  260. package/dist/transform/props.d.cts +45 -0
  261. package/dist/transform/props.d.ts +46 -0
  262. package/dist/transform/props.d.ts.map +1 -0
  263. package/dist/transform/props.js +221 -0
  264. package/dist/transform/props.mjs +1487 -0
  265. package/dist/transform/server-fn-id.cjs +35 -0
  266. package/dist/transform/server-fn-id.d.cts +9 -0
  267. package/dist/transform/server-fn-id.d.ts +10 -0
  268. package/dist/transform/server-fn-id.d.ts.map +1 -0
  269. package/dist/transform/server-fn-id.js +18 -0
  270. package/dist/transform/server-fn-id.mjs +14 -0
  271. package/dist/transform/server-fns.cjs +114 -0
  272. package/dist/transform/server-fns.d.cts +12 -0
  273. package/dist/transform/server-fns.d.ts +13 -0
  274. package/dist/transform/server-fns.d.ts.map +1 -0
  275. package/dist/transform/server-fns.js +94 -0
  276. package/dist/transform/server-fns.mjs +1160 -0
  277. package/dist/transform/source-locations.cjs +393 -0
  278. package/dist/transform/source-locations.d.cts +48 -0
  279. package/dist/transform/source-locations.d.ts +49 -0
  280. package/dist/transform/source-locations.d.ts.map +1 -0
  281. package/dist/transform/source-locations.js +303 -0
  282. package/dist/transform/source-locations.mjs +370 -0
  283. package/dist/transform/styles.cjs +606 -0
  284. package/dist/transform/styles.d.cts +237 -0
  285. package/dist/transform/styles.d.ts +238 -0
  286. package/dist/transform/styles.d.ts.map +1 -0
  287. package/dist/transform/styles.js +743 -0
  288. package/dist/transform/styles.mjs +671 -0
  289. package/dist/transform/templates.cjs +3806 -0
  290. package/dist/transform/templates.d.cts +82 -0
  291. package/dist/transform/templates.d.ts +83 -0
  292. package/dist/transform/templates.d.ts.map +1 -0
  293. package/dist/transform/templates.js +613 -0
  294. package/dist/transform/templates.mjs +4852 -0
  295. package/dist/transform-3W45L3EA.mjs +951 -0
  296. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  297. package/dist/vite-styles.cjs +223 -0
  298. package/dist/vite-styles.d.cts +68 -0
  299. package/dist/vite-styles.d.ts +69 -0
  300. package/dist/vite-styles.d.ts.map +1 -0
  301. package/dist/vite-styles.js +241 -0
  302. package/dist/vite-styles.mjs +214 -0
  303. package/package.json +141 -0
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Which names in a module hold reactive values, and what kind.
3
+ *
4
+ * Resolved from where a name came from, never from how it reads. This has to hold:
5
+ *
6
+ * import { createSignal as useState } from '@fluixi/reactive/signal';
7
+ * const count = useState(0); // a signal
8
+ *
9
+ * function createSignal() { return 42; }
10
+ * const value = createSignal(); // not a signal
11
+ *
12
+ * A name tells you nothing; the binding it resolves to tells you everything. So this
13
+ * walks the imports first, then the declarations that call them, and a local
14
+ * declaration always wins over anything the compiler would otherwise assume.
15
+ *
16
+ * Babel-free by the rule in no-babel-in-core: nodes are read structurally.
17
+ */
18
+ import { INTRINSICS, RUNTIME_PRIMITIVES, isPrimitiveModule, } from './intrinsics.js';
19
+ /** Every name a binding pattern introduces. */
20
+ function patternNames(node, out) {
21
+ if (!node)
22
+ return;
23
+ switch (node.type) {
24
+ case 'Identifier':
25
+ out.add(node.name);
26
+ return;
27
+ case 'ObjectPattern':
28
+ for (const p of node.properties ?? []) {
29
+ if (p.type === 'RestElement')
30
+ patternNames(p.argument, out);
31
+ else
32
+ patternNames(p.value, out);
33
+ }
34
+ return;
35
+ case 'ArrayPattern':
36
+ for (const e of node.elements ?? [])
37
+ patternNames(e, out);
38
+ return;
39
+ case 'AssignmentPattern':
40
+ patternNames(node.left, out);
41
+ return;
42
+ case 'RestElement':
43
+ patternNames(node.argument, out);
44
+ return;
45
+ }
46
+ }
47
+ /** Walk everything under a node. */
48
+ function walk(root, visit) {
49
+ if (!root || typeof root !== 'object' || typeof root.type !== 'string')
50
+ return;
51
+ visit(root);
52
+ for (const key of Object.keys(root)) {
53
+ if (key === 'loc' || key === 'leadingComments' || key === 'trailingComments')
54
+ continue;
55
+ const value = root[key];
56
+ if (Array.isArray(value))
57
+ for (const item of value)
58
+ walk(item, visit);
59
+ else if (value && typeof value === 'object')
60
+ walk(value, visit);
61
+ }
62
+ }
63
+ /** The primitive a call expression resolves to, if it resolves to one at all. */
64
+ function calledPrimitive(node, bindings) {
65
+ if (node.type !== 'CallExpression')
66
+ return undefined;
67
+ const callee = node.callee;
68
+ if (callee?.type !== 'Identifier')
69
+ return undefined;
70
+ const name = callee.name;
71
+ const imported = bindings.primitives.get(name);
72
+ if (imported)
73
+ return imported;
74
+ // `$signal(…)`, unless the module bound that name itself.
75
+ const intrinsic = INTRINSICS[name];
76
+ if (intrinsic && !bindings.shadowed.has(name))
77
+ return intrinsic.returns;
78
+ return undefined;
79
+ }
80
+ /** Record what a declaration's pattern holds, given what the call returns. */
81
+ function classify(id, returns, kinds) {
82
+ if (Array.isArray(returns)) {
83
+ // `const [count, setCount] = $signal(0)`: position decides which is which.
84
+ if (id.type === 'ArrayPattern') {
85
+ id.elements.forEach((element, index) => {
86
+ const kind = returns[index];
87
+ if (element?.type === 'Identifier' && kind)
88
+ kinds.set(element.name, kind);
89
+ });
90
+ }
91
+ return;
92
+ }
93
+ if (id.type === 'Identifier')
94
+ kinds.set(id.name, returns);
95
+ }
96
+ /**
97
+ * Every name the module binds, in any scope.
98
+ *
99
+ * Deliberately scope-blind: it answers "does this file declare this name anywhere", which
100
+ * is the question a diagnostic needs. A component declared inside a function
101
+ * (`const Row = () => …`) is bound just as much as an import, and warning about it would
102
+ * be noise. Over-permissive on purpose: missing a warning beats inventing one.
103
+ */
104
+ export function declaredNames(program) {
105
+ const names = new Set();
106
+ walk(program, (node) => {
107
+ switch (node.type) {
108
+ case 'VariableDeclarator':
109
+ patternNames(node.id, names);
110
+ return;
111
+ case 'FunctionDeclaration':
112
+ case 'FunctionExpression':
113
+ case 'ArrowFunctionExpression':
114
+ patternNames(node.id, names);
115
+ for (const p of node.params ?? [])
116
+ patternNames(p, names);
117
+ return;
118
+ case 'ClassDeclaration':
119
+ case 'ClassExpression':
120
+ patternNames(node.id, names);
121
+ return;
122
+ case 'ImportSpecifier':
123
+ case 'ImportDefaultSpecifier':
124
+ case 'ImportNamespaceSpecifier':
125
+ patternNames(node.local, names);
126
+ return;
127
+ case 'CatchClause':
128
+ patternNames(node.param, names);
129
+ return;
130
+ }
131
+ });
132
+ return names;
133
+ }
134
+ /**
135
+ * Read a module's reactive bindings.
136
+ *
137
+ * Two passes, because a call can only be classified once its callee is known: imports
138
+ * and local declarations first, then the declarations that call them.
139
+ */
140
+ export function resolveReactiveBindings(program) {
141
+ const bindings = { kinds: new Map(), primitives: new Map(), shadowed: new Set() };
142
+ const root = program;
143
+ // Anything the module declares under a `$` name shadows the intrinsic. Checked across
144
+ // the whole module, not just the top level: a nested `const $signal = …` still means
145
+ // the call at that point isn't ours, and refusing the rewrite there is the safe answer.
146
+ walk(root, (node) => {
147
+ const names = new Set();
148
+ if (node.type === 'VariableDeclarator')
149
+ patternNames(node.id, names);
150
+ else if (node.type === 'FunctionDeclaration' || node.type === 'ClassDeclaration')
151
+ patternNames(node.id, names);
152
+ else if (node.type === 'ImportDefaultSpecifier' || node.type === 'ImportNamespaceSpecifier')
153
+ patternNames(node.local, names);
154
+ else if (node.type === 'ImportSpecifier')
155
+ patternNames(node.local, names);
156
+ else if (node.type === 'FunctionExpression' ||
157
+ node.type === 'ArrowFunctionExpression' ||
158
+ node.type === 'FunctionDeclaration') {
159
+ for (const p of node.params ?? [])
160
+ patternNames(p, names);
161
+ }
162
+ for (const name of names)
163
+ if (INTRINSICS[name])
164
+ bindings.shadowed.add(name);
165
+ });
166
+ // Imported primitives, under whatever local name they were given.
167
+ for (const statement of root.body ?? []) {
168
+ if (statement.type !== 'ImportDeclaration')
169
+ continue;
170
+ if (!isPrimitiveModule(statement.source?.value))
171
+ continue;
172
+ for (const specifier of statement.specifiers ?? []) {
173
+ if (specifier.type !== 'ImportSpecifier')
174
+ continue;
175
+ const importedNode = specifier.imported;
176
+ const imported = (importedNode.type === 'Identifier' ? importedNode.name : importedNode.value);
177
+ const returns = RUNTIME_PRIMITIVES[imported];
178
+ if (returns)
179
+ bindings.primitives.set(specifier.local.name, returns);
180
+ }
181
+ }
182
+ // What the declarations that call them hold.
183
+ walk(root, (node) => {
184
+ if (node.type !== 'VariableDeclarator' || !node.init)
185
+ return;
186
+ const returns = calledPrimitive(node.init, bindings);
187
+ if (returns)
188
+ classify(node.id, returns, bindings.kinds);
189
+ });
190
+ return bindings;
191
+ }
@@ -0,0 +1,187 @@
1
+ // src/analyze/intrinsics.ts
2
+ var REACTIVE_MODULE = "@fluixi/reactive/signal";
3
+ var INTRINSICS = {
4
+ $signal: { export: "signal", module: REACTIVE_MODULE, returns: "signal-handle" },
5
+ $memo: { export: "memo", module: REACTIVE_MODULE, returns: "memo-handle" },
6
+ $effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
7
+ $store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
8
+ $resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
9
+ $cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
10
+ // No short runtime form for these yet, so the intrinsic stands for the `create*`
11
+ // name. Still worth having: no import to write, and when a shorter form is
12
+ // designed, the change is this line rather than a compiler pass.
13
+ $selector: { export: "createSelector", module: REACTIVE_MODULE, returns: "memo-accessor" },
14
+ $deferred: { export: "createDeferred", module: REACTIVE_MODULE, returns: "memo-accessor" },
15
+ // Not value constructors, but the compiler has to know them: they change what a read
16
+ // does. `untrack` suppresses dependency collection, which is exactly the kind of thing
17
+ // dependency analysis must not guess at.
18
+ $untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
19
+ $untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
20
+ // Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
21
+ // no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
22
+ $batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
23
+ $cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
24
+ $root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
25
+ $context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
26
+ $renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
27
+ $computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
28
+ // Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
29
+ // handle as far as reads go: the same accessor with `set` on it.
30
+ $storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
31
+ $asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
32
+ $persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
33
+ // An environment variable, public or server-only; the browser build refuses a secret.
34
+ $env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
35
+ };
36
+ var RUNTIME_PRIMITIVES = {
37
+ signal: "signal-handle",
38
+ memo: "memo-handle",
39
+ effect: "effect",
40
+ store: "store-handle",
41
+ createSignal: ["signal-accessor", "signal-setter"],
42
+ createMemo: "memo-accessor",
43
+ createEffect: "effect",
44
+ createRenderEffect: "effect",
45
+ renderEffect: "effect",
46
+ computed: "effect",
47
+ createStore: "reactive-object",
48
+ resource: "resource-handle",
49
+ cachedResource: "resource-handle",
50
+ createResource: "reactive-object",
51
+ createSelector: "memo-accessor",
52
+ createDeferred: "memo-accessor"
53
+ };
54
+ var PRIMITIVE_MODULES = [
55
+ "@fluixi/reactive",
56
+ "@fluixi/reactive/signal",
57
+ "@fluixi/reactive/store",
58
+ "@fluixi/reactive/cached-resource",
59
+ "@fluixi/core"
60
+ ];
61
+ var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
62
+ function isPrimitiveModule(source) {
63
+ return PRIMITIVE_MODULES.includes(source);
64
+ }
65
+
66
+ // src/analyze/reactive-bindings.ts
67
+ function patternNames(node, out) {
68
+ if (!node) return;
69
+ switch (node.type) {
70
+ case "Identifier":
71
+ out.add(node.name);
72
+ return;
73
+ case "ObjectPattern":
74
+ for (const p of node.properties ?? []) {
75
+ if (p.type === "RestElement") patternNames(p.argument, out);
76
+ else patternNames(p.value, out);
77
+ }
78
+ return;
79
+ case "ArrayPattern":
80
+ for (const e of node.elements ?? []) patternNames(e, out);
81
+ return;
82
+ case "AssignmentPattern":
83
+ patternNames(node.left, out);
84
+ return;
85
+ case "RestElement":
86
+ patternNames(node.argument, out);
87
+ return;
88
+ }
89
+ }
90
+ function walk(root, visit) {
91
+ if (!root || typeof root !== "object" || typeof root.type !== "string") return;
92
+ visit(root);
93
+ for (const key of Object.keys(root)) {
94
+ if (key === "loc" || key === "leadingComments" || key === "trailingComments") continue;
95
+ const value = root[key];
96
+ if (Array.isArray(value)) for (const item of value) walk(item, visit);
97
+ else if (value && typeof value === "object") walk(value, visit);
98
+ }
99
+ }
100
+ function calledPrimitive(node, bindings) {
101
+ if (node.type !== "CallExpression") return void 0;
102
+ const callee = node.callee;
103
+ if (callee?.type !== "Identifier") return void 0;
104
+ const name = callee.name;
105
+ const imported = bindings.primitives.get(name);
106
+ if (imported) return imported;
107
+ const intrinsic = INTRINSICS[name];
108
+ if (intrinsic && !bindings.shadowed.has(name)) return intrinsic.returns;
109
+ return void 0;
110
+ }
111
+ function classify(id, returns, kinds) {
112
+ if (Array.isArray(returns)) {
113
+ if (id.type === "ArrayPattern") {
114
+ id.elements.forEach((element, index) => {
115
+ const kind = returns[index];
116
+ if (element?.type === "Identifier" && kind) kinds.set(element.name, kind);
117
+ });
118
+ }
119
+ return;
120
+ }
121
+ if (id.type === "Identifier") kinds.set(id.name, returns);
122
+ }
123
+ function declaredNames(program) {
124
+ const names = /* @__PURE__ */ new Set();
125
+ walk(program, (node) => {
126
+ switch (node.type) {
127
+ case "VariableDeclarator":
128
+ patternNames(node.id, names);
129
+ return;
130
+ case "FunctionDeclaration":
131
+ case "FunctionExpression":
132
+ case "ArrowFunctionExpression":
133
+ patternNames(node.id, names);
134
+ for (const p of node.params ?? []) patternNames(p, names);
135
+ return;
136
+ case "ClassDeclaration":
137
+ case "ClassExpression":
138
+ patternNames(node.id, names);
139
+ return;
140
+ case "ImportSpecifier":
141
+ case "ImportDefaultSpecifier":
142
+ case "ImportNamespaceSpecifier":
143
+ patternNames(node.local, names);
144
+ return;
145
+ case "CatchClause":
146
+ patternNames(node.param, names);
147
+ return;
148
+ }
149
+ });
150
+ return names;
151
+ }
152
+ function resolveReactiveBindings(program) {
153
+ const bindings = { kinds: /* @__PURE__ */ new Map(), primitives: /* @__PURE__ */ new Map(), shadowed: /* @__PURE__ */ new Set() };
154
+ const root = program;
155
+ walk(root, (node) => {
156
+ const names = /* @__PURE__ */ new Set();
157
+ if (node.type === "VariableDeclarator") patternNames(node.id, names);
158
+ else if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") patternNames(node.id, names);
159
+ else if (node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier") patternNames(node.local, names);
160
+ else if (node.type === "ImportSpecifier") patternNames(node.local, names);
161
+ else if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration") {
162
+ for (const p of node.params ?? []) patternNames(p, names);
163
+ }
164
+ for (const name of names) if (INTRINSICS[name]) bindings.shadowed.add(name);
165
+ });
166
+ for (const statement of root.body ?? []) {
167
+ if (statement.type !== "ImportDeclaration") continue;
168
+ if (!isPrimitiveModule(statement.source?.value)) continue;
169
+ for (const specifier of statement.specifiers ?? []) {
170
+ if (specifier.type !== "ImportSpecifier") continue;
171
+ const importedNode = specifier.imported;
172
+ const imported = importedNode.type === "Identifier" ? importedNode.name : importedNode.value;
173
+ const returns = RUNTIME_PRIMITIVES[imported];
174
+ if (returns) bindings.primitives.set(specifier.local.name, returns);
175
+ }
176
+ }
177
+ walk(root, (node) => {
178
+ if (node.type !== "VariableDeclarator" || !node.init) return;
179
+ const returns = calledPrimitive(node.init, bindings);
180
+ if (returns) classify(node.id, returns, bindings.kinds);
181
+ });
182
+ return bindings;
183
+ }
184
+ export {
185
+ declaredNames,
186
+ resolveReactiveBindings
187
+ };
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/analyze/reactive-expr.ts
21
+ var reactive_expr_exports = {};
22
+ __export(reactive_expr_exports, {
23
+ isReactiveShape: () => isReactiveShape
24
+ });
25
+ module.exports = __toCommonJS(reactive_expr_exports);
26
+ var STABLE_MEMBER = "children";
27
+ function isReactiveShape(shape) {
28
+ switch (shape.kind) {
29
+ case "call":
30
+ return true;
31
+ case "member":
32
+ return shape.property !== STABLE_MEMBER;
33
+ case "compound":
34
+ return shape.parts.some(isReactiveShape);
35
+ case "opaque":
36
+ return false;
37
+ }
38
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Which expressions get wired reactively: `count()` re-runs on change, `count`
3
+ * does not, `props.children` is a subtree reference rather than a value.
4
+ *
5
+ * `ExprShape` is four cases and must not grow into a JavaScript AST, a front-end
6
+ * reports what the rule branches on, everything else collapses to `compound` or
7
+ * `opaque`. One rule, one place, whatever the parser.
8
+ */
9
+ export type ExprShape =
10
+ /** A call: `count()`, `t('key')`, `mergeRefs(a, b)`. Always reactive. */
11
+ {
12
+ kind: 'call';
13
+ }
14
+ /**
15
+ * A property access. `property` is the static name, or `null` when the access is
16
+ * computed or otherwise not a plain identifier (`obj[key]`, `obj[fn()]`).
17
+ */
18
+ | {
19
+ kind: 'member';
20
+ property: string | null;
21
+ }
22
+ /**
23
+ * Anything built out of sub-expressions: conditionals, logical and binary
24
+ * operators, template literals, object and array literals. Reactive when any
25
+ * part is, so `class={{ active: active() }}` reacts and `class={{ a: true }}`
26
+ * does not. The front-end decides which children count: a spread element or a
27
+ * computed key contributes nothing, because the compiler cannot see through it.
28
+ */
29
+ | {
30
+ kind: 'compound';
31
+ parts: ExprShape[];
32
+ }
33
+ /** Identifiers, literals, functions, JSX: passed through untouched. */
34
+ | {
35
+ kind: 'opaque';
36
+ };
37
+ /** Whether an expression of this shape must be wired reactively. */
38
+ export declare function isReactiveShape(shape: ExprShape): boolean;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Which expressions get wired reactively: `count()` re-runs on change, `count`
3
+ * does not, `props.children` is a subtree reference rather than a value.
4
+ *
5
+ * `ExprShape` is four cases and must not grow into a JavaScript AST, a front-end
6
+ * reports what the rule branches on, everything else collapses to `compound` or
7
+ * `opaque`. One rule, one place, whatever the parser.
8
+ */
9
+ export type ExprShape =
10
+ /** A call: `count()`, `t('key')`, `mergeRefs(a, b)`. Always reactive. */
11
+ {
12
+ kind: 'call';
13
+ }
14
+ /**
15
+ * A property access. `property` is the static name, or `null` when the access is
16
+ * computed or otherwise not a plain identifier (`obj[key]`, `obj[fn()]`).
17
+ */
18
+ | {
19
+ kind: 'member';
20
+ property: string | null;
21
+ }
22
+ /**
23
+ * Anything built out of sub-expressions: conditionals, logical and binary
24
+ * operators, template literals, object and array literals. Reactive when any
25
+ * part is, so `class={{ active: active() }}` reacts and `class={{ a: true }}`
26
+ * does not. The front-end decides which children count: a spread element or a
27
+ * computed key contributes nothing, because the compiler cannot see through it.
28
+ */
29
+ | {
30
+ kind: 'compound';
31
+ parts: ExprShape[];
32
+ }
33
+ /** Identifiers, literals, functions, JSX: passed through untouched. */
34
+ | {
35
+ kind: 'opaque';
36
+ };
37
+ /** Whether an expression of this shape must be wired reactively. */
38
+ export declare function isReactiveShape(shape: ExprShape): boolean;
39
+ //# sourceMappingURL=reactive-expr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactive-expr.d.ts","sourceRoot":"","sources":["../../src/analyze/reactive-expr.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,SAAS;AACnB,yEAAyE;AACvE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;AAClB;;;GAGG;GACD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE;AAC7C;;;;;;GAMG;GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,SAAS,EAAE,CAAA;CAAE;AAC1C,uEAAuE;GACrE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAavB,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAWzD"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Which expressions get wired reactively: `count()` re-runs on change, `count`
3
+ * does not, `props.children` is a subtree reference rather than a value.
4
+ *
5
+ * `ExprShape` is four cases and must not grow into a JavaScript AST, a front-end
6
+ * reports what the rule branches on, everything else collapses to `compound` or
7
+ * `opaque`. One rule, one place, whatever the parser.
8
+ */
9
+ /**
10
+ * `props.children`: and any `.children` access: is a stable subtree reference,
11
+ * not a reactive value. Compiling it to a `() => props.children` thunk adds an
12
+ * insert layer that fully unwraps the children's Suspense/memo into a static node,
13
+ * severing the reactive binding: a nested lazy/Suspense that resolves later never
14
+ * propagates up through the component-children hop. Passing it through
15
+ * non-reactively (`insert(el, props.children)`) keeps the child's memo intact so
16
+ * `insert` binds to it, which is what a direct `<Outlet/>` does.
17
+ */
18
+ const STABLE_MEMBER = 'children';
19
+ /** Whether an expression of this shape must be wired reactively. */
20
+ export function isReactiveShape(shape) {
21
+ switch (shape.kind) {
22
+ case 'call':
23
+ return true;
24
+ case 'member':
25
+ return shape.property !== STABLE_MEMBER;
26
+ case 'compound':
27
+ return shape.parts.some(isReactiveShape);
28
+ case 'opaque':
29
+ return false;
30
+ }
31
+ }
@@ -0,0 +1,17 @@
1
+ // src/analyze/reactive-expr.ts
2
+ var STABLE_MEMBER = "children";
3
+ function isReactiveShape(shape) {
4
+ switch (shape.kind) {
5
+ case "call":
6
+ return true;
7
+ case "member":
8
+ return shape.property !== STABLE_MEMBER;
9
+ case "compound":
10
+ return shape.parts.some(isReactiveShape);
11
+ case "opaque":
12
+ return false;
13
+ }
14
+ }
15
+ export {
16
+ isReactiveShape
17
+ };