@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
package/src/scheduler.ts CHANGED
@@ -3,22 +3,47 @@ import { ReactiveEffectRunner } from "@vue/reactivity";
3
3
  export interface QueueJob {
4
4
  (): any;
5
5
  }
6
+ const immediateQueue = new Set<QueueJob>();
6
7
  const queue = new Set<QueueJob>();
7
8
 
8
- export function scheduler(jobGetter: () => ReactiveEffectRunner) {
9
+ export function scheduler(
10
+ jobGetter: () => ReactiveEffectRunner,
11
+ immediate = false,
12
+ ) {
9
13
  return () => {
10
- queueJob(jobGetter());
14
+ queueJob(jobGetter(), immediate);
11
15
  };
12
16
  }
13
- export function queueJob(job: QueueJob) {
17
+ export function queueJob(job: QueueJob, immediate = false) {
18
+ // if we have an immediate job, we don't need to queue the normal job.
14
19
  // the set is serving an important purpose here in deduping the effects we run
15
20
  // (which in effect coalesces multiple update effects together).
16
- queue.add(job);
21
+ if (immediate) {
22
+ immediateQueue.add(job);
23
+ } else {
24
+ queue.add(job);
25
+ }
17
26
  }
18
27
 
19
28
  export function flushJobs() {
20
- for (const job of queue) {
21
- queue.delete(job);
29
+ let job;
30
+ while ((job = takeJob()) !== null) {
22
31
  job();
23
32
  }
24
33
  }
34
+
35
+ function takeJob() {
36
+ if (immediateQueue.size > 0) {
37
+ // return first item in immediateQueue
38
+ const job = immediateQueue.values().next().value!;
39
+ immediateQueue.delete(job);
40
+ return job;
41
+ }
42
+ if (queue.size > 0) {
43
+ // return first item in queue
44
+ const job = queue.values().next().value!;
45
+ queue.delete(job);
46
+ return job;
47
+ }
48
+ return null;
49
+ }
package/src/slot.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { ref, Ref } from "@vue/reactivity";
2
- import { OutputSymbol } from "./binder.js";
3
2
  import {
4
3
  Children,
5
4
  Component,
@@ -7,6 +6,7 @@ import {
7
6
  effect,
8
7
  memo,
9
8
  } from "./jsx-runtime.js";
9
+ import { OutputSymbol } from "./symbols/output-symbol.js";
10
10
 
11
11
  export interface SlotInstance extends ComponentDefinition {}
12
12
 
package/src/stc.ts CHANGED
@@ -1,9 +1,9 @@
1
- import {
1
+ import { code, text } from "./code.js";
2
+ import type {
2
3
  Children,
3
4
  ComponentCreator,
4
5
  ComponentDefinition,
5
- } from "@alloy-js/core/jsx-runtime";
6
- import { code, text } from "./code.js";
6
+ } from "./jsx-runtime.js";
7
7
 
8
8
  export type MakeChildrenOptional<T extends object> =
9
9
  T extends { children?: any } ?
package/src/sti.ts CHANGED
@@ -1,10 +1,10 @@
1
+ import { code, text } from "./code.js";
1
2
  import {
2
- Children,
3
+ type Children,
3
4
  createIntrinsic,
4
- IntrinsicElementBase,
5
- JSX,
6
- } from "@alloy-js/core/jsx-runtime";
7
- import { code, text } from "./code.js";
5
+ type IntrinsicElementBase,
6
+ type JSX,
7
+ } from "./jsx-runtime.js";
8
8
 
9
9
  export type StiSignature<T extends keyof JSX.IntrinsicElements> = (
10
10
  ...args: unknown extends T ? []
@@ -0,0 +1,5 @@
1
+ export * from "./output-scope.js";
2
+ export * from "./output-symbol.js";
3
+ export * from "./symbol-flow.js";
4
+ export * from "./symbol-slot.js";
5
+ export * from "./symbol-table.js";
@@ -0,0 +1,323 @@
1
+ import {
2
+ reactive,
3
+ ReactiveFlags,
4
+ shallowReactive,
5
+ track,
6
+ TrackOpTypes,
7
+ trigger,
8
+ TriggerOpTypes,
9
+ watch,
10
+ } from "@vue/reactivity";
11
+ import type { Binder } from "../binder.js";
12
+ import { useBinder } from "../context/binder.js";
13
+ import { useScope } from "../context/scope.js";
14
+ import type { ReactiveUnionSetOptions } from "../reactive-union-set.js";
15
+ import type { Refkey } from "../refkey.js";
16
+ import {
17
+ formatScope,
18
+ formatScopeName,
19
+ trace,
20
+ traceEffect,
21
+ TracePhase,
22
+ } from "../tracer.js";
23
+ import { OutputSymbol } from "./output-symbol.js";
24
+ import { SymbolTable } from "./symbol-table.js";
25
+
26
+ /**
27
+ * Flags that describe an output scope.
28
+ */
29
+ export enum OutputScopeFlags {
30
+ None = 0,
31
+
32
+ /**
33
+ * This scope is a static member scope.
34
+ */
35
+ StaticMemberScope = 1 << 0,
36
+
37
+ /**
38
+ * This scope is an instance member scope.
39
+ */
40
+ InstanceMemberScope = 1 << 1,
41
+
42
+ /**
43
+ * This scope is transient, and only exists to be merged with other scopes.
44
+ */
45
+ Transient = 1 << 2,
46
+
47
+ /**
48
+ * This scope is a member scope. Scopes with this flag will have an `owner`
49
+ * property that points to the symbol whose member this scope holds.
50
+ */
51
+ MemberScope = StaticMemberScope | InstanceMemberScope,
52
+ }
53
+
54
+ let scopeCount = 0;
55
+
56
+ export interface OutputScopeOptions {
57
+ flags?: OutputScopeFlags;
58
+ kind?: string;
59
+ metadata?: Record<string, unknown>;
60
+ parent?: OutputScope;
61
+ owner?: OutputSymbol;
62
+ binder?: Binder;
63
+ }
64
+
65
+ /**
66
+ * A container of symbols accessible within some scope in your output code.
67
+ *
68
+ * @remarks
69
+ *
70
+ * Scopes form a tree. All scopes except the global scope have a parent scope
71
+ * identified by `parent`. Scopes can have nested scopes which can be accessed
72
+ * using the `children` property. Whether a child scope can be accessed from
73
+ * the parent scope is determined by each language's scoping rules.
74
+ *
75
+ * This interface is the base implementation of scope. Generally, most languages
76
+ * will have subtypes of this interface that provide additional metadata about
77
+ * the scope. For example, TypeScript scopes need to track whether the scope
78
+ * represents a package, module, class, function, etc.
79
+ *
80
+ * Scopes are reactive values, which allows you to observe changes to the scope
81
+ * within a reactive context.
82
+ */
83
+ export class OutputScope {
84
+ // my kingdom for decorators
85
+ #name: string;
86
+ /**
87
+ * The name of the scope.
88
+ */
89
+ get name() {
90
+ track(this, TrackOpTypes.GET, "name");
91
+ return this.#name;
92
+ }
93
+ set name(name: string) {
94
+ const old = this.#name;
95
+ this.#name = name;
96
+ trigger(this, TriggerOpTypes.SET, "name", name, old);
97
+ }
98
+
99
+ #id: number;
100
+ /**
101
+ * The unique id of this scope.
102
+ */
103
+ get id() {
104
+ return this.#id;
105
+ }
106
+
107
+ #kind: string;
108
+
109
+ /**
110
+ * The kind of scope. Subtypes will likely provide a set of known scope kinds.
111
+ * The kind is not used by the binder itself.
112
+ */
113
+ get kind() {
114
+ return this.#kind;
115
+ }
116
+
117
+ #flags: OutputScopeFlags;
118
+ /**
119
+ * The flags that describe this scope.
120
+ */
121
+ get flags() {
122
+ track(this, TrackOpTypes.GET, "flags");
123
+ return this.#flags;
124
+ }
125
+ set flags(flags: OutputScopeFlags) {
126
+ const old = this.#flags;
127
+ this.#flags = flags;
128
+ trigger(this, TriggerOpTypes.SET, "flags", flags, old);
129
+ }
130
+
131
+ // read only
132
+ #metadata: Record<string, unknown>;
133
+ get metadata() {
134
+ return this.#metadata;
135
+ }
136
+
137
+ #parent?: OutputScope;
138
+ /**
139
+ * The container of this scope. This is only defined for scopes which don't
140
+ * have the {@link OutputScopeFlags.StaticMemberScope} or
141
+ * {@link OutputScopeFlags.InstanceMemberScope} flag.
142
+ */
143
+ get parent() {
144
+ return this.#parent;
145
+ }
146
+
147
+ #owner?: OutputSymbol;
148
+ /**
149
+ * The symbol that owns this scope. This is only defined for scopes that have
150
+ * the {@link OutputScopeFlags.StaticMemberScope} or
151
+ * {@link OutputScopeFlags.InstanceMemberScope} flag.
152
+ */
153
+ get owner() {
154
+ return this.#owner;
155
+ }
156
+
157
+ #symbols: SymbolTable;
158
+ /**
159
+ * The symbols defined within this scope.
160
+ */
161
+ get symbols() {
162
+ return this.#symbols;
163
+ }
164
+
165
+ #symbolsByRefkey: ReadonlyMap<Refkey, OutputSymbol>;
166
+ /**
167
+ * The symbols defined within this scope, indexed by refkey.
168
+ */
169
+ get symbolsByRefkey() {
170
+ return this.#symbolsByRefkey;
171
+ }
172
+
173
+ #symbolNames: ReadonlySet<string>;
174
+ get symbolNames() {
175
+ return this.#symbolNames;
176
+ }
177
+
178
+ #children: Set<OutputScope>;
179
+ /**
180
+ * The scopes nested within this scope.
181
+ */
182
+ get children() {
183
+ return this.#children;
184
+ }
185
+
186
+ #binder: Binder | undefined;
187
+ /**
188
+ * The binder that created this scope.
189
+ */
190
+ get binder() {
191
+ return this.#binder;
192
+ }
193
+
194
+ [ReactiveFlags.SKIP] = this;
195
+
196
+ constructor(name: string, options: OutputScopeOptions = {}) {
197
+ this.#name = name;
198
+ this.#id = scopeCount++;
199
+ this.#flags = options.flags ?? OutputScopeFlags.None;
200
+ this.#kind = options.kind ?? "scope";
201
+ this.#metadata = reactive(options.metadata ?? {});
202
+ this.#binder = options.binder ?? useBinder();
203
+ this.#owner = options.owner;
204
+ this.#children = shallowReactive(new Set());
205
+
206
+ if (this.#flags & OutputScopeFlags.MemberScope) {
207
+ if (!this.#owner) {
208
+ throw new Error("Member scopes must have an owner");
209
+ }
210
+ } else {
211
+ if (!this.#parent) {
212
+ this.#parent =
213
+ options.parent ?? useScope() ?? this.#binder?.globalScope;
214
+ }
215
+ if (this.#parent) {
216
+ // not global scope
217
+ this.#parent.children.add(this);
218
+ }
219
+ }
220
+
221
+ this.#symbols = new SymbolTable(this, {
222
+ nameConflictResolver: this.#binder?.nameConflictResolver,
223
+ });
224
+ this.#symbolsByRefkey = this.#symbols.createIndex((s) => s.refkeys);
225
+ this.#symbolNames = this.#symbols.createDerivedSet((s) => {
226
+ return s.name;
227
+ });
228
+
229
+ if (this.#parent) {
230
+ this.#parent.children.add(this);
231
+ }
232
+
233
+ this.#binder?.notifyScopeCreated(this);
234
+
235
+ trace(TracePhase.scope.create, () => `${formatScope(this)}`);
236
+ traceEffect(TracePhase.scope.update, () => {
237
+ return `${formatScope(this)}`;
238
+ });
239
+ }
240
+
241
+ moveSymbolsFrom(
242
+ source: OutputScope,
243
+ options?: ReactiveUnionSetOptions<OutputSymbol>,
244
+ ) {
245
+ trace(
246
+ TracePhase.scope.copySymbols,
247
+ () =>
248
+ `Moving symbols from ${formatScopeName(source)} to ${formatScopeName(this)}`,
249
+ );
250
+ this.#symbols.addSubset(source.#symbols, {
251
+ onAdd: (symbol) => {
252
+ if (options?.onAdd) {
253
+ return options.onAdd(symbol);
254
+ }
255
+ symbol.scope = this;
256
+ return symbol;
257
+ },
258
+ onDelete: (symbol) => {
259
+ if (options?.onDelete) {
260
+ options.onDelete(symbol);
261
+ }
262
+ },
263
+ });
264
+ }
265
+
266
+ copySymbolsFrom(
267
+ source: OutputScope,
268
+ options?: ReactiveUnionSetOptions<OutputSymbol>,
269
+ ) {
270
+ trace(
271
+ TracePhase.scope.copySymbols,
272
+ () =>
273
+ `Copying symbols from ${formatScopeName(source)} to ${formatScopeName(this)}`,
274
+ );
275
+ this.#symbols.addSubset(source.#symbols, {
276
+ onAdd: (symbol) => {
277
+ if (options?.onAdd) {
278
+ return options.onAdd(symbol);
279
+ }
280
+ return symbol.copyToScope(this);
281
+ },
282
+ onDelete: (symbol) => {
283
+ if (options?.onDelete) {
284
+ options.onDelete(symbol);
285
+ }
286
+ },
287
+ });
288
+ }
289
+
290
+ clone(options: { parent?: OutputScope; owner?: OutputSymbol } = {}) {
291
+ if (this.#flags & OutputScopeFlags.MemberScope && !options.owner) {
292
+ throw new Error("Member scope clones must specify an owner symbol");
293
+ } else if (this.#flags & ~OutputScopeFlags.MemberScope && !options.parent) {
294
+ throw new Error("Non-member scope clones must specify a parent scope");
295
+ }
296
+ const clone = new OutputScope(this.#name, {
297
+ binder: this.#binder,
298
+ flags: this.#flags,
299
+ kind: this.#kind,
300
+ metadata: this.#metadata,
301
+ parent: options.parent,
302
+ owner: options.owner,
303
+ });
304
+
305
+ watch(
306
+ () => this.name,
307
+ (newName) => (clone.name = newName),
308
+ );
309
+ watch(
310
+ () => this.flags,
311
+ (newFlags) => (clone.flags = newFlags),
312
+ );
313
+ // todo: this should be reactive, but cloning non-member scopes
314
+ // seems like a very rare thing.
315
+ for (const child of this.#children) {
316
+ clone.children.add(child.clone());
317
+ }
318
+
319
+ clone.copySymbolsFrom(this);
320
+
321
+ return clone;
322
+ }
323
+ }