@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
@@ -1,127 +1,16 @@
1
- import { isReactive } from "@vue/reactivity";
2
1
  import Table from "cli-table3";
3
2
  import pc from "picocolors";
4
- import { contextsByKey } from "./context.js";
5
- import { Context, getContext } from "./reactivity.js";
3
+ import { contextsByKey } from "../context.js";
4
+ import { getContext, untrack } from "../reactivity.js";
5
+ import { isReactiveTarget } from "./effects.js";
6
6
 
7
- interface DebugInterface {
8
- component: {
9
- stack(): void;
10
- tree(): void;
11
- watch(): void;
12
- render(): void;
13
- context(): void;
14
- };
15
- }
16
-
17
- const debug: DebugInterface = {
18
- component: {
19
- stack: debugStack,
20
- tree() {
21
- //eslint-disable-next-line no-console
22
- console.log("tree");
23
- },
24
- watch() {
25
- //eslint-disable-next-line no-console
26
- console.log("watch");
27
- },
28
- render() {
29
- //eslint-disable-next-line no-console
30
- console.log("render");
31
- },
32
- context: debugContext,
33
- },
34
- };
35
-
36
- function debugStack() {
37
- let currentContext = getContext();
38
- let foundContexts: Context[] = [];
39
- while (currentContext !== null) {
40
- if (
41
- currentContext.context &&
42
- Object.getOwnPropertySymbols(currentContext.context)[0]
43
- ) {
44
- foundContexts.push(currentContext);
45
- }
46
-
47
- if (
48
- currentContext.componentOwner &&
49
- currentContext.componentOwner.component.name !== "Provider"
50
- ) {
51
- process.stdout.write(
52
- style.component.name(currentContext.componentOwner.component.name) +
53
- "\n",
54
- );
55
- const table = kvTable();
56
- const props = currentContext.componentOwner.props;
57
-
58
- table.push([
59
- { hAlign: "right", content: "props" },
60
- props && Object.keys(props).length > 0 ?
61
- dumpValue(props)
62
- : pc.gray("(none)"),
63
- ]);
64
-
65
- table.push([
66
- { hAlign: "right", content: "contexts" },
67
- foundContexts.length > 0 ?
68
- foundContexts.map((c) => printContext(c, true)).join("\n")
69
- : pc.gray("(none)"),
70
- ]);
71
-
72
- process.stdout.write(table.toString() + "\n\n");
73
- foundContexts = [];
74
- }
75
-
76
- currentContext = currentContext.owner;
77
- }
78
- }
79
-
80
- function debugContext() {
81
- let currentContext = getContext();
82
- while (currentContext !== null) {
83
- //eslint-disable-next-line no-console
84
- console.log(printContext(currentContext));
85
- currentContext = currentContext.owner;
86
- }
87
- }
88
- function printContext(context: Context, omitOwner: boolean = false) {
89
- if (!context.context) return "";
90
- const key = Object.getOwnPropertySymbols(context.context)[0];
91
- if (!key) return "";
92
- const contextDefinition = contextsByKey.get(key);
93
- const contextName = contextDefinition?.name ?? "unknown context";
94
- const value = context.context[key];
95
-
96
- let output = style.context.name(contextName);
97
- if (!omitOwner) {
98
- const owner = findContextOwner(context);
99
- output += " provided by " + style.component.name(owner);
100
- }
101
-
102
- output += "\n" + dumpValue(value) + "\n";
103
-
104
- return output;
105
- }
106
-
107
- function findContextOwner(context: Context) {
108
- let currentContext: Context | null = context;
109
- while (
110
- currentContext &&
111
- (currentContext.componentOwner === undefined ||
112
- currentContext.componentOwner.component.name === "Provider")
113
- ) {
114
- currentContext = currentContext.owner;
7
+ function reactiveTag(value: unknown) {
8
+ if (isReactiveTarget(value)) {
9
+ return " " + pc.greenBright(`reactive`) + " ";
115
10
  }
116
-
117
- return currentContext?.componentOwner?.component.name ?? "unknown";
118
- }
119
- declare global {
120
- var debug: DebugInterface;
11
+ return "";
121
12
  }
122
13
 
123
- globalThis.debug = debug;
124
-
125
14
  const style = {
126
15
  value: {
127
16
  primitive(value: string | number | boolean | null | undefined) {
@@ -151,13 +40,6 @@ const style = {
151
40
  },
152
41
  };
153
42
 
154
- function reactiveTag(value: unknown) {
155
- if (isReactive(value)) {
156
- return " " + pc.greenBright(`reactive`) + " ";
157
- }
158
- return "";
159
- }
160
-
161
43
  function dumpValue(value: unknown, level = 0) {
162
44
  switch (typeof value) {
163
45
  case "boolean":
@@ -209,3 +91,110 @@ function kvTable(sep = " ") {
209
91
  style: { "padding-left": 0, "padding-right": 0 },
210
92
  });
211
93
  }
94
+
95
+ function printContext(
96
+ context: ReturnType<typeof getContext>,
97
+ omitOwner = false,
98
+ ) {
99
+ if (!context?.context) return "";
100
+ const key = Object.getOwnPropertySymbols(context.context)[0];
101
+ if (!key) return "";
102
+ const contextDefinition = contextsByKey.get(key);
103
+ const contextName = contextDefinition?.name ?? "unknown context";
104
+ const value = context.context[key];
105
+
106
+ let output = style.context.name(contextName);
107
+ if (!omitOwner) {
108
+ const owner = findContextOwner(context);
109
+ output += " provided by " + style.component.name(owner);
110
+ }
111
+
112
+ output += "\n" + dumpValue(value) + "\n";
113
+
114
+ return output;
115
+ }
116
+
117
+ function findContextOwner(context: ReturnType<typeof getContext>) {
118
+ let currentContext = context;
119
+ while (
120
+ currentContext &&
121
+ (currentContext.componentOwner === undefined ||
122
+ currentContext.componentOwner.component.name === "Provider")
123
+ ) {
124
+ currentContext = currentContext.owner;
125
+ }
126
+
127
+ return currentContext?.componentOwner?.component.name ?? "unknown";
128
+ }
129
+
130
+ export function debugStack() {
131
+ untrack(() => {
132
+ let currentContext = getContext();
133
+ let foundContexts: (typeof currentContext)[] = [];
134
+ while (currentContext !== null) {
135
+ if (
136
+ currentContext.context &&
137
+ Object.getOwnPropertySymbols(currentContext.context)[0]
138
+ ) {
139
+ foundContexts.push(currentContext);
140
+ }
141
+
142
+ if (
143
+ currentContext.componentOwner &&
144
+ currentContext.componentOwner.component.name !== "Provider"
145
+ ) {
146
+ process.stdout.write(
147
+ style.component.name(currentContext.componentOwner.component.name) +
148
+ "\n",
149
+ );
150
+ const table = kvTable();
151
+ const props = currentContext.componentOwner.props;
152
+
153
+ table.push([
154
+ { hAlign: "right", content: "props" },
155
+ props && Object.keys(props).length > 0 ?
156
+ dumpValue(props)
157
+ : pc.gray("(none)"),
158
+ ]);
159
+
160
+ table.push([
161
+ { hAlign: "right", content: "contexts" },
162
+ foundContexts.length > 0 ?
163
+ foundContexts.map((c) => printContext(c, true)).join("\n")
164
+ : pc.gray("(none)"),
165
+ ]);
166
+
167
+ process.stdout.write(table.toString() + "\n\n");
168
+ foundContexts = [];
169
+ }
170
+
171
+ currentContext = currentContext.owner;
172
+ }
173
+ });
174
+ }
175
+
176
+ export function debugContext() {
177
+ untrack(() => {
178
+ let currentContext = getContext();
179
+ while (currentContext !== null) {
180
+ // eslint-disable-next-line no-console
181
+ console.log(printContext(currentContext));
182
+ currentContext = currentContext.owner;
183
+ }
184
+ });
185
+ }
186
+
187
+ export function debugTree() {
188
+ // eslint-disable-next-line no-console
189
+ console.log("tree");
190
+ }
191
+
192
+ export function debugWatch() {
193
+ // eslint-disable-next-line no-console
194
+ console.log("watch");
195
+ }
196
+
197
+ export function debugRender() {
198
+ // eslint-disable-next-line no-console
199
+ console.log("render");
200
+ }
@@ -0,0 +1,56 @@
1
+ import { afterEach, beforeEach, expect, it } from "vitest";
2
+ import WebSocket from "ws";
3
+ import {
4
+ createMessageCollector,
5
+ type DevtoolsMessage,
6
+ } from "../../testing/devtools-utils.js";
7
+ import { Output } from "../components/Output.jsx";
8
+ import {
9
+ enableDevtools,
10
+ resetDevtoolsServerForTests,
11
+ } from "../devtools/devtools-server.js";
12
+ import { DiagnosticsCollector } from "../diagnostics.js";
13
+ import { renderAsync } from "../render.js";
14
+
15
+ let socket: WebSocket | undefined;
16
+
17
+ beforeEach(async () => {
18
+ const server = await enableDevtools({ port: 0 });
19
+ socket = new WebSocket(`ws://127.0.0.1:${server.port}`);
20
+
21
+ await new Promise<void>((resolve, reject) => {
22
+ socket?.once("open", resolve);
23
+ socket?.once("error", reject);
24
+ });
25
+ });
26
+
27
+ afterEach(async () => {
28
+ if (socket) {
29
+ socket.close();
30
+ socket = undefined;
31
+ }
32
+
33
+ await resetDevtoolsServerForTests();
34
+ });
35
+
36
+ it("emits diagnostics:report messages", async () => {
37
+ const collector = await createMessageCollector(socket!);
38
+ const diagnostics = new DiagnosticsCollector();
39
+
40
+ diagnostics.emit({ message: "Test diagnostic", severity: "warning" });
41
+
42
+ await renderAsync(<Output>{"ok"}</Output>);
43
+
44
+ const messages = await collector.waitForRender();
45
+ const diagnosticsMessages = messages.filter(
46
+ (m: DevtoolsMessage) => m.type === "diagnostics:report",
47
+ );
48
+
49
+ collector.stop();
50
+
51
+ expect(diagnosticsMessages[0]).toMatchObject({
52
+ type: "diagnostics:report",
53
+ message: "Test diagnostic",
54
+ severity: "warning",
55
+ });
56
+ });
@@ -0,0 +1,301 @@
1
+ import { shallowReactive } from "@vue/reactivity";
2
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
3
+ import WebSocket from "ws";
4
+ import {
5
+ createMessageCollector,
6
+ filterEffectsMessages,
7
+ } from "../../testing/devtools-utils.js";
8
+ import { Output } from "../components/Output.jsx";
9
+ import {
10
+ enableDevtools,
11
+ resetDevtoolsServerForTests,
12
+ } from "../devtools/devtools-server.js";
13
+ import { effect, memo, ref } from "../reactivity.js";
14
+ import { renderAsync } from "../render.js";
15
+ import { flushJobsAsync } from "../scheduler.js";
16
+ import { debug } from "./index.js";
17
+
18
+ let socket: WebSocket | undefined;
19
+
20
+ beforeEach(async () => {
21
+ debug.effect.reset();
22
+
23
+ const server = await enableDevtools({ port: 0 });
24
+ socket = new WebSocket(`ws://127.0.0.1:${server.port}`);
25
+ await new Promise<void>((resolve, reject) => {
26
+ socket?.once("open", resolve);
27
+ socket?.once("error", reject);
28
+ });
29
+ });
30
+
31
+ afterEach(async () => {
32
+ if (socket) {
33
+ socket.close();
34
+ socket = undefined;
35
+ }
36
+
37
+ await resetDevtoolsServerForTests();
38
+ debug.effect.reset();
39
+ });
40
+
41
+ it("emits effect, ref, and track messages", async () => {
42
+ const collector = await createMessageCollector(socket!);
43
+ const r1 = ref(0);
44
+ const r2 = ref(1);
45
+
46
+ effect(() => {
47
+ r1.value = r2.value + 1;
48
+ });
49
+
50
+ await renderAsync(<Output>{"ok"}</Output>);
51
+
52
+ const messages = await collector.waitForRender();
53
+ const effectsMessages = filterEffectsMessages(messages);
54
+ collector.stop();
55
+
56
+ expect(effectsMessages[0]).toMatchObject({
57
+ type: "ref:added",
58
+ id: expect.any(Number),
59
+ kind: "ref",
60
+ });
61
+ expect(effectsMessages[1]).toMatchObject({
62
+ type: "ref:added",
63
+ id: expect.any(Number),
64
+ kind: "ref",
65
+ });
66
+ expect(effectsMessages[2]).toMatchObject({
67
+ type: "effect:added",
68
+ id: expect.any(Number),
69
+ });
70
+ expect(effectsMessages[3]).toMatchObject({
71
+ type: "edge:track",
72
+ effect_id: expect.any(Number),
73
+ ref_id: expect.any(Number),
74
+ });
75
+ });
76
+
77
+ describe("unified trigger edges", () => {
78
+ it("ref trigger records consumer and producer (caused_by)", async () => {
79
+ const collector = await createMessageCollector(socket!);
80
+ const r = ref(0);
81
+
82
+ // Producer effect writes to the ref
83
+ const producerName = "test-producer";
84
+ effect(
85
+ () => {
86
+ r.value = 42;
87
+ },
88
+ undefined,
89
+ { debug: { name: producerName } },
90
+ );
91
+
92
+ // Consumer effect reads the ref
93
+ const consumerName = "test-consumer";
94
+ effect(
95
+ () => {
96
+ void r.value;
97
+ },
98
+ undefined,
99
+ { debug: { name: consumerName } },
100
+ );
101
+
102
+ await renderAsync(<Output>{"ok"}</Output>);
103
+ const renderMessages = await collector.waitForRender();
104
+
105
+ // Trigger the consumer by changing the ref
106
+ r.value = 99;
107
+ await flushJobsAsync();
108
+ const flushMessages = await collector.waitForFlush();
109
+ collector.stop();
110
+
111
+ // Find the trigger edge on the consumer
112
+ const triggerEdges = flushMessages.filter(
113
+ (m: any) => m.type === "edge:trigger" && m.ref_id !== undefined,
114
+ );
115
+ expect(triggerEdges.length).toBeGreaterThan(0);
116
+
117
+ // The trigger edge should be on the consumer effect
118
+ const effectsMessages = filterEffectsMessages(renderMessages);
119
+ const consumerEffect = effectsMessages.find(
120
+ (m: any) => m.type === "effect:added" && m.name === consumerName,
121
+ );
122
+ expect(consumerEffect).toBeDefined();
123
+
124
+ const consumerTrigger = triggerEdges.find(
125
+ (m: any) => m.effect_id === consumerEffect!.id,
126
+ );
127
+ expect(consumerTrigger).toBeDefined();
128
+ // caused_by is null since the mutation happens outside any effect (top-level r.value = 99)
129
+ expect(consumerTrigger!.caused_by).toBeNull();
130
+ });
131
+
132
+ it("reactive object trigger records consumer and producer", async () => {
133
+ const collector = await createMessageCollector(socket!);
134
+ const map = shallowReactive(new Map<string, number>());
135
+
136
+ // Consumer: memo reads the map
137
+ const sum = memo(() => {
138
+ let total = 0;
139
+ for (const v of map.values()) total += v;
140
+ return total;
141
+ });
142
+
143
+ // Producer: effect mutates the map
144
+ effect(
145
+ () => {
146
+ const _s = sum();
147
+ map.set("key", 42);
148
+ },
149
+ undefined,
150
+ { debug: { name: "producer-effect" } },
151
+ );
152
+
153
+ await renderAsync(<Output>{"ok"}</Output>);
154
+
155
+ const messages = await collector.waitForRender();
156
+ const effectsMessages = filterEffectsMessages(messages);
157
+ collector.stop();
158
+
159
+ // Find trigger edges for the reactive map
160
+ const triggerEdges = effectsMessages.filter(
161
+ (m: any) => m.type === "edge:trigger" && m.target_id !== undefined,
162
+ );
163
+ expect(triggerEdges.length).toBeGreaterThan(0);
164
+
165
+ // The trigger should have caused_by (the producer effect)
166
+ const producerEffect = effectsMessages.find(
167
+ (m: any) => m.type === "effect:added" && m.name === "producer-effect",
168
+ );
169
+ expect(producerEffect).toBeDefined();
170
+
171
+ const withCause = triggerEdges.filter(
172
+ (m: any) => m.caused_by === producerEffect!.id,
173
+ );
174
+ expect(withCause.length).toBeGreaterThan(0);
175
+ expect(withCause[0]).toMatchObject({
176
+ type: "edge:trigger",
177
+ effect_id: expect.any(Number),
178
+ caused_by: producerEffect!.id,
179
+ target_id: expect.any(Number),
180
+ });
181
+ });
182
+
183
+ it("trigger outside any effect has no caused_by", async () => {
184
+ const collector = await createMessageCollector(socket!);
185
+ const r = ref(0);
186
+
187
+ // Consumer effect
188
+ effect(() => {
189
+ void r.value;
190
+ });
191
+
192
+ await renderAsync(<Output>{"ok"}</Output>);
193
+ await collector.waitForRender();
194
+
195
+ // Trigger from top-level (outside any effect)
196
+ r.value = 1;
197
+ await flushJobsAsync();
198
+ const flushMessages = await collector.waitForFlush();
199
+ collector.stop();
200
+
201
+ const triggerEdges = flushMessages.filter(
202
+ (m: any) => m.type === "edge:trigger",
203
+ );
204
+ expect(triggerEdges.length).toBeGreaterThan(0);
205
+ // caused_by should be null (no producer effect)
206
+ expect(triggerEdges[0].caused_by).toBeNull();
207
+ });
208
+
209
+ it("multiple consumers of same ref get separate trigger edges", async () => {
210
+ const collector = await createMessageCollector(socket!);
211
+ const r = ref(0);
212
+
213
+ // Two consumer effects
214
+ effect(
215
+ () => {
216
+ void r.value;
217
+ },
218
+ undefined,
219
+ { debug: { name: "consumer-a" } },
220
+ );
221
+ effect(
222
+ () => {
223
+ void r.value;
224
+ },
225
+ undefined,
226
+ { debug: { name: "consumer-b" } },
227
+ );
228
+
229
+ await renderAsync(<Output>{"ok"}</Output>);
230
+ const renderMessages = await collector.waitForRender();
231
+
232
+ // Find the effect IDs
233
+ const effectsMessages = filterEffectsMessages(renderMessages);
234
+ const consumerA = effectsMessages.find(
235
+ (m: any) => m.type === "effect:added" && m.name === "consumer-a",
236
+ );
237
+ const consumerB = effectsMessages.find(
238
+ (m: any) => m.type === "effect:added" && m.name === "consumer-b",
239
+ );
240
+ expect(consumerA).toBeDefined();
241
+ expect(consumerB).toBeDefined();
242
+
243
+ // Trigger both by changing the ref
244
+ r.value = 1;
245
+ await flushJobsAsync();
246
+ const flushMessages = await collector.waitForFlush();
247
+ collector.stop();
248
+
249
+ const triggerEdges = flushMessages.filter(
250
+ (m: any) => m.type === "edge:trigger",
251
+ );
252
+
253
+ // Each consumer gets its own trigger edge
254
+ const aTrigger = triggerEdges.find(
255
+ (m: any) => m.effect_id === consumerA!.id,
256
+ );
257
+ const bTrigger = triggerEdges.find(
258
+ (m: any) => m.effect_id === consumerB!.id,
259
+ );
260
+ expect(aTrigger).toBeDefined();
261
+ expect(bTrigger).toBeDefined();
262
+ // Both reference the same ref
263
+ expect(aTrigger!.ref_id).toBe(bTrigger!.ref_id);
264
+ });
265
+
266
+ it("no triggered-by or duplicate trigger edge types exist", async () => {
267
+ const collector = await createMessageCollector(socket!);
268
+ const r = ref(0);
269
+ const map = shallowReactive(new Map<string, number>());
270
+
271
+ effect(() => {
272
+ void r.value;
273
+ for (const _v of map.values()) {
274
+ /* track */
275
+ }
276
+ });
277
+
278
+ effect(() => {
279
+ r.value = 1;
280
+ map.set("x", 1);
281
+ });
282
+
283
+ await renderAsync(<Output>{"ok"}</Output>);
284
+ const messages = await collector.waitForRender();
285
+ collector.stop();
286
+
287
+ // No edge:triggered-by messages should exist
288
+ const triggeredBy = messages.filter(
289
+ (m: any) => m.type === "edge:triggered-by",
290
+ );
291
+ expect(triggeredBy.length).toBe(0);
292
+
293
+ // All edge types should be edge:track or edge:trigger only
294
+ const edges = messages.filter(
295
+ (m: any) => typeof m.type === "string" && m.type.startsWith("edge:"),
296
+ );
297
+ for (const edge of edges) {
298
+ expect(["edge:track", "edge:trigger"]).toContain(edge.type);
299
+ }
300
+ });
301
+ });