@alloy-js/core 0.16.0 → 0.18.0-dev.2

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 (249) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/src/binder.d.ts +19 -235
  3. package/dist/src/binder.d.ts.map +1 -1
  4. package/dist/src/binder.js +85 -386
  5. package/dist/src/code.d.ts +1 -1
  6. package/dist/src/code.d.ts.map +1 -1
  7. package/dist/src/components/Block.d.ts +1 -1
  8. package/dist/src/components/Block.d.ts.map +1 -1
  9. package/dist/src/components/Block.js +3 -1
  10. package/dist/src/components/Declaration.d.ts +2 -2
  11. package/dist/src/components/Declaration.d.ts.map +1 -1
  12. package/dist/src/components/Declaration.js +6 -5
  13. package/dist/src/components/For.d.ts +1 -1
  14. package/dist/src/components/For.d.ts.map +1 -1
  15. package/dist/src/components/For.js +1 -1
  16. package/dist/src/components/Indent.d.ts +1 -1
  17. package/dist/src/components/Indent.d.ts.map +1 -1
  18. package/dist/src/components/List.d.ts +1 -1
  19. package/dist/src/components/List.d.ts.map +1 -1
  20. package/dist/src/components/List.js +3 -1
  21. package/dist/src/components/MemberDeclaration.d.ts +3 -3
  22. package/dist/src/components/MemberDeclaration.d.ts.map +1 -1
  23. package/dist/src/components/MemberDeclaration.js +4 -4
  24. package/dist/src/components/MemberScope.d.ts +2 -2
  25. package/dist/src/components/MemberScope.d.ts.map +1 -1
  26. package/dist/src/components/MemberScope.js +0 -2
  27. package/dist/src/components/Output.d.ts +1 -1
  28. package/dist/src/components/Output.d.ts.map +1 -1
  29. package/dist/src/components/Output.js +1 -1
  30. package/dist/src/components/Prose.d.ts +1 -1
  31. package/dist/src/components/Prose.d.ts.map +1 -1
  32. package/dist/src/components/ReferenceOrContent.d.ts +1 -1
  33. package/dist/src/components/ReferenceOrContent.d.ts.map +1 -1
  34. package/dist/src/components/Scope.d.ts +2 -2
  35. package/dist/src/components/Scope.d.ts.map +1 -1
  36. package/dist/src/components/Scope.js +3 -6
  37. package/dist/src/components/Show.d.ts +1 -1
  38. package/dist/src/components/Show.d.ts.map +1 -1
  39. package/dist/src/components/SourceDirectory.d.ts +1 -1
  40. package/dist/src/components/SourceDirectory.d.ts.map +1 -1
  41. package/dist/src/components/SourceDirectory.js +1 -1
  42. package/dist/src/components/SourceFile.d.ts +1 -1
  43. package/dist/src/components/SourceFile.d.ts.map +1 -1
  44. package/dist/src/components/SourceFile.js +1 -1
  45. package/dist/src/components/StatementList.d.ts +1 -1
  46. package/dist/src/components/StatementList.d.ts.map +1 -1
  47. package/dist/src/components/StatementList.js +1 -1
  48. package/dist/src/components/Switch.d.ts +2 -2
  49. package/dist/src/components/Switch.d.ts.map +1 -1
  50. package/dist/src/components/Switch.js +2 -1
  51. package/dist/src/components/Wrap.d.ts +1 -1
  52. package/dist/src/components/Wrap.d.ts.map +1 -1
  53. package/dist/src/context/assignment.d.ts +1 -1
  54. package/dist/src/context/assignment.d.ts.map +1 -1
  55. package/dist/src/context/binder.d.ts +3 -3
  56. package/dist/src/context/binder.d.ts.map +1 -1
  57. package/dist/src/context/declaration.d.ts +1 -1
  58. package/dist/src/context/declaration.d.ts.map +1 -1
  59. package/dist/src/context/member-declaration.d.ts +1 -1
  60. package/dist/src/context/member-declaration.d.ts.map +1 -1
  61. package/dist/src/context/member-declaration.js +0 -1
  62. package/dist/src/context/member-scope.d.ts +1 -1
  63. package/dist/src/context/member-scope.d.ts.map +1 -1
  64. package/dist/src/context/name-policy.d.ts +1 -1
  65. package/dist/src/context/name-policy.d.ts.map +1 -1
  66. package/dist/src/context/scope.d.ts +1 -1
  67. package/dist/src/context/scope.d.ts.map +1 -1
  68. package/dist/src/context/source-directory.d.ts +1 -1
  69. package/dist/src/context/source-directory.d.ts.map +1 -1
  70. package/dist/src/context/source-file.d.ts +2 -2
  71. package/dist/src/context/source-file.d.ts.map +1 -1
  72. package/dist/src/context.d.ts +2 -2
  73. package/dist/src/context.d.ts.map +1 -1
  74. package/dist/src/context.js +1 -1
  75. package/dist/src/debug.d.ts +1 -0
  76. package/dist/src/debug.d.ts.map +1 -1
  77. package/dist/src/debug.js +4 -1
  78. package/dist/src/index.d.ts +8 -2
  79. package/dist/src/index.d.ts.map +1 -1
  80. package/dist/src/index.js +8 -2
  81. package/dist/src/jsx-runtime.d.ts +4 -272
  82. package/dist/src/jsx-runtime.d.ts.map +1 -1
  83. package/dist/src/jsx-runtime.js +3 -315
  84. package/dist/src/props-combinators.d.ts +19 -0
  85. package/dist/src/props-combinators.d.ts.map +1 -0
  86. package/dist/src/props-combinators.js +108 -0
  87. package/dist/src/reactive-union-set.d.ts +29 -0
  88. package/dist/src/reactive-union-set.d.ts.map +1 -0
  89. package/dist/src/reactive-union-set.js +183 -0
  90. package/dist/src/reactivity.d.ts +75 -0
  91. package/dist/src/reactivity.d.ts.map +1 -0
  92. package/dist/src/reactivity.js +141 -0
  93. package/dist/src/refkey.d.ts +36 -0
  94. package/dist/src/refkey.d.ts.map +1 -1
  95. package/dist/src/refkey.js +40 -0
  96. package/dist/src/render.d.ts +5 -1
  97. package/dist/src/render.d.ts.map +1 -1
  98. package/dist/src/render.js +68 -15
  99. package/dist/src/runtime/component.d.ts +24 -0
  100. package/dist/src/runtime/component.d.ts.map +1 -0
  101. package/dist/src/runtime/component.js +19 -0
  102. package/dist/src/runtime/intrinsic.d.ts +168 -0
  103. package/dist/src/runtime/intrinsic.d.ts.map +1 -0
  104. package/dist/src/runtime/intrinsic.js +11 -0
  105. package/dist/src/scheduler.d.ts +2 -2
  106. package/dist/src/scheduler.d.ts.map +1 -1
  107. package/dist/src/scheduler.js +27 -6
  108. package/dist/src/slot.d.ts +2 -2
  109. package/dist/src/slot.d.ts.map +1 -1
  110. package/dist/src/slot.js +1 -1
  111. package/dist/src/stc.d.ts +1 -1
  112. package/dist/src/stc.d.ts.map +1 -1
  113. package/dist/src/sti.d.ts +7 -6
  114. package/dist/src/sti.d.ts.map +1 -1
  115. package/dist/src/sti.js +1 -1
  116. package/dist/src/symbols/flags.d.ts +70 -0
  117. package/dist/src/symbols/flags.d.ts.map +1 -0
  118. package/dist/src/symbols/flags.js +72 -0
  119. package/dist/src/symbols/index.d.ts +7 -0
  120. package/dist/src/symbols/index.d.ts.map +1 -0
  121. package/dist/src/symbols/index.js +6 -0
  122. package/dist/src/symbols/output-scope.d.ts +94 -0
  123. package/dist/src/symbols/output-scope.d.ts.map +1 -0
  124. package/dist/src/symbols/output-scope.js +222 -0
  125. package/dist/src/symbols/output-symbol.d.ts +89 -0
  126. package/dist/src/symbols/output-symbol.d.ts.map +1 -0
  127. package/dist/src/symbols/output-symbol.js +333 -0
  128. package/dist/src/symbols/symbol-flow.d.ts +13 -0
  129. package/dist/src/symbols/symbol-flow.d.ts.map +1 -0
  130. package/dist/src/symbols/symbol-flow.js +74 -0
  131. package/dist/src/symbols/symbol-slot.d.ts +12 -0
  132. package/dist/src/symbols/symbol-slot.d.ts.map +1 -0
  133. package/dist/src/symbols/symbol-slot.js +36 -0
  134. package/dist/src/symbols/symbol-table.d.ts +14 -0
  135. package/dist/src/symbols/symbol-table.d.ts.map +1 -0
  136. package/dist/src/symbols/symbol-table.js +42 -0
  137. package/dist/src/tap.d.ts +3 -2
  138. package/dist/src/tap.d.ts.map +1 -1
  139. package/dist/src/tracer.d.ts +238 -0
  140. package/dist/src/tracer.d.ts.map +1 -0
  141. package/dist/src/tracer.js +496 -0
  142. package/dist/src/tsdoc-metadata.json +1 -1
  143. package/dist/src/utils.d.ts +4 -3
  144. package/dist/src/utils.d.ts.map +1 -1
  145. package/dist/src/utils.js +2 -1
  146. package/dist/test/components/slot.test.js +5 -7
  147. package/dist/test/props-with-defaults.test.js +1 -1
  148. package/dist/test/reactive-union-set.test.d.ts +2 -0
  149. package/dist/test/reactive-union-set.test.d.ts.map +1 -0
  150. package/dist/test/reactive-union-set.test.js +170 -0
  151. package/dist/test/reactivity/cleanup.test.js +2 -1
  152. package/dist/test/reactivity/memo.test.js +1 -1
  153. package/dist/test/reactivity/untrack.test.js +1 -1
  154. package/dist/test/rendering/memoization.test.js +2 -1
  155. package/dist/test/split-props.test.js +1 -1
  156. package/dist/test/symbols/output-scope.test.d.ts +2 -0
  157. package/dist/test/symbols/output-scope.test.d.ts.map +1 -0
  158. package/dist/test/symbols/output-scope.test.js +343 -0
  159. package/dist/test/symbols/output-symbol.test.d.ts +2 -0
  160. package/dist/test/symbols/output-symbol.test.d.ts.map +1 -0
  161. package/dist/test/symbols/output-symbol.test.js +447 -0
  162. package/dist/test/symbols/resolution.test.d.ts +2 -0
  163. package/dist/test/symbols/resolution.test.d.ts.map +1 -0
  164. package/dist/test/symbols/resolution.test.js +141 -0
  165. package/dist/test/symbols/utils.d.ts +25 -0
  166. package/dist/test/symbols/utils.d.ts.map +1 -0
  167. package/dist/test/symbols/utils.js +47 -0
  168. package/dist/testing/extend-expect.d.ts +15 -0
  169. package/dist/testing/extend-expect.d.ts.map +1 -1
  170. package/dist/testing/extend-expect.js +2 -1
  171. package/dist/testing/render.d.ts +1 -1
  172. package/dist/testing/render.d.ts.map +1 -1
  173. package/dist/tsconfig.tsbuildinfo +1 -1
  174. package/package.json +28 -24
  175. package/src/binder.ts +146 -672
  176. package/src/code.ts +1 -1
  177. package/src/components/Block.tsx +4 -1
  178. package/src/components/Declaration.tsx +8 -7
  179. package/src/components/For.tsx +2 -1
  180. package/src/components/Indent.tsx +1 -1
  181. package/src/components/List.tsx +3 -1
  182. package/src/components/MemberDeclaration.tsx +7 -6
  183. package/src/components/MemberScope.tsx +2 -5
  184. package/src/components/Output.tsx +2 -1
  185. package/src/components/Prose.tsx +1 -1
  186. package/src/components/ReferenceOrContent.tsx +1 -1
  187. package/src/components/Scope.tsx +3 -7
  188. package/src/components/Show.tsx +1 -1
  189. package/src/components/SourceDirectory.tsx +2 -1
  190. package/src/components/SourceFile.tsx +2 -1
  191. package/src/components/StatementList.tsx +2 -1
  192. package/src/components/Switch.tsx +2 -1
  193. package/src/components/Wrap.tsx +1 -1
  194. package/src/context/assignment.ts +1 -1
  195. package/src/context/binder.ts +3 -3
  196. package/src/context/declaration.ts +1 -1
  197. package/src/context/member-declaration.ts +1 -1
  198. package/src/context/member-scope.ts +1 -1
  199. package/src/context/name-policy.ts +1 -1
  200. package/src/context/scope.ts +1 -1
  201. package/src/context/source-directory.ts +1 -1
  202. package/src/context/source-file.ts +2 -2
  203. package/src/context.ts +3 -7
  204. package/src/debug.ts +5 -1
  205. package/src/index.ts +15 -1
  206. package/src/jsx-runtime.ts +15 -674
  207. package/src/props-combinators.ts +148 -0
  208. package/src/reactive-union-set.ts +238 -0
  209. package/src/reactivity.ts +230 -0
  210. package/src/refkey.ts +40 -0
  211. package/src/render.ts +97 -26
  212. package/src/runtime/component.ts +67 -0
  213. package/src/runtime/intrinsic.ts +199 -0
  214. package/src/scheduler.ts +31 -6
  215. package/src/slot.ts +3 -4
  216. package/src/stc.ts +2 -2
  217. package/src/sti.ts +11 -11
  218. package/src/symbols/flags.ts +82 -0
  219. package/src/symbols/index.ts +6 -0
  220. package/src/symbols/output-scope.ts +296 -0
  221. package/src/symbols/output-symbol.ts +459 -0
  222. package/src/symbols/symbol-flow.ts +100 -0
  223. package/src/symbols/symbol-slot.tsx +48 -0
  224. package/src/symbols/symbol-table.ts +72 -0
  225. package/src/tap.ts +3 -2
  226. package/src/tracer.ts +474 -0
  227. package/src/utils.tsx +7 -5
  228. package/temp/api.json +7446 -5133
  229. package/test/components/slot.test.tsx +8 -11
  230. package/test/props-with-defaults.test.ts +1 -1
  231. package/test/reactive-union-set.test.tsx +191 -0
  232. package/test/reactivity/cleanup.test.tsx +2 -1
  233. package/test/reactivity/memo.test.tsx +1 -1
  234. package/test/reactivity/untrack.test.ts +1 -1
  235. package/test/rendering/basic.test.tsx +1 -1
  236. package/test/rendering/memoization.test.tsx +1 -1
  237. package/test/split-props.test.ts +1 -1
  238. package/test/symbols/output-scope.test.ts +300 -0
  239. package/test/symbols/output-symbol.test.ts +456 -0
  240. package/test/symbols/resolution.test.ts +170 -0
  241. package/test/symbols/utils.ts +93 -0
  242. package/test/utils.test.tsx +1 -1
  243. package/testing/extend-expect.ts +16 -0
  244. package/testing/render.ts +1 -2
  245. package/LICENSE +0 -7
  246. package/dist/test/symbols.test.d.ts +0 -2
  247. package/dist/test/symbols.test.d.ts.map +0 -1
  248. package/dist/test/symbols.test.js +0 -884
  249. package/test/symbols.test.ts +0 -1006
