@alloy-js/core 0.23.0-dev.10 → 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.
- package/dist/devtools/index.html +29 -17
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +5 -0
- package/dist/src/binder.js.map +1 -1
- package/dist/src/components/For.d.ts.map +1 -1
- package/dist/src/components/For.js +1 -1
- package/dist/src/components/For.js.map +1 -1
- package/dist/src/components/List.d.ts.map +1 -1
- package/dist/src/components/List.js +1 -1
- package/dist/src/components/List.js.map +1 -1
- package/dist/src/components/Switch.d.ts.map +1 -1
- package/dist/src/components/Switch.js +1 -1
- package/dist/src/components/Switch.js.map +1 -1
- package/dist/src/debug/diagnostics.test.js +3 -2
- package/dist/src/debug/diagnostics.test.js.map +1 -1
- package/dist/src/debug/effects.d.ts +12 -4
- package/dist/src/debug/effects.d.ts.map +1 -1
- package/dist/src/debug/effects.js +182 -52
- package/dist/src/debug/effects.js.map +1 -1
- package/dist/src/debug/effects.test.js +213 -41
- package/dist/src/debug/effects.test.js.map +1 -1
- package/dist/src/debug/files.d.ts.map +1 -1
- package/dist/src/debug/files.js +7 -18
- package/dist/src/debug/files.js.map +1 -1
- package/dist/src/debug/files.test.js +13 -36
- package/dist/src/debug/files.test.js.map +1 -1
- package/dist/src/debug/index.d.ts +4 -2
- package/dist/src/debug/index.d.ts.map +1 -1
- package/dist/src/debug/index.js +4 -2
- package/dist/src/debug/index.js.map +1 -1
- package/dist/src/debug/message-format.test.d.ts +2 -0
- package/dist/src/debug/message-format.test.d.ts.map +1 -0
- package/dist/src/debug/message-format.test.js +700 -0
- package/dist/src/debug/message-format.test.js.map +1 -0
- package/dist/src/debug/render-tree-orphans.test.d.ts +2 -0
- package/dist/src/debug/render-tree-orphans.test.d.ts.map +1 -0
- package/dist/src/debug/render-tree-orphans.test.js +297 -0
- package/dist/src/debug/render-tree-orphans.test.js.map +1 -0
- package/dist/src/debug/render.d.ts.map +1 -1
- package/dist/src/debug/render.js +83 -130
- package/dist/src/debug/render.js.map +1 -1
- package/dist/src/debug/render.test.js +91 -128
- package/dist/src/debug/render.test.js.map +1 -1
- package/dist/src/debug/symbols.d.ts +6 -5
- package/dist/src/debug/symbols.d.ts.map +1 -1
- package/dist/src/debug/symbols.js +46 -23
- package/dist/src/debug/symbols.js.map +1 -1
- package/dist/src/debug/symbols.test.js +15 -26
- package/dist/src/debug/symbols.test.js.map +1 -1
- package/dist/src/debug/trace-writer.d.ts +55 -0
- package/dist/src/debug/trace-writer.d.ts.map +1 -0
- package/dist/src/debug/trace-writer.js +658 -0
- package/dist/src/debug/trace-writer.js.map +1 -0
- package/dist/src/debug/trace.d.ts +10 -10
- package/dist/src/debug/trace.d.ts.map +1 -1
- package/dist/src/debug/trace.js +23 -20
- package/dist/src/debug/trace.js.map +1 -1
- package/dist/src/devtools/devtools-protocol.d.ts +318 -161
- package/dist/src/devtools/devtools-protocol.d.ts.map +1 -1
- package/dist/src/devtools/devtools-server.browser.d.ts +0 -5
- package/dist/src/devtools/devtools-server.browser.d.ts.map +1 -1
- package/dist/src/devtools/devtools-server.browser.js +0 -3
- package/dist/src/devtools/devtools-server.browser.js.map +1 -1
- package/dist/src/devtools/devtools-server.d.ts +0 -6
- package/dist/src/devtools/devtools-server.d.ts.map +1 -1
- package/dist/src/devtools/devtools-server.js +212 -24
- package/dist/src/devtools/devtools-server.js.map +1 -1
- package/dist/src/devtools/devtools-transport.d.ts +2 -2
- package/dist/src/devtools/devtools-transport.d.ts.map +1 -1
- package/dist/src/devtools/devtools-transport.js +2 -2
- package/dist/src/devtools/devtools-transport.js.map +1 -1
- package/dist/src/devtools-entry.browser.d.ts +1 -1
- package/dist/src/devtools-entry.browser.d.ts.map +1 -1
- package/dist/src/devtools-entry.browser.js.map +1 -1
- package/dist/src/devtools-entry.d.ts +1 -1
- package/dist/src/devtools-entry.d.ts.map +1 -1
- package/dist/src/devtools-entry.js.map +1 -1
- package/dist/src/diagnostics.d.ts.map +1 -1
- package/dist/src/diagnostics.js +5 -5
- package/dist/src/diagnostics.js.map +1 -1
- package/dist/src/reactivity.d.ts +13 -2
- package/dist/src/reactivity.d.ts.map +1 -1
- package/dist/src/reactivity.js +96 -13
- package/dist/src/reactivity.js.map +1 -1
- package/dist/src/render.d.ts.map +1 -1
- package/dist/src/render.js +84 -30
- package/dist/src/render.js.map +1 -1
- package/dist/src/scheduler.d.ts +5 -0
- package/dist/src/scheduler.d.ts.map +1 -1
- package/dist/src/scheduler.js +94 -23
- package/dist/src/scheduler.js.map +1 -1
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +11 -5
- package/dist/src/utils.js.map +1 -1
- package/dist/testing/devtools-utils.d.ts +12 -3
- package/dist/testing/devtools-utils.d.ts.map +1 -1
- package/dist/testing/devtools-utils.js +26 -4
- package/dist/testing/devtools-utils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/binder.ts +47 -38
- package/src/components/For.tsx +14 -10
- package/src/components/List.tsx +7 -4
- package/src/components/Switch.tsx +11 -7
- package/src/debug/diagnostics.test.tsx +3 -2
- package/src/debug/effects.test.tsx +248 -36
- package/src/debug/effects.ts +276 -62
- package/src/debug/files.test.tsx +15 -35
- package/src/debug/files.ts +11 -11
- package/src/debug/index.ts +4 -0
- package/src/debug/message-format.test.tsx +759 -0
- package/src/debug/render-tree-orphans.test.tsx +344 -0
- package/src/debug/render.test.tsx +96 -118
- package/src/debug/render.ts +183 -124
- package/src/debug/symbols.test.tsx +19 -20
- package/src/debug/symbols.ts +106 -23
- package/src/debug/trace-writer.ts +969 -0
- package/src/debug/trace.ts +25 -28
- package/src/devtools/devtools-protocol.ts +361 -176
- package/src/devtools/devtools-server.browser.ts +0 -9
- package/src/devtools/devtools-server.ts +210 -32
- package/src/devtools/devtools-transport.ts +4 -4
- package/src/devtools-entry.browser.ts +11 -15
- package/src/devtools-entry.ts +9 -15
- package/src/diagnostics.ts +14 -5
- package/src/reactivity.ts +113 -17
- package/src/render.ts +104 -30
- package/src/scheduler.ts +145 -26
- package/src/utils.tsx +7 -4
- package/temp/api.json +142 -20
- package/testing/devtools-utils.ts +46 -4
package/src/debug/render.ts
CHANGED
|
@@ -13,11 +13,27 @@ import {
|
|
|
13
13
|
type PrintHook,
|
|
14
14
|
type RenderedTextTree,
|
|
15
15
|
} from "../print-hook.js";
|
|
16
|
-
import { untrack } from "../reactivity.js";
|
|
16
|
+
import { getContext, untrack } from "../reactivity.js";
|
|
17
17
|
import type { ComponentCreator } from "../runtime/component.js";
|
|
18
18
|
import { flushJobsAsync } from "../scheduler.js";
|
|
19
19
|
import { sanitizeRecord } from "./serialize.js";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
deleteDirectory,
|
|
22
|
+
deleteOutputFile,
|
|
23
|
+
insertDirectory,
|
|
24
|
+
insertOutputFile,
|
|
25
|
+
insertRenderError,
|
|
26
|
+
insertRenderNode,
|
|
27
|
+
isTraceEnabled,
|
|
28
|
+
notifyFlushComplete,
|
|
29
|
+
notifyRenderComplete,
|
|
30
|
+
notifyRenderReset,
|
|
31
|
+
deleteRenderNode as traceDeleteRenderNode,
|
|
32
|
+
updateRenderNodeProps as traceUpdateRenderNodeProps,
|
|
33
|
+
updateEffectComponentByContext,
|
|
34
|
+
updateRenderNodeContext,
|
|
35
|
+
} from "./trace-writer.js";
|
|
36
|
+
import { isDebugEnabled, logDevtoolsMessage } from "./trace.js";
|
|
21
37
|
|
|
22
38
|
/** The kind discriminant for render tree nodes. */
|
|
23
39
|
export type RenderTreeNodeKind = RenderTreeNode["kind"];
|
|
@@ -63,6 +79,7 @@ type TrackedNode = RenderedTextTree | PrintHook;
|
|
|
63
79
|
let nodeIds = new WeakMap<TrackedNode, number>();
|
|
64
80
|
let idToNode = new Map<number, TrackedNode>();
|
|
65
81
|
let entryIds = new WeakMap<RenderedTextTree, number[]>();
|
|
82
|
+
let nodeKinds = new WeakMap<TrackedNode, { kind: string; name?: string }>();
|
|
66
83
|
let fileNodes = new Map<number, { path: string; filetype: string }>();
|
|
67
84
|
let directoryNodes = new Map<number, { path: string }>();
|
|
68
85
|
let nodeProps = new Map<number, string | undefined>();
|
|
@@ -94,11 +111,7 @@ function serializeRenderTreeProps(input: Record<string, unknown> | undefined) {
|
|
|
94
111
|
|
|
95
112
|
function emitNodeRemoved(parentId: number | null, id: number) {
|
|
96
113
|
clearRenderTreeChildrenForId(id);
|
|
97
|
-
|
|
98
|
-
type: "render:nodeRemoved",
|
|
99
|
-
parentId,
|
|
100
|
-
id,
|
|
101
|
-
});
|
|
114
|
+
traceDeleteRenderNode(id);
|
|
102
115
|
|
|
103
116
|
rerenderActions.delete(id);
|
|
104
117
|
nodeProps.delete(id);
|
|
@@ -106,19 +119,13 @@ function emitNodeRemoved(parentId: number | null, id: number) {
|
|
|
106
119
|
|
|
107
120
|
const fileInfo = fileNodes.get(id);
|
|
108
121
|
if (fileInfo) {
|
|
109
|
-
|
|
110
|
-
type: "files:fileRemoved",
|
|
111
|
-
path: fileInfo.path,
|
|
112
|
-
});
|
|
122
|
+
deleteOutputFile(fileInfo.path);
|
|
113
123
|
fileNodes.delete(id);
|
|
114
124
|
}
|
|
115
125
|
|
|
116
126
|
const dirInfo = directoryNodes.get(id);
|
|
117
127
|
if (dirInfo) {
|
|
118
|
-
|
|
119
|
-
type: "files:directoryRemoved",
|
|
120
|
-
path: dirInfo.path,
|
|
121
|
-
});
|
|
128
|
+
deleteDirectory(dirInfo.path);
|
|
122
129
|
directoryNodes.delete(id);
|
|
123
130
|
}
|
|
124
131
|
}
|
|
@@ -134,7 +141,13 @@ function getEntryList(parent: RenderedTextTree) {
|
|
|
134
141
|
|
|
135
142
|
function getOrCreateNodeId(node: TrackedNode) {
|
|
136
143
|
const existing = nodeIds.get(node);
|
|
137
|
-
if (existing)
|
|
144
|
+
if (existing) {
|
|
145
|
+
// Restore reverse mapping — emitNodeRemoved deletes idToNode but nodeIds
|
|
146
|
+
// (WeakMap) survives. Without this, clearRenderTreeChildrenForId can't
|
|
147
|
+
// find the node on the next cleanup, leaving orphaned children in the DB.
|
|
148
|
+
idToNode.set(existing, node);
|
|
149
|
+
return existing;
|
|
150
|
+
}
|
|
138
151
|
const id = nextId++;
|
|
139
152
|
nodeIds.set(node, id);
|
|
140
153
|
idToNode.set(id, node);
|
|
@@ -142,7 +155,7 @@ function getOrCreateNodeId(node: TrackedNode) {
|
|
|
142
155
|
}
|
|
143
156
|
|
|
144
157
|
export function getRenderNodeId(node: RenderedTextTree | PrintHook) {
|
|
145
|
-
if (!
|
|
158
|
+
if (!isDebugEnabled()) return undefined;
|
|
146
159
|
return getOrCreateNodeId(node);
|
|
147
160
|
}
|
|
148
161
|
|
|
@@ -152,33 +165,38 @@ function setEntryId(parent: RenderedTextTree, index: number, id: number) {
|
|
|
152
165
|
}
|
|
153
166
|
|
|
154
167
|
export function initialize(root: RenderedTextTree) {
|
|
155
|
-
if (!
|
|
168
|
+
if (!isDebugEnabled()) return;
|
|
156
169
|
ensureDevtoolsHandler();
|
|
157
170
|
nodeIds = new WeakMap();
|
|
158
171
|
idToNode = new Map();
|
|
159
172
|
entryIds = new WeakMap();
|
|
173
|
+
nodeKinds = new WeakMap();
|
|
160
174
|
fileNodes = new Map();
|
|
161
175
|
directoryNodes = new Map();
|
|
162
176
|
nodeProps = new Map();
|
|
163
177
|
rerenderActions = new Map();
|
|
164
178
|
nextId = 1;
|
|
165
|
-
|
|
179
|
+
notifyRenderReset();
|
|
166
180
|
const rootId = getOrCreateNodeId(root);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
181
|
+
insertRenderNode(
|
|
182
|
+
rootId,
|
|
183
|
+
null,
|
|
184
|
+
"root",
|
|
185
|
+
undefined,
|
|
186
|
+
undefined,
|
|
187
|
+
undefined,
|
|
188
|
+
undefined,
|
|
189
|
+
undefined,
|
|
190
|
+
null,
|
|
191
|
+
undefined,
|
|
192
|
+
);
|
|
175
193
|
}
|
|
176
194
|
|
|
177
195
|
export function registerRenderNodeActions(
|
|
178
196
|
node: RenderedTextTree | PrintHook,
|
|
179
197
|
actions: RenderNodeActions,
|
|
180
198
|
) {
|
|
181
|
-
if (!
|
|
199
|
+
if (!isDebugEnabled()) return;
|
|
182
200
|
const id = getOrCreateNodeId(node);
|
|
183
201
|
rerenderActions.set(id, actions);
|
|
184
202
|
}
|
|
@@ -186,7 +204,7 @@ export function registerRenderNodeActions(
|
|
|
186
204
|
export function unregisterRenderNodeActions(
|
|
187
205
|
node: RenderedTextTree | PrintHook,
|
|
188
206
|
) {
|
|
189
|
-
if (!
|
|
207
|
+
if (!isDebugEnabled()) return;
|
|
190
208
|
const id = nodeIds.get(node);
|
|
191
209
|
if (id !== undefined) {
|
|
192
210
|
rerenderActions.delete(id);
|
|
@@ -223,18 +241,21 @@ export function recordTextNode(
|
|
|
223
241
|
index: number,
|
|
224
242
|
value: string,
|
|
225
243
|
) {
|
|
226
|
-
if (!
|
|
244
|
+
if (!isDebugEnabled()) return;
|
|
227
245
|
const id = nextId++;
|
|
228
246
|
setEntryId(parent, index, id);
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
247
|
+
insertRenderNode(
|
|
248
|
+
id,
|
|
249
|
+
getOrCreateNodeId(parent),
|
|
250
|
+
"text",
|
|
251
|
+
undefined,
|
|
252
|
+
undefined,
|
|
253
|
+
undefined,
|
|
254
|
+
undefined,
|
|
255
|
+
undefined,
|
|
256
|
+
null,
|
|
257
|
+
value,
|
|
258
|
+
);
|
|
238
259
|
}
|
|
239
260
|
|
|
240
261
|
function recordNodeAdded(
|
|
@@ -243,20 +264,26 @@ function recordNodeAdded(
|
|
|
243
264
|
node: RenderedTextTree | PrintHook,
|
|
244
265
|
info: RenderTreeNodeInfo,
|
|
245
266
|
) {
|
|
246
|
-
if (!
|
|
267
|
+
if (!isDebugEnabled()) return;
|
|
247
268
|
const id = getOrCreateNodeId(node);
|
|
248
269
|
if (info.propsSerialized !== undefined) {
|
|
249
270
|
nodeProps.set(id, info.propsSerialized);
|
|
250
271
|
}
|
|
272
|
+
// Remember the kind so cached re-adds preserve it
|
|
273
|
+
nodeKinds.set(node, { kind: info.kind, name: info.name });
|
|
251
274
|
setEntryId(parent, index, id);
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
275
|
+
insertRenderNode(
|
|
276
|
+
id,
|
|
277
|
+
getOrCreateNodeId(parent),
|
|
278
|
+
info.kind,
|
|
279
|
+
info.name,
|
|
280
|
+
info.propsSerialized,
|
|
281
|
+
info.source?.fileName,
|
|
282
|
+
info.source?.lineNumber,
|
|
283
|
+
info.source?.columnNumber,
|
|
284
|
+
null,
|
|
285
|
+
undefined,
|
|
286
|
+
);
|
|
260
287
|
}
|
|
261
288
|
|
|
262
289
|
function recordSubtreeAdded(
|
|
@@ -264,25 +291,32 @@ function recordSubtreeAdded(
|
|
|
264
291
|
subtree: RenderedTextTree,
|
|
265
292
|
info: RenderTreeNodeInfo = { kind: "fragment" },
|
|
266
293
|
) {
|
|
267
|
-
if (!
|
|
294
|
+
if (!isDebugEnabled()) return;
|
|
268
295
|
const parentId = getOrCreateNodeId(parentNode);
|
|
269
296
|
// Check if this node was previously rendered (cached) by seeing if it already has an ID
|
|
270
297
|
const existingId = nodeIds.get(subtree);
|
|
271
298
|
const isCached = existingId !== undefined;
|
|
272
299
|
const id = isCached ? existingId : getOrCreateNodeId(subtree);
|
|
300
|
+
// Remember the kind so cached re-adds preserve it
|
|
301
|
+
nodeKinds.set(subtree, { kind: info.kind, name: info.name });
|
|
273
302
|
// Track in entryIds so clearRenderTreeChildren can find and remove it
|
|
274
303
|
if (Array.isArray(parentNode)) {
|
|
275
304
|
const list = getEntryList(parentNode);
|
|
276
305
|
list.push(id);
|
|
277
306
|
}
|
|
278
|
-
|
|
279
|
-
|
|
307
|
+
insertRenderNode(
|
|
308
|
+
id,
|
|
280
309
|
parentId,
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
310
|
+
info.kind,
|
|
311
|
+
info.name,
|
|
312
|
+
info.propsSerialized,
|
|
313
|
+
info.source?.fileName,
|
|
314
|
+
info.source?.lineNumber,
|
|
315
|
+
info.source?.columnNumber,
|
|
316
|
+
null,
|
|
317
|
+
undefined,
|
|
318
|
+
);
|
|
319
|
+
|
|
286
320
|
// For cached nodes, we need to recursively re-add all their children since
|
|
287
321
|
// clearRenderTreeChildren removed them when the parent re-rendered
|
|
288
322
|
if (isCached) {
|
|
@@ -297,9 +331,15 @@ function recordSubtreeAdded(
|
|
|
297
331
|
* to be explicitly re-added.
|
|
298
332
|
*/
|
|
299
333
|
function recordCachedSubtreeChildrenRecursively(node: RenderedTextTree) {
|
|
300
|
-
if (!
|
|
334
|
+
if (!isDebugEnabled()) return;
|
|
301
335
|
const parentId = getOrCreateNodeId(node);
|
|
302
336
|
|
|
337
|
+
// Clear any previously-recorded children from the DB before re-adding.
|
|
338
|
+
// The in-memory tree may have changed since the last cached re-add
|
|
339
|
+
// (e.g., a memo inside the cached subtree re-ran), so old DB children
|
|
340
|
+
// that are no longer in the tree would become orphans.
|
|
341
|
+
clearRenderTreeChildren(node);
|
|
342
|
+
|
|
303
343
|
// Rebuild the entryIds for this node
|
|
304
344
|
const list = getEntryList(node);
|
|
305
345
|
list.length = 0;
|
|
@@ -312,55 +352,70 @@ function recordCachedSubtreeChildrenRecursively(node: RenderedTextTree) {
|
|
|
312
352
|
const id = nextId++;
|
|
313
353
|
list.push(id);
|
|
314
354
|
idToNode.set(id, child as unknown as RenderedTextTree);
|
|
315
|
-
|
|
316
|
-
|
|
355
|
+
insertRenderNode(
|
|
356
|
+
id,
|
|
317
357
|
parentId,
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
358
|
+
"text",
|
|
359
|
+
undefined,
|
|
360
|
+
undefined,
|
|
361
|
+
undefined,
|
|
362
|
+
undefined,
|
|
363
|
+
undefined,
|
|
364
|
+
null,
|
|
365
|
+
child,
|
|
366
|
+
);
|
|
324
367
|
}
|
|
325
368
|
} else if (Array.isArray(child)) {
|
|
326
|
-
// Nested RenderedTextTree - record and recurse
|
|
369
|
+
// Nested RenderedTextTree - record and recurse, preserving original kind
|
|
327
370
|
const id = getOrCreateNodeId(child);
|
|
328
371
|
list.push(id);
|
|
329
|
-
|
|
330
|
-
|
|
372
|
+
const savedKind = nodeKinds.get(child);
|
|
373
|
+
insertRenderNode(
|
|
374
|
+
id,
|
|
331
375
|
parentId,
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
376
|
+
savedKind?.kind ?? "fragment",
|
|
377
|
+
savedKind?.name,
|
|
378
|
+
undefined,
|
|
379
|
+
undefined,
|
|
380
|
+
undefined,
|
|
381
|
+
undefined,
|
|
382
|
+
null,
|
|
383
|
+
undefined,
|
|
384
|
+
);
|
|
337
385
|
recordCachedSubtreeChildrenRecursively(child);
|
|
338
386
|
} else if (isPrintHook(child)) {
|
|
339
387
|
// PrintHook - record and recurse into subtree
|
|
340
388
|
const id = getOrCreateNodeId(child);
|
|
341
389
|
list.push(id);
|
|
342
|
-
|
|
343
|
-
|
|
390
|
+
insertRenderNode(
|
|
391
|
+
id,
|
|
344
392
|
parentId,
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
393
|
+
"printHook",
|
|
394
|
+
(child as { name?: string }).name ?? "hook",
|
|
395
|
+
undefined,
|
|
396
|
+
undefined,
|
|
397
|
+
undefined,
|
|
398
|
+
undefined,
|
|
399
|
+
null,
|
|
400
|
+
undefined,
|
|
401
|
+
);
|
|
351
402
|
if (child.subtree) {
|
|
352
403
|
const subtreeId = getOrCreateNodeId(child.subtree);
|
|
353
404
|
const hookList = getEntryList(child as unknown as RenderedTextTree);
|
|
354
405
|
hookList.length = 0;
|
|
355
406
|
hookList.push(subtreeId);
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
407
|
+
insertRenderNode(
|
|
408
|
+
subtreeId,
|
|
409
|
+
id,
|
|
410
|
+
"fragment",
|
|
411
|
+
undefined,
|
|
412
|
+
undefined,
|
|
413
|
+
undefined,
|
|
414
|
+
undefined,
|
|
415
|
+
undefined,
|
|
416
|
+
null,
|
|
417
|
+
undefined,
|
|
418
|
+
);
|
|
364
419
|
recordCachedSubtreeChildrenRecursively(child.subtree);
|
|
365
420
|
}
|
|
366
421
|
}
|
|
@@ -371,20 +426,16 @@ function recordNodePropsUpdated(
|
|
|
371
426
|
node: RenderedTextTree | PrintHook,
|
|
372
427
|
propsSerialized: string | undefined,
|
|
373
428
|
) {
|
|
374
|
-
if (!
|
|
429
|
+
if (!isDebugEnabled()) return;
|
|
375
430
|
const id = getOrCreateNodeId(node);
|
|
376
431
|
const previous = nodeProps.get(id);
|
|
377
432
|
if (previous === propsSerialized) return;
|
|
378
433
|
nodeProps.set(id, propsSerialized);
|
|
379
|
-
|
|
380
|
-
type: "render:nodeUpdated",
|
|
381
|
-
id,
|
|
382
|
-
propsSerialized,
|
|
383
|
-
});
|
|
434
|
+
traceUpdateRenderNodeProps(id, propsSerialized);
|
|
384
435
|
}
|
|
385
436
|
|
|
386
437
|
function clearRenderTreeChildren(parent: RenderedTextTree) {
|
|
387
|
-
if (!
|
|
438
|
+
if (!isDebugEnabled()) return;
|
|
388
439
|
const list = entryIds.get(parent);
|
|
389
440
|
if (!list || list.length === 0) return;
|
|
390
441
|
const parentId = getOrCreateNodeId(parent);
|
|
@@ -403,9 +454,15 @@ function clearRenderTreeChildrenForId(id: number) {
|
|
|
403
454
|
clearRenderTreeChildren(node);
|
|
404
455
|
return;
|
|
405
456
|
}
|
|
457
|
+
// For PrintHook nodes: clear the subtree's children, then remove
|
|
458
|
+
// the subtree node itself (which is a child of this hook).
|
|
406
459
|
const subtree = (node as { subtree?: RenderedTextTree }).subtree;
|
|
407
460
|
if (subtree && Array.isArray(subtree)) {
|
|
408
461
|
clearRenderTreeChildren(subtree);
|
|
462
|
+
const subtreeId = nodeIds.get(subtree);
|
|
463
|
+
if (subtreeId !== undefined) {
|
|
464
|
+
emitNodeRemoved(id, subtreeId);
|
|
465
|
+
}
|
|
409
466
|
}
|
|
410
467
|
}
|
|
411
468
|
|
|
@@ -414,14 +471,11 @@ function clearRenderTreeChildrenForId(id: number) {
|
|
|
414
471
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
415
472
|
|
|
416
473
|
function recordDirectoryNode(node: RenderedTextTree, path: string) {
|
|
417
|
-
if (!
|
|
474
|
+
if (!isDebugEnabled()) return;
|
|
418
475
|
const id = getOrCreateNodeId(node);
|
|
419
476
|
if (directoryNodes.has(id)) return;
|
|
420
477
|
directoryNodes.set(id, { path });
|
|
421
|
-
|
|
422
|
-
type: "files:directoryAdded",
|
|
423
|
-
path,
|
|
424
|
-
});
|
|
478
|
+
insertDirectory(path);
|
|
425
479
|
}
|
|
426
480
|
|
|
427
481
|
function recordFileNode(
|
|
@@ -429,36 +483,25 @@ function recordFileNode(
|
|
|
429
483
|
path: string,
|
|
430
484
|
filetype: string,
|
|
431
485
|
) {
|
|
432
|
-
if (!
|
|
486
|
+
if (!isDebugEnabled()) return;
|
|
433
487
|
const id = getOrCreateNodeId(node);
|
|
434
488
|
if (fileNodes.has(id)) return;
|
|
435
489
|
fileNodes.set(id, { path, filetype });
|
|
436
|
-
|
|
437
|
-
type: "files:fileAdded",
|
|
438
|
-
path,
|
|
439
|
-
filetype,
|
|
440
|
-
renderNodeId: id,
|
|
441
|
-
});
|
|
490
|
+
insertOutputFile(path, filetype, id);
|
|
442
491
|
}
|
|
443
492
|
|
|
444
493
|
function removeFileEntriesForNode(node: RenderedTextTree | PrintHook) {
|
|
445
|
-
if (!
|
|
494
|
+
if (!isDebugEnabled()) return;
|
|
446
495
|
const id = nodeIds.get(node);
|
|
447
496
|
if (id === undefined) return;
|
|
448
497
|
const fileInfo = fileNodes.get(id);
|
|
449
498
|
if (fileInfo) {
|
|
450
|
-
|
|
451
|
-
type: "files:fileRemoved",
|
|
452
|
-
path: fileInfo.path,
|
|
453
|
-
});
|
|
499
|
+
deleteOutputFile(fileInfo.path);
|
|
454
500
|
fileNodes.delete(id);
|
|
455
501
|
}
|
|
456
502
|
const dirInfo = directoryNodes.get(id);
|
|
457
503
|
if (dirInfo) {
|
|
458
|
-
|
|
459
|
-
type: "files:directoryRemoved",
|
|
460
|
-
path: dirInfo.path,
|
|
461
|
-
});
|
|
504
|
+
deleteDirectory(dirInfo.path);
|
|
462
505
|
directoryNodes.delete(id);
|
|
463
506
|
}
|
|
464
507
|
}
|
|
@@ -482,7 +525,7 @@ export function beginComponent(
|
|
|
482
525
|
actions,
|
|
483
526
|
} = options;
|
|
484
527
|
|
|
485
|
-
if (!
|
|
528
|
+
if (!isDebugEnabled()) {
|
|
486
529
|
return {
|
|
487
530
|
recordDirectory() {},
|
|
488
531
|
recordFile() {},
|
|
@@ -511,6 +554,14 @@ export function beginComponent(
|
|
|
511
554
|
source,
|
|
512
555
|
});
|
|
513
556
|
}
|
|
557
|
+
|
|
558
|
+
if (isTraceEnabled()) {
|
|
559
|
+
const ctx = getContext();
|
|
560
|
+
if (ctx) {
|
|
561
|
+
updateRenderNodeContext(getOrCreateNodeId(node), ctx.id);
|
|
562
|
+
updateEffectComponentByContext(ctx.id, componentName);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
514
565
|
recordNodePropsUpdated(node, propsSerialized);
|
|
515
566
|
registerRenderNodeActions(node, actions);
|
|
516
567
|
|
|
@@ -610,7 +661,7 @@ export function error(
|
|
|
610
661
|
error: RenderErrorInfo,
|
|
611
662
|
componentStack: RenderErrorStackEntry[],
|
|
612
663
|
) {
|
|
613
|
-
if (!
|
|
664
|
+
if (!isDebugEnabled()) return;
|
|
614
665
|
const serializedStack = untrack(() =>
|
|
615
666
|
componentStack.map((entry) => ({
|
|
616
667
|
name: entry.name,
|
|
@@ -619,21 +670,29 @@ export function error(
|
|
|
619
670
|
source: entry.source,
|
|
620
671
|
})),
|
|
621
672
|
);
|
|
622
|
-
|
|
673
|
+
logDevtoolsMessage({
|
|
623
674
|
type: "render:error" as const,
|
|
624
675
|
id: nextErrorId++,
|
|
625
676
|
name: error.name,
|
|
626
677
|
message: error.message,
|
|
627
678
|
stack: error.stack,
|
|
628
679
|
componentStack: serializedStack,
|
|
629
|
-
};
|
|
630
|
-
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
insertRenderError(
|
|
683
|
+
error.name,
|
|
684
|
+
error.message,
|
|
685
|
+
error.stack,
|
|
686
|
+
JSON.stringify(serializedStack),
|
|
687
|
+
);
|
|
631
688
|
}
|
|
632
689
|
|
|
633
690
|
export function complete() {
|
|
634
|
-
|
|
691
|
+
logDevtoolsMessage({ type: "render:complete" });
|
|
692
|
+
notifyRenderComplete();
|
|
635
693
|
}
|
|
636
694
|
|
|
637
695
|
export function flushJobsComplete() {
|
|
638
|
-
|
|
696
|
+
logDevtoolsMessage({ type: "flushJobs:complete" });
|
|
697
|
+
notifyFlushComplete();
|
|
639
698
|
}
|
|
@@ -34,7 +34,7 @@ afterEach(async () => {
|
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
it("emits tracking info", async () => {
|
|
37
|
-
const collector = createMessageCollector(socket!);
|
|
37
|
+
const collector = await createMessageCollector(socket!);
|
|
38
38
|
const binder = createOutputBinder();
|
|
39
39
|
|
|
40
40
|
const scope = createScope(BasicScope, "root", undefined, { binder });
|
|
@@ -44,14 +44,14 @@ it("emits tracking info", async () => {
|
|
|
44
44
|
});
|
|
45
45
|
symbol.name = "hi";
|
|
46
46
|
await flushJobsAsync();
|
|
47
|
-
const items = (await collector.waitForFlush()).filter(
|
|
48
|
-
m.type.startsWith("
|
|
47
|
+
const items = (await collector.waitForFlush()).filter(
|
|
48
|
+
(m) => m.type.startsWith("edge:track") && !("triggerIds" in m),
|
|
49
49
|
);
|
|
50
50
|
expect(items.length).toBeGreaterThan(0);
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
it("emits symbol and scope add/update/remove messages", async () => {
|
|
54
|
-
const collector = createMessageCollector(socket!);
|
|
54
|
+
const collector = await createMessageCollector(socket!);
|
|
55
55
|
const binder = createOutputBinder();
|
|
56
56
|
|
|
57
57
|
const scope = createScope(BasicScope, "root", undefined, { binder });
|
|
@@ -70,37 +70,36 @@ it("emits symbol and scope add/update/remove messages", async () => {
|
|
|
70
70
|
|
|
71
71
|
const messages = await collector.waitForFlush();
|
|
72
72
|
const symbolsMessages = messages.filter((m) => {
|
|
73
|
-
return
|
|
73
|
+
return (
|
|
74
|
+
(m.type.startsWith("scope:") || m.type.startsWith("symbol:")) &&
|
|
75
|
+
!("triggerIds" in m)
|
|
76
|
+
);
|
|
74
77
|
});
|
|
75
78
|
collector.stop();
|
|
76
79
|
|
|
77
80
|
expect(symbolsMessages[0]).toMatchObject({
|
|
78
|
-
type: "scope:
|
|
79
|
-
|
|
81
|
+
type: "scope:added",
|
|
82
|
+
name: "root",
|
|
80
83
|
});
|
|
81
84
|
|
|
82
85
|
expect(symbolsMessages[1]).toMatchObject({
|
|
83
|
-
type: "symbol:
|
|
86
|
+
type: "symbol:added",
|
|
87
|
+
name: "Foo",
|
|
84
88
|
});
|
|
85
|
-
|
|
86
89
|
expect(symbolsMessages[2]).toMatchObject({
|
|
87
|
-
type: "
|
|
88
|
-
|
|
90
|
+
type: "scope:updated",
|
|
91
|
+
name: "root-updated",
|
|
89
92
|
});
|
|
90
93
|
expect(symbolsMessages[3]).toMatchObject({
|
|
91
|
-
type: "
|
|
92
|
-
|
|
94
|
+
type: "symbol:updated",
|
|
95
|
+
name: "FooUpdated",
|
|
93
96
|
});
|
|
94
97
|
expect(symbolsMessages[4]).toMatchObject({
|
|
95
|
-
type: "symbol:
|
|
96
|
-
symbol: expect.objectContaining({ name: "FooUpdated" }),
|
|
97
|
-
});
|
|
98
|
-
expect(symbolsMessages[5]).toMatchObject({
|
|
99
|
-
type: "symbol:delete",
|
|
98
|
+
type: "symbol:removed",
|
|
100
99
|
id: expect.any(Number),
|
|
101
100
|
});
|
|
102
|
-
expect(symbolsMessages[
|
|
103
|
-
type: "scope:
|
|
101
|
+
expect(symbolsMessages[5]).toMatchObject({
|
|
102
|
+
type: "scope:removed",
|
|
104
103
|
id: expect.any(Number),
|
|
105
104
|
});
|
|
106
105
|
});
|