@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
@@ -1,1006 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import {
3
- Binder,
4
- createOutputBinder,
5
- OutputScope,
6
- OutputScopeFlags,
7
- OutputSymbol,
8
- OutputSymbolFlags,
9
- } from "../src/binder.js";
10
- import { Refkey, refkey } from "../src/refkey.js";
11
- import { flushJobs } from "../src/scheduler.js";
12
-
13
- it("works", () => {
14
- const binder = createOutputBinder();
15
- const scope = binder.createScope({
16
- kind: "foo",
17
- name: "scope",
18
- parent: binder.globalScope,
19
- });
20
-
21
- const symbol = binder.createSymbol({
22
- name: "sym",
23
- scope,
24
- });
25
-
26
- flushJobs();
27
- expect([...scope.getSymbolNames()]).toEqual(["sym"]);
28
-
29
- symbol.name = "bar";
30
- flushJobs();
31
- expect([...scope.getSymbolNames()]).toEqual(["bar"]);
32
- });
33
-
34
- it("resolves symbol conflicts", () => {
35
- const binder = createOutputBinder();
36
- const scope = binder.createScope({
37
- kind: "foo",
38
- name: "scope",
39
- parent: binder.globalScope,
40
- });
41
-
42
- const _s1 = binder.createSymbol({
43
- name: "sym",
44
- scope,
45
- });
46
-
47
- const s2 = binder.createSymbol({
48
- name: "sym",
49
- scope,
50
- });
51
-
52
- const s3 = binder.createSymbol({
53
- name: "sym",
54
- scope,
55
- });
56
-
57
- flushJobs();
58
-
59
- expect(_s1.name).toEqual("sym");
60
- expect(s2.name).toEqual("sym_2");
61
- expect(s3.name).toEqual("sym_3");
62
- });
63
-
64
- type ScopeRecords = Record<string, ScopeDescriptor>;
65
- type SymbolRecords = Record<string, SymbolDescriptor>;
66
-
67
- interface ScopeDescriptor {
68
- flags?: OutputScopeFlags;
69
- scopes?: ScopeRecords;
70
- symbols: SymbolRecords;
71
- }
72
-
73
- interface SymbolDescriptor {
74
- refkey?: Refkey;
75
- flags?: OutputSymbolFlags;
76
- instanceMembers?: SymbolRecords;
77
- staticMembers?: SymbolRecords;
78
- }
79
-
80
- interface ScopeTreeResult {
81
- symbols: Record<string, OutputSymbol>;
82
- scopes: Record<string, OutputScope>;
83
- }
84
- function createScopeTree(binder: Binder, tree: ScopeRecords): ScopeTreeResult {
85
- const createdItems: ScopeTreeResult = {
86
- symbols: {},
87
- scopes: {},
88
- };
89
-
90
- for (const [name, desc] of Object.entries(tree)) {
91
- createScope(name, desc);
92
- }
93
-
94
- return createdItems;
95
-
96
- function createScope(
97
- name: string,
98
- descriptor: ScopeDescriptor,
99
- parent = binder.globalScope,
100
- ) {
101
- const scope = binder.createScope({
102
- kind: "useless",
103
- name,
104
- parent,
105
- flags: descriptor.flags ?? OutputScopeFlags.None,
106
- });
107
-
108
- createdItems.scopes[name] = scope;
109
-
110
- for (const [name, desc] of Object.entries(descriptor.symbols)) {
111
- createSymbol(name, desc, scope);
112
- }
113
-
114
- for (const [name, desc] of Object.entries(descriptor.scopes ?? {})) {
115
- createScope(name, desc, scope);
116
- }
117
- }
118
-
119
- function createSymbol(
120
- name: string,
121
- descriptor: SymbolDescriptor,
122
- parent: OutputScope,
123
- ) {
124
- const symbol = binder.createSymbol({
125
- name,
126
- scope: parent,
127
- refkey: descriptor.refkey ?? refkey(),
128
- flags: descriptor.flags ?? OutputSymbolFlags.None,
129
- });
130
-
131
- createdItems.symbols[name] = symbol;
132
-
133
- if (descriptor.instanceMembers) {
134
- for (const [name, desc] of Object.entries(descriptor.instanceMembers)) {
135
- createSymbol(name, desc, symbol.instanceMemberScope!);
136
- }
137
- }
138
-
139
- if (descriptor.staticMembers) {
140
- for (const [name, desc] of Object.entries(descriptor.staticMembers)) {
141
- createSymbol(name, desc, symbol.staticMemberScope!);
142
- }
143
- }
144
- }
145
- }
146
- describe("static members", () => {
147
- it("resolves static symbols", () => {
148
- const binder = createOutputBinder();
149
- const {
150
- scopes: { root },
151
- symbols: { root: rootSym, static: staticSym },
152
- } = createScopeTree(binder, {
153
- root: {
154
- symbols: {
155
- root: {
156
- flags:
157
- OutputSymbolFlags.InstanceMemberContainer |
158
- OutputSymbolFlags.StaticMemberContainer,
159
- staticMembers: {
160
- static: {
161
- flags: OutputSymbolFlags.StaticMember,
162
- },
163
- },
164
- },
165
- },
166
- },
167
- });
168
-
169
- const resolution = binder.resolveDeclarationByKey(
170
- root,
171
- undefined,
172
- staticSym.refkeys[0],
173
- );
174
- expect(resolution.value).toBeDefined();
175
- const { commonScope, pathUp, pathDown, targetDeclaration, memberPath } =
176
- resolution.value!;
177
- expect(commonScope).toBe(root);
178
- expect(targetDeclaration).toBe(rootSym);
179
- expect(pathDown).toEqual([]);
180
- expect(pathUp).toEqual([]);
181
- expect(memberPath!.map((s) => s.name)).toEqual(["root", "static"]);
182
- });
183
-
184
- it("resolves deeply nested static symbols", () => {
185
- const binder = createOutputBinder();
186
- const {
187
- scopes: { root },
188
- symbols: { root: rootSym, nested_static },
189
- } = createScopeTree(binder, {
190
- root: {
191
- symbols: {
192
- root: {
193
- flags:
194
- OutputSymbolFlags.InstanceMemberContainer |
195
- OutputSymbolFlags.StaticMemberContainer,
196
- staticMembers: {
197
- static: {
198
- flags:
199
- OutputSymbolFlags.StaticMember |
200
- OutputSymbolFlags.StaticMemberContainer,
201
- staticMembers: {
202
- nested_static: {
203
- flags: OutputSymbolFlags.StaticMember,
204
- },
205
- },
206
- },
207
- },
208
- },
209
- },
210
- },
211
- });
212
-
213
- const resolution = binder.resolveDeclarationByKey(
214
- root,
215
- undefined,
216
- nested_static.refkeys[0],
217
- );
218
- expect(resolution.value).toBeDefined();
219
- const { commonScope, pathUp, pathDown, targetDeclaration, memberPath } =
220
- resolution.value!;
221
- expect(commonScope).toBe(root);
222
- expect(targetDeclaration).toBe(rootSym);
223
- expect(pathDown).toEqual([]);
224
- expect(pathUp).toEqual([]);
225
- expect(memberPath!.map((s) => s.name)).toEqual([
226
- "root",
227
- "static",
228
- "nested_static",
229
- ]);
230
- });
231
-
232
- it("resolves static symbols lazily", () => {
233
- const staticSymRefkey = refkey();
234
-
235
- const binder = createOutputBinder();
236
- const {
237
- scopes: { root },
238
- symbols: { root: rootSym },
239
- } = createScopeTree(binder, {
240
- root: {
241
- symbols: {
242
- root: {
243
- flags:
244
- OutputSymbolFlags.InstanceMemberContainer |
245
- OutputSymbolFlags.StaticMemberContainer,
246
- },
247
- },
248
- },
249
- });
250
-
251
- const resolution = binder.resolveDeclarationByKey(
252
- root,
253
- undefined,
254
- staticSymRefkey,
255
- );
256
- expect(resolution.value).toBeUndefined();
257
- binder.createSymbol({
258
- name: "static",
259
- scope: rootSym.staticMemberScope!,
260
- refkey: staticSymRefkey,
261
- flags: OutputSymbolFlags.StaticMember,
262
- });
263
-
264
- expect(resolution.value).toBeDefined();
265
- const { commonScope, pathUp, pathDown, targetDeclaration, memberPath } =
266
- resolution.value!;
267
- expect(commonScope).toBe(root);
268
- expect(targetDeclaration).toBe(rootSym);
269
- expect(pathDown).toEqual([]);
270
- expect(pathUp).toEqual([]);
271
- expect(memberPath!.map((s) => s.name)).toEqual(["root", "static"]);
272
- });
273
- });
274
-
275
- describe("instance members", () => {
276
- it("resolves", () => {
277
- const binder = createOutputBinder();
278
- const {
279
- symbols: { root: rootSym, instance },
280
- } = createScopeTree(binder, {
281
- root: {
282
- symbols: {
283
- root: {
284
- flags: OutputSymbolFlags.InstanceMemberContainer,
285
- instanceMembers: {
286
- instance: {
287
- flags: OutputSymbolFlags.InstanceMember,
288
- },
289
- },
290
- },
291
- },
292
- },
293
- });
294
-
295
- const resolution = binder.resolveDeclarationByKey(
296
- undefined,
297
- rootSym.instanceMemberScope!,
298
- instance.refkeys[0],
299
- );
300
- expect(resolution.value).toBeDefined();
301
- const { commonScope, pathUp, pathDown, targetDeclaration, memberPath } =
302
- resolution.value!;
303
-
304
- expect(commonScope).toBe(rootSym.instanceMemberScope);
305
- expect(targetDeclaration).toBe(instance);
306
- expect(pathDown).toEqual([]);
307
- expect(pathUp).toEqual([]);
308
- expect(memberPath).toEqual([instance]);
309
- });
310
- });
311
-
312
- describe("instantiating members", () => {
313
- it("instantiates instance members", () => {
314
- const binder = createOutputBinder();
315
-
316
- /**
317
- * The following structure would match code like this:
318
- * ```ts
319
- * // A class with instance members
320
- * class Source {
321
- * instance() {
322
- * print("instance");
323
- * }
324
- * }
325
- *
326
- * // Instantiates into t
327
- * var t = new Source();
328
- *
329
- * t.instance();
330
- * ```
331
- */
332
- const {
333
- symbols: { rootSymbol, instance, instantiation },
334
- } = createScopeTree(binder, {
335
- rootScope: {
336
- symbols: {
337
- rootSymbol: {
338
- flags: OutputSymbolFlags.InstanceMemberContainer,
339
- instanceMembers: {
340
- instance: {
341
- flags: OutputSymbolFlags.InstanceMember,
342
- },
343
- },
344
- },
345
- instantiation: {},
346
- },
347
- },
348
- });
349
-
350
- binder.instantiateSymbolInto(rootSymbol, instantiation);
351
- expect(
352
- instantiation.flags & OutputSymbolFlags.StaticMemberContainer,
353
- ).toBeTruthy();
354
- expect(instantiation.staticMemberScope).toBeDefined();
355
- const expectedRefkey = refkey(
356
- instantiation.refkeys[0],
357
- instance.refkeys[0],
358
- );
359
- expect(
360
- instantiation.staticMemberScope!.symbolsByRefkey.get(expectedRefkey),
361
- ).toBeDefined();
362
- });
363
-
364
- it("doesn't duplicate symbols", () => {
365
- const binder = createOutputBinder();
366
-
367
- const {
368
- symbols: { rootSymbol, instantiation },
369
- } = createScopeTree(binder, {
370
- rootScope: {
371
- symbols: {
372
- rootSymbol: {
373
- flags: OutputSymbolFlags.InstanceMemberContainer,
374
- instanceMembers: {
375
- instance: {
376
- flags: OutputSymbolFlags.InstanceMember,
377
- },
378
- },
379
- },
380
- instantiation: {},
381
- },
382
- },
383
- });
384
-
385
- binder.instantiateSymbolInto(rootSymbol, instantiation);
386
- flushJobs();
387
- expect(instantiation.staticMemberScope!.symbols.size).toBe(1);
388
-
389
- const lateKey = refkey();
390
- // now add a brand‐new static member to source
391
- binder.createSymbol({
392
- name: "lateChild",
393
- scope: rootSymbol.instanceMemberScope!,
394
- refkey: lateKey,
395
- flags: OutputSymbolFlags.InstanceMember,
396
- });
397
-
398
- flushJobs();
399
-
400
- expect(rootSymbol.instanceMemberScope!.symbols.size).toBe(2);
401
- expect(instantiation.staticMemberScope!.symbols.size).toBe(2);
402
- });
403
-
404
- it("should remove members in instance when source deleted them", () => {
405
- const binder = createOutputBinder();
406
-
407
- const {
408
- symbols: { rootSymbol, instantiation },
409
- } = createScopeTree(binder, {
410
- rootScope: {
411
- symbols: {
412
- rootSymbol: {
413
- flags: OutputSymbolFlags.InstanceMemberContainer,
414
- instanceMembers: {
415
- instance: {
416
- flags: OutputSymbolFlags.InstanceMember,
417
- },
418
- },
419
- },
420
- instantiation: {},
421
- },
422
- },
423
- });
424
-
425
- binder.instantiateSymbolInto(rootSymbol, instantiation);
426
- expect(instantiation.staticMemberScope!.symbols.size).toBe(1);
427
-
428
- const lateKey = refkey();
429
- // now add a brand‐new static member to source
430
- binder.createSymbol({
431
- name: "lateChild",
432
- scope: rootSymbol.instanceMemberScope!,
433
- refkey: lateKey,
434
- flags: OutputSymbolFlags.InstanceMember,
435
- });
436
-
437
- flushJobs();
438
-
439
- expect(rootSymbol.instanceMemberScope!.symbols.size).toBe(2);
440
- expect(instantiation.staticMemberScope!.symbols.size).toBe(2);
441
-
442
- binder.deleteSymbol(
443
- rootSymbol.instanceMemberScope!.symbols.values().next().value!,
444
- );
445
- flushJobs();
446
- expect(rootSymbol.instanceMemberScope!.symbols.size).toBe(1);
447
- expect(instantiation.staticMemberScope!.symbols.size).toBe(1);
448
- });
449
-
450
- it("instantiates instance members added after the instantiation", () => {
451
- const binder = createOutputBinder();
452
-
453
- const {
454
- symbols: { rootSymbol, instance, instantiation },
455
- } = createScopeTree(binder, {
456
- rootScope: {
457
- symbols: {
458
- rootSymbol: {
459
- flags: OutputSymbolFlags.InstanceMemberContainer,
460
- instanceMembers: {
461
- instance: {
462
- flags: OutputSymbolFlags.InstanceMember,
463
- },
464
- },
465
- },
466
- instantiation: {},
467
- },
468
- },
469
- });
470
-
471
- binder.instantiateSymbolInto(rootSymbol, instantiation);
472
- flushJobs();
473
- expect(
474
- instantiation.flags & OutputSymbolFlags.StaticMemberContainer,
475
- ).toBeTruthy();
476
- expect(instantiation.staticMemberScope).toBeDefined();
477
- const expectedRefkey = refkey(
478
- instantiation.refkeys[0],
479
- instance.refkeys[0],
480
- );
481
- expect(
482
- instantiation.staticMemberScope!.symbolsByRefkey.get(expectedRefkey),
483
- ).toBeDefined();
484
-
485
- const newInstanceMemberRefkey = refkey();
486
- binder.createSymbol({
487
- name: "newInstanceMember",
488
- scope: rootSymbol.instanceMemberScope!,
489
- refkey: newInstanceMemberRefkey,
490
- flags: OutputSymbolFlags.InstanceMember,
491
- });
492
- const newExpectedRefkey = refkey(
493
- instantiation.refkeys[0],
494
- newInstanceMemberRefkey,
495
- );
496
- flushJobs();
497
- expect(
498
- instantiation.staticMemberScope!.symbolsByRefkey.get(newExpectedRefkey),
499
- ).toBeDefined();
500
- });
501
-
502
- it("instantiates static symbols for a static container source", () => {
503
- const binder = createOutputBinder();
504
-
505
- /**
506
- * The following structure would match code like this:
507
- * ```ts
508
- * // A class with instance members
509
- * class Source {
510
- * static child() {
511
- * print("child");
512
- * }
513
- * }
514
- *
515
- *
516
- * var printChild = Source.child;
517
- *
518
- * printChild();
519
- * ```
520
- */
521
- const {
522
- symbols: { source, child, target },
523
- } = createScopeTree(binder, {
524
- root: {
525
- symbols: {
526
- source: {
527
- flags: OutputSymbolFlags.StaticMemberContainer,
528
- staticMembers: {
529
- child: { flags: OutputSymbolFlags.StaticMember },
530
- },
531
- },
532
- target: {},
533
- },
534
- },
535
- });
536
-
537
- binder.instantiateSymbolInto(source, target);
538
-
539
- // target must now be a StaticMemberContainer too
540
- expect(target.flags & OutputSymbolFlags.StaticMemberContainer).toBeTruthy();
541
- expect(target.staticMemberScope).toBeDefined();
542
-
543
- const expectedKey = refkey(target.refkeys[0], child.refkeys[0]);
544
- expect(
545
- target.staticMemberScope!.symbolsByRefkey.get(expectedKey),
546
- ).toBeDefined();
547
- });
548
-
549
- it("instantiates static symbols added after instantiation", () => {
550
- const binder = createOutputBinder();
551
- const lateKey = refkey();
552
-
553
- const {
554
- symbols: { source, target },
555
- } = createScopeTree(binder, {
556
- root: {
557
- symbols: {
558
- source: {
559
- flags: OutputSymbolFlags.StaticMemberContainer,
560
- },
561
- target: {},
562
- },
563
- },
564
- });
565
-
566
- // hook up instantiation
567
- binder.instantiateSymbolInto(source, target);
568
-
569
- // now add a brand‐new static member to source
570
- const late = binder.createSymbol({
571
- name: "lateChild",
572
- scope: source.staticMemberScope!,
573
- refkey: lateKey,
574
- flags: OutputSymbolFlags.StaticMember,
575
- });
576
-
577
- flushJobs();
578
-
579
- // it should *automatically* show up on target.staticMemberScope
580
- const expectedKey = refkey(target.refkeys[0], late.refkeys[0]);
581
- expect(
582
- target.staticMemberScope!.symbolsByRefkey.get(expectedKey),
583
- ).toBeDefined();
584
- });
585
-
586
- it("recursively instantiates nested static members", () => {
587
- const binder = createOutputBinder();
588
-
589
- /**
590
- * The following structure would match code like this:
591
- * ```ts
592
- * class Source {
593
- * static Level1 = class {
594
- * static level2() { print("deep"); }
595
- * }
596
- * }
597
- *
598
- * var target = Source;
599
- *
600
- * target.Level1.level2()
601
- * ```
602
- */
603
- const {
604
- symbols: { source, level1, level2, target },
605
- } = createScopeTree(binder, {
606
- root: {
607
- symbols: {
608
- source: {
609
- flags: OutputSymbolFlags.StaticMemberContainer,
610
- staticMembers: {
611
- level1: {
612
- flags:
613
- OutputSymbolFlags.StaticMember |
614
- OutputSymbolFlags.StaticMemberContainer,
615
- staticMembers: {
616
- level2: { flags: OutputSymbolFlags.StaticMember },
617
- },
618
- },
619
- },
620
- },
621
- target: {},
622
- },
623
- },
624
- });
625
-
626
- binder.instantiateSymbolInto(source, target);
627
-
628
- // level1 should appear under target.staticMemberScope
629
- const key1 = refkey(target.refkeys[0], level1.refkeys[0]);
630
- const instantiated1 = target.staticMemberScope!.symbolsByRefkey.get(key1)!;
631
- expect(instantiated1.name).toBe(level1.name);
632
-
633
- // and level2 should appear under the *child* staticMemberScope of that instantiated level1
634
- const childScope = instantiated1.staticMemberScope!;
635
- const key2 = refkey(instantiated1.refkeys[0], level2.refkeys[0]);
636
- expect(childScope.symbolsByRefkey.get(key2)).toBeDefined();
637
- });
638
-
639
- it("copies both instance *and* static members when source has both flags", () => {
640
- const binder = createOutputBinder();
641
-
642
- /**
643
- * ```ts
644
- * class Source {
645
- * instance() { print("inst"); }
646
- * static s1() { print("static"); }
647
- * }
648
- *
649
- * let t = new Source()
650
- * t.instance()
651
- * t.s1()
652
- * ```
653
- */
654
- const {
655
- symbols: { source, inst },
656
- } = createScopeTree(binder, {
657
- root: {
658
- symbols: {
659
- source: {
660
- flags:
661
- OutputSymbolFlags.InstanceMemberContainer |
662
- OutputSymbolFlags.StaticMemberContainer,
663
- instanceMembers: {
664
- i1: { flags: OutputSymbolFlags.InstanceMember },
665
- },
666
- staticMembers: {
667
- s1: { flags: OutputSymbolFlags.StaticMember },
668
- },
669
- },
670
- inst: {},
671
- },
672
- },
673
- });
674
-
675
- binder.instantiateSymbolInto(source, inst);
676
-
677
- expect(inst.staticMemberScope).toBeDefined();
678
- expect(
679
- [...inst.staticMemberScope!.symbols].some((s) => s.name === "i1"),
680
- ).toBe(true);
681
-
682
- // static side
683
- const symbols = [...source.staticMemberScope!.symbols];
684
- expect(inst.staticMemberScope).toBeDefined();
685
- const sKey = refkey(inst.refkeys[0], symbols[0].refkeys[0]);
686
- expect(inst.staticMemberScope!.symbolsByRefkey.has(sKey)).toBe(true);
687
- });
688
-
689
- it("is idempotent, calling twice does not duplicate", () => {
690
- const binder = createOutputBinder();
691
- const {
692
- symbols: { source, target },
693
- } = createScopeTree(binder, {
694
- root: {
695
- symbols: {
696
- source: {
697
- flags: OutputSymbolFlags.StaticMemberContainer,
698
- staticMembers: {
699
- a: { flags: OutputSymbolFlags.StaticMember },
700
- },
701
- },
702
- target: {},
703
- },
704
- },
705
- });
706
-
707
- binder.instantiateSymbolInto(source, target);
708
- flushJobs();
709
- const initialCount = target.staticMemberScope!.symbols.size;
710
- binder.instantiateSymbolInto(source, target);
711
- flushJobs();
712
- expect(target.staticMemberScope!.symbols.size).toBe(initialCount);
713
- });
714
-
715
- it("instantiates static children of instance members under the instance scope", () => {
716
- const binder = createOutputBinder();
717
- /**
718
- * ```ts
719
- * class Source {
720
- * instM = class {
721
- * static deep() { print("deep"); }
722
- * }
723
- * }
724
- *
725
- * var t = new Source();
726
- * t.instM.deep();
727
- * ```
728
- */
729
- const {
730
- symbols: { source, deep, target },
731
- } = createScopeTree(binder, {
732
- root: {
733
- symbols: {
734
- source: {
735
- flags: OutputSymbolFlags.InstanceMemberContainer,
736
- instanceMembers: {
737
- instM: {
738
- flags:
739
- OutputSymbolFlags.InstanceMember |
740
- OutputSymbolFlags.StaticMemberContainer,
741
- staticMembers: {
742
- deep: { flags: OutputSymbolFlags.StaticMember },
743
- },
744
- },
745
- },
746
- },
747
- target: {},
748
- },
749
- },
750
- });
751
-
752
- binder.instantiateSymbolInto(source, target);
753
-
754
- // Find the instantiated copy of instM under target.instanceMemberScope
755
- const instMSym = [...target.staticMemberScope!.symbols].find(
756
- (s) => s.name === "instM",
757
- )!;
758
-
759
- // instMSym should have gotten its own staticMemberScope via the StaticMemberContainer flag
760
- expect(instMSym.staticMemberScope).toBeDefined();
761
-
762
- // compute the expected key for the deep child:
763
- // (<target>, <instM>) then (on that) (<deep original>)
764
- const expectedDeepKey = refkey(instMSym.refkeys[0], deep.refkeys[0]);
765
-
766
- expect(
767
- instMSym.staticMemberScope!.symbolsByRefkey.has(expectedDeepKey),
768
- ).toBe(true);
769
- });
770
- });
771
-
772
- describe("symbol name resolution", () => {
773
- it("resolves static symbols", () => {
774
- const binder = createOutputBinder();
775
- const {
776
- symbols: { static: staticSym },
777
- } = createScopeTree(binder, {
778
- root: {
779
- symbols: {
780
- root: {
781
- flags:
782
- OutputSymbolFlags.InstanceMemberContainer |
783
- OutputSymbolFlags.StaticMemberContainer,
784
- staticMembers: {
785
- static: {
786
- flags: OutputSymbolFlags.StaticMember,
787
- },
788
- },
789
- },
790
- },
791
- },
792
- });
793
-
794
- const result = binder.resolveFQN("root.root.static");
795
- expect(result.value).toEqual(staticSym);
796
- });
797
-
798
- it("resolves static symbols that are added later", () => {
799
- const binder = createOutputBinder();
800
- const result = binder.resolveFQN("root.root.static");
801
- expect(result.value).toBeUndefined();
802
-
803
- const {
804
- symbols: { static: staticSym },
805
- } = createScopeTree(binder, {
806
- root: {
807
- symbols: {
808
- root: {
809
- flags:
810
- OutputSymbolFlags.InstanceMemberContainer |
811
- OutputSymbolFlags.StaticMemberContainer,
812
- staticMembers: {
813
- static: {
814
- flags: OutputSymbolFlags.StaticMember,
815
- },
816
- },
817
- },
818
- },
819
- },
820
- });
821
-
822
- expect(result.value).toEqual(staticSym);
823
- });
824
-
825
- it("resolves instance symbols", () => {
826
- const binder = createOutputBinder();
827
- const {
828
- symbols: { instance },
829
- } = createScopeTree(binder, {
830
- root: {
831
- symbols: {
832
- root: {
833
- flags: OutputSymbolFlags.InstanceMemberContainer,
834
- instanceMembers: {
835
- instance: {
836
- flags: OutputSymbolFlags.InstanceMember,
837
- },
838
- },
839
- },
840
- },
841
- },
842
- });
843
-
844
- const result = binder.resolveFQN("root.root#instance");
845
- expect(result.value).toEqual(instance);
846
- });
847
-
848
- it("resolves instance symbols that are added later", () => {
849
- const binder = createOutputBinder();
850
- const result = binder.resolveFQN("root.root#instance");
851
- expect(result.value).toBeUndefined();
852
-
853
- const {
854
- symbols: { instance },
855
- } = createScopeTree(binder, {
856
- root: {
857
- symbols: {
858
- root: {
859
- flags: OutputSymbolFlags.InstanceMemberContainer,
860
- instanceMembers: {
861
- instance: {
862
- flags: OutputSymbolFlags.InstanceMember,
863
- },
864
- },
865
- },
866
- },
867
- },
868
- });
869
-
870
- expect(result.value).toEqual(instance);
871
- });
872
- });
873
-
874
- describe("refkey resolution", () => {
875
- it("resolves existing symbols by refkey", () => {
876
- const key = refkey();
877
- const binder = createOutputBinder();
878
- const sym = binder.createSymbol({
879
- name: "foo",
880
- refkey: key,
881
- scope: binder.globalScope,
882
- });
883
-
884
- const resolvedSym = binder.resolveDeclarationByKey(
885
- undefined,
886
- undefined,
887
- key,
888
- );
889
- expect(resolvedSym.value?.targetDeclaration).toBe(sym);
890
- });
891
-
892
- it("resolves symbols by refkey when symbol is added later", () => {
893
- const key = refkey();
894
- const binder = createOutputBinder();
895
-
896
- const resolvedSym = binder.resolveDeclarationByKey(
897
- undefined,
898
- undefined,
899
- key,
900
- );
901
-
902
- const sym = binder.createSymbol({
903
- name: "foo",
904
- refkey: key,
905
- scope: binder.globalScope,
906
- });
907
-
908
- expect(resolvedSym.value?.targetDeclaration).toBe(sym);
909
- });
910
-
911
- it("resolves symbols by refkey when refkey is added later", () => {
912
- const key = refkey();
913
- const binder = createOutputBinder();
914
-
915
- const resolvedSym = binder.resolveDeclarationByKey(
916
- undefined,
917
- undefined,
918
- key,
919
- );
920
-
921
- const sym = binder.createSymbol({
922
- name: "foo",
923
- scope: binder.globalScope,
924
- });
925
-
926
- expect(resolvedSym.value).toBe(undefined);
927
-
928
- sym.refkeys[0] = key;
929
- flushJobs();
930
- expect(resolvedSym.value?.targetDeclaration).toBe(sym);
931
- });
932
- });
933
-
934
- describe("Deleting symbols", () => {
935
- it("updates resolutions", () => {
936
- const key = refkey();
937
- const binder = createOutputBinder();
938
-
939
- const resolvedSym = binder.resolveDeclarationByKey(
940
- undefined,
941
- undefined,
942
- key,
943
- );
944
-
945
- const sym = binder.createSymbol({
946
- name: "foo",
947
- scope: binder.globalScope,
948
- });
949
-
950
- expect(resolvedSym.value).toBe(undefined);
951
-
952
- sym.refkeys[0] = key;
953
- flushJobs();
954
- expect(resolvedSym.value?.targetDeclaration).toBe(sym);
955
-
956
- binder.deleteSymbol(sym);
957
- flushJobs();
958
- expect(resolvedSym.value).toBe(undefined);
959
- });
960
-
961
- it("removes from parent scopes", () => {
962
- const binder = createOutputBinder();
963
- const result = binder.resolveFQN("root.root#instance");
964
- expect(result.value).toBeUndefined();
965
-
966
- const {
967
- symbols: { instance, root, staticc },
968
- scopes: { rootScope },
969
- } = createScopeTree(binder, {
970
- rootScope: {
971
- symbols: {
972
- root: {
973
- flags:
974
- OutputSymbolFlags.InstanceMemberContainer |
975
- OutputSymbolFlags.StaticMemberContainer,
976
- instanceMembers: {
977
- instance: {
978
- flags: OutputSymbolFlags.InstanceMember,
979
- },
980
- },
981
- staticMembers: {
982
- staticc: {
983
- flags: OutputSymbolFlags.StaticMember,
984
- },
985
- },
986
- },
987
- },
988
- },
989
- });
990
-
991
- const staticScope = root.staticMemberScope!;
992
- const instanceScope = root.instanceMemberScope!;
993
-
994
- expect(staticScope.symbols.size).toBe(1);
995
- binder.deleteSymbol(staticc);
996
- expect(staticScope.symbols.size).toBe(0);
997
-
998
- expect(instanceScope.symbols.size).toBe(1);
999
- binder.deleteSymbol(instance);
1000
- expect(instanceScope.symbols.size).toBe(0);
1001
-
1002
- expect(rootScope.symbols.size).toBe(1);
1003
- binder.deleteSymbol(root);
1004
- expect(rootScope.symbols.size).toBe(0);
1005
- });
1006
- });