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

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 (337) hide show
  1. package/CHANGELOG.md +0 -22
  2. package/dist/devtools/index.html +80 -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 +60 -12
  6. package/dist/src/binder.js.map +1 -1
  7. package/dist/src/components/AccessExpression.d.ts +78 -0
  8. package/dist/src/components/AccessExpression.d.ts.map +1 -0
  9. package/dist/src/components/AccessExpression.js +218 -0
  10. package/dist/src/components/AccessExpression.js.map +1 -0
  11. package/dist/src/components/AccessExpression.test.d.ts +2 -0
  12. package/dist/src/components/AccessExpression.test.d.ts.map +1 -0
  13. package/dist/src/components/AccessExpression.test.js +137 -0
  14. package/dist/src/components/AccessExpression.test.js.map +1 -0
  15. package/dist/src/components/AppendFile.d.ts.map +1 -1
  16. package/dist/src/components/AppendFile.js +14 -3
  17. package/dist/src/components/AppendFile.js.map +1 -1
  18. package/dist/src/components/Block.js +1 -1
  19. package/dist/src/components/Block.js.map +1 -1
  20. package/dist/src/components/Declaration.d.ts.map +1 -1
  21. package/dist/src/components/Declaration.js +2 -1
  22. package/dist/src/components/Declaration.js.map +1 -1
  23. package/dist/src/components/For.d.ts.map +1 -1
  24. package/dist/src/components/For.js +1 -1
  25. package/dist/src/components/For.js.map +1 -1
  26. package/dist/src/components/List.d.ts.map +1 -1
  27. package/dist/src/components/List.js +1 -1
  28. package/dist/src/components/List.js.map +1 -1
  29. package/dist/src/components/Prose.js +2 -2
  30. package/dist/src/components/Prose.js.map +1 -1
  31. package/dist/src/components/Scope.d.ts.map +1 -1
  32. package/dist/src/components/Scope.js +6 -1
  33. package/dist/src/components/Scope.js.map +1 -1
  34. package/dist/src/components/SourceDirectory.d.ts.map +1 -1
  35. package/dist/src/components/SourceDirectory.js +1 -2
  36. package/dist/src/components/SourceDirectory.js.map +1 -1
  37. package/dist/src/components/Switch.d.ts.map +1 -1
  38. package/dist/src/components/Switch.js +1 -1
  39. package/dist/src/components/Switch.js.map +1 -1
  40. package/dist/src/components/TemplateFile.d.ts.map +1 -1
  41. package/dist/src/components/TemplateFile.js +18 -3
  42. package/dist/src/components/TemplateFile.js.map +1 -1
  43. package/dist/src/components/index.d.ts +1 -0
  44. package/dist/src/components/index.d.ts.map +1 -1
  45. package/dist/src/components/index.js +1 -0
  46. package/dist/src/components/index.js.map +1 -1
  47. package/dist/src/content-slot.d.ts.map +1 -1
  48. package/dist/src/content-slot.js +7 -6
  49. package/dist/src/content-slot.js.map +1 -1
  50. package/dist/src/context.d.ts.map +1 -1
  51. package/dist/src/context.js +10 -3
  52. package/dist/src/context.js.map +1 -1
  53. package/dist/src/debug/cli.d.ts +6 -0
  54. package/dist/src/debug/cli.d.ts.map +1 -0
  55. package/dist/src/{debug.js → debug/cli.js} +79 -82
  56. package/dist/src/debug/cli.js.map +1 -0
  57. package/dist/src/debug/diagnostics.test.d.ts +2 -0
  58. package/dist/src/debug/diagnostics.test.d.ts.map +1 -0
  59. package/dist/src/debug/diagnostics.test.js +46 -0
  60. package/dist/src/debug/diagnostics.test.js.map +1 -0
  61. package/dist/src/debug/effects.d.ts +81 -0
  62. package/dist/src/debug/effects.d.ts.map +1 -0
  63. package/dist/src/debug/effects.js +358 -0
  64. package/dist/src/debug/effects.js.map +1 -0
  65. package/dist/src/debug/effects.test.d.ts +2 -0
  66. package/dist/src/debug/effects.test.d.ts.map +1 -0
  67. package/dist/src/debug/effects.test.js +256 -0
  68. package/dist/src/debug/effects.test.js.map +1 -0
  69. package/dist/src/debug/files.d.ts +14 -0
  70. package/dist/src/debug/files.d.ts.map +1 -0
  71. package/dist/src/debug/files.js +29 -0
  72. package/dist/src/debug/files.js.map +1 -0
  73. package/dist/src/debug/files.test.d.ts +2 -0
  74. package/dist/src/debug/files.test.d.ts.map +1 -0
  75. package/dist/src/debug/files.test.js +66 -0
  76. package/dist/src/debug/files.test.js.map +1 -0
  77. package/dist/src/debug/index.d.ts +63 -0
  78. package/dist/src/debug/index.d.ts.map +1 -0
  79. package/dist/src/debug/index.js +71 -0
  80. package/dist/src/debug/index.js.map +1 -0
  81. package/dist/src/debug/message-format.test.d.ts +2 -0
  82. package/dist/src/debug/message-format.test.d.ts.map +1 -0
  83. package/dist/src/debug/message-format.test.js +700 -0
  84. package/dist/src/debug/message-format.test.js.map +1 -0
  85. package/dist/src/debug/render-tree-orphans.test.d.ts +2 -0
  86. package/dist/src/debug/render-tree-orphans.test.d.ts.map +1 -0
  87. package/dist/src/debug/render-tree-orphans.test.js +297 -0
  88. package/dist/src/debug/render-tree-orphans.test.js.map +1 -0
  89. package/dist/src/debug/render.d.ts +57 -0
  90. package/dist/src/debug/render.d.ts.map +1 -0
  91. package/dist/src/debug/render.js +472 -0
  92. package/dist/src/debug/render.js.map +1 -0
  93. package/dist/src/debug/render.test.d.ts +2 -0
  94. package/dist/src/debug/render.test.d.ts.map +1 -0
  95. package/dist/src/debug/render.test.js +291 -0
  96. package/dist/src/debug/render.test.js.map +1 -0
  97. package/dist/src/debug/serialize.d.ts +9 -0
  98. package/dist/src/debug/serialize.d.ts.map +1 -0
  99. package/dist/src/debug/serialize.js +70 -0
  100. package/dist/src/debug/serialize.js.map +1 -0
  101. package/dist/src/debug/symbols.d.ts +16 -0
  102. package/dist/src/debug/symbols.d.ts.map +1 -0
  103. package/dist/src/debug/symbols.js +196 -0
  104. package/dist/src/debug/symbols.js.map +1 -0
  105. package/dist/src/debug/symbols.test.d.ts +2 -0
  106. package/dist/src/debug/symbols.test.d.ts.map +1 -0
  107. package/dist/src/debug/symbols.test.js +93 -0
  108. package/dist/src/debug/symbols.test.js.map +1 -0
  109. package/dist/src/debug/trace-writer.d.ts +55 -0
  110. package/dist/src/debug/trace-writer.d.ts.map +1 -0
  111. package/dist/src/debug/trace-writer.js +658 -0
  112. package/dist/src/debug/trace-writer.js.map +1 -0
  113. package/dist/src/debug/trace.d.ts +342 -0
  114. package/dist/src/debug/trace.d.ts.map +1 -0
  115. package/dist/src/debug/trace.js +446 -0
  116. package/dist/src/debug/trace.js.map +1 -0
  117. package/dist/src/devtools/devtools-protocol.d.ts +389 -0
  118. package/dist/src/devtools/devtools-protocol.d.ts.map +1 -0
  119. package/dist/src/devtools/devtools-protocol.js +2 -0
  120. package/dist/src/devtools/devtools-protocol.js.map +1 -0
  121. package/dist/src/devtools/devtools-server.browser.d.ts +23 -0
  122. package/dist/src/devtools/devtools-server.browser.d.ts.map +1 -0
  123. package/dist/src/devtools/devtools-server.browser.js +33 -0
  124. package/dist/src/devtools/devtools-server.browser.js.map +1 -0
  125. package/dist/src/devtools/devtools-server.d.ts +66 -0
  126. package/dist/src/devtools/devtools-server.d.ts.map +1 -0
  127. package/dist/src/devtools/devtools-server.js +444 -0
  128. package/dist/src/devtools/devtools-server.js.map +1 -0
  129. package/dist/src/devtools/devtools-transport.d.ts +23 -0
  130. package/dist/src/devtools/devtools-transport.d.ts.map +1 -0
  131. package/dist/src/devtools/devtools-transport.js +114 -0
  132. package/dist/src/devtools/devtools-transport.js.map +1 -0
  133. package/dist/src/devtools-entry.browser.d.ts +4 -0
  134. package/dist/src/devtools-entry.browser.d.ts.map +1 -0
  135. package/dist/src/devtools-entry.browser.js +2 -0
  136. package/dist/src/devtools-entry.browser.js.map +1 -0
  137. package/dist/src/devtools-entry.d.ts +4 -0
  138. package/dist/src/devtools-entry.d.ts.map +1 -0
  139. package/dist/src/devtools-entry.js +2 -0
  140. package/dist/src/devtools-entry.js.map +1 -0
  141. package/dist/src/diagnostics.d.ts +34 -0
  142. package/dist/src/diagnostics.d.ts.map +1 -0
  143. package/dist/src/diagnostics.js +89 -0
  144. package/dist/src/diagnostics.js.map +1 -0
  145. package/dist/src/index.d.ts +3 -2
  146. package/dist/src/index.d.ts.map +1 -1
  147. package/dist/src/index.js +3 -2
  148. package/dist/src/index.js.map +1 -1
  149. package/dist/src/print-hook.d.ts +14 -0
  150. package/dist/src/print-hook.d.ts.map +1 -0
  151. package/dist/src/print-hook.js +10 -0
  152. package/dist/src/print-hook.js.map +1 -0
  153. package/dist/src/reactive-union-set.d.ts.map +1 -1
  154. package/dist/src/reactive-union-set.js +28 -3
  155. package/dist/src/reactive-union-set.js.map +1 -1
  156. package/dist/src/reactivity.d.ts +60 -7
  157. package/dist/src/reactivity.d.ts.map +1 -1
  158. package/dist/src/reactivity.js +308 -39
  159. package/dist/src/reactivity.js.map +1 -1
  160. package/dist/src/render-stack.d.ts +18 -1
  161. package/dist/src/render-stack.d.ts.map +1 -1
  162. package/dist/src/render-stack.js +61 -1
  163. package/dist/src/render-stack.js.map +1 -1
  164. package/dist/src/render.d.ts +8 -15
  165. package/dist/src/render.d.ts.map +1 -1
  166. package/dist/src/render.js +424 -109
  167. package/dist/src/render.js.map +1 -1
  168. package/dist/src/resource.d.ts.map +1 -1
  169. package/dist/src/resource.js +5 -0
  170. package/dist/src/resource.js.map +1 -1
  171. package/dist/src/scheduler.d.ts +13 -0
  172. package/dist/src/scheduler.d.ts.map +1 -1
  173. package/dist/src/scheduler.js +150 -13
  174. package/dist/src/scheduler.js.map +1 -1
  175. package/dist/src/symbols/basic-symbol.d.ts.map +1 -1
  176. package/dist/src/symbols/basic-symbol.js +6 -1
  177. package/dist/src/symbols/basic-symbol.js.map +1 -1
  178. package/dist/src/symbols/decl.d.ts.map +1 -1
  179. package/dist/src/symbols/decl.js +5 -1
  180. package/dist/src/symbols/decl.js.map +1 -1
  181. package/dist/src/symbols/output-scope.d.ts +2 -1
  182. package/dist/src/symbols/output-scope.d.ts.map +1 -1
  183. package/dist/src/symbols/output-scope.js +13 -8
  184. package/dist/src/symbols/output-scope.js.map +1 -1
  185. package/dist/src/symbols/output-symbol.d.ts +1 -0
  186. package/dist/src/symbols/output-symbol.d.ts.map +1 -1
  187. package/dist/src/symbols/output-symbol.js +25 -8
  188. package/dist/src/symbols/output-symbol.js.map +1 -1
  189. package/dist/src/symbols/symbol-flow.d.ts.map +1 -1
  190. package/dist/src/symbols/symbol-flow.js +24 -8
  191. package/dist/src/symbols/symbol-flow.js.map +1 -1
  192. package/dist/src/symbols/symbol-slot.d.ts.map +1 -1
  193. package/dist/src/symbols/symbol-slot.js +15 -0
  194. package/dist/src/symbols/symbol-slot.js.map +1 -1
  195. package/dist/src/symbols/symbol-slot.test.d.ts +2 -0
  196. package/dist/src/symbols/symbol-slot.test.d.ts.map +1 -0
  197. package/dist/src/symbols/symbol-slot.test.js +35 -0
  198. package/dist/src/symbols/symbol-slot.test.js.map +1 -0
  199. package/dist/src/symbols/symbol-table.d.ts.map +1 -1
  200. package/dist/src/symbols/symbol-table.js +6 -5
  201. package/dist/src/symbols/symbol-table.js.map +1 -1
  202. package/dist/src/trace.d.ts +2 -0
  203. package/dist/src/trace.d.ts.map +1 -0
  204. package/dist/src/trace.js +2 -0
  205. package/dist/src/trace.js.map +1 -0
  206. package/dist/src/tracer.d.ts +2 -228
  207. package/dist/src/tracer.d.ts.map +1 -1
  208. package/dist/src/tracer.js +5 -298
  209. package/dist/src/tracer.js.map +1 -1
  210. package/dist/src/utils.d.ts.map +1 -1
  211. package/dist/src/utils.js +17 -9
  212. package/dist/src/utils.js.map +1 -1
  213. package/dist/test/components/append-file.test.d.ts.map +1 -1
  214. package/dist/test/components/append-file.test.js +18 -10
  215. package/dist/test/components/append-file.test.js.map +1 -1
  216. package/dist/test/components/template-file.test.d.ts.map +1 -1
  217. package/dist/test/components/template-file.test.js +6 -4
  218. package/dist/test/components/template-file.test.js.map +1 -1
  219. package/dist/test/lazy-isempty.test.d.ts +2 -0
  220. package/dist/test/lazy-isempty.test.d.ts.map +1 -0
  221. package/dist/test/lazy-isempty.test.js +89 -0
  222. package/dist/test/lazy-isempty.test.js.map +1 -0
  223. package/dist/test/reactive-union-set-disposers.test.d.ts +2 -0
  224. package/dist/test/reactive-union-set-disposers.test.d.ts.map +1 -0
  225. package/dist/test/reactive-union-set-disposers.test.js +98 -0
  226. package/dist/test/reactive-union-set-disposers.test.js.map +1 -0
  227. package/dist/test/reactivity/shallow-reactive.test.d.ts +2 -0
  228. package/dist/test/reactivity/shallow-reactive.test.d.ts.map +1 -0
  229. package/dist/test/reactivity/shallow-reactive.test.js +52 -0
  230. package/dist/test/reactivity/shallow-reactive.test.js.map +1 -0
  231. package/dist/test/rendering/basic.test.js +3 -0
  232. package/dist/test/rendering/basic.test.js.map +1 -1
  233. package/dist/test/rendering/print-render-stack.test.d.ts.map +1 -1
  234. package/dist/test/rendering/print-render-stack.test.js +91 -98
  235. package/dist/test/rendering/print-render-stack.test.js.map +1 -1
  236. package/dist/test/scheduler-extended.test.d.ts +2 -0
  237. package/dist/test/scheduler-extended.test.d.ts.map +1 -0
  238. package/dist/test/scheduler-extended.test.js +96 -0
  239. package/dist/test/scheduler-extended.test.js.map +1 -0
  240. package/dist/test/scheduler.test.d.ts +2 -0
  241. package/dist/test/scheduler.test.d.ts.map +1 -0
  242. package/dist/test/scheduler.test.js +46 -0
  243. package/dist/test/scheduler.test.js.map +1 -0
  244. package/dist/testing/create-test-wrapper.d.ts +1 -1
  245. package/dist/testing/create-test-wrapper.d.ts.map +1 -1
  246. package/dist/testing/create-test-wrapper.js +1 -1
  247. package/dist/testing/create-test-wrapper.js.map +1 -1
  248. package/dist/testing/devtools-utils.d.ts +35 -0
  249. package/dist/testing/devtools-utils.d.ts.map +1 -0
  250. package/dist/testing/devtools-utils.js +162 -0
  251. package/dist/testing/devtools-utils.js.map +1 -0
  252. package/dist/testing/extend-expect.d.ts.map +1 -1
  253. package/dist/testing/extend-expect.js +63 -1
  254. package/dist/testing/extend-expect.js.map +1 -1
  255. package/dist/testing/render.d.ts +2 -2
  256. package/dist/testing/render.d.ts.map +1 -1
  257. package/dist/testing/render.js +2 -2
  258. package/dist/testing/render.js.map +1 -1
  259. package/dist/tsconfig.tsbuildinfo +1 -1
  260. package/package.json +21 -7
  261. package/scripts/copy-devtools-ui.mjs +26 -0
  262. package/src/binder.ts +117 -53
  263. package/src/components/AccessExpression.test.tsx +132 -0
  264. package/src/components/AccessExpression.tsx +344 -0
  265. package/src/components/AppendFile.tsx +14 -9
  266. package/src/components/Block.tsx +1 -1
  267. package/src/components/Declaration.tsx +2 -1
  268. package/src/components/For.tsx +14 -10
  269. package/src/components/List.tsx +7 -4
  270. package/src/components/Prose.tsx +1 -1
  271. package/src/components/Scope.tsx +6 -1
  272. package/src/components/SourceDirectory.tsx +1 -2
  273. package/src/components/Switch.tsx +11 -7
  274. package/src/components/TemplateFile.tsx +18 -9
  275. package/src/components/index.tsx +1 -0
  276. package/src/content-slot.tsx +7 -7
  277. package/src/context.ts +17 -6
  278. package/src/{debug.ts → debug/cli.ts} +114 -125
  279. package/src/debug/diagnostics.test.tsx +56 -0
  280. package/src/debug/effects.test.tsx +301 -0
  281. package/src/debug/effects.ts +531 -0
  282. package/src/debug/files.test.tsx +76 -0
  283. package/src/debug/files.ts +40 -0
  284. package/src/debug/index.ts +132 -0
  285. package/src/debug/message-format.test.tsx +759 -0
  286. package/src/debug/render-tree-orphans.test.tsx +344 -0
  287. package/src/debug/render.test.tsx +357 -0
  288. package/src/debug/render.ts +698 -0
  289. package/src/debug/serialize.ts +85 -0
  290. package/src/debug/symbols.test.tsx +105 -0
  291. package/src/debug/symbols.ts +322 -0
  292. package/src/debug/trace-writer.ts +969 -0
  293. package/src/debug/trace.ts +309 -0
  294. package/src/devtools/devtools-protocol.ts +497 -0
  295. package/src/devtools/devtools-server.browser.ts +62 -0
  296. package/src/devtools/devtools-server.ts +468 -0
  297. package/src/devtools/devtools-transport.ts +154 -0
  298. package/src/devtools-entry.browser.ts +48 -0
  299. package/src/devtools-entry.ts +48 -0
  300. package/src/diagnostics.ts +150 -0
  301. package/src/index.ts +2 -7
  302. package/src/print-hook.ts +22 -0
  303. package/src/reactive-union-set.ts +85 -44
  304. package/src/reactivity.ts +396 -58
  305. package/src/render-stack.ts +73 -1
  306. package/src/render.ts +544 -161
  307. package/src/resource.ts +28 -19
  308. package/src/scheduler.ts +209 -14
  309. package/src/symbols/basic-symbol.ts +6 -1
  310. package/src/symbols/decl.ts +5 -1
  311. package/src/symbols/output-scope.ts +21 -13
  312. package/src/symbols/output-symbol.ts +34 -14
  313. package/src/symbols/symbol-flow.ts +76 -39
  314. package/src/symbols/symbol-slot.test.tsx +41 -0
  315. package/src/symbols/symbol-slot.tsx +47 -20
  316. package/src/symbols/symbol-table.ts +6 -10
  317. package/src/trace.ts +1 -0
  318. package/src/tracer.ts +13 -242
  319. package/src/utils.tsx +31 -21
  320. package/temp/api.json +5700 -3015
  321. package/test/components/append-file.test.tsx +36 -29
  322. package/test/components/template-file.test.tsx +11 -11
  323. package/test/lazy-isempty.test.tsx +106 -0
  324. package/test/reactive-union-set-disposers.test.tsx +112 -0
  325. package/test/reactivity/shallow-reactive.test.tsx +56 -0
  326. package/test/rendering/basic.test.tsx +4 -0
  327. package/test/rendering/print-render-stack.test.tsx +52 -43
  328. package/test/scheduler-extended.test.tsx +122 -0
  329. package/test/scheduler.test.tsx +50 -0
  330. package/testing/create-test-wrapper.tsx +1 -1
  331. package/testing/devtools-utils.ts +245 -0
  332. package/testing/extend-expect.ts +89 -0
  333. package/testing/render.ts +2 -2
  334. package/testing/vitest.d.ts +9 -0
  335. package/dist/src/debug.d.ts +0 -14
  336. package/dist/src/debug.d.ts.map +0 -1
  337. 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,17 +1,61 @@
