@alloy-js/core 0.23.0-dev.1 → 0.23.0-dev.8

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 (263) hide show
  1. package/CHANGELOG.md +0 -22
  2. package/dist/devtools/index.html +68 -0
  3. package/dist/src/binder.d.ts +2 -0
  4. package/dist/src/binder.d.ts.map +1 -1
  5. package/dist/src/binder.js +55 -12
  6. package/dist/src/binder.js.map +1 -1
  7. package/dist/src/components/AppendFile.d.ts.map +1 -1
  8. package/dist/src/components/AppendFile.js +14 -3
  9. package/dist/src/components/AppendFile.js.map +1 -1
  10. package/dist/src/components/Block.js +1 -1
  11. package/dist/src/components/Block.js.map +1 -1
  12. package/dist/src/components/Declaration.d.ts.map +1 -1
  13. package/dist/src/components/Declaration.js +2 -1
  14. package/dist/src/components/Declaration.js.map +1 -1
  15. package/dist/src/components/Scope.d.ts.map +1 -1
  16. package/dist/src/components/Scope.js +4 -1
  17. package/dist/src/components/Scope.js.map +1 -1
  18. package/dist/src/components/TemplateFile.d.ts.map +1 -1
  19. package/dist/src/components/TemplateFile.js +18 -3
  20. package/dist/src/components/TemplateFile.js.map +1 -1
  21. package/dist/src/content-slot.d.ts.map +1 -1
  22. package/dist/src/content-slot.js +6 -5
  23. package/dist/src/content-slot.js.map +1 -1
  24. package/dist/src/context.d.ts.map +1 -1
  25. package/dist/src/context.js +8 -1
  26. package/dist/src/context.js.map +1 -1
  27. package/dist/src/debug/cli.d.ts +6 -0
  28. package/dist/src/debug/cli.d.ts.map +1 -0
  29. package/dist/src/{debug.js → debug/cli.js} +79 -82
  30. package/dist/src/debug/cli.js.map +1 -0
  31. package/dist/src/debug/diagnostics.test.d.ts +2 -0
  32. package/dist/src/debug/diagnostics.test.d.ts.map +1 -0
  33. package/dist/src/debug/diagnostics.test.js +45 -0
  34. package/dist/src/debug/diagnostics.test.js.map +1 -0
  35. package/dist/src/debug/effects.d.ts +69 -0
  36. package/dist/src/debug/effects.d.ts.map +1 -0
  37. package/dist/src/debug/effects.js +228 -0
  38. package/dist/src/debug/effects.js.map +1 -0
  39. package/dist/src/debug/effects.test.d.ts +2 -0
  40. package/dist/src/debug/effects.test.d.ts.map +1 -0
  41. package/dist/src/debug/effects.test.js +86 -0
  42. package/dist/src/debug/effects.test.js.map +1 -0
  43. package/dist/src/debug/files.d.ts +14 -0
  44. package/dist/src/debug/files.d.ts.map +1 -0
  45. package/dist/src/debug/files.js +40 -0
  46. package/dist/src/debug/files.js.map +1 -0
  47. package/dist/src/debug/files.test.d.ts +2 -0
  48. package/dist/src/debug/files.test.d.ts.map +1 -0
  49. package/dist/src/debug/files.test.js +89 -0
  50. package/dist/src/debug/files.test.js.map +1 -0
  51. package/dist/src/debug/index.d.ts +60 -0
  52. package/dist/src/debug/index.d.ts.map +1 -0
  53. package/dist/src/debug/index.js +68 -0
  54. package/dist/src/debug/index.js.map +1 -0
  55. package/dist/src/debug/render.d.ts +57 -0
  56. package/dist/src/debug/render.d.ts.map +1 -0
  57. package/dist/src/debug/render.js +519 -0
  58. package/dist/src/debug/render.js.map +1 -0
  59. package/dist/src/debug/render.test.d.ts +2 -0
  60. package/dist/src/debug/render.test.d.ts.map +1 -0
  61. package/dist/src/debug/render.test.js +328 -0
  62. package/dist/src/debug/render.test.js.map +1 -0
  63. package/dist/src/debug/serialize.d.ts +9 -0
  64. package/dist/src/debug/serialize.d.ts.map +1 -0
  65. package/dist/src/debug/serialize.js +70 -0
  66. package/dist/src/debug/serialize.js.map +1 -0
  67. package/dist/src/debug/symbols.d.ts +9 -0
  68. package/dist/src/debug/symbols.d.ts.map +1 -0
  69. package/dist/src/debug/symbols.js +164 -0
  70. package/dist/src/debug/symbols.js.map +1 -0
  71. package/dist/src/debug/symbols.test.d.ts +2 -0
  72. package/dist/src/debug/symbols.test.d.ts.map +1 -0
  73. package/dist/src/debug/symbols.test.js +104 -0
  74. package/dist/src/debug/symbols.test.js.map +1 -0
  75. package/dist/src/debug/trace.d.ts +342 -0
  76. package/dist/src/debug/trace.d.ts.map +1 -0
  77. package/dist/src/debug/trace.js +443 -0
  78. package/dist/src/debug/trace.js.map +1 -0
  79. package/dist/src/devtools/devtools-protocol.d.ts +232 -0
  80. package/dist/src/devtools/devtools-protocol.d.ts.map +1 -0
  81. package/dist/src/devtools/devtools-protocol.js +2 -0
  82. package/dist/src/devtools/devtools-protocol.js.map +1 -0
  83. package/dist/src/devtools/devtools-server.browser.d.ts +28 -0
  84. package/dist/src/devtools/devtools-server.browser.d.ts.map +1 -0
  85. package/dist/src/devtools/devtools-server.browser.js +36 -0
  86. package/dist/src/devtools/devtools-server.browser.js.map +1 -0
  87. package/dist/src/devtools/devtools-server.d.ts +72 -0
  88. package/dist/src/devtools/devtools-server.d.ts.map +1 -0
  89. package/dist/src/devtools/devtools-server.js +256 -0
  90. package/dist/src/devtools/devtools-server.js.map +1 -0
  91. package/dist/src/devtools/devtools-transport.d.ts +23 -0
  92. package/dist/src/devtools/devtools-transport.d.ts.map +1 -0
  93. package/dist/src/devtools/devtools-transport.js +114 -0
  94. package/dist/src/devtools/devtools-transport.js.map +1 -0
  95. package/dist/src/devtools-entry.browser.d.ts +4 -0
  96. package/dist/src/devtools-entry.browser.d.ts.map +1 -0
  97. package/dist/src/devtools-entry.browser.js +2 -0
  98. package/dist/src/devtools-entry.browser.js.map +1 -0
  99. package/dist/src/devtools-entry.d.ts +4 -0
  100. package/dist/src/devtools-entry.d.ts.map +1 -0
  101. package/dist/src/devtools-entry.js +2 -0
  102. package/dist/src/devtools-entry.js.map +1 -0
  103. package/dist/src/diagnostics.d.ts +34 -0
  104. package/dist/src/diagnostics.d.ts.map +1 -0
  105. package/dist/src/diagnostics.js +89 -0
  106. package/dist/src/diagnostics.js.map +1 -0
  107. package/dist/src/index.d.ts +3 -2
  108. package/dist/src/index.d.ts.map +1 -1
  109. package/dist/src/index.js +3 -2
  110. package/dist/src/index.js.map +1 -1
  111. package/dist/src/print-hook.d.ts +14 -0
  112. package/dist/src/print-hook.d.ts.map +1 -0
  113. package/dist/src/print-hook.js +10 -0
  114. package/dist/src/print-hook.js.map +1 -0
  115. package/dist/src/reactive-union-set.d.ts.map +1 -1
  116. package/dist/src/reactive-union-set.js +15 -0
  117. package/dist/src/reactive-union-set.js.map +1 -1
  118. package/dist/src/reactivity.d.ts +17 -3
  119. package/dist/src/reactivity.d.ts.map +1 -1
  120. package/dist/src/reactivity.js +162 -14
  121. package/dist/src/reactivity.js.map +1 -1
  122. package/dist/src/render-stack.d.ts +17 -1
  123. package/dist/src/render-stack.d.ts.map +1 -1
  124. package/dist/src/render-stack.js +57 -1
  125. package/dist/src/render-stack.js.map +1 -1
  126. package/dist/src/render.d.ts +8 -15
  127. package/dist/src/render.d.ts.map +1 -1
  128. package/dist/src/render.js +362 -103
  129. package/dist/src/render.js.map +1 -1
  130. package/dist/src/resource.d.ts.map +1 -1
  131. package/dist/src/resource.js +5 -0
  132. package/dist/src/resource.js.map +1 -1
  133. package/dist/src/scheduler.d.ts +3 -0
  134. package/dist/src/scheduler.d.ts.map +1 -1
  135. package/dist/src/scheduler.js +45 -2
  136. package/dist/src/scheduler.js.map +1 -1
  137. package/dist/src/symbols/basic-symbol.d.ts.map +1 -1
  138. package/dist/src/symbols/basic-symbol.js +6 -1
  139. package/dist/src/symbols/basic-symbol.js.map +1 -1
  140. package/dist/src/symbols/decl.d.ts.map +1 -1
  141. package/dist/src/symbols/decl.js +5 -1
  142. package/dist/src/symbols/decl.js.map +1 -1
  143. package/dist/src/symbols/output-scope.d.ts +2 -1
  144. package/dist/src/symbols/output-scope.d.ts.map +1 -1
  145. package/dist/src/symbols/output-scope.js +13 -8
  146. package/dist/src/symbols/output-scope.js.map +1 -1
  147. package/dist/src/symbols/output-symbol.d.ts +1 -0
  148. package/dist/src/symbols/output-symbol.d.ts.map +1 -1
  149. package/dist/src/symbols/output-symbol.js +23 -6
  150. package/dist/src/symbols/output-symbol.js.map +1 -1
  151. package/dist/src/symbols/symbol-flow.d.ts.map +1 -1
  152. package/dist/src/symbols/symbol-flow.js +22 -6
  153. package/dist/src/symbols/symbol-flow.js.map +1 -1
  154. package/dist/src/symbols/symbol-slot.d.ts.map +1 -1
  155. package/dist/src/symbols/symbol-slot.js +15 -0
  156. package/dist/src/symbols/symbol-slot.js.map +1 -1
  157. package/dist/src/symbols/symbol-slot.test.d.ts +2 -0
  158. package/dist/src/symbols/symbol-slot.test.d.ts.map +1 -0
  159. package/dist/src/symbols/symbol-slot.test.js +35 -0
  160. package/dist/src/symbols/symbol-slot.test.js.map +1 -0
  161. package/dist/src/symbols/symbol-table.d.ts.map +1 -1
  162. package/dist/src/symbols/symbol-table.js +6 -5
  163. package/dist/src/symbols/symbol-table.js.map +1 -1
  164. package/dist/src/trace.d.ts +2 -0
  165. package/dist/src/trace.d.ts.map +1 -0
  166. package/dist/src/trace.js +2 -0
  167. package/dist/src/trace.js.map +1 -0
  168. package/dist/src/tracer.d.ts +2 -228
  169. package/dist/src/tracer.d.ts.map +1 -1
  170. package/dist/src/tracer.js +5 -298
  171. package/dist/src/tracer.js.map +1 -1
  172. package/dist/src/utils.d.ts.map +1 -1
  173. package/dist/src/utils.js +5 -0
  174. package/dist/src/utils.js.map +1 -1
  175. package/dist/test/components/append-file.test.d.ts.map +1 -1
  176. package/dist/test/components/append-file.test.js +18 -10
  177. package/dist/test/components/append-file.test.js.map +1 -1
  178. package/dist/test/components/template-file.test.d.ts.map +1 -1
  179. package/dist/test/components/template-file.test.js +6 -4
  180. package/dist/test/components/template-file.test.js.map +1 -1
  181. package/dist/test/rendering/basic.test.js +3 -0
  182. package/dist/test/rendering/basic.test.js.map +1 -1
  183. package/dist/test/rendering/print-render-stack.test.d.ts.map +1 -1
  184. package/dist/test/rendering/print-render-stack.test.js +91 -98
  185. package/dist/test/rendering/print-render-stack.test.js.map +1 -1
  186. package/dist/testing/create-test-wrapper.d.ts +1 -1
  187. package/dist/testing/create-test-wrapper.d.ts.map +1 -1
  188. package/dist/testing/create-test-wrapper.js +1 -1
  189. package/dist/testing/create-test-wrapper.js.map +1 -1
  190. package/dist/testing/devtools-utils.d.ts +26 -0
  191. package/dist/testing/devtools-utils.d.ts.map +1 -0
  192. package/dist/testing/devtools-utils.js +140 -0
  193. package/dist/testing/devtools-utils.js.map +1 -0
  194. package/dist/testing/extend-expect.d.ts.map +1 -1
  195. package/dist/testing/extend-expect.js +63 -1
  196. package/dist/testing/extend-expect.js.map +1 -1
  197. package/dist/testing/render.d.ts +2 -2
  198. package/dist/testing/render.d.ts.map +1 -1
  199. package/dist/testing/render.js +2 -2
  200. package/dist/testing/render.js.map +1 -1
  201. package/dist/tsconfig.tsbuildinfo +1 -1
  202. package/package.json +21 -7
  203. package/scripts/copy-devtools-ui.mjs +26 -0
  204. package/src/binder.ts +71 -16
  205. package/src/components/AppendFile.tsx +14 -9
  206. package/src/components/Block.tsx +1 -1
  207. package/src/components/Declaration.tsx +2 -1
  208. package/src/components/Scope.tsx +4 -1
  209. package/src/components/TemplateFile.tsx +18 -9
  210. package/src/content-slot.tsx +6 -6
  211. package/src/context.ts +15 -4
  212. package/src/{debug.ts → debug/cli.ts} +114 -125
  213. package/src/debug/diagnostics.test.tsx +55 -0
  214. package/src/debug/effects.test.tsx +96 -0
  215. package/src/debug/effects.ts +313 -0
  216. package/src/debug/files.test.tsx +96 -0
  217. package/src/debug/files.ts +40 -0
  218. package/src/debug/index.ts +126 -0
  219. package/src/debug/render.test.tsx +379 -0
  220. package/src/debug/render.ts +639 -0
  221. package/src/debug/serialize.ts +85 -0
  222. package/src/debug/symbols.test.tsx +106 -0
  223. package/src/debug/symbols.ts +230 -0
  224. package/src/debug/trace.ts +312 -0
  225. package/src/devtools/devtools-protocol.ts +312 -0
  226. package/src/devtools/devtools-server.browser.ts +71 -0
  227. package/src/devtools/devtools-server.ts +290 -0
  228. package/src/devtools/devtools-transport.ts +154 -0
  229. package/src/devtools-entry.browser.ts +52 -0
  230. package/src/devtools-entry.ts +54 -0
  231. package/src/diagnostics.ts +141 -0
  232. package/src/index.ts +2 -6
  233. package/src/print-hook.ts +22 -0
  234. package/src/reactive-union-set.ts +71 -41
  235. package/src/reactivity.ts +206 -23
  236. package/src/render-stack.ts +68 -1
  237. package/src/render.ts +464 -157
  238. package/src/resource.ts +28 -19
  239. package/src/scheduler.ts +55 -3
  240. package/src/symbols/basic-symbol.ts +6 -1
  241. package/src/symbols/decl.ts +5 -1
  242. package/src/symbols/output-scope.ts +21 -12
  243. package/src/symbols/output-symbol.ts +33 -12
  244. package/src/symbols/symbol-flow.ts +68 -37
  245. package/src/symbols/symbol-slot.test.tsx +41 -0
  246. package/src/symbols/symbol-slot.tsx +47 -20
  247. package/src/symbols/symbol-table.ts +6 -10
  248. package/src/trace.ts +1 -0
  249. package/src/tracer.ts +13 -242
  250. package/src/utils.tsx +22 -13
  251. package/temp/api.json +1675 -162
  252. package/test/components/append-file.test.tsx +36 -29
  253. package/test/components/template-file.test.tsx +11 -11
  254. package/test/rendering/basic.test.tsx +4 -0
  255. package/test/rendering/print-render-stack.test.tsx +52 -43
  256. package/testing/create-test-wrapper.tsx +1 -1
  257. package/testing/devtools-utils.ts +203 -0
  258. package/testing/extend-expect.ts +89 -0
  259. package/testing/render.ts +2 -2
  260. package/testing/vitest.d.ts +9 -0
  261. package/dist/src/debug.d.ts +0 -14
  262. package/dist/src/debug.d.ts.map +0 -1
  263. package/dist/src/debug.js.map +0 -1