@@ -0,0 +1,459 @@
1
+ import {
2
+ reactive,
3
+ ReactiveFlags,
4
+ shallowReactive,
5
+ track,
6
+ TrackOpTypes,
7
+ trigger,
8
+ TriggerOpTypes,
9
+ watch,
10
+ } from "@vue/reactivity";
11
+ import type { Binder } from "../binder.js";
12
+ import { useBinder } from "../context/binder.js";
13
+ import { useMemberScope } from "../context/member-scope.js";
14
+ import { useScope } from "../context/scope.js";
15
+ import { isRefkey, refkey, type Refkey } from "../refkey.js";
16
+ import {
17
+ formatScopeName,
18
+ formatSymbol,
19
+ formatSymbolName,
20
+ trace,
21
+ traceEffect,
22
+ TracePhase,
23
+ } from "../tracer.js";
24
+ import { OutputScopeFlags, OutputSymbolFlags } from "./flags.js";
25
+ import { OutputScope } from "./output-scope.js";
26
+
27
+ export interface OutputSymbolOptions {
28
+ binder?: Binder;
29
+ scope?: OutputScope;
30
+ flags?: OutputSymbolFlags;
31
+ refkeys?: Refkey | Refkey[];
32
+ metadata?: Record<string, unknown>;
33
+ aliasTarget?: OutputSymbol;
34
+ }
35
+
36
+ let symbolCount = 0;
37
+
38
+ /**
39
+ * An output symbol is a named entity that can be referenced in your output
40
+ * code.
41
+ *
42
+ * @remarks
43
+ *
44
+ * This class is the base implementation of symbol. Most languages will have
45
+ * subtypes that provide additional metadata. Symbols are reactive values, so
46
+ * you can observe changes to their properties in a reactive context.
47
+ */
48
+ export class OutputSymbol {
49
+ #originalName: string;
50
+ get originalName() {
51
+ return this.#originalName;
52
+ }
53
+
54
+ #name: string;
55
+ get name() {
56
+ track(this, TrackOpTypes.GET, "name");
57
+ return this.#name;
58
+ }
59
+ set name(name: string) {
60
+ const old = this.#name;
61
+
62
+ if (old === name) {
63
+ return;
64
+ }
65
+
66
+ this.#name = name;
67
+ trigger(this, TriggerOpTypes.SET, "name", name, old);
68
+ }
69
+
70
+ #id: number;
71
+ get id() {
72
+ return this.#id;
73
+ }
74
+
75
+ #flags: OutputSymbolFlags;
76
+ get flags() {
77
+ track(this, TrackOpTypes.GET, "flags");
78
+ return this.#flags;
79
+ }
80
+ set flags(flags: OutputSymbolFlags) {
81
+ const old = this.#flags;
82
+
83
+ if (old === flags) {
84
+ return;
85
+ }
86
+
87
+ this.#flags = flags;
88
+ trigger(this, TriggerOpTypes.SET, "flags", flags, old);
89
+
90
+ this.#createInstanceMemberScope();
91
+ this.#createStaticMemberScope();
92
+ }
93
+
94
+ #scope: OutputScope;
95
+ get scope() {
96
+ track(this, TrackOpTypes.GET, "scope");
97
+ return this.#scope;
98
+ }
99
+
100
+ set scope(scope: OutputScope) {
101
+ const old = this.#scope;
102
+
103
+ if (old === scope) {
104
+ return;
105
+ }
106
+
107
+ this.#handleNewScope(scope, old);
108
+
109
+ this.#scope = scope;
110
+
111
+ trigger(this, TriggerOpTypes.SET, "scope", scope, old);
112
+ }
113
+
114
+ #handleNewScope(newScope: OutputScope, oldScope?: OutputScope) {
115
+ if (oldScope) {
116
+ // ensure when changing scope that this symbol only belongs to one of them
117
+ oldScope.symbols.delete(this);
118
+ }
119
+
120
+ if (!newScope) {
121
+ return;
122
+ }
123
+
124
+ newScope.symbols.add(this);
125
+
126
+ if (newScope.flags & OutputScopeFlags.InstanceMemberScope) {
127
+ this.flags |= OutputSymbolFlags.InstanceMember;
128
+ }
129
+
130
+ if (newScope.flags & OutputScopeFlags.StaticMemberScope) {
131
+ this.flags |= OutputSymbolFlags.StaticMember;
132
+ }
133
+ }
134
+
135
+ #binder: Binder | undefined;
136
+ get binder() {
137
+ return this.#binder;
138
+ }
139
+
140
+ #refkeys: Refkey[];
141
+ get refkeys() {
142
+ track(this, TrackOpTypes.GET, "refkeys");
143
+ return this.#refkeys;
144
+ }
145
+
146
+ set refkeys(refkeys: Refkey[]) {
147
+ const old = this.#refkeys;
148
+
149
+ if (old === refkeys) {
150
+ return;
151
+ }
152
+
153
+ this.#refkeys = shallowReactive(
154
+ Array.isArray(refkeys) ? refkeys : [refkeys],
155
+ );
156
+ trigger(this, TriggerOpTypes.SET, "refkeys", this.#refkeys, old);
157
+ }
158
+
159
+ #instanceMemberScope?: OutputScope;
160
+ get instanceMemberScope() {
161
+ track(this, TrackOpTypes.GET, "instanceMemberScope");
162
+ return this.#instanceMemberScope;
163
+ }
164
+
165
+ #aliasTarget?: OutputSymbol;
166
+ get aliasTarget() {
167
+ return this.#aliasTarget;
168
+ }
169
+
170
+ #createInstanceMemberScope() {
171
+ if (
172
+ this.#instanceMemberScope ||
173
+ !(this.#flags & OutputSymbolFlags.InstanceMemberContainer)
174
+ ) {
175
+ return;
176
+ }
177
+
178
+ this.#instanceMemberScope = new OutputScope(
179
+ `${this.name} instance members`,
180
+ {
181
+ binder: this.#binder,
182
+ owner: this,
183
+ flags: OutputScopeFlags.InstanceMemberScope,
184
+ },
185
+ );
186
+ trigger(
187
+ this,
188
+ TriggerOpTypes.SET,
189
+ "instanceMemberScope",
190
+ this.#instanceMemberScope,
191
+ undefined,
192
+ );
193
+ }
194
+
195
+ /**
196
+ * Create an output scope to hold member symbols. By default this just creates
197
+ * an OutputScope, but can be subclassed to build scope subtypes when needed.
198
+ */
199
+ protected createMemberScope(
200
+ name: string,
201
+ options: {
202
+ owner?: OutputSymbol;
203
+ flags?: OutputScopeFlags;
204
+ },
205
+ ) {
206
+ return new OutputScope(name, {
207
+ binder: this.#binder,
208
+ owner: options.owner,
209
+ flags: options.flags,
210
+ });
211
+ }
212
+
213
+ #staticMemberScope?: OutputScope;
214
+ get staticMemberScope() {
215
+ track(this, TrackOpTypes.GET, "staticMemberScope");
216
+ return this.#staticMemberScope;
217
+ }
218
+
219
+ #createStaticMemberScope() {
220
+ if (
221
+ this.#staticMemberScope ||
222
+ !(this.#flags & OutputSymbolFlags.StaticMemberContainer)
223
+ ) {
224
+ return;
225
+ }
226
+
227
+ this.#staticMemberScope = new OutputScope(`${this.name} static members`, {
228
+ binder: this.#binder,
229
+ owner: this,
230
+ flags: OutputScopeFlags.StaticMemberScope,
231
+ });
232
+ trigger(
233
+ this,
234
+ TriggerOpTypes.SET,
235
+ "staticMemberScope",
236
+ this.#staticMemberScope,
237
+ undefined,
238
+ );
239
+ }
240
+
241
+ #metadata: Record<string, unknown>;
242
+ get metadata() {
243
+ return this.#metadata;
244
+ }
245
+
246
+ /**
247
+ * Tell \@vue/reactivity that this symbol should never be wrapped in a reactive
248
+ * proxy.
249
+ */
250
+ [ReactiveFlags.SKIP] = true;
251
+
252
+ constructor(name: string, options: OutputSymbolOptions = {}) {
253
+ this.#binder = options.binder ?? useBinder();
254
+ this.#name = name;
255
+ this.#originalName = name;
256
+ this.#id = symbolCount++;
257
+ this.#flags = options.flags ?? OutputSymbolFlags.None;
258
+ this.#scope = options.scope ?? (this.#defaultScope() as OutputScope);
259
+ this.#aliasTarget = options.aliasTarget;
260
+ if (this.#aliasTarget) {
261
+ this.#flags |= OutputSymbolFlags.Alias;
262
+ this.#flags &= ~(
263
+ OutputSymbolFlags.MemberContainer | OutputSymbolFlags.Member
264
+ );
265
+ }
266
+ this.#refkeys = shallowReactive(
267
+ Array.isArray(options.refkeys) ? options.refkeys
268
+ : isRefkey(options.refkeys) ? [options.refkeys]
269
+ : [],
270
+ );
271
+ this.#metadata = reactive(options.metadata ?? {});
272
+ this.#createInstanceMemberScope();
273
+ this.#createStaticMemberScope();
274
+ this.#handleNewScope(this.#scope);
275
+
276
+ trace(TracePhase.symbol.create, () => `${formatSymbol(this)}`);
277
+ traceEffect(TracePhase.symbol.update, () => {
278
+ return `${formatSymbol(this)}`;
279
+ });
280
+ this.#binder?.notifySymbolCreated(this);
281
+ }
282
+
283
+ delete() {
284
+ trace(TracePhase.symbol.delete, () => `${formatSymbolName(this)}`);
285
+ if (this.#scope) {
286
+ this.#scope.symbols.delete(this);
287
+ }
288
+
289
+ this.#binder?.notifySymbolDeleted(this);
290
+ }
291
+
292
+ /**
293
+ * Takes the instance members or static members on this symbol and creates
294
+ * corresponding static members on the target symbol. Instance or static
295
+ * members of instantiated symbols are copied. The refkey of any instantiated
296
+ * symbols are set to a composite refkey of the target symbol's refkey and the
297
+ * instantiated symbol's refkey.
298
+ */
299
+ instantiateTo(targetSymbol: OutputSymbol): void {
300
+ if (this.#aliasTarget) {
301
+ return this.#aliasTarget.instantiateTo(targetSymbol);
302
+ }
303
+
304
+ trace(TracePhase.symbol.instantiate, () => {
305
+ return `${formatSymbolName(this)} -> ${formatSymbolName(targetSymbol)}`;
306
+ });
307
+
308
+ const from = this.#instanceMemberScope ?? this.#staticMemberScope;
309
+
310
+ if (from) {
311
+ targetSymbol.flags |= OutputSymbolFlags.StaticMemberContainer;
312
+ targetSymbol.#createStaticMemberScope();
313
+ targetSymbol.#staticMemberScope!.copySymbolsFrom(from, {
314
+ onAdd: (symbol) => {
315
+ const clone = symbol.copyToScope(
316
+ targetSymbol.#staticMemberScope!,
317
+ targetSymbol,
318
+ );
319
+ clone.#flags &= ~OutputSymbolFlags.InstanceMember;
320
+ clone.#flags |= OutputSymbolFlags.StaticMember;
321
+ return clone;
322
+ },
323
+ });
324
+ }
325
+ }
326
+
327
+ #instantiationRk(base: OutputSymbol, member: OutputSymbol) {
328
+ const instantiationRks = [];
329
+ for (const baseRk of base.refkeys) {
330
+ for (const targetRk of member.refkeys) {
331
+ instantiationRks.push(refkey(baseRk, targetRk));
332
+ }
333
+ }
334
+
335
+ return instantiationRks;
336
+ }
337
+
338
+ /**
339
+ * Copy member symbols from the target symbol into the target symbol. The
340
+ * copied symbols have their refkey set to
341
+ * `refkey(targetSymbol.refkey, this.refkey)`.
342
+ */
343
+ copyTo(targetSymbol: OutputSymbol): void {
344
+ if (this.#aliasTarget) {
345
+ return this.#aliasTarget.copyTo(targetSymbol);
346
+ }
347
+ if (this.staticMemberScope) {
348
+ targetSymbol.flags |= OutputSymbolFlags.StaticMemberContainer;
349
+ targetSymbol.staticMemberScope!.copySymbolsFrom(this.staticMemberScope);
350
+ }
351
+
352
+ if (this.instanceMemberScope) {
353
+ targetSymbol.flags |= OutputSymbolFlags.InstanceMemberContainer;
354
+ targetSymbol.instanceMemberScope!.copySymbolsFrom(
355
+ this.instanceMemberScope,
356
+ );
357
+ }
358
+ }
359
+
360
+ /**
361
+ * Move member symbols from this transient symbol to the target symbol.
362
+ */
363
+ moveTo(targetSymbol: OutputSymbol): void {
364
+ if (this.#aliasTarget) {
365
+ return this.#aliasTarget.moveTo(targetSymbol);
366
+ }
367
+
368
+ if (!(this.flags & OutputSymbolFlags.Transient)) {
369
+ throw new Error("Can only move members from transient symbols");
370
+ }
371
+ if (this.staticMemberScope) {
372
+ targetSymbol.flags |= OutputSymbolFlags.StaticMemberContainer;
373
+ targetSymbol.staticMemberScope!.moveSymbolsFrom(this.staticMemberScope);
374
+ }
375
+
376
+ if (this.instanceMemberScope) {
377
+ targetSymbol.flags |= OutputSymbolFlags.InstanceMemberContainer;
378
+ targetSymbol.instanceMemberScope!.moveSymbolsFrom(
379
+ this.instanceMemberScope,
380
+ );
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Makes a copy of this symbol which will update the name and flags
386
+ * of the clone when the original symbol is updated.
387
+ *
388
+ * @remarks
389
+ *
390
+ * This is used to create a symbol that is a copy of this symbol, but
391
+ * with a different scope. Changes to the copy will not affect the
392
+ * original symbol, and changes to the original symbol's name and flags
393
+ * will overwrite the copy's name and flags.
394
+ *
395
+ * @param newScope - The scope to use for the copy.
396
+ */
397
+ copyToScope(newScope: OutputScope, baseSymbol?: OutputSymbol): OutputSymbol {
398
+ if (this.#aliasTarget) {
399
+ return this.#aliasTarget.copyToScope(newScope, baseSymbol);
400
+ }
401
+ trace(TracePhase.symbol.clone, () => {
402
+ return `${formatSymbolName(this)} -> ${formatScopeName(newScope)}`;
403
+ });
404
+ const clone = new OutputSymbol(this.#name, {
405
+ binder: this.#binder,
406
+ scope: newScope,
407
+ flags: this.#flags,
408
+ refkeys: baseSymbol ? this.#instantiationRk(baseSymbol, this) : [],
409
+ metadata: this.#metadata,
410
+ });
411
+
412
+ if (this.instanceMemberScope) {
413
+ clone.#instanceMemberScope = this.instanceMemberScope.clone({
414
+ owner: clone,
415
+ });
416
+ }
417
+
418
+ if (this.staticMemberScope) {
419
+ clone.#staticMemberScope = this.staticMemberScope.clone({ owner: clone });
420
+ }
421
+
422
+ watch(
423
+ () => this.name,
424
+ (newName) => (clone.name = newName),
425
+ );
426
+ watch(
427
+ () => this.flags,
428
+ (newFlags) => (clone.flags = newFlags),
429
+ );
430
+
431
+ return clone;
432
+ }
433
+
434
+ #defaultScope() {
435
+ if ((this.#flags & OutputSymbolFlags.Member) === 0) {
436
+ return useScope();
437
+ } else {
438
+ const memberScope = useMemberScope();
439
+ if (!memberScope) {
440
+ throw new Error("Cannot declare member symbols without a member scope");
441
+ }
442
+ if (this.#flags & OutputSymbolFlags.InstanceMember) {
443
+ if (!memberScope.instanceMembers) {
444
+ throw new Error(
445
+ "Cannot declare instance member symbols without an instance member scope",
446
+ );
447
+ }
448
+ return memberScope.instanceMembers;
449
+ } else {
450
+ if (!memberScope.staticMembers) {
451
+ throw new Error(
452
+ "Cannot declare static member symbols without a static member scope",
453
+ );
454
+ }
455
+ return memberScope.staticMembers;
456
+ }
457
+ }
458
+ }
459
+ }
@@ -0,0 +1,100 @@
1
+ import { isRef, Ref, shallowReactive } from "@vue/reactivity";
2
+ import { Context, effect, getContext, onCleanup } from "../reactivity.js";
3
+
4
+ import { MemberScopeContext } from "../context/member-scope.js";
5
+ import { ScopeContext } from "../context/scope.js";
6
+ import { OutputSymbolFlags } from "./flags.js";
7
+ import { OutputSymbol } from "./output-symbol.js";
8
+
9
+ export interface TakeSymbolCallback {
10
+ (symbol: OutputSymbol): void;
11
+ }
12
+
13
+ export interface TakeSymbolsCallback {
14
+ (symbols: Set<OutputSymbol>): void;
15
+ }
16
+
17
+ export function takeSymbols(cb?: (symbol: OutputSymbol) => void) {
18
+ const context = getContext()!;
19
+ context.takesSymbols = true;
20
+ context.takenSymbols = shallowReactive(new Set<OutputSymbol>());
21
+ if (cb) {
22
+ effect<Set<OutputSymbol>>((oldSymbols) => {
23
+ for (const symbol of context.takenSymbols!) {
24
+ if (oldSymbols && oldSymbols.has(symbol)) {
25
+ continue;
26
+ }
27
+ cb(symbol);
28
+ }
29
+
30
+ return new Set(context.takenSymbols!);
31
+ });
32
+ }
33
+ return context.takenSymbols;
34
+ }
35
+
36
+ export function emitSymbol(
37
+ symbol: OutputSymbol | Ref<OutputSymbol | undefined>,
38
+ ) {
39
+ let symbolTaker: Context | undefined;
40
+ let context = getContext()!.owner;
41
+ while (context) {
42
+ if (context.takesSymbols) {
43
+ symbolTaker = context;
44
+ break;
45
+ }
46
+
47
+ if (
48
+ context.context &&
49
+ (context.context[ScopeContext.id] ||
50
+ context.context[MemberScopeContext.id])
51
+ ) {
52
+ // don't cross scope boundaries.
53
+ break;
54
+ }
55
+
56
+ context = context.owner;
57
+ }
58
+
59
+ if (!symbolTaker) {
60
+ return;
61
+ }
62
+
63
+ if (isRef(symbol)) {
64
+ effect<OutputSymbol | undefined>((prevSymbol) => {
65
+ onCleanup(() => {
66
+ if (symbol.value) {
67
+ symbolTaker.takenSymbols!.delete(symbol.value);
68
+ }
69
+ });
70
+ if (symbol.value === undefined) {
71
+ symbolTaker.takenSymbols!.delete(prevSymbol!);
72
+ return undefined;
73
+ } else {
74
+ symbolTaker.takenSymbols!.add(symbol.value);
75
+ return symbol.value;
76
+ }
77
+ });
78
+ } else {
79
+ symbolTaker.takenSymbols!.add(symbol);
80
+ onCleanup(() => {
81
+ context!.takenSymbols!.delete(symbol);
82
+ });
83
+ }
84
+ }
85
+
86
+ export function moveTakenMembersTo(baseSymbol: OutputSymbol) {
87
+ const taken = takeSymbols();
88
+
89
+ effect(() => {
90
+ for (const symbol of taken) {
91
+ if (symbol.flags & OutputSymbolFlags.Transient) {
92
+ symbol.moveTo(baseSymbol);
93
+ }
94
+ }
95
+ });
96
+ }
97
+
98
+ export function instantiateTakenMembersTo(baseSymbol: OutputSymbol) {
99
+ takeSymbols((symbol) => symbol.instantiateTo(baseSymbol));
100
+ }
@@ -0,0 +1,48 @@
1
+ import { Ref, ShallowReactive, shallowRef } from "@vue/reactivity";
2
+ import { effect, onCleanup } from "../reactivity.js";
3
+ import type { Children } from "../runtime/component.js";
4
+ import { OutputSymbol } from "./output-symbol.js";
5
+ import { takeSymbols } from "./symbol-flow.js";
6
+
7
+ export function createSymbolSlot() {
8
+ const symbolSlotRef: Ref<ShallowReactive<Set<OutputSymbol>> | undefined> =
9
+ shallowRef();
10
+ function SymbolSlot(props: { children: Children }) {
11
+ const set = takeSymbols();
12
+ symbolSlotRef.value = set;
13
+
14
+ onCleanup(() => {
15
+ symbolSlotRef.value = undefined;
16
+ });
17
+
18
+ return props.children;
19
+ }
20
+
21
+ SymbolSlot.ref = symbolSlotRef;
22
+
23
+ SymbolSlot.instantiateInto = (baseSymbol: OutputSymbol) => {
24
+ effect(() => {
25
+ if (!symbolSlotRef.value) {
26
+ return;
27
+ }
28
+
29
+ for (const symbol of symbolSlotRef.value) {
30
+ symbol.instantiateTo(baseSymbol);
31
+ }
32
+ });
33
+ };
34
+
35
+ SymbolSlot.copyInto = (baseSymbol: OutputSymbol) => {
36
+ effect(() => {
37
+ if (!symbolSlotRef.value) {
38
+ return;
39
+ }
40
+
41
+ for (const symbol of symbolSlotRef.value) {
42
+ symbol.copyTo(baseSymbol);
43
+ }
44
+ });
45
+ };
46
+
47
+ return SymbolSlot;
48
+ }
@@ -0,0 +1,72 @@
1
+ import type { NameConflictResolver } from "../binder.js";
2
+ import { ReactiveUnionSet } from "../reactive-union-set.js";
3
+ import { queueJob } from "../scheduler.js";
4
+ import {
5
+ formatScopeName,
6
+ formatSymbolName,
7
+ trace,
8
+ TracePhase,
9
+ } from "../tracer.js";
10
+ import type { OutputScope } from "./output-scope.js";
11
+ import type { OutputSymbol } from "./output-symbol.js";
12
+
13
+ export class SymbolTable extends ReactiveUnionSet<OutputSymbol> {
14
+ private _namesToDeconflict: Set<string> = new Set();
15
+ private _nameConflictResolver?: NameConflictResolver;
16
+ private _deconflictNames = () => {
17
+ for (const name of this._namesToDeconflict) {
18
+ const conflictedSymbols = [...this].filter(
19
+ (sym) => sym.originalName === name,
20
+ );
21
+ if (this._nameConflictResolver) {
22
+ this._nameConflictResolver(name, conflictedSymbols);
23
+ } else {
24
+ defaultConflictHandler(name, conflictedSymbols);
25
+ }
26
+ this._namesToDeconflict.delete(name);
27
+ }
28
+ };
29
+ public scope;
30
+ constructor(
31
+ scope: OutputScope,
32
+ options: {
33
+ nameConflictResolver?: NameConflictResolver;
34
+ } = {},
35
+ ) {
36
+ super({
37
+ onAdd: (symbol) => {
38
+ trace(
39
+ TracePhase.symbol.addToScope,
40
+ () => `${formatSymbolName(symbol)} -> ${formatScopeName(scope)}`,
41
+ );
42
+
43
+ this._namesToDeconflict.add(symbol.name);
44
+
45
+ queueJob(this._deconflictNames);
46
+
47
+ return symbol;
48
+ },
49
+ onDelete(symbol) {
50
+ trace(
51
+ TracePhase.symbol.removeFromScope,
52
+ () => `${formatSymbolName(symbol)} -> ${formatScopeName(scope)}`,
53
+ );
54
+ },
55
+ });
56
+
57
+ this.scope = scope;
58
+
59
+ this._nameConflictResolver = options.nameConflictResolver;
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Default conflict handler. This will rename all but the first symbol
65
+ * to have a suffix of _2, _3, etc.
66
+ */
67
+ function defaultConflictHandler(_: string, conflictedSymbols: OutputSymbol[]) {
68
+ for (let i = 1; i < conflictedSymbols.length; i++) {
69
+ conflictedSymbols[i].name =
70
+ conflictedSymbols[i].originalName + "_" + (i + 1);
71
+ }
72
+ }
package/src/tap.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { ShallowRef, shallowRef } from "@vue/reactivity";
2
- import { OutputScope, OutputSymbol } from "./binder.js";
3
2
  import { useContext } from "./context.js";
4
3
  import { DeclarationContext } from "./context/declaration.js";
5
4
  import { MemberDeclarationContext } from "./context/member-declaration.js";
6
5
  import { useScope } from "./context/scope.js";
7
6
  import { SourceFileContext } from "./context/source-file.js";
8
- import { ComponentDefinition } from "./jsx-runtime.js";
7
+ import type { ComponentDefinition } from "./runtime/component.js";
8
+ import { OutputScope } from "./symbols/output-scope.js";
9
+ import { OutputSymbol } from "./symbols/output-symbol.js";
9
10
 
10
11
  /**
11
12
  * The return value of {@link createTap}, this holds a reference to the tapped