@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.
- package/CHANGELOG.md +23 -0
- package/dist/src/binder.d.ts +18 -235
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +85 -386
- package/dist/src/components/Block.d.ts +1 -1
- package/dist/src/components/Block.d.ts.map +1 -1
- package/dist/src/components/Block.js +3 -1
- package/dist/src/components/Declaration.d.ts +1 -1
- package/dist/src/components/Declaration.d.ts.map +1 -1
- package/dist/src/components/Declaration.js +5 -4
- package/dist/src/components/For.d.ts +1 -1
- package/dist/src/components/For.d.ts.map +1 -1
- package/dist/src/components/For.js +1 -1
- package/dist/src/components/Indent.d.ts +1 -1
- package/dist/src/components/Indent.d.ts.map +1 -1
- package/dist/src/components/List.d.ts +1 -1
- package/dist/src/components/List.d.ts.map +1 -1
- package/dist/src/components/List.js +2 -1
- package/dist/src/components/MemberDeclaration.d.ts +1 -1
- package/dist/src/components/MemberDeclaration.d.ts.map +1 -1
- package/dist/src/components/MemberDeclaration.js +3 -4
- package/dist/src/components/MemberScope.d.ts +1 -1
- package/dist/src/components/MemberScope.d.ts.map +1 -1
- package/dist/src/components/MemberScope.js +0 -2
- package/dist/src/components/Prose.d.ts +1 -1
- package/dist/src/components/Prose.d.ts.map +1 -1
- package/dist/src/components/ReferenceOrContent.d.ts +1 -1
- package/dist/src/components/ReferenceOrContent.d.ts.map +1 -1
- package/dist/src/components/Scope.d.ts +1 -1
- package/dist/src/components/Scope.d.ts.map +1 -1
- package/dist/src/components/Scope.js +3 -6
- package/dist/src/components/Show.d.ts +1 -1
- package/dist/src/components/Show.d.ts.map +1 -1
- package/dist/src/components/StatementList.d.ts +1 -1
- package/dist/src/components/StatementList.d.ts.map +1 -1
- package/dist/src/components/StatementList.js +1 -1
- package/dist/src/components/Switch.d.ts +1 -1
- package/dist/src/components/Switch.d.ts.map +1 -1
- package/dist/src/components/Switch.js +1 -1
- package/dist/src/components/Wrap.d.ts +1 -1
- package/dist/src/components/Wrap.d.ts.map +1 -1
- package/dist/src/context/assignment.d.ts +1 -1
- package/dist/src/context/assignment.d.ts.map +1 -1
- package/dist/src/context/binder.d.ts +2 -2
- package/dist/src/context/binder.d.ts.map +1 -1
- package/dist/src/context/declaration.d.ts +1 -1
- package/dist/src/context/declaration.d.ts.map +1 -1
- package/dist/src/context/member-declaration.d.ts +1 -1
- package/dist/src/context/member-declaration.d.ts.map +1 -1
- package/dist/src/context/member-declaration.js +0 -1
- package/dist/src/context/member-scope.d.ts +1 -1
- package/dist/src/context/member-scope.d.ts.map +1 -1
- package/dist/src/context/name-policy.d.ts +1 -1
- package/dist/src/context/name-policy.d.ts.map +1 -1
- package/dist/src/context/scope.d.ts +1 -1
- package/dist/src/context/scope.d.ts.map +1 -1
- package/dist/src/context/source-directory.d.ts +1 -1
- package/dist/src/context/source-directory.d.ts.map +1 -1
- package/dist/src/context/source-file.d.ts +2 -2
- package/dist/src/context/source-file.d.ts.map +1 -1
- package/dist/src/index.d.ts +4 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -1
- package/dist/src/jsx-runtime.d.ts +12 -3
- package/dist/src/jsx-runtime.d.ts.map +1 -1
- package/dist/src/jsx-runtime.js +6 -2
- package/dist/src/reactive-union-set.d.ts +29 -0
- package/dist/src/reactive-union-set.d.ts.map +1 -0
- package/dist/src/reactive-union-set.js +183 -0
- package/dist/src/refkey.d.ts +36 -0
- package/dist/src/refkey.d.ts.map +1 -1
- package/dist/src/refkey.js +40 -0
- package/dist/src/scheduler.d.ts +2 -2
- package/dist/src/scheduler.d.ts.map +1 -1
- package/dist/src/scheduler.js +27 -6
- package/dist/src/slot.d.ts +1 -1
- package/dist/src/slot.d.ts.map +1 -1
- package/dist/src/stc.d.ts +1 -1
- package/dist/src/stc.d.ts.map +1 -1
- package/dist/src/sti.d.ts +1 -1
- package/dist/src/sti.d.ts.map +1 -1
- package/dist/src/sti.js +1 -1
- package/dist/src/symbols/index.d.ts +6 -0
- package/dist/src/symbols/index.d.ts.map +1 -0
- package/dist/src/symbols/index.js +5 -0
- package/dist/src/symbols/output-scope.d.ts +116 -0
- package/dist/src/symbols/output-scope.d.ts.map +1 -0
- package/dist/src/symbols/output-scope.js +246 -0
- package/dist/src/symbols/output-symbol.d.ts +134 -0
- package/dist/src/symbols/output-symbol.d.ts.map +1 -0
- package/dist/src/symbols/output-symbol.js +379 -0
- package/dist/src/symbols/symbol-flow.d.ts +13 -0
- package/dist/src/symbols/symbol-flow.d.ts.map +1 -0
- package/dist/src/symbols/symbol-flow.js +74 -0
- package/dist/src/symbols/symbol-slot.d.ts +12 -0
- package/dist/src/symbols/symbol-slot.d.ts.map +1 -0
- package/dist/src/symbols/symbol-slot.js +36 -0
- package/dist/src/symbols/symbol-table.d.ts +14 -0
- package/dist/src/symbols/symbol-table.d.ts.map +1 -0
- package/dist/src/symbols/symbol-table.js +42 -0
- package/dist/src/tap.d.ts +2 -1
- package/dist/src/tap.d.ts.map +1 -1
- package/dist/src/tracer.d.ts +181 -0
- package/dist/src/tracer.d.ts.map +1 -0
- package/dist/src/tracer.js +441 -0
- package/dist/src/tsdoc-metadata.json +1 -1
- package/dist/test/components/slot.test.js +5 -7
- package/dist/test/reactive-union-set.test.d.ts +2 -0
- package/dist/test/reactive-union-set.test.d.ts.map +1 -0
- package/dist/test/reactive-union-set.test.js +170 -0
- package/dist/test/symbols/output-scope.test.d.ts +2 -0
- package/dist/test/symbols/output-scope.test.d.ts.map +1 -0
- package/dist/test/symbols/output-scope.test.js +342 -0
- package/dist/test/symbols/output-symbol.test.d.ts +2 -0
- package/dist/test/symbols/output-symbol.test.d.ts.map +1 -0
- package/dist/test/symbols/output-symbol.test.js +446 -0
- package/dist/test/symbols/resolution.test.d.ts +2 -0
- package/dist/test/symbols/resolution.test.d.ts.map +1 -0
- package/dist/test/symbols/resolution.test.js +140 -0
- package/dist/test/symbols/utils.d.ts +24 -0
- package/dist/test/symbols/utils.d.ts.map +1 -0
- package/dist/test/symbols/utils.js +46 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/binder.ts +148 -672
- package/src/components/Block.tsx +4 -1
- package/src/components/Declaration.tsx +6 -6
- package/src/components/For.tsx +1 -1
- package/src/components/Indent.tsx +1 -1
- package/src/components/List.tsx +1 -1
- package/src/components/MemberDeclaration.tsx +4 -4
- package/src/components/MemberScope.tsx +2 -5
- package/src/components/Prose.tsx +1 -1
- package/src/components/ReferenceOrContent.tsx +1 -1
- package/src/components/Scope.tsx +2 -6
- package/src/components/Show.tsx +1 -1
- package/src/components/StatementList.tsx +2 -1
- package/src/components/Switch.tsx +1 -1
- package/src/components/Wrap.tsx +1 -1
- package/src/context/assignment.ts +1 -1
- package/src/context/binder.ts +2 -2
- package/src/context/declaration.ts +1 -1
- package/src/context/member-declaration.ts +1 -1
- package/src/context/member-scope.ts +1 -1
- package/src/context/name-policy.ts +1 -1
- package/src/context/scope.ts +1 -1
- package/src/context/source-directory.ts +1 -1
- package/src/context/source-file.ts +2 -2
- package/src/index.ts +15 -0
- package/src/jsx-runtime.ts +18 -2
- package/src/reactive-union-set.ts +238 -0
- package/src/refkey.ts +40 -0
- package/src/scheduler.ts +31 -6
- package/src/slot.ts +1 -1
- package/src/stc.ts +3 -3
- package/src/sti.ts +5 -5
- package/src/symbols/index.ts +5 -0
- package/src/symbols/output-scope.ts +323 -0
- package/src/symbols/output-symbol.ts +512 -0
- package/src/symbols/symbol-flow.ts +104 -0
- package/src/symbols/symbol-slot.tsx +47 -0
- package/src/symbols/symbol-table.ts +72 -0
- package/src/tap.ts +2 -1
- package/src/tracer.ts +440 -0
- package/temp/api.json +4172 -1582
- package/test/components/slot.test.tsx +8 -11
- package/test/reactive-union-set.test.tsx +191 -0
- package/test/symbols/output-scope.test.ts +302 -0
- package/test/symbols/output-symbol.test.ts +459 -0
- package/test/symbols/resolution.test.ts +172 -0
- package/test/symbols/utils.ts +95 -0
- package/dist/test/symbols.test.d.ts +0 -2
- package/dist/test/symbols.test.d.ts.map +0 -1
- package/dist/test/symbols.test.js +0 -884
- package/test/symbols.test.ts +0 -1006
|
@@ -0,0 +1,446 @@
|
|
|
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 { ScopeContext } from "../../src/index.browser.js";
|
|
5
|
+
import { renderTree } from "../../src/render.js";
|
|
6
|
+
import { flushJobs } from "../../src/scheduler.js";
|
|
7
|
+
import { OutputScope, OutputScopeFlags } from "../../src/symbols/output-scope.js";
|
|
8
|
+
import { OutputSymbol, OutputSymbolFlags } from "../../src/symbols/output-symbol.js";
|
|
9
|
+
import { MemberScopeContext } from "../../src/context/member-scope.js";
|
|
10
|
+
let binder;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
binder = createOutputBinder();
|
|
13
|
+
});
|
|
14
|
+
describe("OutputSymbol reactivity", () => {
|
|
15
|
+
it("keeps symbol names up-to-date", () => {
|
|
16
|
+
const scope = new OutputScope("scope", {
|
|
17
|
+
binder
|
|
18
|
+
});
|
|
19
|
+
const symbol = new OutputSymbol("sym", {
|
|
20
|
+
binder,
|
|
21
|
+
scope
|
|
22
|
+
});
|
|
23
|
+
flushJobs();
|
|
24
|
+
expect(scope.symbolNames.has("sym")).toBe(true);
|
|
25
|
+
symbol.name = "bar";
|
|
26
|
+
flushJobs();
|
|
27
|
+
expect(scope.symbolNames.has("bar")).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
it("resolves symbol conflicts", () => {
|
|
30
|
+
const scope = new OutputScope("scope", {
|
|
31
|
+
binder
|
|
32
|
+
});
|
|
33
|
+
const s1 = new OutputSymbol("sym", {
|
|
34
|
+
binder,
|
|
35
|
+
scope
|
|
36
|
+
});
|
|
37
|
+
const s2 = new OutputSymbol("sym", {
|
|
38
|
+
binder,
|
|
39
|
+
scope
|
|
40
|
+
});
|
|
41
|
+
const s3 = new OutputSymbol("sym", {
|
|
42
|
+
binder,
|
|
43
|
+
scope
|
|
44
|
+
});
|
|
45
|
+
flushJobs();
|
|
46
|
+
expect(s1.name).toEqual("sym");
|
|
47
|
+
expect(s2.name).toEqual("sym_2");
|
|
48
|
+
expect(s3.name).toEqual("sym_3");
|
|
49
|
+
});
|
|
50
|
+
it("is reactive on name, flags, scope, instanceMemberScope, and staticMemberScope", () => {
|
|
51
|
+
const scope = new OutputScope("scope", {
|
|
52
|
+
binder
|
|
53
|
+
});
|
|
54
|
+
const symbol = new OutputSymbol("sym", {
|
|
55
|
+
binder,
|
|
56
|
+
scope
|
|
57
|
+
});
|
|
58
|
+
const nameSpy = vi.fn();
|
|
59
|
+
watch(() => symbol.name, nameSpy);
|
|
60
|
+
const flagsSpy = vi.fn();
|
|
61
|
+
watch(() => symbol.flags, flagsSpy);
|
|
62
|
+
const scopeSpy = vi.fn();
|
|
63
|
+
watch(() => symbol.scope, scopeSpy);
|
|
64
|
+
const instanceMemberScopeSpy = vi.fn();
|
|
65
|
+
watch(() => symbol.instanceMemberScope, instanceMemberScopeSpy);
|
|
66
|
+
const staticMemberScopeSpy = vi.fn();
|
|
67
|
+
watch(() => symbol.staticMemberScope, staticMemberScopeSpy);
|
|
68
|
+
symbol.name = "foo";
|
|
69
|
+
symbol.flags = 0;
|
|
70
|
+
symbol.scope = new OutputScope("new-scope", {
|
|
71
|
+
binder
|
|
72
|
+
});
|
|
73
|
+
symbol.flags |= OutputSymbolFlags.InstanceMemberContainer | OutputSymbolFlags.StaticMemberContainer;
|
|
74
|
+
expect(nameSpy).toHaveBeenCalled();
|
|
75
|
+
expect(flagsSpy).toHaveBeenCalled();
|
|
76
|
+
expect(scopeSpy).toHaveBeenCalled();
|
|
77
|
+
expect(instanceMemberScopeSpy).toHaveBeenCalled();
|
|
78
|
+
expect(staticMemberScopeSpy).toHaveBeenCalled();
|
|
79
|
+
});
|
|
80
|
+
it("doesn't get wrapped in a reactive proxy", () => {
|
|
81
|
+
const scope = new OutputScope("scope", {
|
|
82
|
+
binder
|
|
83
|
+
});
|
|
84
|
+
const symbol = new OutputSymbol("sym", {
|
|
85
|
+
binder,
|
|
86
|
+
scope
|
|
87
|
+
});
|
|
88
|
+
const rSymbol = reactive(symbol);
|
|
89
|
+
expect(rSymbol).toBe(symbol);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe("OutputSymbol#flags", () => {
|
|
93
|
+
it("sets member flags based on parent scope", () => {
|
|
94
|
+
const scope = new OutputScope("scope", {
|
|
95
|
+
binder
|
|
96
|
+
});
|
|
97
|
+
const symbol = new OutputSymbol("sym", {
|
|
98
|
+
binder,
|
|
99
|
+
scope
|
|
100
|
+
});
|
|
101
|
+
expect(symbol.flags & OutputSymbolFlags.Member).toBeFalsy();
|
|
102
|
+
const memberScope = new OutputScope("member-scope", {
|
|
103
|
+
binder,
|
|
104
|
+
owner: symbol,
|
|
105
|
+
flags: OutputScopeFlags.InstanceMemberScope
|
|
106
|
+
});
|
|
107
|
+
const memberSymbol = new OutputSymbol("member-sym", {
|
|
108
|
+
binder,
|
|
109
|
+
scope: memberScope
|
|
110
|
+
});
|
|
111
|
+
expect(memberSymbol.flags & OutputSymbolFlags.InstanceMember).toBeTruthy();
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe("OutputSymbol#staticMemberScope", () => {
|
|
115
|
+
it("is created when needed", () => {
|
|
116
|
+
const scope = new OutputScope("scope", {
|
|
117
|
+
binder
|
|
118
|
+
});
|
|
119
|
+
const symbol = new OutputSymbol("sym", {
|
|
120
|
+
binder,
|
|
121
|
+
scope,
|
|
122
|
+
flags: OutputSymbolFlags.StaticMemberContainer
|
|
123
|
+
});
|
|
124
|
+
expect(symbol.staticMemberScope).toBeDefined();
|
|
125
|
+
expect(symbol.staticMemberScope.symbols.size).toEqual(0);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
describe("OutputSymbol#instanceMemberScope", () => {
|
|
129
|
+
it("is created when needed", () => {
|
|
130
|
+
const scope = new OutputScope("scope", {
|
|
131
|
+
binder
|
|
132
|
+
});
|
|
133
|
+
const symbol = new OutputSymbol("sym", {
|
|
134
|
+
binder,
|
|
135
|
+
scope,
|
|
136
|
+
flags: OutputSymbolFlags.InstanceMemberContainer
|
|
137
|
+
});
|
|
138
|
+
expect(symbol.instanceMemberScope).toBeDefined();
|
|
139
|
+
expect(symbol.instanceMemberScope.symbols.size).toEqual(0);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe("OutputSymbol#metadata", () => {
|
|
143
|
+
it("is reactive", () => {
|
|
144
|
+
const scope = new OutputScope("scope", {
|
|
145
|
+
binder
|
|
146
|
+
});
|
|
147
|
+
const symbol = new OutputSymbol("sym", {
|
|
148
|
+
binder,
|
|
149
|
+
scope,
|
|
150
|
+
metadata: {
|
|
151
|
+
foo: "bar"
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
const metadataSpy = vi.fn();
|
|
155
|
+
watch(() => symbol.metadata.foo, metadataSpy);
|
|
156
|
+
symbol.metadata.foo = "baz";
|
|
157
|
+
expect(metadataSpy).toHaveBeenCalled();
|
|
158
|
+
expect(symbol.metadata.foo).toEqual("baz");
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
describe("OutputSymbol#scope", () => {
|
|
162
|
+
it("adds to parent scope", () => {
|
|
163
|
+
const scope = new OutputScope("parent", {
|
|
164
|
+
binder
|
|
165
|
+
});
|
|
166
|
+
const symbol = new OutputSymbol("sym", {
|
|
167
|
+
binder,
|
|
168
|
+
scope
|
|
169
|
+
});
|
|
170
|
+
expect(scope.symbols.has(symbol)).toBe(true);
|
|
171
|
+
});
|
|
172
|
+
it("defaults to the current lexical scope when not a member", () => {
|
|
173
|
+
const scope = new OutputScope("parent", {
|
|
174
|
+
binder
|
|
175
|
+
});
|
|
176
|
+
withContext([[ScopeContext, scope]], () => {
|
|
177
|
+
const symbol = new OutputSymbol("sym", {
|
|
178
|
+
binder
|
|
179
|
+
});
|
|
180
|
+
expect(scope.symbols.has(symbol)).toBe(true);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
it("defaults to the current member scope when a member", () => {
|
|
184
|
+
const symbol = new OutputSymbol("Class", {
|
|
185
|
+
binder,
|
|
186
|
+
scope: binder.globalScope,
|
|
187
|
+
flags: OutputSymbolFlags.MemberContainer
|
|
188
|
+
});
|
|
189
|
+
withContext([[MemberScopeContext, {
|
|
190
|
+
instanceMembers: symbol.instanceMemberScope,
|
|
191
|
+
staticMembers: symbol.staticMemberScope
|
|
192
|
+
}]], () => {
|
|
193
|
+
const ms = new OutputSymbol("ms", {
|
|
194
|
+
binder,
|
|
195
|
+
flags: OutputSymbolFlags.InstanceMember
|
|
196
|
+
});
|
|
197
|
+
const ss = new OutputSymbol("ss", {
|
|
198
|
+
binder,
|
|
199
|
+
flags: OutputSymbolFlags.StaticMember
|
|
200
|
+
});
|
|
201
|
+
expect(symbol.instanceMemberScope.symbols.has(ms)).toBe(true);
|
|
202
|
+
expect(symbol.staticMemberScope.symbols.has(ss)).toBe(true);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
function withContext(contexts, fn) {
|
|
207
|
+
let children = fn;
|
|
208
|
+
for (let i = 0; i < contexts.length; i++) {
|
|
209
|
+
const [context, value] = contexts[i];
|
|
210
|
+
children = context.ProviderStc({
|
|
211
|
+
value
|
|
212
|
+
}).children(children);
|
|
213
|
+
}
|
|
214
|
+
renderTree(children);
|
|
215
|
+
}
|
|
216
|
+
describe("Symbol#delete", () => {
|
|
217
|
+
it("deletes from parent scope", () => {
|
|
218
|
+
const scope = new OutputScope("parent", {
|
|
219
|
+
binder
|
|
220
|
+
});
|
|
221
|
+
const symbol = new OutputSymbol("sym", {
|
|
222
|
+
binder,
|
|
223
|
+
scope
|
|
224
|
+
});
|
|
225
|
+
expect(scope.symbols.has(symbol)).toBe(true);
|
|
226
|
+
symbol.delete();
|
|
227
|
+
expect(scope.symbols.has(symbol)).toBe(false);
|
|
228
|
+
});
|
|
229
|
+
it("updates resolution");
|
|
230
|
+
});
|
|
231
|
+
describe("OutputSymbol#cloneInto", () => {
|
|
232
|
+
it("copies values and propagates updates", () => {
|
|
233
|
+
const scope = new OutputScope("scope", {
|
|
234
|
+
binder
|
|
235
|
+
});
|
|
236
|
+
const scope2 = new OutputScope("scope2", {
|
|
237
|
+
binder
|
|
238
|
+
});
|
|
239
|
+
const symbol = new OutputSymbol("sym", {
|
|
240
|
+
binder,
|
|
241
|
+
scope
|
|
242
|
+
});
|
|
243
|
+
const clone = symbol.copyToScope(scope2);
|
|
244
|
+
expect(clone.name).toEqual("sym");
|
|
245
|
+
expect(clone.flags).toEqual(symbol.flags);
|
|
246
|
+
expect(clone.originalName).toEqual(symbol.originalName);
|
|
247
|
+
symbol.name = "bar";
|
|
248
|
+
symbol.flags = OutputSymbolFlags.InstanceMemberContainer;
|
|
249
|
+
flushJobs();
|
|
250
|
+
expect(clone.name).toEqual("bar");
|
|
251
|
+
expect(clone.flags).toEqual(OutputSymbolFlags.InstanceMemberContainer);
|
|
252
|
+
});
|
|
253
|
+
it("works simply", () => {
|
|
254
|
+
const scope = new OutputScope("scope", {
|
|
255
|
+
binder
|
|
256
|
+
});
|
|
257
|
+
const symbol = new OutputSymbol("sym", {
|
|
258
|
+
binder,
|
|
259
|
+
scope,
|
|
260
|
+
flags: OutputSymbolFlags.StaticMemberContainer
|
|
261
|
+
});
|
|
262
|
+
const sourceStaticMember = new OutputSymbol("static-member", {
|
|
263
|
+
binder,
|
|
264
|
+
scope: symbol.staticMemberScope
|
|
265
|
+
});
|
|
266
|
+
const scope2 = new OutputScope("scope2", {
|
|
267
|
+
binder
|
|
268
|
+
});
|
|
269
|
+
const clone = symbol.copyToScope(scope2);
|
|
270
|
+
expect(clone.staticMemberScope.symbols.size).toBe(1);
|
|
271
|
+
sourceStaticMember.delete();
|
|
272
|
+
flushJobs();
|
|
273
|
+
expect(clone.staticMemberScope.symbols.size).toBe(0);
|
|
274
|
+
});
|
|
275
|
+
it("clones instance and static member scopes", () => {
|
|
276
|
+
const scope = new OutputScope("scope", {
|
|
277
|
+
binder
|
|
278
|
+
});
|
|
279
|
+
const symbol = new OutputSymbol("sym", {
|
|
280
|
+
binder,
|
|
281
|
+
scope,
|
|
282
|
+
flags: OutputSymbolFlags.MemberContainer
|
|
283
|
+
});
|
|
284
|
+
const sourceStaticMember = new OutputSymbol("static-member", {
|
|
285
|
+
binder,
|
|
286
|
+
scope: symbol.staticMemberScope,
|
|
287
|
+
flags: OutputSymbolFlags.StaticMemberContainer
|
|
288
|
+
});
|
|
289
|
+
const sourceInstanceMember = new OutputSymbol("instance-member", {
|
|
290
|
+
binder,
|
|
291
|
+
scope: symbol.instanceMemberScope
|
|
292
|
+
});
|
|
293
|
+
const scope2 = new OutputScope("scope2", {
|
|
294
|
+
binder
|
|
295
|
+
});
|
|
296
|
+
const clone = symbol.copyToScope(scope2);
|
|
297
|
+
expect(clone.instanceMemberScope).toBeDefined();
|
|
298
|
+
expect(clone.staticMemberScope).toBeDefined();
|
|
299
|
+
const clonedStaticMember = [...clone.staticMemberScope.symbols][0];
|
|
300
|
+
expect(clonedStaticMember.name).toBe("static-member");
|
|
301
|
+
expect(clonedStaticMember).toBeDefined();
|
|
302
|
+
expect(clonedStaticMember.flags).toBe(sourceStaticMember.flags);
|
|
303
|
+
const clonedInstanceMember = [...clone.instanceMemberScope.symbols][0];
|
|
304
|
+
expect(clonedInstanceMember.name).toBe("instance-member");
|
|
305
|
+
expect(clonedInstanceMember).toBeDefined();
|
|
306
|
+
expect(clonedInstanceMember.flags).toBe(sourceInstanceMember.flags);
|
|
307
|
+
expect(clonedInstanceMember.staticMemberScope).toBeUndefined();
|
|
308
|
+
|
|
309
|
+
// test reactivity
|
|
310
|
+
const newStaticSym = new OutputSymbol("new-sym", {
|
|
311
|
+
binder,
|
|
312
|
+
scope: symbol.staticMemberScope
|
|
313
|
+
});
|
|
314
|
+
const newInstanceSym = new OutputSymbol("new-sym", {
|
|
315
|
+
binder,
|
|
316
|
+
scope: symbol.instanceMemberScope
|
|
317
|
+
});
|
|
318
|
+
flushJobs();
|
|
319
|
+
expect(clone.staticMemberScope.symbolNames.has("new-sym")).toBe(true);
|
|
320
|
+
expect(clone.instanceMemberScope.symbolNames.has("new-sym")).toBe(true);
|
|
321
|
+
newStaticSym.delete();
|
|
322
|
+
newInstanceSym.delete();
|
|
323
|
+
flushJobs();
|
|
324
|
+
expect(clone.staticMemberScope.symbolNames.has("new-sym")).toBe(false);
|
|
325
|
+
expect(clone.instanceMemberScope.symbolNames.has("new-sym")).toBe(false);
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
describe("OutputSymbol#instantiateInto", () => {
|
|
329
|
+
it("copies instance members to static member scope", () => {
|
|
330
|
+
const scope = new OutputScope("scope", {
|
|
331
|
+
binder
|
|
332
|
+
});
|
|
333
|
+
const classSym = new OutputSymbol("Class", {
|
|
334
|
+
binder,
|
|
335
|
+
scope,
|
|
336
|
+
flags: OutputSymbolFlags.MemberContainer
|
|
337
|
+
});
|
|
338
|
+
new OutputSymbol("instance-member", {
|
|
339
|
+
binder,
|
|
340
|
+
scope: classSym.instanceMemberScope
|
|
341
|
+
});
|
|
342
|
+
new OutputSymbol("static-member", {
|
|
343
|
+
binder,
|
|
344
|
+
scope: classSym.staticMemberScope
|
|
345
|
+
});
|
|
346
|
+
const targetSym = new OutputSymbol("Target", {
|
|
347
|
+
binder,
|
|
348
|
+
scope
|
|
349
|
+
});
|
|
350
|
+
classSym.instantiateTo(targetSym);
|
|
351
|
+
expect(targetSym.staticMemberScope).toBeDefined();
|
|
352
|
+
const staticNames = targetSym.staticMemberScope.symbolNames;
|
|
353
|
+
expect(staticNames.size).toEqual(1);
|
|
354
|
+
expect(staticNames.has("instance-member")).toBe(true);
|
|
355
|
+
const instantiatedSym = [...targetSym.staticMemberScope.symbols][0];
|
|
356
|
+
expect(instantiatedSym.flags & OutputSymbolFlags.StaticMember).toBeTruthy();
|
|
357
|
+
});
|
|
358
|
+
it("is reactive to new instance members", () => {
|
|
359
|
+
const scope = new OutputScope("scope", {
|
|
360
|
+
binder
|
|
361
|
+
});
|
|
362
|
+
const classSym = new OutputSymbol("Class", {
|
|
363
|
+
binder,
|
|
364
|
+
scope,
|
|
365
|
+
flags: OutputSymbolFlags.MemberContainer
|
|
366
|
+
});
|
|
367
|
+
new OutputSymbol("instance-member", {
|
|
368
|
+
binder,
|
|
369
|
+
scope: classSym.instanceMemberScope
|
|
370
|
+
});
|
|
371
|
+
const targetSym = new OutputSymbol("Target", {
|
|
372
|
+
binder,
|
|
373
|
+
scope
|
|
374
|
+
});
|
|
375
|
+
classSym.instantiateTo(targetSym);
|
|
376
|
+
new OutputSymbol("new-instance-member", {
|
|
377
|
+
binder,
|
|
378
|
+
scope: classSym.instanceMemberScope
|
|
379
|
+
});
|
|
380
|
+
expect(targetSym.staticMemberScope.symbolNames.has("new-instance-member")).toBeDefined();
|
|
381
|
+
expect(targetSym.instanceMemberScope).toBeUndefined();
|
|
382
|
+
});
|
|
383
|
+
it("copies static members of instance members", () => {
|
|
384
|
+
const scope = new OutputScope("scope", {
|
|
385
|
+
binder
|
|
386
|
+
});
|
|
387
|
+
const classSym = new OutputSymbol("Class", {
|
|
388
|
+
binder,
|
|
389
|
+
scope,
|
|
390
|
+
flags: OutputSymbolFlags.MemberContainer
|
|
391
|
+
});
|
|
392
|
+
const instanceMemberSym = new OutputSymbol("instance-member", {
|
|
393
|
+
binder,
|
|
394
|
+
scope: classSym.instanceMemberScope,
|
|
395
|
+
flags: OutputSymbolFlags.StaticMemberContainer
|
|
396
|
+
});
|
|
397
|
+
new OutputSymbol("static-of-instance", {
|
|
398
|
+
binder,
|
|
399
|
+
scope: instanceMemberSym.staticMemberScope
|
|
400
|
+
});
|
|
401
|
+
const targetSym = new OutputSymbol("Target", {
|
|
402
|
+
binder,
|
|
403
|
+
scope
|
|
404
|
+
});
|
|
405
|
+
classSym.instantiateTo(targetSym);
|
|
406
|
+
expect(targetSym.staticMemberScope.symbolNames.has("instance-member")).toBeTruthy();
|
|
407
|
+
expect(targetSym.instanceMemberScope).toBeUndefined();
|
|
408
|
+
const instantiatedSS = [...targetSym.staticMemberScope.symbols][0];
|
|
409
|
+
expect(instantiatedSS.staticMemberScope).toBeDefined();
|
|
410
|
+
expect(instantiatedSS.staticMemberScope.symbolNames.has("static-of-instance")).toBeTruthy();
|
|
411
|
+
|
|
412
|
+
// check reactivity
|
|
413
|
+
const newSym = new OutputSymbol("new-static-of-instance", {
|
|
414
|
+
binder,
|
|
415
|
+
scope: instanceMemberSym.staticMemberScope
|
|
416
|
+
});
|
|
417
|
+
flushJobs();
|
|
418
|
+
expect(instantiatedSS.staticMemberScope.symbolNames.has("new-static-of-instance")).toBeTruthy();
|
|
419
|
+
newSym.delete();
|
|
420
|
+
flushJobs();
|
|
421
|
+
expect(instantiatedSS.staticMemberScope.symbolNames.has("static-member-2")).toBeFalsy();
|
|
422
|
+
});
|
|
423
|
+
it("is idempotent", () => {
|
|
424
|
+
const scope = new OutputScope("scope", {
|
|
425
|
+
binder
|
|
426
|
+
});
|
|
427
|
+
const source = new OutputSymbol("sym", {
|
|
428
|
+
binder,
|
|
429
|
+
scope,
|
|
430
|
+
flags: OutputSymbolFlags.InstanceMemberContainer
|
|
431
|
+
});
|
|
432
|
+
new OutputSymbol("instance-member", {
|
|
433
|
+
binder,
|
|
434
|
+
scope: source.instanceMemberScope
|
|
435
|
+
});
|
|
436
|
+
const target = new OutputSymbol("target", {
|
|
437
|
+
binder,
|
|
438
|
+
scope
|
|
439
|
+
});
|
|
440
|
+
source.instantiateTo(target);
|
|
441
|
+
source.instantiateTo(target);
|
|
442
|
+
expect(target.staticMemberScope).toBeDefined();
|
|
443
|
+
expect(target.staticMemberScope.symbolNames.size).toEqual(1);
|
|
444
|
+
expect(target.staticMemberScope.symbolNames.has("instance-member")).toBe(true);
|
|
445
|
+
});
|
|
446
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolution.test.d.ts","sourceRoot":"","sources":["../../../test/symbols/resolution.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { createOutputBinder, refkey } from "../../src/index.browser.js";
|
|
3
|
+
import { flushJobs } from "../../src/scheduler.js";
|
|
4
|
+
import { OutputSymbol, OutputSymbolFlags } from "../../src/symbols/output-symbol.js";
|
|
5
|
+
import { createScopeTree } from "./utils.js";
|
|
6
|
+
describe("Symbol name resolution", () => {
|
|
7
|
+
it("resolves static symbols", () => {
|
|
8
|
+
const binder = createOutputBinder();
|
|
9
|
+
const {
|
|
10
|
+
symbols: {
|
|
11
|
+
static: staticSym
|
|
12
|
+
}
|
|
13
|
+
} = createScopeTree(binder, {
|
|
14
|
+
root: {
|
|
15
|
+
symbols: {
|
|
16
|
+
root: {
|
|
17
|
+
flags: OutputSymbolFlags.InstanceMemberContainer | OutputSymbolFlags.StaticMemberContainer,
|
|
18
|
+
staticMembers: {
|
|
19
|
+
static: {
|
|
20
|
+
flags: OutputSymbolFlags.StaticMember
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
const result = binder.resolveFQN("root.root.static");
|
|
28
|
+
expect(result.value).toEqual(staticSym);
|
|
29
|
+
});
|
|
30
|
+
it("resolves static symbols that are added later", () => {
|
|
31
|
+
const binder = createOutputBinder();
|
|
32
|
+
const result = binder.resolveFQN("root.root.static");
|
|
33
|
+
expect(result.value).toBeUndefined();
|
|
34
|
+
const {
|
|
35
|
+
symbols: {
|
|
36
|
+
static: staticSym
|
|
37
|
+
}
|
|
38
|
+
} = createScopeTree(binder, {
|
|
39
|
+
root: {
|
|
40
|
+
symbols: {
|
|
41
|
+
root: {
|
|
42
|
+
flags: OutputSymbolFlags.InstanceMemberContainer | OutputSymbolFlags.StaticMemberContainer,
|
|
43
|
+
staticMembers: {
|
|
44
|
+
static: {
|
|
45
|
+
flags: OutputSymbolFlags.StaticMember
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
expect(result.value).toEqual(staticSym);
|
|
53
|
+
});
|
|
54
|
+
it("resolves instance symbols", () => {
|
|
55
|
+
const binder = createOutputBinder();
|
|
56
|
+
const {
|
|
57
|
+
symbols: {
|
|
58
|
+
instance
|
|
59
|
+
}
|
|
60
|
+
} = createScopeTree(binder, {
|
|
61
|
+
root: {
|
|
62
|
+
symbols: {
|
|
63
|
+
root: {
|
|
64
|
+
flags: OutputSymbolFlags.InstanceMemberContainer,
|
|
65
|
+
instanceMembers: {
|
|
66
|
+
instance: {
|
|
67
|
+
flags: OutputSymbolFlags.InstanceMember
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
const result = binder.resolveFQN("root.root#instance");
|
|
75
|
+
expect(result.value).toEqual(instance);
|
|
76
|
+
});
|
|
77
|
+
it("resolves instance symbols that are added later", () => {
|
|
78
|
+
const binder = createOutputBinder();
|
|
79
|
+
const result = binder.resolveFQN("root.root#instance");
|
|
80
|
+
expect(result.value).toBeUndefined();
|
|
81
|
+
const {
|
|
82
|
+
symbols: {
|
|
83
|
+
instance
|
|
84
|
+
}
|
|
85
|
+
} = createScopeTree(binder, {
|
|
86
|
+
root: {
|
|
87
|
+
symbols: {
|
|
88
|
+
root: {
|
|
89
|
+
flags: OutputSymbolFlags.InstanceMemberContainer,
|
|
90
|
+
instanceMembers: {
|
|
91
|
+
instance: {
|
|
92
|
+
flags: OutputSymbolFlags.InstanceMember
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
expect(result.value).toEqual(instance);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe("refkey resolution", () => {
|
|
103
|
+
it("resolves existing symbols by refkey", () => {
|
|
104
|
+
const key = refkey();
|
|
105
|
+
const binder = createOutputBinder();
|
|
106
|
+
const sym = new OutputSymbol("foo", {
|
|
107
|
+
binder,
|
|
108
|
+
scope: binder.globalScope,
|
|
109
|
+
refkeys: [key]
|
|
110
|
+
});
|
|
111
|
+
const resolvedSym = binder.resolveDeclarationByKey(undefined, undefined, key);
|
|
112
|
+
expect(resolvedSym.value?.targetDeclaration).toBe(sym);
|
|
113
|
+
});
|
|
114
|
+
it("resolves symbols by refkey when symbol is added later", () => {
|
|
115
|
+
const key = refkey();
|
|
116
|
+
const binder = createOutputBinder();
|
|
117
|
+
const resolvedSym = binder.resolveDeclarationByKey(undefined, undefined, key);
|
|
118
|
+
const sym = new OutputSymbol("foo", {
|
|
119
|
+
binder,
|
|
120
|
+
scope: binder.globalScope,
|
|
121
|
+
refkeys: [key]
|
|
122
|
+
});
|
|
123
|
+
expect(resolvedSym.value?.targetDeclaration).toBe(sym);
|
|
124
|
+
});
|
|
125
|
+
it("handles deleted symbols by updating resolutions", () => {
|
|
126
|
+
const key = refkey();
|
|
127
|
+
const binder = createOutputBinder();
|
|
128
|
+
const resolvedSym = binder.resolveDeclarationByKey(undefined, undefined, key);
|
|
129
|
+
const sym = new OutputSymbol("foo", {
|
|
130
|
+
binder,
|
|
131
|
+
scope: binder.globalScope,
|
|
132
|
+
refkeys: [key]
|
|
133
|
+
});
|
|
134
|
+
flushJobs();
|
|
135
|
+
expect(resolvedSym.value?.targetDeclaration).toBe(sym);
|
|
136
|
+
sym.delete();
|
|
137
|
+
flushJobs();
|
|
138
|
+
expect(resolvedSym.value).toBe(undefined);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Binder } from "../../src/index.browser.js";
|
|
2
|
+
import { Refkey } from "../../src/refkey.js";
|
|
3
|
+
import { OutputScope, OutputScopeFlags } from "../../src/symbols/output-scope.js";
|
|
4
|
+
import { OutputSymbol, OutputSymbolFlags } from "../../src/symbols/output-symbol.js";
|
|
5
|
+
type ScopeRecords = Record<string, ScopeDescriptor>;
|
|
6
|
+
type SymbolRecords = Record<string, SymbolDescriptor>;
|
|
7
|
+
interface ScopeDescriptor {
|
|
8
|
+
flags?: OutputScopeFlags;
|
|
9
|
+
scopes?: ScopeRecords;
|
|
10
|
+
symbols: SymbolRecords;
|
|
11
|
+
}
|
|
12
|
+
interface SymbolDescriptor {
|
|
13
|
+
refkey?: Refkey;
|
|
14
|
+
flags?: OutputSymbolFlags;
|
|
15
|
+
instanceMembers?: SymbolRecords;
|
|
16
|
+
staticMembers?: SymbolRecords;
|
|
17
|
+
}
|
|
18
|
+
interface ScopeTreeResult {
|
|
19
|
+
symbols: Record<string, OutputSymbol>;
|
|
20
|
+
scopes: Record<string, OutputScope>;
|
|
21
|
+
}
|
|
22
|
+
export declare function createScopeTree(binder: Binder, tree: ScopeRecords): ScopeTreeResult;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../test/symbols/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,MAAM,EAAU,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,WAAW,EACX,gBAAgB,EACjB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,iBAAiB,EAClB,MAAM,oCAAoC,CAAC;AAE5C,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AACpD,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAEtD,UAAU,eAAe;IACvB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,UAAU,gBAAgB;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,eAAe,CAAC,EAAE,aAAa,CAAC;IAChC,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACrC;AACD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,YAAY,GACjB,eAAe,CA4DjB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { refkey } from "../../src/refkey.js";
|
|
2
|
+
import { OutputScope } from "../../src/symbols/output-scope.js";
|
|
3
|
+
import { OutputSymbol, OutputSymbolFlags } from "../../src/symbols/output-symbol.js";
|
|
4
|
+
export function createScopeTree(binder, tree) {
|
|
5
|
+
const createdItems = {
|
|
6
|
+
symbols: {},
|
|
7
|
+
scopes: {}
|
|
8
|
+
};
|
|
9
|
+
for (const [name, desc] of Object.entries(tree)) {
|
|
10
|
+
createScope(name, desc);
|
|
11
|
+
}
|
|
12
|
+
return createdItems;
|
|
13
|
+
function createScope(name, descriptor, parent = binder.globalScope) {
|
|
14
|
+
const scope = new OutputScope(name, {
|
|
15
|
+
binder,
|
|
16
|
+
parent,
|
|
17
|
+
flags: descriptor.flags
|
|
18
|
+
});
|
|
19
|
+
createdItems.scopes[name] = scope;
|
|
20
|
+
for (const [name, desc] of Object.entries(descriptor.symbols)) {
|
|
21
|
+
createSymbol(name, desc, scope);
|
|
22
|
+
}
|
|
23
|
+
for (const [name, desc] of Object.entries(descriptor.scopes ?? {})) {
|
|
24
|
+
createScope(name, desc, scope);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function createSymbol(name, descriptor, parent) {
|
|
28
|
+
const symbol = new OutputSymbol(name, {
|
|
29
|
+
binder,
|
|
30
|
+
scope: parent,
|
|
31
|
+
refkeys: [descriptor.refkey ?? refkey()],
|
|
32
|
+
flags: descriptor.flags ?? OutputSymbolFlags.None
|
|
33
|
+
});
|
|
34
|
+
createdItems.symbols[name] = symbol;
|
|
35
|
+
if (descriptor.instanceMembers) {
|
|
36
|
+
for (const [name, desc] of Object.entries(descriptor.instanceMembers)) {
|
|
37
|
+
createSymbol(name, desc, symbol.instanceMemberScope);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (descriptor.staticMembers) {
|
|
41
|
+
for (const [name, desc] of Object.entries(descriptor.staticMembers)) {
|
|
42
|
+
createSymbol(name, desc, symbol.staticMemberScope);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|