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