@alloy-js/core 0.15.0 → 0.17.0

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 (175) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/src/binder.d.ts +18 -235
  3. package/dist/src/binder.d.ts.map +1 -1
  4. package/dist/src/binder.js +85 -386
  5. package/dist/src/components/Block.d.ts +1 -1
  6. package/dist/src/components/Block.d.ts.map +1 -1
  7. package/dist/src/components/Block.js +3 -1
  8. package/dist/src/components/Declaration.d.ts +1 -1
  9. package/dist/src/components/Declaration.d.ts.map +1 -1
  10. package/dist/src/components/Declaration.js +5 -4
  11. package/dist/src/components/For.d.ts +1 -1
  12. package/dist/src/components/For.d.ts.map +1 -1
  13. package/dist/src/components/For.js +1 -1
  14. package/dist/src/components/Indent.d.ts +1 -1
  15. package/dist/src/components/Indent.d.ts.map +1 -1
  16. package/dist/src/components/List.d.ts +1 -1
  17. package/dist/src/components/List.d.ts.map +1 -1
  18. package/dist/src/components/List.js +2 -1
  19. package/dist/src/components/MemberDeclaration.d.ts +1 -1
  20. package/dist/src/components/MemberDeclaration.d.ts.map +1 -1
  21. package/dist/src/components/MemberDeclaration.js +3 -4
  22. package/dist/src/components/MemberScope.d.ts +1 -1
  23. package/dist/src/components/MemberScope.d.ts.map +1 -1
  24. package/dist/src/components/MemberScope.js +0 -2
  25. package/dist/src/components/Prose.d.ts +1 -1
  26. package/dist/src/components/Prose.d.ts.map +1 -1
  27. package/dist/src/components/ReferenceOrContent.d.ts +1 -1
  28. package/dist/src/components/ReferenceOrContent.d.ts.map +1 -1
  29. package/dist/src/components/Scope.d.ts +1 -1
  30. package/dist/src/components/Scope.d.ts.map +1 -1
  31. package/dist/src/components/Scope.js +3 -6
  32. package/dist/src/components/Show.d.ts +1 -1
  33. package/dist/src/components/Show.d.ts.map +1 -1
  34. package/dist/src/components/StatementList.d.ts +1 -1
  35. package/dist/src/components/StatementList.d.ts.map +1 -1
  36. package/dist/src/components/StatementList.js +1 -1
  37. package/dist/src/components/Switch.d.ts +1 -1
  38. package/dist/src/components/Switch.d.ts.map +1 -1
  39. package/dist/src/components/Switch.js +1 -1
  40. package/dist/src/components/Wrap.d.ts +1 -1
  41. package/dist/src/components/Wrap.d.ts.map +1 -1
  42. package/dist/src/context/assignment.d.ts +1 -1
  43. package/dist/src/context/assignment.d.ts.map +1 -1
  44. package/dist/src/context/binder.d.ts +2 -2
  45. package/dist/src/context/binder.d.ts.map +1 -1
  46. package/dist/src/context/declaration.d.ts +1 -1
  47. package/dist/src/context/declaration.d.ts.map +1 -1
  48. package/dist/src/context/member-declaration.d.ts +1 -1
  49. package/dist/src/context/member-declaration.d.ts.map +1 -1
  50. package/dist/src/context/member-declaration.js +0 -1
  51. package/dist/src/context/member-scope.d.ts +1 -1
  52. package/dist/src/context/member-scope.d.ts.map +1 -1
  53. package/dist/src/context/name-policy.d.ts +1 -1
  54. package/dist/src/context/name-policy.d.ts.map +1 -1
  55. package/dist/src/context/scope.d.ts +1 -1
  56. package/dist/src/context/scope.d.ts.map +1 -1
  57. package/dist/src/context/source-directory.d.ts +1 -1
  58. package/dist/src/context/source-directory.d.ts.map +1 -1
  59. package/dist/src/context/source-file.d.ts +2 -2
  60. package/dist/src/context/source-file.d.ts.map +1 -1
  61. package/dist/src/index.d.ts +4 -1
  62. package/dist/src/index.d.ts.map +1 -1
  63. package/dist/src/index.js +4 -1
  64. package/dist/src/jsx-runtime.d.ts +12 -3
  65. package/dist/src/jsx-runtime.d.ts.map +1 -1
  66. package/dist/src/jsx-runtime.js +6 -2
  67. package/dist/src/reactive-union-set.d.ts +29 -0
  68. package/dist/src/reactive-union-set.d.ts.map +1 -0
  69. package/dist/src/reactive-union-set.js +183 -0
  70. package/dist/src/refkey.d.ts +36 -0
  71. package/dist/src/refkey.d.ts.map +1 -1
  72. package/dist/src/refkey.js +40 -0
  73. package/dist/src/scheduler.d.ts +2 -2
  74. package/dist/src/scheduler.d.ts.map +1 -1
  75. package/dist/src/scheduler.js +27 -6
  76. package/dist/src/slot.d.ts +1 -1
  77. package/dist/src/slot.d.ts.map +1 -1
  78. package/dist/src/stc.d.ts +1 -1
  79. package/dist/src/stc.d.ts.map +1 -1
  80. package/dist/src/sti.d.ts +1 -1
  81. package/dist/src/sti.d.ts.map +1 -1
  82. package/dist/src/sti.js +1 -1
  83. package/dist/src/symbols/index.d.ts +6 -0
  84. package/dist/src/symbols/index.d.ts.map +1 -0
  85. package/dist/src/symbols/index.js +5 -0
  86. package/dist/src/symbols/output-scope.d.ts +116 -0
  87. package/dist/src/symbols/output-scope.d.ts.map +1 -0
  88. package/dist/src/symbols/output-scope.js +246 -0
  89. package/dist/src/symbols/output-symbol.d.ts +134 -0
  90. package/dist/src/symbols/output-symbol.d.ts.map +1 -0
  91. package/dist/src/symbols/output-symbol.js +379 -0
  92. package/dist/src/symbols/symbol-flow.d.ts +13 -0
  93. package/dist/src/symbols/symbol-flow.d.ts.map +1 -0
  94. package/dist/src/symbols/symbol-flow.js +74 -0
  95. package/dist/src/symbols/symbol-slot.d.ts +12 -0
  96. package/dist/src/symbols/symbol-slot.d.ts.map +1 -0
  97. package/dist/src/symbols/symbol-slot.js +36 -0
  98. package/dist/src/symbols/symbol-table.d.ts +14 -0
  99. package/dist/src/symbols/symbol-table.d.ts.map +1 -0
  100. package/dist/src/symbols/symbol-table.js +42 -0
  101. package/dist/src/tap.d.ts +2 -1
  102. package/dist/src/tap.d.ts.map +1 -1
  103. package/dist/src/tracer.d.ts +181 -0
  104. package/dist/src/tracer.d.ts.map +1 -0
  105. package/dist/src/tracer.js +441 -0
  106. package/dist/src/tsdoc-metadata.json +1 -1
  107. package/dist/test/components/slot.test.js +5 -7
  108. package/dist/test/reactive-union-set.test.d.ts +2 -0
  109. package/dist/test/reactive-union-set.test.d.ts.map +1 -0
  110. package/dist/test/reactive-union-set.test.js +170 -0
  111. package/dist/test/symbols/output-scope.test.d.ts +2 -0
  112. package/dist/test/symbols/output-scope.test.d.ts.map +1 -0
  113. package/dist/test/symbols/output-scope.test.js +342 -0
  114. package/dist/test/symbols/output-symbol.test.d.ts +2 -0
  115. package/dist/test/symbols/output-symbol.test.d.ts.map +1 -0
  116. package/dist/test/symbols/output-symbol.test.js +446 -0
  117. package/dist/test/symbols/resolution.test.d.ts +2 -0
  118. package/dist/test/symbols/resolution.test.d.ts.map +1 -0
  119. package/dist/test/symbols/resolution.test.js +140 -0
  120. package/dist/test/symbols/utils.d.ts +24 -0
  121. package/dist/test/symbols/utils.d.ts.map +1 -0
  122. package/dist/test/symbols/utils.js +46 -0
  123. package/dist/tsconfig.tsbuildinfo +1 -1
  124. package/package.json +3 -3
  125. package/src/binder.ts +148 -672
  126. package/src/components/Block.tsx +4 -1
  127. package/src/components/Declaration.tsx +6 -6
  128. package/src/components/For.tsx +1 -1
  129. package/src/components/Indent.tsx +1 -1
  130. package/src/components/List.tsx +1 -1
  131. package/src/components/MemberDeclaration.tsx +4 -4
  132. package/src/components/MemberScope.tsx +2 -5
  133. package/src/components/Prose.tsx +1 -1
  134. package/src/components/ReferenceOrContent.tsx +1 -1
  135. package/src/components/Scope.tsx +2 -6
  136. package/src/components/Show.tsx +1 -1
  137. package/src/components/StatementList.tsx +2 -1
  138. package/src/components/Switch.tsx +1 -1
  139. package/src/components/Wrap.tsx +1 -1
  140. package/src/context/assignment.ts +1 -1
  141. package/src/context/binder.ts +2 -2
  142. package/src/context/declaration.ts +1 -1
  143. package/src/context/member-declaration.ts +1 -1
  144. package/src/context/member-scope.ts +1 -1
  145. package/src/context/name-policy.ts +1 -1
  146. package/src/context/scope.ts +1 -1
  147. package/src/context/source-directory.ts +1 -1
  148. package/src/context/source-file.ts +2 -2
  149. package/src/index.ts +15 -0
  150. package/src/jsx-runtime.ts +18 -2
  151. package/src/reactive-union-set.ts +238 -0
  152. package/src/refkey.ts +40 -0
  153. package/src/scheduler.ts +31 -6
  154. package/src/slot.ts +1 -1
  155. package/src/stc.ts +3 -3
  156. package/src/sti.ts +5 -5
  157. package/src/symbols/index.ts +5 -0
  158. package/src/symbols/output-scope.ts +323 -0
  159. package/src/symbols/output-symbol.ts +512 -0
  160. package/src/symbols/symbol-flow.ts +104 -0
  161. package/src/symbols/symbol-slot.tsx +47 -0
  162. package/src/symbols/symbol-table.ts +72 -0
  163. package/src/tap.ts +2 -1
  164. package/src/tracer.ts +440 -0
  165. package/temp/api.json +4172 -1582
  166. package/test/components/slot.test.tsx +8 -11
  167. package/test/reactive-union-set.test.tsx +191 -0
  168. package/test/symbols/output-scope.test.ts +302 -0
  169. package/test/symbols/output-symbol.test.ts +459 -0
  170. package/test/symbols/resolution.test.ts +172 -0
  171. package/test/symbols/utils.ts +95 -0
  172. package/dist/test/symbols.test.d.ts +0 -2
  173. package/dist/test/symbols.test.d.ts.map +0 -1
  174. package/dist/test/symbols.test.js +0 -884
  175. package/test/symbols.test.ts +0 -1006