1
1
  import { ReactiveEffect } from "@vue/reactivity";
2
+ import { debug } from "./debug/index.js";
3
+ import {
4
+ beginTransaction,
5
+ commitTransaction,
6
+ insertEffectLifecycle,
7
+ insertSchedulerFlush,
8
+ insertSchedulerJob,
9
+ } from "./debug/trace-writer.js";
10
+ import { isTraceEnabled } from "./debug/trace.js";
11
+ import { getEffectDebugId } from "./reactivity.js";
2
12
 
3
13
  export interface QueueJob {
4
14
  run(): void;
5
15
  }
6
16
  const immediateQueue = new Set<QueueJob>();
7
17
  const queue = new Set<QueueJob>();
18
+
19
+ function isJobActive(job: QueueJob): boolean {
20
+ // ReactiveEffect uses bit 0 (flags & 1) as the ACTIVE flag.
21
+ // Skip effects that were stopped after being queued.
22
+ const flags = (job as any).flags;
23
+ return flags === undefined || (flags & 1) !== 0;
24
+ }
8
25
  const pendingPromises = new Set<Promise<any>>();
26
+ let waitForSignalPromise: Promise<void> | null = null;
27
+ let resolveWaitForSignal: (() => void) | null = null;
28
+ let jobSignalPromise: Promise<void> | null = null;
29
+ let resolveJobSignal: (() => void) | null = null;
30
+
31
+ // Maps effect debug IDs to the ref that most recently triggered them.
32
+ // Intentionally overwrites on repeated triggers for the same effect before flush —
33
+ // we only need the last trigger ref for lifecycle recording, not all intermediate ones.
34
+ const lastTriggerRef = new Map<number, number>();
35
+
36
+ /**
37
+ * Record which ref triggered an effect re-run.
38
+ * Called from the onTrigger debug hook before the effect is scheduled.
39
+ *
40
+ * Note: if an effect is triggered multiple times before flush, only the last
41
+ * trigger ref is retained. This is intentional — we care about the most
42
+ * recent cause, and tracking all triggers would add overhead with minimal
43
+ * diagnostic value since only the last mutation actually caused the re-run.
44
+ */
45
+ export function setLastTriggerRef(effectDebugId: number, refId: number): void {
46
+ lastTriggerRef.set(effectDebugId, refId);
47
+ }
9
48
 
