@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,303 @@
1
+ /**
2
+ * Record where each reactive primitive was created, for the devtools graph.
3
+ *
4
+ * const count = signal(0);
5
+ * → globalThis.__fx_source?.("src/App.ts",1,14,"count"); const count = signal(0);
6
+ *
7
+ * A statement in front of the one that creates the node, not a wrapper round the call: the
8
+ * call may already be being rewritten: `$signal` becomes `signal`, and two passes editing
9
+ * one span is a splice over a splice.
10
+ *
11
+ * A global rather than an import, so the author's modules do not each take a dependency on
12
+ * @fluixi/devtools to carry a debug string. Nothing installs it by default.
13
+ *
14
+ * Positions come from the original source, before any pass moves anything.
15
+ *
16
+ * Development only, and one mark per statement: the runtime keeps a single slot, so
17
+ * marking two calls in one statement would hand the first node the second's location.
18
+ */
19
+ import { INTRINSICS, isIntrinsicName } from '../analyze/intrinsics.js';
20
+ import { resolveReactiveBindings } from '../analyze/reactive-bindings.js';
21
+ /** Installed by @fluixi/devtools; undefined everywhere else. */
22
+ export const SOURCE_MARKER = '__fx_source';
23
+ /** Where a component was declared. Keyed by name, since that is all the runtime carries. */
24
+ export const COMPONENT_MARKER = '__fx_component';
25
+ /**
26
+ * Where a class that extends another was declared, keyed by the class itself: a custom
27
+ * element's definition, which the runtime can only reach through `element.constructor`.
28
+ */
29
+ export const CLASS_MARKER = '__fx_class';
30
+ /**
31
+ * Where one reactive hole was written. This one wraps: the position has to travel with the
32
+ * accessor to wherever the dom wires it up. A template is emitted as one overwrite, so the
33
+ * source map has a single entry for the root and every hole traces back to it.
34
+ *
35
+ * `?? (f => f)` and not `?.()`: the value is the accessor, and returning undefined would
36
+ * delete the binding.
37
+ */
38
+ export const HOLE_MARKER = '__fx_hole';
39
+ /**
40
+ * `_(() => x(), 9, 25)`, or the accessor untouched when nothing is watching.
41
+ *
42
+ * `name` is the source text the value came from, for a `ref` where knowing which variable
43
+ * holds the element is the whole question.
44
+ */
45
+ export const markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === undefined ? '' : `,${JSON.stringify(name)}`})`;
46
+ /**
47
+ * Where each prop of a component tag was written.
48
+ *
49
+ * The props object is built as getters, so nothing in it can carry a position of its own.
50
+ * The marker takes the object and a name-to-position map, and hands the object straight
51
+ * back: devtools keeps the map, and a build without it passes the object through.
52
+ */
53
+ export const PROPS_MARKER = '__fx_props';
54
+ /** `_({ get a() {…} }, {"a":[9,25]})`, or the object untouched when nothing is watching. */
55
+ export const markProps = (object, at) => `(globalThis.${PROPS_MARKER} ?? ((p) => p))(${object},${JSON.stringify(at)})`;
56
+ /** The runtime names that make a node. */
57
+ const RUNTIME_PRIMITIVES = new Set([
58
+ 'signal', 'memo', 'effect', 'store', 'resource', 'watch',
59
+ 'createSignal', 'createMemo', 'createEffect', 'createStore', 'createResource',
60
+ ]);
61
+ /** Whether a module has anything to mark: a primitive call or a subclass. Cheap enough to run before parsing. */
62
+ export function mayHaveSourceMarks(code) {
63
+ for (const name of RUNTIME_PRIMITIVES) {
64
+ if (code.includes(name))
65
+ return true;
66
+ }
67
+ if (code.includes('$signal') || code.includes('$memo') || code.includes('$effect') || code.includes('$store'))
68
+ return true;
69
+ // A subclass gets a declaration mark, so an element with no signal of its own is still found.
70
+ return /\bclass\b[^{;]*\bextends\b/.test(code);
71
+ }
72
+ /** Positions where the grammar allows exactly one statement, so a second one changes it. */
73
+ const SINGLE_STATEMENT_PARENTS = new Set([
74
+ 'IfStatement', 'ForStatement', 'ForInStatement', 'ForOfStatement',
75
+ 'WhileStatement', 'DoWhileStatement', 'LabeledStatement', 'WithStatement',
76
+ ]);
77
+ function isLoneBranch(statement, parent) {
78
+ if (!parent || statement.type === 'BlockStatement')
79
+ return false;
80
+ return SINGLE_STATEMENT_PARENTS.has(parent.type);
81
+ }
82
+ function isExport(node) {
83
+ return node.type === 'ExportNamedDeclaration' || node.type === 'ExportDefaultDeclaration';
84
+ }
85
+ /** Where a class holds a per-instance initializer: the value of a field. */
86
+ const CLASS_FIELDS = new Set(['PropertyDefinition', 'ClassProperty', 'ClassPrivateProperty', 'AccessorProperty']);
87
+ function isStatement(node) {
88
+ return node.type.endsWith('Statement') || node.type === 'VariableDeclaration';
89
+ }
90
+ function walk(node, visit, stack = []) {
91
+ if (!node || typeof node.type !== 'string')
92
+ return;
93
+ visit(node, stack);
94
+ stack.push(node);
95
+ for (const key of Object.keys(node)) {
96
+ if (key === 'loc' || key === 'parent')
97
+ continue;
98
+ const value = node[key];
99
+ if (Array.isArray(value)) {
100
+ for (const child of value)
101
+ walk(child, visit, stack);
102
+ }
103
+ else if (value && typeof value.type === 'string') {
104
+ walk(value, visit, stack);
105
+ }
106
+ }
107
+ stack.pop();
108
+ }
109
+ /**
110
+ * const count = signal(0) → count
111
+ * const [count, setCount] = … → count, the accessor rather than the setter
112
+ * effect(() => …) → nothing
113
+ */
114
+ function nameFor(stack) {
115
+ const declarator = stack[stack.length - 1];
116
+ // `#count = signal(0)` and `count = signal(0)`: the field's name, without the `#`.
117
+ if (declarator && CLASS_FIELDS.has(declarator.type)) {
118
+ const key = declarator.key;
119
+ if (key?.type === 'Identifier' || key?.type === 'PrivateIdentifier' || key?.type === 'PrivateName') {
120
+ const name = (key.name ?? key.id?.name);
121
+ return name;
122
+ }
123
+ return undefined;
124
+ }
125
+ if (declarator?.type !== 'VariableDeclarator')
126
+ return undefined;
127
+ const id = declarator.id;
128
+ if (id?.type === 'Identifier')
129
+ return id.name;
130
+ if (id?.type === 'ArrayPattern') {
131
+ const first = id.elements?.[0];
132
+ if (first?.type === 'Identifier')
133
+ return first.name;
134
+ }
135
+ return undefined;
136
+ }
137
+ /** A capitalised function is how JSX tells a component from an element. */
138
+ function componentName(node) {
139
+ if (node.type === 'FunctionDeclaration') {
140
+ const name = node.id?.name;
141
+ return name && name[0] === name[0]?.toUpperCase() ? name : undefined;
142
+ }
143
+ if (node.type === 'VariableDeclarator') {
144
+ const id = node.id;
145
+ const init = node.init;
146
+ if (id?.type !== 'Identifier' || !init)
147
+ return undefined;
148
+ if (init.type !== 'ArrowFunctionExpression' && init.type !== 'FunctionExpression')
149
+ return undefined;
150
+ const name = id.name;
151
+ return name[0] === name[0]?.toUpperCase() ? name : undefined;
152
+ }
153
+ return undefined;
154
+ }
155
+ export function collectSourceEdits(program, filename) {
156
+ const edits = [];
157
+ // A single slot cannot describe more than the first primitive in a statement.
158
+ const claimed = new Set();
159
+ const { primitives, shadowed } = resolveReactiveBindings(program);
160
+ walk(program, (node, stack) => {
161
+ // The compiler wraps every component in a memo, and the memo is what the graph sees. It
162
+ // has no way back to the declaration, so the declaration says where it is by name.
163
+ const component = componentName(node);
164
+ if (component) {
165
+ const at = node.loc?.start;
166
+ // After the whole declaration, not after the function: `const Row = () => <b/>` ends
167
+ // where its jsx ends, and an insertion on that boundary is inside the span the
168
+ // template pass overwrites.
169
+ //
170
+ // Only through what wraps a declaration. Anything else above it is a block or an
171
+ // argument list, and a statement appended there lands outside the grammar ,
172
+ // `function Page(){}` inside `it('…', () => { … })` ended up between the `}` and the
173
+ // `)`, which is a syntax error in a file that compiled a moment earlier.
174
+ let end = node.end;
175
+ for (let i = stack.length - 1; i >= 0; i--) {
176
+ const up = stack[i];
177
+ if (up.type !== 'VariableDeclaration' &&
178
+ up.type !== 'ExportNamedDeclaration' &&
179
+ up.type !== 'ExportDefaultDeclaration') {
180
+ break;
181
+ }
182
+ end = up.end;
183
+ }
184
+ if (at) {
185
+ edits.push({
186
+ start: end,
187
+ end,
188
+ code: `;globalThis.${COMPONENT_MARKER}?.(${JSON.stringify(component)},${JSON.stringify(filename)},${at.line},${at.column});`,
189
+ });
190
+ }
191
+ }
192
+ // A static block at the top of the body runs once, when the class is defined, with `this`
193
+ // bound to the class. Only a subclass: that covers every custom element and keeps the mark
194
+ // off plain classes. An ambient `declare class` has no body to run.
195
+ if ((node.type === 'ClassDeclaration' || node.type === 'ClassExpression') && node.superClass && !node.declare) {
196
+ const at = node.loc?.start;
197
+ const body = node.body;
198
+ if (at && body) {
199
+ edits.push({
200
+ start: body.start + 1,
201
+ end: body.start + 1,
202
+ code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`,
203
+ });
204
+ }
205
+ }
206
+ if (node.type !== 'CallExpression')
207
+ return;
208
+ const callee = node.callee;
209
+ if (callee?.type !== 'Identifier')
210
+ return;
211
+ const name = callee.name;
212
+ // The same test the intrinsics pass makes, so the two agree on what is a primitive.
213
+ const intrinsic = isIntrinsicName(name) && !shadowed.has(name) ? INTRINSICS[name] : undefined;
214
+ // resolveReactiveBindings has followed the import, so `signal as state` is covered and
215
+ // a local function of the same name is not.
216
+ const imported = primitives.has(name) || RUNTIME_PRIMITIVES.has(name);
217
+ if (!intrinsic && !imported)
218
+ return;
219
+ const position = node.loc?.start;
220
+ if (!position)
221
+ return;
222
+ // A class field (`#count = signal(0)`) runs once per instance, and the class body has no
223
+ // statement to put the mark in front of. Hoisting it before the class runs it once, at
224
+ // definition, and the next node created anywhere took its name and line; inside a function
225
+ // (a mixin) the nearest statement was the function's body block, and the mark landed in
226
+ // front of the `{`. The call itself carries the mark instead, so it runs right before the
227
+ // node it describes.
228
+ for (let i = stack.length - 1; i >= 0; i--) {
229
+ const up = stack[i];
230
+ if (isStatement(up))
231
+ break;
232
+ if (CLASS_FIELDS.has(up.type)) {
233
+ if (claimed.has(node.start))
234
+ return;
235
+ claimed.add(node.start);
236
+ const label = nameFor(stack);
237
+ // An instance field also hands over `this`: the constructor runs before a custom
238
+ // element opens its scope, and the instance is what ties the node to it later.
239
+ const own = !up.static;
240
+ const args = [
241
+ JSON.stringify(filename),
242
+ String(position.line),
243
+ String(position.column),
244
+ label ? JSON.stringify(label) : own ? 'undefined' : undefined,
245
+ own ? 'this' : undefined,
246
+ ]
247
+ .filter((a) => a !== undefined)
248
+ .join(',');
249
+ edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args}),` });
250
+ edits.push({ start: node.end, end: node.end, code: ')' });
251
+ return;
252
+ }
253
+ }
254
+ // The mark goes in front of the statement, clear of any span another pass rewrites.
255
+ let statement;
256
+ let parent;
257
+ let index = -1;
258
+ for (let i = stack.length - 1; i >= 0; i--) {
259
+ if (isStatement(stack[i]) || isExport(stack[i])) {
260
+ statement = stack[i];
261
+ parent = stack[i - 1];
262
+ index = i;
263
+ break;
264
+ }
265
+ }
266
+ if (!statement)
267
+ return;
268
+ // `export const [cart] = createStore(…)` finds the declaration, which starts after the
269
+ // keyword: a mark there splits `export` from what it exports.
270
+ let start = statement.start;
271
+ let end = statement.end;
272
+ for (let i = index - 1; i >= 0; i--) {
273
+ if (!isExport(stack[i]))
274
+ break;
275
+ start = stack[i].start;
276
+ end = stack[i].end;
277
+ parent = stack[i - 1];
278
+ }
279
+ if (claimed.has(start))
280
+ return;
281
+ claimed.add(start);
282
+ const label = nameFor(stack);
283
+ const args = [
284
+ JSON.stringify(filename),
285
+ String(position.line),
286
+ String(position.column),
287
+ label ? JSON.stringify(label) : undefined,
288
+ ]
289
+ .filter((a) => a !== undefined)
290
+ .join(',');
291
+ const mark = `globalThis.${SOURCE_MARKER}?.(${args});`;
292
+ // `if (c) effect(…)` has one statement where the grammar allows one statement, so
293
+ // putting the mark in front of it moves the branch body out of the branch. Braces are
294
+ // added around both rather than skipping the mark.
295
+ if (isLoneBranch(statement, parent)) {
296
+ edits.push({ start, end: start, code: `{${mark}` });
297
+ edits.push({ start: end, end, code: '}' });
298
+ return;
299
+ }
300
+ edits.push({ start, end: start, code: mark });
301
+ });
302
+ return { edits, marked: edits.length };
303
+ }
@@ -0,0 +1,370 @@
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 isIntrinsicName(name) {
63
+ return Object.prototype.hasOwnProperty.call(INTRINSICS, name);
64
+ }
65
+ function isPrimitiveModule(source) {
66
+ return PRIMITIVE_MODULES.includes(source);
67
+ }
68
+
69
+ // src/analyze/reactive-bindings.ts
70
+ function patternNames(node, out) {
71
+ if (!node) return;
72
+ switch (node.type) {
73
+ case "Identifier":
74
+ out.add(node.name);
75
+ return;
76
+ case "ObjectPattern":
77
+ for (const p of node.properties ?? []) {
78
+ if (p.type === "RestElement") patternNames(p.argument, out);
79
+ else patternNames(p.value, out);
80
+ }
81
+ return;
82
+ case "ArrayPattern":
83
+ for (const e of node.elements ?? []) patternNames(e, out);
84
+ return;
85
+ case "AssignmentPattern":
86
+ patternNames(node.left, out);
87
+ return;
88
+ case "RestElement":
89
+ patternNames(node.argument, out);
90
+ return;
91
+ }
92
+ }
93
+ function walk(root, visit) {
94
+ if (!root || typeof root !== "object" || typeof root.type !== "string") return;
95
+ visit(root);
96
+ for (const key of Object.keys(root)) {
97
+ if (key === "loc" || key === "leadingComments" || key === "trailingComments") continue;
98
+ const value = root[key];
99
+ if (Array.isArray(value)) for (const item of value) walk(item, visit);
100
+ else if (value && typeof value === "object") walk(value, visit);
101
+ }
102
+ }
103
+ function calledPrimitive(node, bindings) {
104
+ if (node.type !== "CallExpression") return void 0;
105
+ const callee = node.callee;
106
+ if (callee?.type !== "Identifier") return void 0;
107
+ const name = callee.name;
108
+ const imported = bindings.primitives.get(name);
109
+ if (imported) return imported;
110
+ const intrinsic = INTRINSICS[name];
111
+ if (intrinsic && !bindings.shadowed.has(name)) return intrinsic.returns;
112
+ return void 0;
113
+ }
114
+ function classify(id, returns, kinds) {
115
+ if (Array.isArray(returns)) {
116
+ if (id.type === "ArrayPattern") {
117
+ id.elements.forEach((element, index) => {
118
+ const kind = returns[index];
119
+ if (element?.type === "Identifier" && kind) kinds.set(element.name, kind);
120
+ });
121
+ }
122
+ return;
123
+ }
124
+ if (id.type === "Identifier") kinds.set(id.name, returns);
125
+ }
126
+ function resolveReactiveBindings(program) {
127
+ const bindings = { kinds: /* @__PURE__ */ new Map(), primitives: /* @__PURE__ */ new Map(), shadowed: /* @__PURE__ */ new Set() };
128
+ const root = program;
129
+ walk(root, (node) => {
130
+ const names = /* @__PURE__ */ new Set();
131
+ if (node.type === "VariableDeclarator") patternNames(node.id, names);
132
+ else if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") patternNames(node.id, names);
133
+ else if (node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier") patternNames(node.local, names);
134
+ else if (node.type === "ImportSpecifier") patternNames(node.local, names);
135
+ else if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration") {
136
+ for (const p of node.params ?? []) patternNames(p, names);
137
+ }
138
+ for (const name of names) if (INTRINSICS[name]) bindings.shadowed.add(name);
139
+ });
140
+ for (const statement of root.body ?? []) {
141
+ if (statement.type !== "ImportDeclaration") continue;
142
+ if (!isPrimitiveModule(statement.source?.value)) continue;
143
+ for (const specifier of statement.specifiers ?? []) {
144
+ if (specifier.type !== "ImportSpecifier") continue;
145
+ const importedNode = specifier.imported;
146
+ const imported = importedNode.type === "Identifier" ? importedNode.name : importedNode.value;
147
+ const returns = RUNTIME_PRIMITIVES[imported];
148
+ if (returns) bindings.primitives.set(specifier.local.name, returns);
149
+ }
150
+ }
151
+ walk(root, (node) => {
152
+ if (node.type !== "VariableDeclarator" || !node.init) return;
153
+ const returns = calledPrimitive(node.init, bindings);
154
+ if (returns) classify(node.id, returns, bindings.kinds);
155
+ });
156
+ return bindings;
157
+ }
158
+
159
+ // src/transform/source-locations.ts
160
+ var SOURCE_MARKER = "__fx_source";
161
+ var COMPONENT_MARKER = "__fx_component";
162
+ var CLASS_MARKER = "__fx_class";
163
+ var HOLE_MARKER = "__fx_hole";
164
+ var markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
165
+ var PROPS_MARKER = "__fx_props";
166
+ var markProps = (object, at) => `(globalThis.${PROPS_MARKER} ?? ((p) => p))(${object},${JSON.stringify(at)})`;
167
+ var RUNTIME_PRIMITIVES2 = /* @__PURE__ */ new Set([
168
+ "signal",
169
+ "memo",
170
+ "effect",
171
+ "store",
172
+ "resource",
173
+ "watch",
174
+ "createSignal",
175
+ "createMemo",
176
+ "createEffect",
177
+ "createStore",
178
+ "createResource"
179
+ ]);
180
+ function mayHaveSourceMarks(code) {
181
+ for (const name of RUNTIME_PRIMITIVES2) {
182
+ if (code.includes(name)) return true;
183
+ }
184
+ if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
185
+ return /\bclass\b[^{;]*\bextends\b/.test(code);
186
+ }
187
+ var SINGLE_STATEMENT_PARENTS = /* @__PURE__ */ new Set([
188
+ "IfStatement",
189
+ "ForStatement",
190
+ "ForInStatement",
191
+ "ForOfStatement",
192
+ "WhileStatement",
193
+ "DoWhileStatement",
194
+ "LabeledStatement",
195
+ "WithStatement"
196
+ ]);
197
+ function isLoneBranch(statement, parent) {
198
+ if (!parent || statement.type === "BlockStatement") return false;
199
+ return SINGLE_STATEMENT_PARENTS.has(parent.type);
200
+ }
201
+ function isExport(node) {
202
+ return node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
203
+ }
204
+ var CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
205
+ function isStatement(node) {
206
+ return node.type.endsWith("Statement") || node.type === "VariableDeclaration";
207
+ }
208
+ function walk2(node, visit, stack = []) {
209
+ if (!node || typeof node.type !== "string") return;
210
+ visit(node, stack);
211
+ stack.push(node);
212
+ for (const key of Object.keys(node)) {
213
+ if (key === "loc" || key === "parent") continue;
214
+ const value = node[key];
215
+ if (Array.isArray(value)) {
216
+ for (const child of value) walk2(child, visit, stack);
217
+ } else if (value && typeof value.type === "string") {
218
+ walk2(value, visit, stack);
219
+ }
220
+ }
221
+ stack.pop();
222
+ }
223
+ function nameFor(stack) {
224
+ const declarator = stack[stack.length - 1];
225
+ if (declarator && CLASS_FIELDS.has(declarator.type)) {
226
+ const key = declarator.key;
227
+ if (key?.type === "Identifier" || key?.type === "PrivateIdentifier" || key?.type === "PrivateName") {
228
+ const name = key.name ?? key.id?.name;
229
+ return name;
230
+ }
231
+ return void 0;
232
+ }
233
+ if (declarator?.type !== "VariableDeclarator") return void 0;
234
+ const id = declarator.id;
235
+ if (id?.type === "Identifier") return id.name;
236
+ if (id?.type === "ArrayPattern") {
237
+ const first = id.elements?.[0];
238
+ if (first?.type === "Identifier") return first.name;
239
+ }
240
+ return void 0;
241
+ }
242
+ function componentName(node) {
243
+ if (node.type === "FunctionDeclaration") {
244
+ const name = node.id?.name;
245
+ return name && name[0] === name[0]?.toUpperCase() ? name : void 0;
246
+ }
247
+ if (node.type === "VariableDeclarator") {
248
+ const id = node.id;
249
+ const init = node.init;
250
+ if (id?.type !== "Identifier" || !init) return void 0;
251
+ if (init.type !== "ArrowFunctionExpression" && init.type !== "FunctionExpression") return void 0;
252
+ const name = id.name;
253
+ return name[0] === name[0]?.toUpperCase() ? name : void 0;
254
+ }
255
+ return void 0;
256
+ }
257
+ function collectSourceEdits(program, filename) {
258
+ const edits = [];
259
+ const claimed = /* @__PURE__ */ new Set();
260
+ const { primitives, shadowed } = resolveReactiveBindings(program);
261
+ walk2(program, (node, stack) => {
262
+ const component = componentName(node);
263
+ if (component) {
264
+ const at = node.loc?.start;
265
+ let end2 = node.end;
266
+ for (let i = stack.length - 1; i >= 0; i--) {
267
+ const up = stack[i];
268
+ if (up.type !== "VariableDeclaration" && up.type !== "ExportNamedDeclaration" && up.type !== "ExportDefaultDeclaration") {
269
+ break;
270
+ }
271
+ end2 = up.end;
272
+ }
273
+ if (at) {
274
+ edits.push({
275
+ start: end2,
276
+ end: end2,
277
+ code: `;globalThis.${COMPONENT_MARKER}?.(${JSON.stringify(component)},${JSON.stringify(filename)},${at.line},${at.column});`
278
+ });
279
+ }
280
+ }
281
+ if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.superClass && !node.declare) {
282
+ const at = node.loc?.start;
283
+ const body = node.body;
284
+ if (at && body) {
285
+ edits.push({
286
+ start: body.start + 1,
287
+ end: body.start + 1,
288
+ code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`
289
+ });
290
+ }
291
+ }
292
+ if (node.type !== "CallExpression") return;
293
+ const callee = node.callee;
294
+ if (callee?.type !== "Identifier") return;
295
+ const name = callee.name;
296
+ const intrinsic = isIntrinsicName(name) && !shadowed.has(name) ? INTRINSICS[name] : void 0;
297
+ const imported = primitives.has(name) || RUNTIME_PRIMITIVES2.has(name);
298
+ if (!intrinsic && !imported) return;
299
+ const position = node.loc?.start;
300
+ if (!position) return;
301
+ for (let i = stack.length - 1; i >= 0; i--) {
302
+ const up = stack[i];
303
+ if (isStatement(up)) break;
304
+ if (CLASS_FIELDS.has(up.type)) {
305
+ if (claimed.has(node.start)) return;
306
+ claimed.add(node.start);
307
+ const label2 = nameFor(stack);
308
+ const own = !up.static;
309
+ const args2 = [
310
+ JSON.stringify(filename),
311
+ String(position.line),
312
+ String(position.column),
313
+ label2 ? JSON.stringify(label2) : own ? "undefined" : void 0,
314
+ own ? "this" : void 0
315
+ ].filter((a) => a !== void 0).join(",");
316
+ edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args2}),` });
317
+ edits.push({ start: node.end, end: node.end, code: ")" });
318
+ return;
319
+ }
320
+ }
321
+ let statement;
322
+ let parent;
323
+ let index = -1;
324
+ for (let i = stack.length - 1; i >= 0; i--) {
325
+ if (isStatement(stack[i]) || isExport(stack[i])) {
326
+ statement = stack[i];
327
+ parent = stack[i - 1];
328
+ index = i;
329
+ break;
330
+ }
331
+ }
332
+ if (!statement) return;
333
+ let start = statement.start;
334
+ let end = statement.end;
335
+ for (let i = index - 1; i >= 0; i--) {
336
+ if (!isExport(stack[i])) break;
337
+ start = stack[i].start;
338
+ end = stack[i].end;
339
+ parent = stack[i - 1];
340
+ }
341
+ if (claimed.has(start)) return;
342
+ claimed.add(start);
343
+ const label = nameFor(stack);
344
+ const args = [
345
+ JSON.stringify(filename),
346
+ String(position.line),
347
+ String(position.column),
348
+ label ? JSON.stringify(label) : void 0
349
+ ].filter((a) => a !== void 0).join(",");
350
+ const mark = `globalThis.${SOURCE_MARKER}?.(${args});`;
351
+ if (isLoneBranch(statement, parent)) {
352
+ edits.push({ start, end: start, code: `{${mark}` });
353
+ edits.push({ start: end, end, code: "}" });
354
+ return;
355
+ }
356
+ edits.push({ start, end: start, code: mark });
357
+ });
358
+ return { edits, marked: edits.length };
359
+ }
360
+ export {
361
+ CLASS_MARKER,
362
+ COMPONENT_MARKER,
363
+ HOLE_MARKER,
364
+ PROPS_MARKER,
365
+ SOURCE_MARKER,
366
+ collectSourceEdits,
367
+ markHole,
368
+ markProps,
369
+ mayHaveSourceMarks
370
+ };