@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,226 @@
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/props-destructure.ts
21
+ var props_destructure_exports = {};
22
+ __export(props_destructure_exports, {
23
+ explainBail: () => explainBail,
24
+ planPropsDestructure: () => planPropsDestructure
25
+ });
26
+ module.exports = __toCommonJS(props_destructure_exports);
27
+ function patternNames(node, out) {
28
+ if (!node) return;
29
+ switch (node.type) {
30
+ case "Identifier":
31
+ out.add(node.name);
32
+ return;
33
+ case "ObjectPattern":
34
+ for (const p of node.properties) {
35
+ if (p.type === "RestElement") patternNames(p.argument, out);
36
+ else patternNames(p.value, out);
37
+ }
38
+ return;
39
+ case "ArrayPattern":
40
+ for (const e of node.elements) patternNames(e, out);
41
+ return;
42
+ case "AssignmentPattern":
43
+ patternNames(node.left, out);
44
+ return;
45
+ case "RestElement":
46
+ patternNames(node.argument, out);
47
+ return;
48
+ }
49
+ }
50
+ function isSafeDefault(node) {
51
+ switch (node.type) {
52
+ case "StringLiteral":
53
+ case "NumericLiteral":
54
+ case "BooleanLiteral":
55
+ case "NullLiteral":
56
+ case "BigIntLiteral":
57
+ case "RegExpLiteral":
58
+ case "Identifier":
59
+ return true;
60
+ // ESTree spells every literal as `Literal`; both shapes reach this analysis.
61
+ case "Literal":
62
+ return true;
63
+ case "TemplateLiteral":
64
+ return node.expressions.every(isSafeDefault);
65
+ case "UnaryExpression":
66
+ return isSafeDefault(node.argument);
67
+ case "MemberExpression":
68
+ return false;
69
+ default:
70
+ return false;
71
+ }
72
+ }
73
+ function walk(root, visit) {
74
+ if (!root || typeof root !== "object") return;
75
+ visit(root);
76
+ for (const key of Object.keys(root)) {
77
+ if (key === "loc" || key === "range" || key === "leadingComments" || key === "trailingComments") continue;
78
+ const value = root[key];
79
+ if (Array.isArray(value)) {
80
+ for (const item of value) if (item && typeof item === "object") walk(item, visit);
81
+ } else if (value && typeof value === "object" && typeof value.type === "string") {
82
+ walk(value, visit);
83
+ }
84
+ }
85
+ }
86
+ function reassignedNames(body) {
87
+ const written = /* @__PURE__ */ new Set();
88
+ walk(body, (node) => {
89
+ if (node.type === "AssignmentExpression") patternNames(node.left, written);
90
+ else if (node.type === "UpdateExpression") {
91
+ const arg = node.argument;
92
+ if (arg?.type === "Identifier") written.add(arg.name);
93
+ }
94
+ });
95
+ return written;
96
+ }
97
+ function shadowedNames(body, candidates) {
98
+ const shadowed = /* @__PURE__ */ new Set();
99
+ const note = (node) => {
100
+ const names = /* @__PURE__ */ new Set();
101
+ patternNames(node, names);
102
+ for (const n of names) if (candidates.has(n)) shadowed.add(n);
103
+ };
104
+ walk(body, (node) => {
105
+ switch (node.type) {
106
+ case "VariableDeclarator":
107
+ note(node.id);
108
+ return;
109
+ case "FunctionDeclaration":
110
+ case "FunctionExpression":
111
+ case "ArrowFunctionExpression":
112
+ note(node.id);
113
+ for (const p of node.params ?? []) note(p);
114
+ return;
115
+ case "CatchClause":
116
+ note(node.param);
117
+ return;
118
+ case "ClassDeclaration":
119
+ case "ClassExpression":
120
+ note(node.id);
121
+ return;
122
+ }
123
+ });
124
+ return shadowed;
125
+ }
126
+ function collect(pattern, path, plan) {
127
+ for (const property of pattern.properties ?? []) {
128
+ if (property.type === "RestElement") {
129
+ const argument = property.argument;
130
+ if (argument?.type !== "Identifier" || path.length > 0) {
131
+ const names2 = /* @__PURE__ */ new Set();
132
+ patternNames(argument, names2);
133
+ for (const name of names2) plan.bails.push({ name, reason: "rest" });
134
+ continue;
135
+ }
136
+ plan.rest = { name: argument.name, keys: [] };
137
+ continue;
138
+ }
139
+ if (property.computed) {
140
+ const names2 = /* @__PURE__ */ new Set();
141
+ patternNames(property.value, names2);
142
+ for (const name of names2) plan.bails.push({ name, reason: "computed" });
143
+ continue;
144
+ }
145
+ const key = property.key;
146
+ const propertyName = key.type === "Identifier" ? key.name : key.value;
147
+ let value = property.value;
148
+ let fallback;
149
+ if (value.type === "AssignmentPattern") {
150
+ fallback = value.right;
151
+ value = value.left;
152
+ }
153
+ const here = [...path, propertyName];
154
+ if (value.type === "Identifier") {
155
+ if (fallback && !isSafeDefault(fallback)) {
156
+ plan.bails.push({ name: value.name, reason: "unsafe-default" });
157
+ continue;
158
+ }
159
+ plan.reads.push({ name: value.name, path: here, ...fallback ? { fallback } : {} });
160
+ continue;
161
+ }
162
+ if (value.type === "ObjectPattern") {
163
+ if (fallback) {
164
+ const names2 = /* @__PURE__ */ new Set();
165
+ patternNames(value, names2);
166
+ for (const name of names2) plan.bails.push({ name, reason: "unsafe-default" });
167
+ continue;
168
+ }
169
+ collect(value, here, plan);
170
+ continue;
171
+ }
172
+ const names = /* @__PURE__ */ new Set();
173
+ patternNames(value, names);
174
+ for (const name of names) plan.bails.push({ name, reason: "computed" });
175
+ }
176
+ }
177
+ function planPropsDestructure(pattern, body) {
178
+ const plan = { reads: [], bails: [] };
179
+ if (pattern?.type !== "ObjectPattern") return plan;
180
+ collect(pattern, [], plan);
181
+ if (plan.rest) {
182
+ if (body?.type !== "BlockStatement") {
183
+ plan.bails.push({ name: plan.rest.name, reason: "rest" });
184
+ delete plan.rest;
185
+ } else {
186
+ plan.rest.keys = (pattern.properties ?? []).filter((p) => p.type !== "RestElement" && !p.computed).map((p) => {
187
+ const key = p.key;
188
+ return key.type === "Identifier" ? key.name : key.value;
189
+ });
190
+ }
191
+ }
192
+ if (plan.reads.length === 0 && !plan.rest) return plan;
193
+ const candidates = new Set(plan.reads.map((r) => r.name));
194
+ if (plan.rest) candidates.add(plan.rest.name);
195
+ const written = reassignedNames(body);
196
+ const shadowed = shadowedNames(body, candidates);
197
+ const kept = [];
198
+ for (const read of plan.reads) {
199
+ if (written.has(read.name)) plan.bails.push({ name: read.name, reason: "reassigned" });
200
+ else if (shadowed.has(read.name)) plan.bails.push({ name: read.name, reason: "shadowed" });
201
+ else kept.push(read);
202
+ }
203
+ plan.reads = kept;
204
+ if (plan.rest && written.has(plan.rest.name)) {
205
+ plan.bails.push({ name: plan.rest.name, reason: "reassigned" });
206
+ delete plan.rest;
207
+ } else if (plan.rest && shadowed.has(plan.rest.name)) {
208
+ plan.bails.push({ name: plan.rest.name, reason: "shadowed" });
209
+ delete plan.rest;
210
+ }
211
+ return plan;
212
+ }
213
+ function explainBail(reason) {
214
+ switch (reason) {
215
+ case "rest":
216
+ return "this rest element cannot be served by splitProps, and copying the props into a plain object would lose the getters";
217
+ case "computed":
218
+ return "the property is not known until it runs";
219
+ case "reassigned":
220
+ return "the binding is assigned to, and props are read-only";
221
+ case "shadowed":
222
+ return "an inner scope binds the same name";
223
+ case "unsafe-default":
224
+ return "the default would have to run again on every read";
225
+ }
226
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Props destructuring, without losing reactivity.
3
+ *
4
+ * Props come in as an object of getters, so `props.name` re-reads every time and that
5
+ * keeps a binding current. `const { name } = props` copies the value out once, which is
6
+ * why we call splitProps in about 84 components.
7
+ *
8
+ * The plan here rewrites `name` to `props.name` at each use rather than making it an
9
+ * accessor. `() => props.name` would change the binding's type, and then every use has
10
+ * to change with it: passed to a plain function, stored in an array, compared with
11
+ * `===`. That's a whole-program job. Substitution is one function body and a rename.
12
+ *
13
+ * It does change one thing. A read that happens later sees the current value instead of
14
+ * the value at destructure time, which is the reason to do this at all. Anything past
15
+ * that I leave as written and report, so splitProps stays correct where it's still the
16
+ * right answer.
17
+ *
18
+ * No babel in here (see no-babel-in-core.spec.ts), nodes are read structurally, the way
19
+ * transform/bindings.ts does, so either front-end can drive it.
20
+ */
21
+ interface Node {
22
+ type: string;
23
+ [key: string]: unknown;
24
+ }
25
+ /** Why a binding was left alone. All of these change more than when the read happens. */
26
+ export type DestructureBail =
27
+ /**
28
+ * A rest we can't serve: destructured further (`...{ a }`), or in a function with no
29
+ * block to put the splitProps call in (`({ a, ...rest }) => …`).
30
+ */
31
+ 'rest'
32
+ /** `const { [key]: a } = props`: we don't know the property until it runs. */
33
+ | 'computed'
34
+ /** The binding gets assigned to, and props are read-only, so it can't become a member. */
35
+ | 'reassigned'
36
+ /** An inner scope binds the same name, so a use site could mean either one. */
37
+ | 'shadowed'
38
+ /**
39
+ * A default we can't re-run on every read: a function hands out a new identity each
40
+ * time, a call runs its side effect each time.
41
+ */
42
+ | 'unsafe-default';
43
+ export interface PropsRead {
44
+ /** The local name the pattern introduced. */
45
+ name: string;
46
+ /** Property path to read through instead: `['user', 'name']` for `{ user: { name } }`. */
47
+ path: string[];
48
+ /**
49
+ * Default from the pattern. JS only applies one for `undefined`, not for null, so
50
+ * codegen has to test `=== undefined` rather than reach for `??`, and re-run it on
51
+ * every read.
52
+ */
53
+ fallback?: Node;
54
+ }
55
+ export interface DestructurePlan {
56
+ /** Bindings we can rewrite to a property read. */
57
+ reads: PropsRead[];
58
+ /** Bindings we left alone, with the reason to report. */
59
+ bails: {
60
+ name: string;
61
+ reason: DestructureBail;
62
+ }[];
63
+ /**
64
+ * A `...rest`, and the keys it has to exclude.
65
+ *
66
+ * This is what splitProps is for: it copies the getters across rather than reading
67
+ * them, which is the reason a plain `...rest` can't be rewritten. So instead of
68
+ * refusing the pattern, we write the splitProps call the author would have written.
69
+ */
70
+ rest?: {
71
+ name: string;
72
+ keys: string[];
73
+ };
74
+ }
75
+ /**
76
+ * Plan one props pattern. `pattern` is the ObjectPattern, `body` the function body its
77
+ * bindings live in. Every binding ends up in `reads` (rewrite it) or `bails` (leave it
78
+ * and say why).
79
+ */
80
+ export declare function planPropsDestructure(pattern: Node, body: Node | null | undefined): DestructurePlan;
81
+ /** Reason text for the diagnostic. */
82
+ export declare function explainBail(reason: DestructureBail): string;
83
+ export {};
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Props destructuring, without losing reactivity.
3
+ *
4
+ * Props come in as an object of getters, so `props.name` re-reads every time and that
5
+ * keeps a binding current. `const { name } = props` copies the value out once, which is
6
+ * why we call splitProps in about 84 components.
7
+ *
8
+ * The plan here rewrites `name` to `props.name` at each use rather than making it an
9
+ * accessor. `() => props.name` would change the binding's type, and then every use has
10
+ * to change with it: passed to a plain function, stored in an array, compared with
11
+ * `===`. That's a whole-program job. Substitution is one function body and a rename.
12
+ *
13
+ * It does change one thing. A read that happens later sees the current value instead of
14
+ * the value at destructure time, which is the reason to do this at all. Anything past
15
+ * that I leave as written and report, so splitProps stays correct where it's still the
16
+ * right answer.
17
+ *
18
+ * No babel in here (see no-babel-in-core.spec.ts), nodes are read structurally, the way
19
+ * transform/bindings.ts does, so either front-end can drive it.
20
+ */
21
+ interface Node {
22
+ type: string;
23
+ [key: string]: unknown;
24
+ }
25
+ /** Why a binding was left alone. All of these change more than when the read happens. */
26
+ export type DestructureBail =
27
+ /**
28
+ * A rest we can't serve: destructured further (`...{ a }`), or in a function with no
29
+ * block to put the splitProps call in (`({ a, ...rest }) => …`).
30
+ */
31
+ 'rest'
32
+ /** `const { [key]: a } = props`: we don't know the property until it runs. */
33
+ | 'computed'
34
+ /** The binding gets assigned to, and props are read-only, so it can't become a member. */
35
+ | 'reassigned'
36
+ /** An inner scope binds the same name, so a use site could mean either one. */
37
+ | 'shadowed'
38
+ /**
39
+ * A default we can't re-run on every read: a function hands out a new identity each
40
+ * time, a call runs its side effect each time.
41
+ */
42
+ | 'unsafe-default';
43
+ export interface PropsRead {
44
+ /** The local name the pattern introduced. */
45
+ name: string;
46
+ /** Property path to read through instead: `['user', 'name']` for `{ user: { name } }`. */
47
+ path: string[];
48
+ /**
49
+ * Default from the pattern. JS only applies one for `undefined`, not for null, so
50
+ * codegen has to test `=== undefined` rather than reach for `??`, and re-run it on
51
+ * every read.
52
+ */
53
+ fallback?: Node;
54
+ }
55
+ export interface DestructurePlan {
56
+ /** Bindings we can rewrite to a property read. */
57
+ reads: PropsRead[];
58
+ /** Bindings we left alone, with the reason to report. */
59
+ bails: {
60
+ name: string;
61
+ reason: DestructureBail;
62
+ }[];
63
+ /**
64
+ * A `...rest`, and the keys it has to exclude.
65
+ *
66
+ * This is what splitProps is for: it copies the getters across rather than reading
67
+ * them, which is the reason a plain `...rest` can't be rewritten. So instead of
68
+ * refusing the pattern, we write the splitProps call the author would have written.
69
+ */
70
+ rest?: {
71
+ name: string;
72
+ keys: string[];
73
+ };
74
+ }
75
+ /**
76
+ * Plan one props pattern. `pattern` is the ObjectPattern, `body` the function body its
77
+ * bindings live in. Every binding ends up in `reads` (rewrite it) or `bails` (leave it
78
+ * and say why).
79
+ */
80
+ export declare function planPropsDestructure(pattern: Node, body: Node | null | undefined): DestructurePlan;
81
+ /** Reason text for the diagnostic. */
82
+ export declare function explainBail(reason: DestructureBail): string;
83
+ export {};
84
+ //# sourceMappingURL=props-destructure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"props-destructure.d.ts","sourceRoot":"","sources":["../../src/analyze/props-destructure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,UAAU,IAAI;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,yFAAyF;AACzF,MAAM,MAAM,eAAe;AACzB;;;GAGG;AACD,MAAM;AACR,8EAA8E;GAC5E,UAAU;AACZ,0FAA0F;GACxF,YAAY;AACd,+EAA+E;GAC7E,UAAU;AACZ;;;GAGG;GACD,gBAAgB,CAAC;AAErB,MAAM,WAAW,SAAS;IACxB,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,0FAA0F;IAC1F,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,yDAAyD;IACzD,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,eAAe,CAAA;KAAE,EAAE,CAAC;IACnD;;;;;;OAMG;IACH,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACzC;AAoLD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,eAAe,CAgDlG;AAED,sCAAsC;AACtC,wBAAgB,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAa3D"}
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Props destructuring, without losing reactivity.
3
+ *
4
+ * Props come in as an object of getters, so `props.name` re-reads every time and that
5
+ * keeps a binding current. `const { name } = props` copies the value out once, which is
6
+ * why we call splitProps in about 84 components.
7
+ *
8
+ * The plan here rewrites `name` to `props.name` at each use rather than making it an
9
+ * accessor. `() => props.name` would change the binding's type, and then every use has
10
+ * to change with it: passed to a plain function, stored in an array, compared with
11
+ * `===`. That's a whole-program job. Substitution is one function body and a rename.
12
+ *
13
+ * It does change one thing. A read that happens later sees the current value instead of
14
+ * the value at destructure time, which is the reason to do this at all. Anything past
15
+ * that I leave as written and report, so splitProps stays correct where it's still the
16
+ * right answer.
17
+ *
18
+ * No babel in here (see no-babel-in-core.spec.ts), nodes are read structurally, the way
19
+ * transform/bindings.ts does, so either front-end can drive it.
20
+ */
21
+ /** Every name a pattern introduces, so we can check each one for shadowing and writes. */
22
+ function patternNames(node, out) {
23
+ if (!node)
24
+ return;
25
+ switch (node.type) {
26
+ case 'Identifier':
27
+ out.add(node.name);
28
+ return;
29
+ case 'ObjectPattern':
30
+ for (const p of node.properties) {
31
+ if (p.type === 'RestElement')
32
+ patternNames(p.argument, out);
33
+ else
34
+ patternNames(p.value, out);
35
+ }
36
+ return;
37
+ case 'ArrayPattern':
38
+ for (const e of node.elements)
39
+ patternNames(e, out);
40
+ return;
41
+ case 'AssignmentPattern':
42
+ patternNames(node.left, out);
43
+ return;
44
+ case 'RestElement':
45
+ patternNames(node.argument, out);
46
+ return;
47
+ }
48
+ }
49
+ /**
50
+ * Defaults get re-run on every read now, so they have to be cheap and stable. Literals
51
+ * and identifiers are. A function isn't: it hands out a new identity each read, which
52
+ * breaks anything comparing props: and neither is a call.
53
+ */
54
+ function isSafeDefault(node) {
55
+ switch (node.type) {
56
+ case 'StringLiteral':
57
+ case 'NumericLiteral':
58
+ case 'BooleanLiteral':
59
+ case 'NullLiteral':
60
+ case 'BigIntLiteral':
61
+ case 'RegExpLiteral':
62
+ case 'Identifier':
63
+ return true;
64
+ // ESTree spells every literal as `Literal`; both shapes reach this analysis.
65
+ case 'Literal':
66
+ return true;
67
+ case 'TemplateLiteral':
68
+ return node.expressions.every(isSafeDefault);
69
+ case 'UnaryExpression':
70
+ return isSafeDefault(node.argument);
71
+ case 'MemberExpression':
72
+ // Could be a getter, and we'd be running it on every read.
73
+ return false;
74
+ default:
75
+ return false;
76
+ }
77
+ }
78
+ /** Walk everything under `root`. No visitor API here, so it's hand-rolled. */
79
+ function walk(root, visit) {
80
+ if (!root || typeof root !== 'object')
81
+ return;
82
+ visit(root);
83
+ for (const key of Object.keys(root)) {
84
+ if (key === 'loc' || key === 'range' || key === 'leadingComments' || key === 'trailingComments')
85
+ continue;
86
+ const value = root[key];
87
+ if (Array.isArray(value)) {
88
+ for (const item of value)
89
+ if (item && typeof item === 'object')
90
+ walk(item, visit);
91
+ }
92
+ else if (value && typeof value === 'object' && typeof value.type === 'string') {
93
+ walk(value, visit);
94
+ }
95
+ }
96
+ }
97
+ /** Anything written to in the body: `name = x`, `name++`, `[name] = …`. */
98
+ function reassignedNames(body) {
99
+ const written = new Set();
100
+ walk(body, (node) => {
101
+ if (node.type === 'AssignmentExpression')
102
+ patternNames(node.left, written);
103
+ else if (node.type === 'UpdateExpression') {
104
+ const arg = node.argument;
105
+ if (arg?.type === 'Identifier')
106
+ written.add(arg.name);
107
+ }
108
+ });
109
+ return written;
110
+ }
111
+ /** Names an inner scope re-binds, where a use site would mean something else. */
112
+ function shadowedNames(body, candidates) {
113
+ const shadowed = new Set();
114
+ const note = (node) => {
115
+ const names = new Set();
116
+ patternNames(node, names);
117
+ for (const n of names)
118
+ if (candidates.has(n))
119
+ shadowed.add(n);
120
+ };
121
+ walk(body, (node) => {
122
+ switch (node.type) {
123
+ case 'VariableDeclarator':
124
+ note(node.id);
125
+ return;
126
+ case 'FunctionDeclaration':
127
+ case 'FunctionExpression':
128
+ case 'ArrowFunctionExpression':
129
+ note(node.id);
130
+ for (const p of node.params ?? [])
131
+ note(p);
132
+ return;
133
+ case 'CatchClause':
134
+ note(node.param);
135
+ return;
136
+ case 'ClassDeclaration':
137
+ case 'ClassExpression':
138
+ note(node.id);
139
+ return;
140
+ }
141
+ });
142
+ return shadowed;
143
+ }
144
+ /** One level of an object pattern, recursing into nested ones. */
145
+ function collect(pattern, path, plan) {
146
+ for (const property of pattern.properties ?? []) {
147
+ if (property.type === 'RestElement') {
148
+ const argument = property.argument;
149
+ // Only a plain name. `...{ a }` would need its own splitProps and its own rules.
150
+ if (argument?.type !== 'Identifier' || path.length > 0) {
151
+ const names = new Set();
152
+ patternNames(argument, names);
153
+ for (const name of names)
154
+ plan.bails.push({ name, reason: 'rest' });
155
+ continue;
156
+ }
157
+ plan.rest = { name: argument.name, keys: [] };
158
+ continue;
159
+ }
160
+ if (property.computed) {
161
+ const names = new Set();
162
+ patternNames(property.value, names);
163
+ for (const name of names)
164
+ plan.bails.push({ name, reason: 'computed' });
165
+ continue;
166
+ }
167
+ const key = property.key;
168
+ const propertyName = (key.type === 'Identifier' ? key.name : key.value);
169
+ let value = property.value;
170
+ let fallback;
171
+ if (value.type === 'AssignmentPattern') {
172
+ fallback = value.right;
173
+ value = value.left;
174
+ }
175
+ const here = [...path, propertyName];
176
+ if (value.type === 'Identifier') {
177
+ if (fallback && !isSafeDefault(fallback)) {
178
+ plan.bails.push({ name: value.name, reason: 'unsafe-default' });
179
+ continue;
180
+ }
181
+ plan.reads.push({ name: value.name, path: here, ...(fallback ? { fallback } : {}) });
182
+ continue;
183
+ }
184
+ if (value.type === 'ObjectPattern') {
185
+ // `{ user: { name } = {} }` would have to build the default object on every read.
186
+ if (fallback) {
187
+ const names = new Set();
188
+ patternNames(value, names);
189
+ for (const name of names)
190
+ plan.bails.push({ name, reason: 'unsafe-default' });
191
+ continue;
192
+ }
193
+ collect(value, here, plan);
194
+ continue;
195
+ }
196
+ // An array pattern indexes into a value we can't prove is stable, so leave it.
197
+ const names = new Set();
198
+ patternNames(value, names);
199
+ for (const name of names)
200
+ plan.bails.push({ name, reason: 'computed' });
201
+ }
202
+ }
203
+ /**
204
+ * Plan one props pattern. `pattern` is the ObjectPattern, `body` the function body its
205
+ * bindings live in. Every binding ends up in `reads` (rewrite it) or `bails` (leave it
206
+ * and say why).
207
+ */
208
+ export function planPropsDestructure(pattern, body) {
209
+ const plan = { reads: [], bails: [] };
210
+ if (pattern?.type !== 'ObjectPattern')
211
+ return plan;
212
+ collect(pattern, [], plan);
213
+ if (plan.rest) {
214
+ // The splitProps call is a statement, so there has to be somewhere to put it.
215
+ if (body?.type !== 'BlockStatement') {
216
+ plan.bails.push({ name: plan.rest.name, reason: 'rest' });
217
+ delete plan.rest;
218
+ }
219
+ else {
220
+ // Keys the rest has to exclude: every top-level property the pattern names.
221
+ plan.rest.keys = (pattern.properties ?? [])
222
+ .filter((p) => p.type !== 'RestElement' && !p.computed)
223
+ .map((p) => {
224
+ const key = p.key;
225
+ return (key.type === 'Identifier' ? key.name : key.value);
226
+ });
227
+ }
228
+ }
229
+ if (plan.reads.length === 0 && !plan.rest)
230
+ return plan;
231
+ const candidates = new Set(plan.reads.map((r) => r.name));
232
+ if (plan.rest)
233
+ candidates.add(plan.rest.name);
234
+ const written = reassignedNames(body);
235
+ const shadowed = shadowedNames(body, candidates);
236
+ const kept = [];
237
+ for (const read of plan.reads) {
238
+ if (written.has(read.name))
239
+ plan.bails.push({ name: read.name, reason: 'reassigned' });
240
+ else if (shadowed.has(read.name))
241
+ plan.bails.push({ name: read.name, reason: 'shadowed' });
242
+ else
243
+ kept.push(read);
244
+ }
245
+ plan.reads = kept;
246
+ // The rest binding is declared by the code we emit, so it has to survive the same
247
+ // checks: reassigning it or shadowing the name would break what we wrote.
248
+ if (plan.rest && written.has(plan.rest.name)) {
249
+ plan.bails.push({ name: plan.rest.name, reason: 'reassigned' });
250
+ delete plan.rest;
251
+ }
252
+ else if (plan.rest && shadowed.has(plan.rest.name)) {
253
+ plan.bails.push({ name: plan.rest.name, reason: 'shadowed' });
254
+ delete plan.rest;
255
+ }
256
+ return plan;
257
+ }
258
+ /** Reason text for the diagnostic. */
259
+ export function explainBail(reason) {
260
+ switch (reason) {
261
+ case 'rest':
262
+ return 'this rest element cannot be served by splitProps, and copying the props into a plain object would lose the getters';
263
+ case 'computed':
264
+ return 'the property is not known until it runs';
265
+ case 'reassigned':
266
+ return 'the binding is assigned to, and props are read-only';
267
+ case 'shadowed':
268
+ return 'an inner scope binds the same name';
269
+ case 'unsafe-default':
270
+ return 'the default would have to run again on every read';
271
+ }
272
+ }