@@ -0,0 +1,170 @@
1
+ import { effect } from "@alloy-js/core/jsx-runtime";
2
+ import { reactive } from "@vue/reactivity";
3
+ import { describe, expect, it } from "vitest";
4
+ import { ReactiveUnionSet } from "../src/reactive-union-set.js";
5
+ import { flushJobs } from "../src/scheduler.js";
6
+ describe("is reactive", () => {
7
+ it("on size", () => {
8
+ const set = new ReactiveUnionSet();
9
+ let callCount = 0;
10
+ effect(() => {
11
+ callCount++;
12
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
13
+ set.size;
14
+ });
15
+ set.add(1);
16
+ flushJobs();
17
+ expect(callCount).toBe(2);
18
+ });
19
+ it("on iteration", () => {
20
+ const set = new ReactiveUnionSet();
21
+ let callCount = 0;
22
+ effect(() => {
23
+ callCount++;
24
+ for (const _ of set) {
25
+ // do nothing
26
+ }
27
+ });
28
+ set.add(1);
29
+ flushJobs();
30
+ expect(callCount).toBe(2);
31
+ });
32
+ it("on deletion with iteration", () => {
33
+ const set = new ReactiveUnionSet();
34
+ let callCount = 0;
35
+ effect(() => {
36
+ callCount++;
37
+ for (const _ of set) {
38
+ // do nothing
39
+ }
40
+ });
41
+ set.add(1);
42
+ flushJobs();
43
+ expect(callCount).toBe(2);
44
+ set.delete(1);
45
+ flushJobs();
46
+ expect(callCount).toBe(3);
47
+ });
48
+ });
49
+ it("adds items to main set from subset", () => {
50
+ const set = new ReactiveUnionSet();
51
+ const subset1 = reactive(new Set());
52
+ const subset2 = reactive(new Set());
53
+ set.addSubset(subset1);
54
+ set.addSubset(subset2);
55
+ subset1.add(1);
56
+ subset2.add(2);
57
+ flushJobs();
58
+ expect(set.has(1)).toBe(true);
59
+ expect(set.has(2)).toBe(true);
60
+ subset1.delete(1);
61
+ flushJobs();
62
+ expect(set.has(1)).toBe(false);
63
+ });
64
+ it("doesn't remove items that are present in more than one subset", () => {
65
+ const set = new ReactiveUnionSet();
66
+ const subset1 = reactive(new Set());
67
+ const subset2 = reactive(new Set());
68
+ set.addSubset(subset1);
69
+ set.addSubset(subset2);
70
+ subset1.add(1);
71
+ subset2.add(1);
72
+ flushJobs();
73
+ expect(set.has(1)).toBe(true);
74
+ subset1.delete(1);
75
+ flushJobs();
76
+ expect(set.has(1)).toBe(true);
77
+ subset2.delete(1);
78
+ flushJobs();
79
+ expect(set.has(1)).toBe(false);
80
+ });
81
+ it("removes all items when you clear the subset", () => {
82
+ const set = new ReactiveUnionSet();
83
+ const subset1 = reactive(new Set());
84
+ const subset2 = reactive(new Set());
85
+ set.addSubset(subset1);
86
+ set.addSubset(subset2);
87
+ subset1.add(1);
88
+ subset1.add(2);
89
+ subset1.add(3);
90
+ subset2.add(1);
91
+ flushJobs();
92
+ expect(set.size).toBe(3);
93
+ subset1.clear();
94
+ flushJobs();
95
+ expect(set.size).toBe(1);
96
+ });
97
+ describe("indexing", () => {
98
+ it("creates an index of properties", () => {
99
+ const set = new ReactiveUnionSet();
100
+ const index = set.createIndex(item => item.id);
101
+ let callCount = 0;
102
+ effect(() => {
103
+ callCount++;
104
+ index.values();
105
+ });
106
+ const brian = {
107
+ id: 1,
108
+ name: "brian"
109
+ };
110
+ const timothee = {
111
+ id: 2,
112
+ name: "timothee"
113
+ };
114
+ set.add(brian);
115
+ set.add(timothee);
116
+ flushJobs();
117
+ expect(callCount).toBe(2);
118
+ expect(index.get(1)).toEqual(brian);
119
+ expect(index.get(2)).toEqual(timothee);
120
+ set.delete(brian);
121
+ flushJobs();
122
+ expect(callCount).toBe(3);
123
+ expect(index.get(1)).toBeUndefined();
124
+ });
125
+ it("updates the index when the item changeS", () => {
126
+ const set = new ReactiveUnionSet();
127
+ const index = set.createIndex(item => item.id);
128
+ let callCount = 0;
129
+ effect(() => {
130
+ callCount++;
131
+ index.values();
132
+ });
133
+ const brian = reactive({
134
+ id: 1,
135
+ name: "brian"
136
+ });
137
+ set.add(brian);
138
+ flushJobs();
139
+ expect(index.get(1)).toEqual(brian);
140
+ brian.id = 2;
141
+ flushJobs();
142
+ expect(callCount).toBe(3);
143
+ expect(index.get(2)).toEqual(brian);
144
+ });
145
+ });
146
+ describe("derived sets", () => {
147
+ it("creates a derived set", () => {
148
+ const set = new ReactiveUnionSet();
149
+ const derivedSet = set.createDerivedSet(item => item.name);
150
+ const brian = {
151
+ id: 1,
152
+ name: "brian"
153
+ };
154
+ const timothee = {
155
+ id: 2,
156
+ name: "timothee"
157
+ };
158
+ set.add(brian);
159
+ set.add(timothee);
160
+ flushJobs();
161
+ expect(derivedSet.size).toBe(2);
162
+ expect(derivedSet.has("brian")).toBe(true);
163
+ expect(derivedSet.has("timothee")).toBe(true);
164
+ set.delete(brian);
165
+ flushJobs();
166
+ expect(derivedSet.size).toBe(1);
167
+ expect(derivedSet.has("brian")).toBe(false);
168
+ expect(derivedSet.has("timothee")).toBe(true);
169
+ });
170
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=output-scope.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-scope.test.d.ts","sourceRoot":"","sources":["../../../test/symbols/output-scope.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,342 @@
1
+ import { reactive, watch } from "@vue/reactivity";
2
+ import { beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { createOutputBinder } from "../../src/binder.js";
4
+ import { flushJobs } from "../../src/scheduler.js";
5
+ import { OutputScope, OutputScopeFlags } from "../../src/symbols/output-scope.js";
6
+ import { OutputSymbol } from "../../src/symbols/output-symbol.js";
7
+ import { SymbolTable } from "../../src/symbols/symbol-table.js";
8
+ let binder;
9
+ beforeEach(() => {
10
+ binder = createOutputBinder();
11
+ });
12
+ describe("OutputScope constructor", () => {
13
+ it("initializes properties correctly with default options", () => {
14
+ const scope = new OutputScope("testScope", {
15
+ binder
16
+ });
17
+ expect(scope.name).toBe("testScope");
18
+ expect(scope.binder).toBe(binder);
19
+ expect(scope.id).toEqual(expect.any(Number));
20
+ expect(scope.kind).toBe("scope");
21
+ expect(scope.flags).toBe(OutputScopeFlags.None);
22
+ expect(scope.metadata).toEqual({});
23
+ expect(scope.parent).toBe(binder.globalScope);
24
+ expect(scope.owner).toBeUndefined();
25
+ expect(scope.symbols).toBeInstanceOf(SymbolTable);
26
+ expect(scope.symbolNames.size).toBe(0);
27
+ expect(scope.children.size).toBe(0);
28
+ });
29
+ it("initializes properties correctly with custom options", () => {
30
+ const parentScope = new OutputScope("parentScope", {
31
+ binder
32
+ });
33
+ const metadata = {
34
+ foo: "bar"
35
+ };
36
+ const scope = new OutputScope("testScope", {
37
+ binder,
38
+ kind: "namespace",
39
+ metadata,
40
+ parent: parentScope
41
+ });
42
+ expect(scope.name).toBe("testScope");
43
+ expect(scope.kind).toBe("namespace");
44
+ expect(scope.flags).toBe(OutputScopeFlags.None);
45
+ expect(scope.metadata.foo).toBe("bar");
46
+ expect(scope.parent).toBe(parentScope);
47
+ expect(parentScope.children.has(scope)).toBe(true);
48
+ });
49
+ });
50
+ describe("OutputScope reactivity", () => {
51
+ it("is reactive on name", () => {
52
+ const scope = new OutputScope("initialName", {
53
+ binder
54
+ });
55
+ const nameSpy = vi.fn();
56
+ watch(() => scope.name, nameSpy);
57
+ scope.name = "newName";
58
+ flushJobs();
59
+ expect(nameSpy).toHaveBeenCalled();
60
+ expect(scope.name).toBe("newName");
61
+ });
62
+ it("is reactive on flags", () => {
63
+ const scope = new OutputScope("scope", {
64
+ binder
65
+ });
66
+ const flagsSpy = vi.fn();
67
+ watch(() => scope.flags, flagsSpy);
68
+ scope.flags = OutputScopeFlags.InstanceMemberScope;
69
+ flushJobs();
70
+ expect(flagsSpy).toHaveBeenCalled();
71
+ expect(scope.flags).toBe(OutputScopeFlags.InstanceMemberScope);
72
+ });
73
+ it("updates symbolNames when symbols are added", () => {
74
+ const scope = new OutputScope("scope", {
75
+ binder
76
+ });
77
+ const symbolNamesSpy = vi.fn();
78
+ watch(() => scope.symbolNames.size, symbolNamesSpy);
79
+ new OutputSymbol("symbol1", {
80
+ binder,
81
+ scope
82
+ });
83
+ flushJobs();
84
+ expect(symbolNamesSpy).toHaveBeenCalled();
85
+ expect(scope.symbolNames.has("symbol1")).toBe(true);
86
+ });
87
+ it("updates symbolNames when a symbol's name changes", () => {
88
+ const scope = new OutputScope("scope", {
89
+ binder
90
+ });
91
+ const symbol = new OutputSymbol("oldName", {
92
+ binder,
93
+ scope
94
+ });
95
+ flushJobs();
96
+
97
+ // Verify initial state
98
+ expect(scope.symbolNames.has("oldName")).toBe(true);
99
+ expect(scope.symbolNames.has("newName")).toBe(false);
100
+
101
+ // Set up tracking for symbol names
102
+ const symbolNamesTracker = vi.fn();
103
+ watch(() => ({
104
+ hasOld: scope.symbolNames.has("oldName"),
105
+ hasNew: scope.symbolNames.has("newName")
106
+ }), symbolNamesTracker, {
107
+ deep: true
108
+ });
109
+
110
+ // Change the name
111
+ symbol.name = "newName";
112
+ flushJobs();
113
+
114
+ // Verify the changes
115
+ expect(symbolNamesTracker).toHaveBeenCalled();
116
+ expect(scope.symbolNames.has("oldName")).toBe(false);
117
+ expect(scope.symbolNames.has("newName")).toBe(true);
118
+ });
119
+ it("doesn't get wrapped in a reactive proxy", () => {
120
+ const scope = new OutputScope("scope", {
121
+ binder
122
+ });
123
+ const rScope = reactive(scope);
124
+ expect(rScope).toBe(scope);
125
+ });
126
+ });
127
+ describe("OutputScope#symbols", () => {
128
+ it("adds symbols to its collection", () => {
129
+ const scope = new OutputScope("scope", {
130
+ binder
131
+ });
132
+ const sym1 = new OutputSymbol("sym1", {
133
+ binder,
134
+ scope
135
+ });
136
+ const sym2 = new OutputSymbol("sym2", {
137
+ binder,
138
+ scope
139
+ });
140
+ flushJobs();
141
+ expect(scope.symbols.size).toBe(2);
142
+ expect(scope.symbols.has(sym1)).toBe(true);
143
+ expect(scope.symbols.has(sym2)).toBe(true);
144
+ });
145
+ it("resolves symbol name conflicts", () => {
146
+ const scope = new OutputScope("scope", {
147
+ binder
148
+ });
149
+ const s1 = new OutputSymbol("sym", {
150
+ binder,
151
+ scope
152
+ });
153
+ const s2 = new OutputSymbol("sym", {
154
+ binder,
155
+ scope
156
+ });
157
+ const s3 = new OutputSymbol("sym", {
158
+ binder,
159
+ scope
160
+ });
161
+ flushJobs();
162
+ expect(s1.name).toBe("sym");
163
+ expect(s2.name).toBe("sym_2");
164
+ expect(s3.name).toBe("sym_3");
165
+ expect(scope.symbolNames.has("sym")).toBe(true);
166
+ expect(scope.symbolNames.has("sym_2")).toBe(true);
167
+ expect(scope.symbolNames.has("sym_3")).toBe(true);
168
+ });
169
+ it("updates when a symbol is deleted", () => {
170
+ const scope = new OutputScope("scope", {
171
+ binder
172
+ });
173
+ const sym = new OutputSymbol("sym", {
174
+ binder,
175
+ scope
176
+ });
177
+ flushJobs();
178
+ expect(scope.symbols.size).toBe(1);
179
+ expect(scope.symbols.has(sym)).toBe(true);
180
+ expect(scope.symbolNames.has("sym")).toBe(true);
181
+ sym.delete();
182
+ flushJobs();
183
+ expect(scope.symbols.size).toBe(0);
184
+ expect(scope.symbols.has(sym)).toBe(false);
185
+ expect(scope.symbolNames.has("sym")).toBe(false);
186
+ });
187
+ it("updates when a symbol changes scope", () => {
188
+ const scope1 = new OutputScope("scope1", {
189
+ binder
190
+ });
191
+ const scope2 = new OutputScope("scope2", {
192
+ binder
193
+ });
194
+ const sym = new OutputSymbol("sym", {
195
+ binder,
196
+ scope: scope1
197
+ });
198
+ flushJobs();
199
+ expect(scope1.symbols.size).toBe(1);
200
+ expect(scope2.symbols.size).toBe(0);
201
+ sym.scope = scope2;
202
+ flushJobs();
203
+ expect(scope1.symbols.size).toBe(0);
204
+ expect(scope2.symbols.size).toBe(1);
205
+ expect(scope1.symbols.has(sym)).toBe(false);
206
+ expect(scope2.symbols.has(sym)).toBe(true);
207
+ expect(scope1.symbolNames.has("sym")).toBe(false);
208
+ expect(scope2.symbolNames.has("sym")).toBe(true);
209
+ });
210
+ });
211
+ describe("OutputScope#symbolsByRefkey", () => {
212
+ it("maps refkeys to symbols", () => {
213
+ const scope = new OutputScope("scope", {
214
+ binder
215
+ });
216
+
217
+ // Use the refkey function to create refkeys
218
+ // This is based on how refkey is being imported in binder.ts
219
+ const key1 = "key1";
220
+ const key2a = "key2a";
221
+ const key2b = "key2b";
222
+
223
+ // Create a symbol with a refkey
224
+ const sym1 = new OutputSymbol("sym1", {
225
+ binder,
226
+ scope,
227
+ refkeys: [key1]
228
+ });
229
+
230
+ // Create a symbol with multiple refkeys
231
+ const sym2 = new OutputSymbol("sym2", {
232
+ binder,
233
+ scope,
234
+ refkeys: [key2a, key2b]
235
+ });
236
+ flushJobs();
237
+ expect(scope.symbolsByRefkey.get(key1)).toBe(sym1);
238
+ expect(scope.symbolsByRefkey.get(key2a)).toBe(sym2);
239
+ expect(scope.symbolsByRefkey.get(key2b)).toBe(sym2);
240
+ });
241
+ });
242
+ describe("OutputScope#children", () => {
243
+ it("tracks child scopes", () => {
244
+ const parentScope = new OutputScope("parent", {
245
+ binder
246
+ });
247
+ const child1 = new OutputScope("child1", {
248
+ binder,
249
+ parent: parentScope
250
+ });
251
+ const child2 = new OutputScope("child2", {
252
+ binder,
253
+ parent: parentScope
254
+ });
255
+ flushJobs();
256
+ expect(parentScope.children.size).toBe(2);
257
+ expect(parentScope.children.has(child1)).toBe(true);
258
+ expect(parentScope.children.has(child2)).toBe(true);
259
+
260
+ // Check that each child's parent is set correctly
261
+ expect(child1.parent).toBe(parentScope);
262
+ expect(child2.parent).toBe(parentScope);
263
+ });
264
+ });
265
+ describe("OutputScope#clone", () => {
266
+ let originalScope;
267
+ const originalMetadata = {
268
+ data: "original",
269
+ nested: {
270
+ value: 1
271
+ }
272
+ };
273
+ beforeEach(() => {
274
+ const parentScope = new OutputScope("parent", {
275
+ binder
276
+ });
277
+ originalScope = new OutputScope("original", {
278
+ binder: binder,
279
+ kind: "class",
280
+ metadata: {
281
+ ...originalMetadata
282
+ },
283
+ parent: parentScope
284
+ });
285
+
286
+ // Add a symbol and child scope to the original
287
+ new OutputSymbol("symbolInOriginal", {
288
+ binder,
289
+ scope: originalScope
290
+ });
291
+ new OutputScope("childOfOriginal", {
292
+ binder,
293
+ parent: originalScope
294
+ });
295
+ flushJobs();
296
+ });
297
+ it("clones basic properties", () => {
298
+ const newScope = new OutputScope("newScope", {
299
+ binder
300
+ });
301
+ const clonedScope = originalScope.clone({
302
+ parent: newScope
303
+ });
304
+ expect(clonedScope.name).toBe(originalScope.name);
305
+ expect(clonedScope.kind).toBe(originalScope.kind);
306
+ expect(clonedScope.flags).toBe(originalScope.flags);
307
+ expect(clonedScope.id).not.toBe(originalScope.id);
308
+ expect(clonedScope.metadata).toEqual(originalScope.metadata);
309
+ expect(clonedScope.symbols.size).toBe(1);
310
+ expect(clonedScope.children.size).toBe(1);
311
+ });
312
+ it("can override parent in clone options", () => {
313
+ const newParent = new OutputScope("newParent", {
314
+ binder
315
+ });
316
+ const clonedScope = originalScope.clone({
317
+ parent: newParent
318
+ });
319
+ flushJobs();
320
+ expect(clonedScope.parent).toBe(newParent);
321
+ expect(newParent.children.has(clonedScope)).toBe(true);
322
+ });
323
+ it("can override owner in clone options", () => {
324
+ const newOwnerParent = new OutputScope("newOwnerParent", {
325
+ binder
326
+ });
327
+ const newOwner = new OutputSymbol("newOwner", {
328
+ binder,
329
+ scope: newOwnerParent
330
+ });
331
+ const clonedScope = originalScope.clone({
332
+ owner: newOwner
333
+ });
334
+ flushJobs();
335
+ expect(clonedScope.owner).toBe(newOwner);
336
+ });
337
+ it("allows independent changes to clone properties", () => {
338
+ const clonedScope = originalScope.clone();
339
+ clonedScope.name = "clonedName";
340
+ expect(originalScope.name).toBe("original");
341
+ });
342
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=output-symbol.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-symbol.test.d.ts","sourceRoot":"","sources":["../../../test/symbols/output-symbol.test.ts"],"names":[],"mappings":""}