package/src/resource.ts CHANGED
@@ -101,26 +101,35 @@ export function createResource<T, U>(
101
101
  }),
102
102
  );
103
103
  } else {
104
- effect(() => {
105
- let input: T;
106
- if (isRef(getter)) {
107
- input = getter.value;
108
- } else {
109
- input = getter();
110
- }
111
- const promise = (fetcher as (input: T) => Promise<U>)(input);
112
- trackPromise(promise);
113
- promise.then(
114
- (result) => {
115
- resource.data = result;
116
- resource.loading = false;
117
- },
118
- (error) => {
119
- resource.error = error;
120
- resource.loading = false;
104
+ effect(
105
+ () => {
106
+ let input: T;
107
+ if (isRef(getter)) {
108
+ input = getter.value;
109
+ } else {
110
+ input = getter();
111
+ }
112
+ const promise = (fetcher as (input: T) => Promise<U>)(input);
113
+ trackPromise(promise);
114
+ promise.then(
115
+ (result) => {
116
+ resource.data = result;
117
+ resource.loading = false;
118
+ },
119
+ (error) => {
120
+ resource.error = error;
121
+ resource.loading = false;
122
+ },
123
+ );
124
+ },
125
+ undefined,
126
+ {
127
+ debug: {
128
+ name: "resource:fetch",
129
+ type: "resource",
121
130
  },
122
- );
123
- });
131
+ },
132
+ );
124
133
  }
125
134
 
126
135
  return resource;
package/src/scheduler.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { ReactiveEffect } from "@vue/reactivity";
2
+ import { debug } from "./debug/index.js";
2
3
 
3
4
  export interface QueueJob {
4
5
  run(): void;
@@ -6,6 +7,10 @@ export interface QueueJob {
6
7
  const immediateQueue = new Set<QueueJob>();
7
8
  const queue = new Set<QueueJob>();
8
9
  const pendingPromises = new Set<Promise<any>>();
10
+ let waitForSignalPromise: Promise<void> | null = null;
11
+ let resolveWaitForSignal: (() => void) | null = null;
12
+ let jobSignalPromise: Promise<void> | null = null;
13
+ let resolveJobSignal: (() => void) | null = null;
9
14
 
10
15
  export function scheduler(immediate = false) {
11
16
  return function (this: ReactiveEffect) {
@@ -19,12 +24,17 @@ export function queueJob(job: QueueJob | (() => void), immediate = false) {
19
24
  if (typeof job === "function") {
20
25
  job = { run: job };
21
26
  }
22
-
23
27
  if (immediate) {
24
28
  immediateQueue.add(job);
25
29
  } else {
26
30
  queue.add(job);
27
31
  }
32
+
33
+ if (resolveJobSignal) {
34
+ resolveJobSignal();
35
+ resolveJobSignal = null;
36
+ jobSignalPromise = null;
37
+ }
28
38
  }
29
39
 
30
40
  /**
@@ -51,6 +61,33 @@ export function flushJobs() {
51
61
  "Asynchronous jobs were found but render was called synchronously. Use `renderAsync` instead.",
52
62
  );
53
63
  }
64
+
65
+ debug.render.flushJobsComplete();
66
+ }
67
+
68
+ export function waitForSignal(): Promise<void> {
69
+ if (!waitForSignalPromise) {
70
+ waitForSignalPromise = new Promise<void>((resolve) => {
71
+ resolveWaitForSignal = resolve;
72
+ });
73
+ pendingPromises.add(waitForSignalPromise);
74
+ }
75
+ return waitForSignalPromise;
76
+ }
77
+
78
+ export function signalSchedulerWait() {
79
+ if (resolveWaitForSignal) {
80
+ resolveWaitForSignal();
81
+ resolveWaitForSignal = null;
82
+ }
83
+ if (waitForSignalPromise) {
84
+ pendingPromises.delete(waitForSignalPromise);
85
+ }
86
+ waitForSignalPromise = null;
87
+ }
88
+
89
+ export function isWaitingForSignal() {
90
+ return waitForSignalPromise !== null;
54
91
  }
55
92
 
56
93
  export async function flushJobsAsync() {
@@ -67,9 +104,24 @@ export async function flushJobsAsync() {
67
104
  break;
68
105
  }
69
106
 
70
- // Wait for all current promises to complete
71
- await Promise.allSettled(Array.from(pendingPromises));
107
+ if (!jobSignalPromise) {
108
+ jobSignalPromise = new Promise<void>((resolve) => {
109
+ resolveJobSignal = resolve;
110
+ });
111
+ }
112
+
113
+ // Wait for either pending promises to complete or new jobs to arrive
114
+ await Promise.race([
115
+ Promise.allSettled(Array.from(pendingPromises)),
116
+ jobSignalPromise,
117
+ ]);
118
+
119
+ // Clear the job signal after each iteration so we create a new one next time
120
+ jobSignalPromise = null;
121
+ resolveJobSignal = null;
72
122
  }
123
+
124
+ debug.render.flushJobsComplete();
73
125
  }
74
126
 
75
127
  function takeJob() {
@@ -1,3 +1,4 @@
1
+ import { createSymbol } from "../binder.js";
1
2
  import { OutputSymbol } from "./output-symbol.js";
2
3
 
3
4
  /**
@@ -16,7 +17,11 @@ export class BasicSymbol extends OutputSymbol {
16
17
 
17
18
  copy() {
18
19
  const options = this.getCopyOptions();
19
- const copiedSymbol = new BasicSymbol(this.name, undefined, options);
20
+ const binder = this.binder;
21
+ const copiedSymbol = createSymbol(BasicSymbol, this.name, undefined, {
22
+ ...options,
23
+ binder,
24
+ });
20
25
  this.initializeCopy(copiedSymbol);
21
26
 
22
27
  return copiedSymbol;
@@ -1,4 +1,5 @@
1
1
  import { toRef } from "@vue/reactivity";
2
+ import { createSymbol } from "../binder.js";
2
3
  import { useScope } from "../context/scope.js";
3
4
  import { Namekey } from "../refkey.js";
4
5
  import { createComponent } from "../runtime/component.js";
@@ -18,7 +19,10 @@ export function decl(namekey: Namekey) {
18
19
  `Cannot declare symbol in non-basic scope: ${currentScope.constructor.name}. Use a language-specific 'decl' function instead.`,
19
20
  );
20
21
  }
21
- const symbol = new BasicSymbol(namekey, currentScope.symbols);
22
+ const binder = currentScope.binder;
23
+ const symbol = createSymbol(BasicSymbol, namekey, currentScope.symbols, {
24
+ binder,
25
+ });
22
26
 
23
27
  return toRef(symbol, "name");
24
28
  }, {});
@@ -1,5 +1,4 @@
1
1
  import {
2
- effect,
3
2
  reactive,
4
3
  ReactiveFlags,
5
4
  shallowReactive,
@@ -11,8 +10,7 @@ import {
11
10
  import type { Binder } from "../binder.js";
12
11
  import { useBinder } from "../context/binder.js";
13
12
  import { inspect } from "../inspect.js";
14
- import { untrack } from "../reactivity.js";
15
- import { formatScope, trace, traceEffect, TracePhase } from "../tracer.js";
13
+ import { effect, untrack } from "../reactivity.js";
16
14
  import { OutputDeclarationSpace, OutputSpace } from "./output-space.js";
17
15
  import { OutputSymbol } from "./output-symbol.js";
18
16
 
@@ -154,7 +152,7 @@ export abstract class OutputScope {
154
152
  return this.#binder;
155
153
  }
156
154
 
157
- [ReactiveFlags.SKIP] = this;
155
+ [ReactiveFlags.SKIP] = true;
158
156
 
159
157
  constructor(
160
158
  name: string,
@@ -167,9 +165,20 @@ export abstract class OutputScope {
167
165
  this.#binder = options.binder ?? useBinder();
168
166
  this.#children = shallowReactive(new Set());
169
167
  this.#parent = parentScope;
170
- effect(() => {
171
- this.#setOwnerSymbol(options.ownerSymbol?.movedTo ?? options.ownerSymbol);
172
- });
168
+ effect(
169
+ () => {
170
+ this.#setOwnerSymbol(
171
+ options.ownerSymbol?.movedTo ?? options.ownerSymbol,
172
+ );
173
+ },
174
+ undefined,
175
+ {
176
+ debug: {
177
+ name: "outputScope:ownerSymbol",
178
+ type: "symbol",
179
+ },
180
+ },
181
+ );
173
182
 
174
183
  if (this.#parent) {
175
184
  this.#parent.children.add(this);
@@ -184,12 +193,8 @@ export abstract class OutputScope {
184
193
  ]),
185
194
  );
186
195
 
196
+ // Notify binder so resolution tracking works even without createScope
187
197
  this.#binder?.notifyScopeCreated(this);
188
-
189
- trace(TracePhase.scope.create, () => `${formatScope(this)}`);
190
- traceEffect(TracePhase.scope.update, () => {
191
- return `${formatScope(this)}`;
192
- });
193
198
  }
194
199
 
195
200
  /**
@@ -215,6 +220,10 @@ export abstract class OutputScope {
215
220
  return this.#ownerSymbol;
216
221
  }
217
222
 
223
+ get debugInfo(): Record<string, unknown> {
224
+ return {};
225
+ }
226
+
218
227
  #setOwnerSymbol(value: OutputSymbol | undefined) {
219
228
  const old = this.#ownerSymbol;
220
229
  this.#ownerSymbol = value;
@@ -12,17 +12,19 @@ import {
12
12
  } from "@vue/reactivity";
13
13
  import type { Binder } from "../binder.js";
14
14
  import { useBinder } from "../context/binder.js";
15
+ import { debug, TracePhase } from "../debug/index.js";
15
16
  import { inspect } from "../inspect.js";
16
17
  import { NamePolicyGetter } from "../name-policy.js";
17
18
  import { untrack } from "../reactivity.js";
18
- import { Namekey, type Refkey } from "../refkey.js";
19
19
  import {
20
- formatSymbol,
21
- formatSymbolName,
22
- trace,
23
- traceEffect,
24
- TracePhase,
25
- } from "../tracer.js";
20
+ isMemberRefkey,
21
+ isNamekey,
22
+ isSymbolRefkey,
23
+ Namekey,
24
+ toRefkey,
25
+ type Refkey,
26
+ } from "../refkey.js";
27
+ import { formatSymbolName } from "../tracer.js";
26
28
  import {
27
29
  OutputDeclarationSpace,
28
30
  OutputMemberSpace,
@@ -459,6 +461,10 @@ export abstract class OutputSymbol {
459
461
  return this.#isTyped;
460
462
  }
461
463
 
464
+ get debugInfo(): Record<string, unknown> {
465
+ return {};
466
+ }
467
+
462
468
  #namePolicy: NamePolicyGetter | undefined;
463
469
  get namePolicy() {
464
470
  return this.#namePolicy;
@@ -552,10 +558,7 @@ export abstract class OutputSymbol {
552
558
  ]),
553
559
  );
554
560
 
555
- trace(TracePhase.symbol.create, () => `${formatSymbol(this)}`);
556
- traceEffect(TracePhase.symbol.update, () => {
557
- return `${formatSymbol(this)}`;
558
- });
561
+ // Notify binder so resolution tracking works even without createSymbol
559
562
  this.#binder?.notifySymbolCreated(this);
560
563
  }
561
564
 
@@ -570,7 +573,7 @@ export abstract class OutputSymbol {
570
573
  }
571
574
 
572
575
  delete() {
573
- trace(TracePhase.symbol.delete, () => `${formatSymbolName(this)}`);
576
+ debug.trace(TracePhase.symbol.delete, () => `${formatSymbolName(this)}`);
574
577
  if (this.#spaces) {
575
578
  this.#spaces.forEach((space) => space.delete(this));
576
579
  }
@@ -677,3 +680,21 @@ export abstract class OutputSymbol {
677
680
  return untrack(() => `${this.constructor.name} "${this.name}"[${this.id}]`);
678
681
  }
679
682
  }
683
+
684
+ function _formatRefkey(refkey: Refkey): string {
685
+ if (isNamekey(refkey)) {
686
+ return `name:${refkey.name}`;
687
+ }
688
+ if (isMemberRefkey(refkey)) {
689
+ const base = _formatRefkey(toRefkey(refkey.base));
690
+ const member =
691
+ typeof refkey.member === "string" ?
692
+ refkey.member
693
+ : _formatRefkey(toRefkey(refkey.member));
694
+ return `member:${base}.${member}`;
695
+ }
696
+ if (isSymbolRefkey(refkey)) {
697
+ return `key:${refkey.key}`;
698
+ }
699
+ return "refkey";
700
+ }
@@ -3,7 +3,8 @@ import { Context, effect, getContext, onCleanup } from "../reactivity.js";
3
3
 
4
4
  import { MemberContext } from "../context/member-scope.js";
5
5
  import { ScopeContext } from "../context/scope.js";
6
- import { formatSymbolName, trace, TracePhase } from "../tracer.js";
6
+ import { debug, TracePhase } from "../debug/index.js";
7
+ import { formatSymbolName } from "../tracer.js";
7
8
  import { OutputSymbol } from "./output-symbol.js";
8
9
 
9
10
  export interface TakeSymbolCallback {
@@ -19,16 +20,25 @@ export function takeSymbols(cb?: (symbol: OutputSymbol) => void) {
19
20
  context.takesSymbols = true;
20
21
  context.takenSymbols = shallowReactive(new Set<OutputSymbol>());
21
22
  if (cb) {
22
- effect<Set<OutputSymbol>>((oldSymbols) => {
23
- for (const symbol of context.takenSymbols!) {
24
- if (oldSymbols && oldSymbols.has(symbol)) {
25
- continue;
23
+ effect<Set<OutputSymbol>>(
24
+ (oldSymbols) => {
25
+ for (const symbol of context.takenSymbols!) {
26
+ if (oldSymbols && oldSymbols.has(symbol)) {
27
+ continue;
28
+ }
29
+ cb(symbol);
26
30
  }
27
- cb(symbol);
28
- }
29
31
 
30
- return new Set(context.takenSymbols!);
31
- });
32
+ return new Set(context.takenSymbols!);
33
+ },
34
+ undefined,
35
+ {
36
+ debug: {
37
+ name: "symbolFlow:takeSymbols",
38
+ type: "symbol",
39
+ },
40
+ },
41
+ );
32
42
  }
33
43
  return context.takenSymbols;
34
44
  }
@@ -37,9 +47,9 @@ export function emitSymbol(
37
47
  symbol: OutputSymbol | Ref<OutputSymbol | undefined>,
38
48
  ) {
39
49
  if (isRef(symbol)) {
40
- trace(TracePhase.symbol.flow, () => `Emitting ref to symbol`);
50
+ debug.trace(TracePhase.symbol.flow, () => `Emitting ref to symbol`);
41
51
  } else {
42
- trace(
52
+ debug.trace(
43
53
  TracePhase.symbol.flow,
44
54
  () => `Emitting symbol ${formatSymbolName(symbol)}`,
45
55
  );
@@ -58,7 +68,7 @@ export function emitSymbol(
58
68
  (context.context[ScopeContext.id] || context.context[MemberContext.id])
59
69
  ) {
60
70
  // don't cross scope boundaries.
61
- trace(
71
+ debug.trace(
62
72
  TracePhase.symbol.flow,
63
73
  () => `Not emitting symbol across scope boundary`,
64
74
  );
@@ -69,27 +79,39 @@ export function emitSymbol(
69
79
  }
70
80
 
71
81
  if (!symbolTaker) {
72
- trace(TracePhase.symbol.flow, () => `No symbol taker found, not emitting`);
82
+ debug.trace(
83
+ TracePhase.symbol.flow,
84
+ () => `No symbol taker found, not emitting`,
85
+ );
73
86
  return;
74
87
  }
75
88
 
76
89
  if (isRef(symbol)) {
77
- effect<OutputSymbol | undefined>((prevSymbol) => {
78
- onCleanup(() => {
79
- if (symbol.value) {
80
- symbolTaker.takenSymbols!.delete(symbol.value);
90
+ effect<OutputSymbol | undefined>(
91
+ (prevSymbol) => {
92
+ onCleanup(() => {
93
+ if (symbol.value) {
94
+ symbolTaker.takenSymbols!.delete(symbol.value);
95
+ }
96
+ });
97
+ if (symbol.value === undefined) {
98
+ symbolTaker.takenSymbols!.delete(prevSymbol!);
99
+ return undefined;
100
+ } else {
101
+ symbolTaker.takenSymbols!.add(symbol.value);
102
+ return symbol.value;
81
103
  }
82
- });
83
- if (symbol.value === undefined) {
84
- symbolTaker.takenSymbols!.delete(prevSymbol!);
85
- return undefined;
86
- } else {
87
- symbolTaker.takenSymbols!.add(symbol.value);
88
- return symbol.value;
89
- }
90
- });
104
+ },
105
+ undefined,
106
+ {
107
+ debug: {
108
+ name: "symbolFlow:emitRef",
109
+ type: "symbol",
110
+ },
111
+ },
112
+ );
91
113
  } else {
92
- trace(
114
+ debug.trace(
93
115
  TracePhase.symbol.flow,
94
116
  () =>
95
117
  `Emitting symbol ${formatSymbolName(symbol)} taken by ${symbolTaker.componentOwner?.name ?? "unknown component"}`,
@@ -103,19 +125,28 @@ export function emitSymbol(
103
125
 
104
126
  export function moveTakenMembersTo(baseSymbol: OutputSymbol) {
105
127
  const taken = takeSymbols();
106
- effect(() => {
107
- for (const symbol of taken) {
108
- if (symbol.isTransient) {
109
- symbol.moveMembersTo(baseSymbol);
110
- }
128
+ effect(
129
+ () => {
130
+ for (const symbol of taken) {
131
+ if (symbol.isTransient) {
132
+ symbol.moveMembersTo(baseSymbol);
133
+ }
111
134
 
112
- for (const refkey of symbol.refkeys) {
113
- if (!baseSymbol.refkeys.includes(refkey)) {
114
- baseSymbol.refkeys.push(refkey);
135
+ for (const refkey of symbol.refkeys) {
136
+ if (!baseSymbol.refkeys.includes(refkey)) {
137
+ baseSymbol.refkeys.push(refkey);
138
+ }
115
139
  }
116
140
  }
117
- }
118
- });
141
+ },
142
+ undefined,
143
+ {
144
+ debug: {
145
+ name: "symbolFlow:moveTakenMembers",
146
+ type: "symbol",
147
+ },
148
+ },
149
+ );
119
150
  }
120
151
 
121
152
  export function instantiateTakenMembersTo(
@@ -0,0 +1,41 @@
1
+ import { shallowRef } from "@vue/reactivity";
2
+ import { expect, it } from "vitest";
3
+ import { renderTree } from "../render.js";
4
+ import { flushJobs } from "../scheduler.js";
5
+ import { BasicSymbol } from "./basic-symbol.js";
6
+ import { emitSymbol } from "./symbol-flow.js";
7
+ import { createSymbolSlot } from "./symbol-slot.jsx";
8
+
9
+ it("captures firstSymbol", async () => {
10
+ const Slot = createSymbolSlot();
11
+
12
+ renderTree(
13
+ <Slot>
14
+ {() => {
15
+ emitSymbol(new BasicSymbol("a", undefined));
16
+ }}
17
+ </Slot>,
18
+ );
19
+ await flushJobs();
20
+ expect(Slot.firstSymbol.value).toBeDefined();
21
+ expect(Slot.firstSymbol.value!.name).toBe("a");
22
+ });
23
+
24
+ it("captures firstSymbol when emitting a ref to a symbol", async () => {
25
+ const Slot = createSymbolSlot();
26
+ const symref = shallowRef<BasicSymbol | undefined>();
27
+
28
+ renderTree(
29
+ <Slot>
30
+ {() => {
31
+ emitSymbol(symref);
32
+ }}
33
+ </Slot>,
34
+ );
35
+ await flushJobs();
36
+ expect(Slot.firstSymbol.value).toBeUndefined();
37
+ symref.value = new BasicSymbol("a", undefined);
38
+ await flushJobs();
39
+ expect(Slot.firstSymbol.value).toBeDefined();
40
+ expect(Slot.firstSymbol.value!.name).toBe("a");
41
+ });
@@ -50,36 +50,63 @@ export function createSymbolSlot(): SymbolSlot {
50
50
  Object.defineProperty(SymbolSlot, "firstSymbol", {
51
51
  get() {
52
52
  const ref = shallowRef();
53
- effect(() => {
54
- ref.value = symbolSlotRef.value?.values().next().value;
55
- });
53
+ effect(
54
+ () => {
55
+ ref.value = symbolSlotRef.value?.values().next().value;
56
+ },
57
+ undefined,
58
+ {
59
+ debug: {
60
+ name: "symbolSlot:firstSymbol",
61
+ type: "symbol",
62
+ },
63
+ },
64
+ );
56
65
  return ref;
57
66
  },
58
67
  });
59
68
 
60
69
  SymbolSlot.copyMembersTo = (baseSymbol: OutputSymbol) => {
61
- effect(() => {
62
- if (!symbolSlotRef.value) {
63
- return;
64
- }
70
+ effect(
71
+ () => {
72
+ if (!symbolSlotRef.value) {
73
+ return;
74
+ }
65
75
 
66
- for (const symbol of symbolSlotRef.value) {
67
- symbol.copyMembersTo(baseSymbol);
68
- }
69
- });
76
+ for (const symbol of symbolSlotRef.value) {
77
+ symbol.copyMembersTo(baseSymbol);
78
+ }
79
+ },
80
+ undefined,
81
+ {
82
+ debug: {
83
+ name: "symbolSlot:copyMembers",
84
+ type: "symbol",
85
+ },
86
+ },
87
+ );
70
88
  };
71
89
 
72
90
  SymbolSlot.moveMembersTo = (baseSymbol: OutputSymbol) => {
73
- effect(() => {
74
- if (!symbolSlotRef.value) {
75
- return;
76
- }
77
- for (const symbol of symbolSlotRef.value) {
78
- if (symbol.isTransient) {
79
- symbol.moveMembersTo(baseSymbol);
91
+ effect(
92
+ () => {
93
+ if (!symbolSlotRef.value) {
94
+ return;
80
95
  }
81
- }
82
- });
96
+ for (const symbol of symbolSlotRef.value) {
97
+ if (symbol.isTransient) {
98
+ symbol.moveMembersTo(baseSymbol);
99
+ }
100
+ }
101
+ },
102
+ undefined,
103
+ {
104
+ debug: {
105
+ name: "symbolSlot:moveMembers",
106
+ type: "symbol",
107
+ },
108
+ },
109
+ );
83
110
  };
84
111
 
85
112
  return SymbolSlot as any;
@@ -1,13 +1,9 @@
1
1
  import type { Binder, NameConflictResolver } from "../binder.js";
2
+ import { debug, TracePhase } from "../debug/index.js";
2
3
  import { ReactiveUnionSet } from "../reactive-union-set.js";
3
4
  import { Refkey } from "../refkey.js";
4
5
  import { queueJob } from "../scheduler.js";
5
- import {
6
- formatSymbolName,
7
- formatSymbolTableName,
8
- trace,
9
- TracePhase,
10
- } from "../tracer.js";
6
+ import { formatSymbolName, formatSymbolTableName } from "../tracer.js";
11
7
  import { OutputSpace } from "./output-space.js";
12
8
  import type { OutputSymbol } from "./output-symbol.js";
13
9
 
@@ -65,7 +61,7 @@ export abstract class SymbolTable extends ReactiveUnionSet<OutputSymbol> {
65
61
  ) {
66
62
  super({
67
63
  onAdd: (symbol) => {
68
- trace(
64
+ debug.trace(
69
65
  TracePhase.symbol.addToScope,
70
66
  () =>
71
67
  `${formatSymbolName(symbol)} added to ${formatSymbolTableName(this)}`,
@@ -78,7 +74,7 @@ export abstract class SymbolTable extends ReactiveUnionSet<OutputSymbol> {
78
74
  return symbol;
79
75
  },
80
76
  onDelete: (symbol) => {
81
- trace(
77
+ debug.trace(
82
78
  TracePhase.symbol.removeFromScope,
83
79
  () =>
84
80
  `${formatSymbolName(symbol)} removed from ${formatSymbolTableName(this)}`,
@@ -97,7 +93,7 @@ export abstract class SymbolTable extends ReactiveUnionSet<OutputSymbol> {
97
93
  }
98
94
 
99
95
  moveTo(target: SymbolTable): void {
100
- trace(
96
+ debug.trace(
101
97
  TracePhase.scope.moveSymbols,
102
98
  () =>
103
99
  `${formatSymbolTableName(this)} -> ${formatSymbolTableName(target)}`,
@@ -117,7 +113,7 @@ export abstract class SymbolTable extends ReactiveUnionSet<OutputSymbol> {
117
113
  createRefkeys?(sourceSymbol: OutputSymbol): Refkey[];
118
114
  } = {},
119
115
  ): void {
120
- trace(
116
+ debug.trace(
121
117
  TracePhase.scope.copySymbols,
122
118
  () =>
123
119
  `${formatSymbolTableName(this)} copied to ${formatSymbolTableName(target)}`,
package/src/trace.ts ADDED
@@ -0,0 +1 @@
1
+ // Legacy module removed in favor of ./debug.ts.