10
49
  export function scheduler(immediate = false) {
50
+ if (!immediate) return defaultScheduler;
11
51
  return function (this: ReactiveEffect) {
12
- queueJob(this, immediate);
52
+ queueJob(this, true);
13
53
  };
14
54
  }
55
+
56
+ const defaultScheduler = function (this: ReactiveEffect) {
57
+ queueJob(this, false);
58
+ };
15
59
  export function queueJob(job: QueueJob | (() => void), immediate = false) {
16
60
  // if we have an immediate job, we don't need to queue the normal job.
17
61
  // the set is serving an important purpose here in deduping the effects we run
@@ -19,12 +63,29 @@ export function queueJob(job: QueueJob | (() => void), immediate = false) {
19
63
  if (typeof job === "function") {
20
64
  job = { run: job };
21
65
  }
22
-
23
66
  if (immediate) {
24
67
  immediateQueue.add(job);
25
68
  } else {
26
69
  queue.add(job);
27
70
  }
71
+
72
+ if (isTraceEnabled()) {
73
+ const effectId = getEffectDebugId(job as object);
74
+ if (effectId !== undefined) {
75
+ insertSchedulerJob(
76
+ "queue",
77
+ effectId,
78
+ immediate,
79
+ immediateQueue.size + queue.size,
80
+ );
81
+ }
82
+ }
83
+
84
+ if (resolveJobSignal) {
85
+ resolveJobSignal();
86
+ resolveJobSignal = null;
87
+ jobSignalPromise = null;
88
+ }
28
89
  }
29
90
 
30
91
  /**
@@ -40,36 +101,170 @@ export function trackPromise(promise: Promise<any>) {
40
101
 
41
102
  export function flushJobs() {
42
103
  // First, run all synchronous jobs
104
+ if (isTraceEnabled()) beginTransaction();
43
105
  let job;
106
+ let jobCount = 0;
44
107
  while ((job = takeJob()) !== null) {
108
+ if (isTraceEnabled()) {
109
+ const effectId = getEffectDebugId(job as object);
110
+ if (effectId !== undefined) {
111
+ insertSchedulerJob(
112
+ "run",
113
+ effectId,
114
+ false,
115
+ immediateQueue.size + queue.size,
116
+ );
117
+ }
118
+ }
119
+ if (!isJobActive(job)) {
120
+ if (isTraceEnabled()) {
121
+ const effectId = getEffectDebugId(job as object);
122
+ if (effectId !== undefined) {
123
+ insertEffectLifecycle(
124
+ effectId,
125
+ "skipped",
126
+ undefined,
127
+ undefined,
128
+ undefined,
129
+ undefined,
130
+ );
131
+ }
132
+ }
133
+ continue;
134
+ }
135
+ if (isTraceEnabled()) {
136
+ const effectId = getEffectDebugId(job as object);
137
+ if (effectId !== undefined) {
138
+ const triggerRefId = lastTriggerRef.get(effectId);
139
+ lastTriggerRef.delete(effectId);
140
+ insertEffectLifecycle(
141
+ effectId,
142
+ "ran",
143
+ triggerRefId,
144
+ undefined,
145
+ undefined,
146
+ undefined,
147
+ );
148
+ }
149
+ }
45
150
  job.run();
151
+ jobCount++;
46
152
  }
47
153
 
48
154
  // If there are no pending promises, we're done
49
155
  if (pendingPromises.size > 0) {
156
+ if (isTraceEnabled()) commitTransaction();
50
157
  throw new Error(
51
158
  "Asynchronous jobs were found but render was called synchronously. Use `renderAsync` instead.",
52
159
  );
53
160
  }
161
+
162
+ if (isTraceEnabled()) {
163
+ insertSchedulerFlush(jobCount);
164
+ commitTransaction();
165
+ }
166
+
167
+ debug.render.flushJobsComplete();
168
+ }
169
+
170
+ export function waitForSignal(): Promise<void> {
171
+ if (!waitForSignalPromise) {
172
+ waitForSignalPromise = new Promise<void>((resolve) => {
173
+ resolveWaitForSignal = resolve;
174
+ });
175
+ pendingPromises.add(waitForSignalPromise);
176
+ }
177
+ return waitForSignalPromise;
178
+ }
179
+
180
+ export function signalSchedulerWait() {
181
+ if (resolveWaitForSignal) {
182
+ resolveWaitForSignal();
183
+ resolveWaitForSignal = null;
184
+ }
185
+ if (waitForSignalPromise) {
186
+ pendingPromises.delete(waitForSignalPromise);
187
+ }
188
+ waitForSignalPromise = null;
189
+ }
190
+
191
+ export function isWaitingForSignal() {
192
+ return waitForSignalPromise !== null;
54
193
  }
55
194
 
56
195
  export async function flushJobsAsync() {
57
196
  // Keep running jobs until both the queues are empty and all promises are resolved
58
- while (true) {
59
- // First, run all synchronous jobs
60
- let job;
61
- while ((job = takeJob()) !== null) {
62
- job.run();
63
- }
197
+ if (isTraceEnabled()) beginTransaction();
198
+ try {
199
+ while (true) {
200
+ // First, run all synchronous jobs
201
+ let job;
202
+ while ((job = takeJob()) !== null) {
203
+ if (!isJobActive(job)) {
204
+ if (isTraceEnabled()) {
205
+ const effectId = getEffectDebugId(job as object);
206
+ if (effectId !== undefined) {
207
+ insertEffectLifecycle(
208
+ effectId,
209
+ "skipped",
210
+ undefined,
211
+ undefined,
212
+ undefined,
213
+ undefined,
214
+ );
215
+ }
216
+ }
217
+ continue;
218
+ }
219
+ if (isTraceEnabled()) {
220
+ const effectId = getEffectDebugId(job as object);
221
+ if (effectId !== undefined) {
222
+ const triggerRefId = lastTriggerRef.get(effectId);
223
+ lastTriggerRef.delete(effectId);
224
+ insertEffectLifecycle(
225
+ effectId,
226
+ "ran",
227
+ triggerRefId,
228
+ undefined,
229
+ undefined,
230
+ undefined,
231
+ );
232
+ }
233
+ }
234
+ job.run();
235
+ }
64
236
 
65
- // If there are no pending promises, we're done
66
- if (pendingPromises.size === 0) {
67
- break;
68
- }
237
+ // If there are no pending promises, we're done
238
+ if (pendingPromises.size === 0) {
239
+ break;
240
+ }
241
+
242
+ // Commit before awaiting so writes are visible, then re-open after
243
+ if (isTraceEnabled()) commitTransaction();
244
+
245
+ if (!jobSignalPromise) {
246
+ jobSignalPromise = new Promise<void>((resolve) => {
247
+ resolveJobSignal = resolve;
248
+ });
249
+ }
69
250
 
70
- // Wait for all current promises to complete
71
- await Promise.allSettled(Array.from(pendingPromises));
251
+ // Wait for either pending promises to complete or new jobs to arrive
252
+ await Promise.race([
253
+ Promise.allSettled(Array.from(pendingPromises)),
254
+ jobSignalPromise,
255
+ ]);
256
+
257
+ // Clear the job signal after each iteration so we create a new one next time
258
+ jobSignalPromise = null;
259
+ resolveJobSignal = null;
260
+
261
+ if (isTraceEnabled()) beginTransaction();
262
+ }
263
+ } finally {
264
+ if (isTraceEnabled()) commitTransaction();
72
265
  }
266
+
267
+ debug.render.flushJobsComplete();
73
268
  }
74
269
 
75
270
  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,8 +1,6 @@
1
1
  import {
2
- effect,
3
2
  reactive,
4
3
  ReactiveFlags,
5
- shallowReactive,
6
4
  track,
7
5
  TrackOpTypes,
8
6
  trigger,
@@ -11,8 +9,7 @@ import {
11
9
  import type { Binder } from "../binder.js";
12
10
  import { useBinder } from "../context/binder.js";
13
11
  import { inspect } from "../inspect.js";
14
- import { untrack } from "../reactivity.js";
15
- import { formatScope, trace, traceEffect, TracePhase } from "../tracer.js";
12
+ import { effect, shallowReactive, untrack } from "../reactivity.js";
16
13
  import { OutputDeclarationSpace, OutputSpace } from "./output-space.js";
17
14
  import { OutputSymbol } from "./output-symbol.js";
18
15
 
@@ -154,7 +151,7 @@ export abstract class OutputScope {
154
151
  return this.#binder;
155
152
  }
156
153
 
157
- [ReactiveFlags.SKIP] = this;
154
+ [ReactiveFlags.SKIP] = true;
158
155
 
159
156
  constructor(
160
157
  name: string,
@@ -167,9 +164,20 @@ export abstract class OutputScope {
167
164
  this.#binder = options.binder ?? useBinder();
168
165
  this.#children = shallowReactive(new Set());
169
166
  this.#parent = parentScope;
170
- effect(() => {
171
- this.#setOwnerSymbol(options.ownerSymbol?.movedTo ?? options.ownerSymbol);
172
- });
167
+ effect(
168
+ () => {
169
+ this.#setOwnerSymbol(
170
+ options.ownerSymbol?.movedTo ?? options.ownerSymbol,
171
+ );
172
+ },
173
+ undefined,
174
+ {
175
+ debug: {
176
+ name: "outputScope:ownerSymbol",
177
+ type: "symbol",
178
+ },
179
+ },
180
+ );
173
181
 
174
182
  if (this.#parent) {
175
183
  this.#parent.children.add(this);
@@ -184,12 +192,8 @@ export abstract class OutputScope {
184
192
  ]),
185
193
  );
186
194
 
195
+ // Notify binder so resolution tracking works even without createScope
187
196
  this.#binder?.notifyScopeCreated(this);
188
-
189
- trace(TracePhase.scope.create, () => `${formatScope(this)}`);
190
- traceEffect(TracePhase.scope.update, () => {
191
- return `${formatScope(this)}`;
192
- });
193
197
  }
194
198
 
195
199
  /**
@@ -215,6 +219,10 @@ export abstract class OutputScope {
215
219
  return this.#ownerSymbol;
216
220
  }
217
221
 
222
+ get debugInfo(): Record<string, unknown> {
223
+ return {};
224
+ }
225
+
218
226
  #setOwnerSymbol(value: OutputSymbol | undefined) {
219
227
  const old = this.#ownerSymbol;
220
228
  this.#ownerSymbol = value;
@@ -3,7 +3,6 @@ import {
3
3
  reactive,
4
4
  ReactiveFlags,
5
5
  Ref,
6
- shallowReactive,
7
6
  track,
8
7
  TrackOpTypes,
9
8
  trigger,
@@ -12,17 +11,19 @@ import {
12
11
  } from "@vue/reactivity";
13
12
  import type { Binder } from "../binder.js";
14
13
  import { useBinder } from "../context/binder.js";
14
+ import { debug, TracePhase } from "../debug/index.js";
15
15
  import { inspect } from "../inspect.js";
16
16
  import { NamePolicyGetter } from "../name-policy.js";
17
- import { untrack } from "../reactivity.js";
18
- import { Namekey, type Refkey } from "../refkey.js";
17
+ import { shallowReactive, untrack } from "../reactivity.js";
19
18
  import {
20
- formatSymbol,
21
- formatSymbolName,
22
- trace,
23
- traceEffect,
24
- TracePhase,
25
- } from "../tracer.js";
19
+ isMemberRefkey,
20
+ isNamekey,
21
+ isSymbolRefkey,
22
+ Namekey,
23
+ toRefkey,
24
+ type Refkey,
25
+ } from "../refkey.js";
26
+ import { formatSymbolName } from "../tracer.js";
26
27
  import {
27
28
  OutputDeclarationSpace,
28
29
  OutputMemberSpace,
@@ -459,6 +460,10 @@ export abstract class OutputSymbol {
459
460
  return this.#isTyped;
460
461
  }
461
462
 
463
+ get debugInfo(): Record<string, unknown> {
464
+ return {};
465
+ }
466
+
462
467
  #namePolicy: NamePolicyGetter | undefined;
463
468
  get namePolicy() {
464
469
  return this.#namePolicy;
@@ -552,10 +557,7 @@ export abstract class OutputSymbol {
552
557
  ]),
553
558
  );
554
559
 
555
- trace(TracePhase.symbol.create, () => `${formatSymbol(this)}`);
556
- traceEffect(TracePhase.symbol.update, () => {
557
- return `${formatSymbol(this)}`;
558
- });
560
+ // Notify binder so resolution tracking works even without createSymbol
559
561
  this.#binder?.notifySymbolCreated(this);
560
562
  }
561
563
 
@@ -570,7 +572,7 @@ export abstract class OutputSymbol {
570
572
  }
571
573
 
572
574
  delete() {
573
- trace(TracePhase.symbol.delete, () => `${formatSymbolName(this)}`);
575
+ debug.trace(TracePhase.symbol.delete, () => `${formatSymbolName(this)}`);
574
576
  if (this.#spaces) {
575
577
  this.#spaces.forEach((space) => space.delete(this));
576
578
  }
@@ -677,3 +679,21 @@ export abstract class OutputSymbol {
677
679
  return untrack(() => `${this.constructor.name} "${this.name}"[${this.id}]`);
678
680
  }
679
681
  }
682
+
683
+ function _formatRefkey(refkey: Refkey): string {
684
+ if (isNamekey(refkey)) {
685
+ return `name:${refkey.name}`;
686
+ }
687
+ if (isMemberRefkey(refkey)) {
688
+ const base = _formatRefkey(toRefkey(refkey.base));
689
+ const member =
690
+ typeof refkey.member === "string" ?
691
+ refkey.member
692
+ : _formatRefkey(toRefkey(refkey.member));
693
+ return `member:${base}.${member}`;
694
+ }
695
+ if (isSymbolRefkey(refkey)) {
696
+ return `key:${refkey.key}`;
697
+ }
698
+ return "refkey";
699
+ }
@@ -1,9 +1,16 @@
1
- import { isRef, Ref, shallowReactive } from "@vue/reactivity";
2
- import { Context, effect, getContext, onCleanup } from "../reactivity.js";
1
+ import { isRef, Ref } from "@vue/reactivity";
2
+ import {
3
+ Context,
4
+ effect,
5
+ getContext,
6
+ onCleanup,
7
+ shallowReactive,
8
+ } from "../reactivity.js";
3
9
 
4
10
  import { MemberContext } from "../context/member-scope.js";
5
11
  import { ScopeContext } from "../context/scope.js";
6
- import { formatSymbolName, trace, TracePhase } from "../tracer.js";
12
+ import { debug, TracePhase } from "../debug/index.js";
13
+ import { formatSymbolName } from "../tracer.js";
7
14
  import { OutputSymbol } from "./output-symbol.js";
8
15
 
9
16
  export interface TakeSymbolCallback {
@@ -19,16 +26,25 @@ export function takeSymbols(cb?: (symbol: OutputSymbol) => void) {
19
26
  context.takesSymbols = true;
20
27
  context.takenSymbols = shallowReactive(new Set<OutputSymbol>());
21
28
  if (cb) {
22
- effect<Set<OutputSymbol>>((oldSymbols) => {
23
- for (const symbol of context.takenSymbols!) {
24
- if (oldSymbols && oldSymbols.has(symbol)) {
25
- continue;
29
+ effect<Set<OutputSymbol>>(
30
+ (oldSymbols) => {
31
+ for (const symbol of context.takenSymbols!) {
32
+ if (oldSymbols && oldSymbols.has(symbol)) {
33
+ continue;
34
+ }
35
+ cb(symbol);
26
36
  }
27
- cb(symbol);
28
- }
29
37
 
30
- return new Set(context.takenSymbols!);
31
- });
38
+ return new Set(context.takenSymbols!);
39
+ },
40
+ undefined,
41
+ {
42
+ debug: {
43
+ name: "symbolFlow:takeSymbols",
44
+ type: "symbol",
45
+ },
46
+ },
47
+ );
32
48
  }
33
49
  return context.takenSymbols;
34
50
  }
@@ -37,9 +53,9 @@ export function emitSymbol(
37
53
  symbol: OutputSymbol | Ref<OutputSymbol | undefined>,
38
54
  ) {
39
55
  if (isRef(symbol)) {
40
- trace(TracePhase.symbol.flow, () => `Emitting ref to symbol`);
56
+ debug.trace(TracePhase.symbol.flow, () => `Emitting ref to symbol`);
41
57
  } else {
42
- trace(
58
+ debug.trace(
43
59
  TracePhase.symbol.flow,
44
60
  () => `Emitting symbol ${formatSymbolName(symbol)}`,
45
61
  );
@@ -58,7 +74,7 @@ export function emitSymbol(
58
74
  (context.context[ScopeContext.id] || context.context[MemberContext.id])
59
75
  ) {
60
76
  // don't cross scope boundaries.
61
- trace(
77
+ debug.trace(
62
78
  TracePhase.symbol.flow,
63
79
  () => `Not emitting symbol across scope boundary`,
64
80
  );
@@ -69,27 +85,39 @@ export function emitSymbol(
69
85
  }
70
86
 
71
87
  if (!symbolTaker) {
72
- trace(TracePhase.symbol.flow, () => `No symbol taker found, not emitting`);
88
+ debug.trace(
89
+ TracePhase.symbol.flow,
90
+ () => `No symbol taker found, not emitting`,
91
+ );
73
92
  return;
74
93
  }
75
94
 
76
95
  if (isRef(symbol)) {
77
- effect<OutputSymbol | undefined>((prevSymbol) => {
78
- onCleanup(() => {
79
- if (symbol.value) {
80
- symbolTaker.takenSymbols!.delete(symbol.value);
96
+ effect<OutputSymbol | undefined>(
97
+ (prevSymbol) => {
98
+ onCleanup(() => {
99
+ if (symbol.value) {
100
+ symbolTaker.takenSymbols!.delete(symbol.value);
101
+ }
102
+ });
103
+ if (symbol.value === undefined) {
104
+ symbolTaker.takenSymbols!.delete(prevSymbol!);
105
+ return undefined;
106
+ } else {
107
+ symbolTaker.takenSymbols!.add(symbol.value);
108
+ return symbol.value;
81
109
  }
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
- });
110
+ },
111
+ undefined,
112
+ {
113
+ debug: {
114
+ name: "symbolFlow:emitRef",
115
+ type: "symbol",
116
+ },
117
+ },
118
+ );
91
119
  } else {
92
- trace(
120
+ debug.trace(
93
121
  TracePhase.symbol.flow,
94
122
  () =>
95
123
  `Emitting symbol ${formatSymbolName(symbol)} taken by ${symbolTaker.componentOwner?.name ?? "unknown component"}`,
@@ -103,19 +131,28 @@ export function emitSymbol(
103
131
 
104
132
  export function moveTakenMembersTo(baseSymbol: OutputSymbol) {
105
133
  const taken = takeSymbols();
106
- effect(() => {
107
- for (const symbol of taken) {
108
- if (symbol.isTransient) {
109
- symbol.moveMembersTo(baseSymbol);
110
- }
134
+ effect(
135
+ () => {
136
+ for (const symbol of taken) {
137
+ if (symbol.isTransient) {
138
+ symbol.moveMembersTo(baseSymbol);
139
+ }
111
140
 
112
- for (const refkey of symbol.refkeys) {
113
- if (!baseSymbol.refkeys.includes(refkey)) {
114
- baseSymbol.refkeys.push(refkey);
141
+ for (const refkey of symbol.refkeys) {
142
+ if (!baseSymbol.refkeys.includes(refkey)) {
143
+ baseSymbol.refkeys.push(refkey);
144
+ }
115
145
  }
116
146
  }
117
- }
118
- });
147
+ },
148
+ undefined,
149
+ {
150
+ debug: {
151
+ name: "symbolFlow:moveTakenMembers",
152
+ type: "symbol",
153
+ },
154
+ },
155
+ );
119
156
  }
120
157
 
121
158
  export function instantiateTakenMembersTo(