@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.
- package/CHANGELOG.md +0 -22
- package/dist/devtools/index.html +80 -0
- package/dist/src/binder.d.ts +2 -0
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +60 -12
- package/dist/src/binder.js.map +1 -1
- package/dist/src/components/AccessExpression.d.ts +78 -0
- package/dist/src/components/AccessExpression.d.ts.map +1 -0
- package/dist/src/components/AccessExpression.js +218 -0
- package/dist/src/components/AccessExpression.js.map +1 -0
- package/dist/src/components/AccessExpression.test.d.ts +2 -0
- package/dist/src/components/AccessExpression.test.d.ts.map +1 -0
- package/dist/src/components/AccessExpression.test.js +137 -0
- package/dist/src/components/AccessExpression.test.js.map +1 -0
- package/dist/src/components/AppendFile.d.ts.map +1 -1
- package/dist/src/components/AppendFile.js +14 -3
- package/dist/src/components/AppendFile.js.map +1 -1
- package/dist/src/components/Block.js +1 -1
- package/dist/src/components/Block.js.map +1 -1
- package/dist/src/components/Declaration.d.ts.map +1 -1
- package/dist/src/components/Declaration.js +2 -1
- package/dist/src/components/Declaration.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/Prose.js +2 -2
- package/dist/src/components/Prose.js.map +1 -1
- package/dist/src/components/Scope.d.ts.map +1 -1
- package/dist/src/components/Scope.js +6 -1
- package/dist/src/components/Scope.js.map +1 -1
- package/dist/src/components/SourceDirectory.d.ts.map +1 -1
- package/dist/src/components/SourceDirectory.js +1 -2
- package/dist/src/components/SourceDirectory.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/components/TemplateFile.d.ts.map +1 -1
- package/dist/src/components/TemplateFile.js +18 -3
- package/dist/src/components/TemplateFile.js.map +1 -1
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +1 -0
- package/dist/src/components/index.js.map +1 -1
- package/dist/src/content-slot.d.ts.map +1 -1
- package/dist/src/content-slot.js +7 -6
- package/dist/src/content-slot.js.map +1 -1
- package/dist/src/context.d.ts.map +1 -1
- package/dist/src/context.js +10 -3
- package/dist/src/context.js.map +1 -1
- package/dist/src/debug/cli.d.ts +6 -0
- package/dist/src/debug/cli.d.ts.map +1 -0
- package/dist/src/{debug.js → debug/cli.js} +79 -82
- package/dist/src/debug/cli.js.map +1 -0
- package/dist/src/debug/diagnostics.test.d.ts +2 -0
- package/dist/src/debug/diagnostics.test.d.ts.map +1 -0
- package/dist/src/debug/diagnostics.test.js +46 -0
- package/dist/src/debug/diagnostics.test.js.map +1 -0
- package/dist/src/debug/effects.d.ts +81 -0
- package/dist/src/debug/effects.d.ts.map +1 -0
- package/dist/src/debug/effects.js +358 -0
- package/dist/src/debug/effects.js.map +1 -0
- package/dist/src/debug/effects.test.d.ts +2 -0
- package/dist/src/debug/effects.test.d.ts.map +1 -0
- package/dist/src/debug/effects.test.js +256 -0
- package/dist/src/debug/effects.test.js.map +1 -0
- package/dist/src/debug/files.d.ts +14 -0
- package/dist/src/debug/files.d.ts.map +1 -0
- package/dist/src/debug/files.js +29 -0
- package/dist/src/debug/files.js.map +1 -0
- package/dist/src/debug/files.test.d.ts +2 -0
- package/dist/src/debug/files.test.d.ts.map +1 -0
- package/dist/src/debug/files.test.js +66 -0
- package/dist/src/debug/files.test.js.map +1 -0
- package/dist/src/debug/index.d.ts +63 -0
- package/dist/src/debug/index.d.ts.map +1 -0
- package/dist/src/debug/index.js +71 -0
- package/dist/src/debug/index.js.map +1 -0
- 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 +57 -0
- package/dist/src/debug/render.d.ts.map +1 -0
- package/dist/src/debug/render.js +472 -0
- package/dist/src/debug/render.js.map +1 -0
- package/dist/src/debug/render.test.d.ts +2 -0
- package/dist/src/debug/render.test.d.ts.map +1 -0
- package/dist/src/debug/render.test.js +291 -0
- package/dist/src/debug/render.test.js.map +1 -0
- package/dist/src/debug/serialize.d.ts +9 -0
- package/dist/src/debug/serialize.d.ts.map +1 -0
- package/dist/src/debug/serialize.js +70 -0
- package/dist/src/debug/serialize.js.map +1 -0
- package/dist/src/debug/symbols.d.ts +16 -0
- package/dist/src/debug/symbols.d.ts.map +1 -0
- package/dist/src/debug/symbols.js +196 -0
- package/dist/src/debug/symbols.js.map +1 -0
- package/dist/src/debug/symbols.test.d.ts +2 -0
- package/dist/src/debug/symbols.test.d.ts.map +1 -0
- package/dist/src/debug/symbols.test.js +93 -0
- package/dist/src/debug/symbols.test.js.map +1 -0
- 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 +342 -0
- package/dist/src/debug/trace.d.ts.map +1 -0
- package/dist/src/debug/trace.js +446 -0
- package/dist/src/debug/trace.js.map +1 -0
- package/dist/src/devtools/devtools-protocol.d.ts +389 -0
- package/dist/src/devtools/devtools-protocol.d.ts.map +1 -0
- package/dist/src/devtools/devtools-protocol.js +2 -0
- package/dist/src/devtools/devtools-protocol.js.map +1 -0
- package/dist/src/devtools/devtools-server.browser.d.ts +23 -0
- package/dist/src/devtools/devtools-server.browser.d.ts.map +1 -0
- package/dist/src/devtools/devtools-server.browser.js +33 -0
- package/dist/src/devtools/devtools-server.browser.js.map +1 -0
- package/dist/src/devtools/devtools-server.d.ts +66 -0
- package/dist/src/devtools/devtools-server.d.ts.map +1 -0
- package/dist/src/devtools/devtools-server.js +444 -0
- package/dist/src/devtools/devtools-server.js.map +1 -0
- package/dist/src/devtools/devtools-transport.d.ts +23 -0
- package/dist/src/devtools/devtools-transport.d.ts.map +1 -0
- package/dist/src/devtools/devtools-transport.js +114 -0
- package/dist/src/devtools/devtools-transport.js.map +1 -0
- package/dist/src/devtools-entry.browser.d.ts +4 -0
- package/dist/src/devtools-entry.browser.d.ts.map +1 -0
- package/dist/src/devtools-entry.browser.js +2 -0
- package/dist/src/devtools-entry.browser.js.map +1 -0
- package/dist/src/devtools-entry.d.ts +4 -0
- package/dist/src/devtools-entry.d.ts.map +1 -0
- package/dist/src/devtools-entry.js +2 -0
- package/dist/src/devtools-entry.js.map +1 -0
- package/dist/src/diagnostics.d.ts +34 -0
- package/dist/src/diagnostics.d.ts.map +1 -0
- package/dist/src/diagnostics.js +89 -0
- package/dist/src/diagnostics.js.map +1 -0
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/print-hook.d.ts +14 -0
- package/dist/src/print-hook.d.ts.map +1 -0
- package/dist/src/print-hook.js +10 -0
- package/dist/src/print-hook.js.map +1 -0
- package/dist/src/reactive-union-set.d.ts.map +1 -1
- package/dist/src/reactive-union-set.js +28 -3
- package/dist/src/reactive-union-set.js.map +1 -1
- package/dist/src/reactivity.d.ts +60 -7
- package/dist/src/reactivity.d.ts.map +1 -1
- package/dist/src/reactivity.js +308 -39
- package/dist/src/reactivity.js.map +1 -1
- package/dist/src/render-stack.d.ts +18 -1
- package/dist/src/render-stack.d.ts.map +1 -1
- package/dist/src/render-stack.js +61 -1
- package/dist/src/render-stack.js.map +1 -1
- package/dist/src/render.d.ts +8 -15
- package/dist/src/render.d.ts.map +1 -1
- package/dist/src/render.js +424 -109
- package/dist/src/render.js.map +1 -1
- package/dist/src/resource.d.ts.map +1 -1
- package/dist/src/resource.js +5 -0
- package/dist/src/resource.js.map +1 -1
- package/dist/src/scheduler.d.ts +13 -0
- package/dist/src/scheduler.d.ts.map +1 -1
- package/dist/src/scheduler.js +150 -13
- package/dist/src/scheduler.js.map +1 -1
- package/dist/src/symbols/basic-symbol.d.ts.map +1 -1
- package/dist/src/symbols/basic-symbol.js +6 -1
- package/dist/src/symbols/basic-symbol.js.map +1 -1
- package/dist/src/symbols/decl.d.ts.map +1 -1
- package/dist/src/symbols/decl.js +5 -1
- package/dist/src/symbols/decl.js.map +1 -1
- package/dist/src/symbols/output-scope.d.ts +2 -1
- package/dist/src/symbols/output-scope.d.ts.map +1 -1
- package/dist/src/symbols/output-scope.js +13 -8
- package/dist/src/symbols/output-scope.js.map +1 -1
- package/dist/src/symbols/output-symbol.d.ts +1 -0
- package/dist/src/symbols/output-symbol.d.ts.map +1 -1
- package/dist/src/symbols/output-symbol.js +25 -8
- package/dist/src/symbols/output-symbol.js.map +1 -1
- package/dist/src/symbols/symbol-flow.d.ts.map +1 -1
- package/dist/src/symbols/symbol-flow.js +24 -8
- package/dist/src/symbols/symbol-flow.js.map +1 -1
- package/dist/src/symbols/symbol-slot.d.ts.map +1 -1
- package/dist/src/symbols/symbol-slot.js +15 -0
- package/dist/src/symbols/symbol-slot.js.map +1 -1
- package/dist/src/symbols/symbol-slot.test.d.ts +2 -0
- package/dist/src/symbols/symbol-slot.test.d.ts.map +1 -0
- package/dist/src/symbols/symbol-slot.test.js +35 -0
- package/dist/src/symbols/symbol-slot.test.js.map +1 -0
- package/dist/src/symbols/symbol-table.d.ts.map +1 -1
- package/dist/src/symbols/symbol-table.js +6 -5
- package/dist/src/symbols/symbol-table.js.map +1 -1
- package/dist/src/trace.d.ts +2 -0
- package/dist/src/trace.d.ts.map +1 -0
- package/dist/src/trace.js +2 -0
- package/dist/src/trace.js.map +1 -0
- package/dist/src/tracer.d.ts +2 -228
- package/dist/src/tracer.d.ts.map +1 -1
- package/dist/src/tracer.js +5 -298
- package/dist/src/tracer.js.map +1 -1
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +17 -9
- package/dist/src/utils.js.map +1 -1
- package/dist/test/components/append-file.test.d.ts.map +1 -1
- package/dist/test/components/append-file.test.js +18 -10
- package/dist/test/components/append-file.test.js.map +1 -1
- package/dist/test/components/template-file.test.d.ts.map +1 -1
- package/dist/test/components/template-file.test.js +6 -4
- package/dist/test/components/template-file.test.js.map +1 -1
- package/dist/test/lazy-isempty.test.d.ts +2 -0
- package/dist/test/lazy-isempty.test.d.ts.map +1 -0
- package/dist/test/lazy-isempty.test.js +89 -0
- package/dist/test/lazy-isempty.test.js.map +1 -0
- package/dist/test/reactive-union-set-disposers.test.d.ts +2 -0
- package/dist/test/reactive-union-set-disposers.test.d.ts.map +1 -0
- package/dist/test/reactive-union-set-disposers.test.js +98 -0
- package/dist/test/reactive-union-set-disposers.test.js.map +1 -0
- package/dist/test/reactivity/shallow-reactive.test.d.ts +2 -0
- package/dist/test/reactivity/shallow-reactive.test.d.ts.map +1 -0
- package/dist/test/reactivity/shallow-reactive.test.js +52 -0
- package/dist/test/reactivity/shallow-reactive.test.js.map +1 -0
- package/dist/test/rendering/basic.test.js +3 -0
- package/dist/test/rendering/basic.test.js.map +1 -1
- package/dist/test/rendering/print-render-stack.test.d.ts.map +1 -1
- package/dist/test/rendering/print-render-stack.test.js +91 -98
- package/dist/test/rendering/print-render-stack.test.js.map +1 -1
- package/dist/test/scheduler-extended.test.d.ts +2 -0
- package/dist/test/scheduler-extended.test.d.ts.map +1 -0
- package/dist/test/scheduler-extended.test.js +96 -0
- package/dist/test/scheduler-extended.test.js.map +1 -0
- package/dist/test/scheduler.test.d.ts +2 -0
- package/dist/test/scheduler.test.d.ts.map +1 -0
- package/dist/test/scheduler.test.js +46 -0
- package/dist/test/scheduler.test.js.map +1 -0
- package/dist/testing/create-test-wrapper.d.ts +1 -1
- package/dist/testing/create-test-wrapper.d.ts.map +1 -1
- package/dist/testing/create-test-wrapper.js +1 -1
- package/dist/testing/create-test-wrapper.js.map +1 -1
- package/dist/testing/devtools-utils.d.ts +35 -0
- package/dist/testing/devtools-utils.d.ts.map +1 -0
- package/dist/testing/devtools-utils.js +162 -0
- package/dist/testing/devtools-utils.js.map +1 -0
- package/dist/testing/extend-expect.d.ts.map +1 -1
- package/dist/testing/extend-expect.js +63 -1
- package/dist/testing/extend-expect.js.map +1 -1
- package/dist/testing/render.d.ts +2 -2
- package/dist/testing/render.d.ts.map +1 -1
- package/dist/testing/render.js +2 -2
- package/dist/testing/render.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +21 -7
- package/scripts/copy-devtools-ui.mjs +26 -0
- package/src/binder.ts +117 -53
- package/src/components/AccessExpression.test.tsx +132 -0
- package/src/components/AccessExpression.tsx +344 -0
- package/src/components/AppendFile.tsx +14 -9
- package/src/components/Block.tsx +1 -1
- package/src/components/Declaration.tsx +2 -1
- package/src/components/For.tsx +14 -10
- package/src/components/List.tsx +7 -4
- package/src/components/Prose.tsx +1 -1
- package/src/components/Scope.tsx +6 -1
- package/src/components/SourceDirectory.tsx +1 -2
- package/src/components/Switch.tsx +11 -7
- package/src/components/TemplateFile.tsx +18 -9
- package/src/components/index.tsx +1 -0
- package/src/content-slot.tsx +7 -7
- package/src/context.ts +17 -6
- package/src/{debug.ts → debug/cli.ts} +114 -125
- package/src/debug/diagnostics.test.tsx +56 -0
- package/src/debug/effects.test.tsx +301 -0
- package/src/debug/effects.ts +531 -0
- package/src/debug/files.test.tsx +76 -0
- package/src/debug/files.ts +40 -0
- package/src/debug/index.ts +132 -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 +357 -0
- package/src/debug/render.ts +698 -0
- package/src/debug/serialize.ts +85 -0
- package/src/debug/symbols.test.tsx +105 -0
- package/src/debug/symbols.ts +322 -0
- package/src/debug/trace-writer.ts +969 -0
- package/src/debug/trace.ts +309 -0
- package/src/devtools/devtools-protocol.ts +497 -0
- package/src/devtools/devtools-server.browser.ts +62 -0
- package/src/devtools/devtools-server.ts +468 -0
- package/src/devtools/devtools-transport.ts +154 -0
- package/src/devtools-entry.browser.ts +48 -0
- package/src/devtools-entry.ts +48 -0
- package/src/diagnostics.ts +150 -0
- package/src/index.ts +2 -7
- package/src/print-hook.ts +22 -0
- package/src/reactive-union-set.ts +85 -44
- package/src/reactivity.ts +396 -58
- package/src/render-stack.ts +73 -1
- package/src/render.ts +544 -161
- package/src/resource.ts +28 -19
- package/src/scheduler.ts +209 -14
- package/src/symbols/basic-symbol.ts +6 -1
- package/src/symbols/decl.ts +5 -1
- package/src/symbols/output-scope.ts +21 -13
- package/src/symbols/output-symbol.ts +34 -14
- package/src/symbols/symbol-flow.ts +76 -39
- package/src/symbols/symbol-slot.test.tsx +41 -0
- package/src/symbols/symbol-slot.tsx +47 -20
- package/src/symbols/symbol-table.ts +6 -10
- package/src/trace.ts +1 -0
- package/src/tracer.ts +13 -242
- package/src/utils.tsx +31 -21
- package/temp/api.json +5700 -3015
- package/test/components/append-file.test.tsx +36 -29
- package/test/components/template-file.test.tsx +11 -11
- package/test/lazy-isempty.test.tsx +106 -0
- package/test/reactive-union-set-disposers.test.tsx +112 -0
- package/test/reactivity/shallow-reactive.test.tsx +56 -0
- package/test/rendering/basic.test.tsx +4 -0
- package/test/rendering/print-render-stack.test.tsx +52 -43
- package/test/scheduler-extended.test.tsx +122 -0
- package/test/scheduler.test.tsx +50 -0
- package/testing/create-test-wrapper.tsx +1 -1
- package/testing/devtools-utils.ts +245 -0
- package/testing/extend-expect.ts +89 -0
- package/testing/render.ts +2 -2
- package/testing/vitest.d.ts +9 -0
- package/dist/src/debug.d.ts +0 -14
- package/dist/src/debug.d.ts.map +0 -1
- package/dist/src/debug.js.map +0 -1
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
import { watch } from "@vue/reactivity";
|
|
2
|
+
import * as devalue from "devalue";
|
|
3
|
+
import type {
|
|
4
|
+
RenderErrorStackEntry as ProtocolRenderErrorStackEntry,
|
|
5
|
+
RenderTreeNode,
|
|
6
|
+
} from "../devtools/devtools-protocol.js";
|
|
7
|
+
import {
|
|
8
|
+
isDevtoolsEnabled,
|
|
9
|
+
registerDevtoolsMessageHandler,
|
|
10
|
+
} from "../devtools/devtools-server.js";
|
|
11
|
+
import {
|
|
12
|
+
isPrintHook,
|
|
13
|
+
type PrintHook,
|
|
14
|
+
type RenderedTextTree,
|
|
15
|
+
} from "../print-hook.js";
|
|
16
|
+
import { getContext, untrack } from "../reactivity.js";
|
|
17
|
+
import type { ComponentCreator } from "../runtime/component.js";
|
|
18
|
+
import { flushJobsAsync } from "../scheduler.js";
|
|
19
|
+
import { sanitizeRecord } from "./serialize.js";
|
|
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";
|
|
37
|
+
|
|
38
|
+
/** The kind discriminant for render tree nodes. */
|
|
39
|
+
export type RenderTreeNodeKind = RenderTreeNode["kind"];
|
|
40
|
+
|
|
41
|
+
/** Information about a render tree node, used when recording nodes to devtools. */
|
|
42
|
+
export interface RenderTreeNodeInfo {
|
|
43
|
+
kind: RenderTreeNodeKind;
|
|
44
|
+
name?: string;
|
|
45
|
+
propsSerialized?: string;
|
|
46
|
+
value?: string;
|
|
47
|
+
source?: RenderTreeNode["source"];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface RenderNodeActions {
|
|
51
|
+
rerender: () => void;
|
|
52
|
+
rerenderAndBreak: () => void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface BeginComponentOptions {
|
|
56
|
+
parent: RenderedTextTree;
|
|
57
|
+
index: number;
|
|
58
|
+
node: RenderedTextTree;
|
|
59
|
+
component: ComponentCreator<unknown>;
|
|
60
|
+
propsSource: Record<string, unknown> | undefined;
|
|
61
|
+
source: RenderTreeNodeInfo["source"] | undefined;
|
|
62
|
+
isExisting: boolean;
|
|
63
|
+
actions: RenderNodeActions;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface ComponentDebugSession {
|
|
67
|
+
recordDirectory(path: string): void;
|
|
68
|
+
recordFile(path: string, filetype: string): void;
|
|
69
|
+
dispose(): void;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Any node tracked by the devtools render tree. */
|
|
73
|
+
type TrackedNode = RenderedTextTree | PrintHook;
|
|
74
|
+
|
|
75
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
76
|
+
// Module state — reset in initialize()
|
|
77
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
78
|
+
|
|
79
|
+
let nodeIds = new WeakMap<TrackedNode, number>();
|
|
80
|
+
let idToNode = new Map<number, TrackedNode>();
|
|
81
|
+
let entryIds = new WeakMap<RenderedTextTree, number[]>();
|
|
82
|
+
let nodeKinds = new WeakMap<TrackedNode, { kind: string; name?: string }>();
|
|
83
|
+
let fileNodes = new Map<number, { path: string; filetype: string }>();
|
|
84
|
+
let directoryNodes = new Map<number, { path: string }>();
|
|
85
|
+
let nodeProps = new Map<number, string | undefined>();
|
|
86
|
+
let rerenderActions = new Map<number, RenderNodeActions>();
|
|
87
|
+
let nextId = 1;
|
|
88
|
+
let handlerRegistered = false;
|
|
89
|
+
|
|
90
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
91
|
+
// Props serialization
|
|
92
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
93
|
+
|
|
94
|
+
function serializeRenderTreeProps(input: Record<string, unknown> | undefined) {
|
|
95
|
+
return untrack(() => {
|
|
96
|
+
if (!input) return undefined;
|
|
97
|
+
const { children: _children, ...rest } = input;
|
|
98
|
+
const sanitized = sanitizeRecord(rest);
|
|
99
|
+
if (!sanitized) return undefined;
|
|
100
|
+
try {
|
|
101
|
+
return devalue.stringify(sanitized);
|
|
102
|
+
} catch {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
109
|
+
// Node ID management & tree structure
|
|
110
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
function emitNodeRemoved(parentId: number | null, id: number) {
|
|
113
|
+
clearRenderTreeChildrenForId(id);
|
|
114
|
+
traceDeleteRenderNode(id);
|
|
115
|
+
|
|
116
|
+
rerenderActions.delete(id);
|
|
117
|
+
nodeProps.delete(id);
|
|
118
|
+
idToNode.delete(id);
|
|
119
|
+
|
|
120
|
+
const fileInfo = fileNodes.get(id);
|
|
121
|
+
if (fileInfo) {
|
|
122
|
+
deleteOutputFile(fileInfo.path);
|
|
123
|
+
fileNodes.delete(id);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const dirInfo = directoryNodes.get(id);
|
|
127
|
+
if (dirInfo) {
|
|
128
|
+
deleteDirectory(dirInfo.path);
|
|
129
|
+
directoryNodes.delete(id);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function getEntryList(parent: RenderedTextTree) {
|
|
134
|
+
let list = entryIds.get(parent);
|
|
135
|
+
if (!list) {
|
|
136
|
+
list = [];
|
|
137
|
+
entryIds.set(parent, list);
|
|
138
|
+
}
|
|
139
|
+
return list;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function getOrCreateNodeId(node: TrackedNode) {
|
|
143
|
+
const existing = nodeIds.get(node);
|
|
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
|
+
}
|
|
151
|
+
const id = nextId++;
|
|
152
|
+
nodeIds.set(node, id);
|
|
153
|
+
idToNode.set(id, node);
|
|
154
|
+
return id;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function getRenderNodeId(node: RenderedTextTree | PrintHook) {
|
|
158
|
+
if (!isDebugEnabled()) return undefined;
|
|
159
|
+
return getOrCreateNodeId(node);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function setEntryId(parent: RenderedTextTree, index: number, id: number) {
|
|
163
|
+
const list = getEntryList(parent);
|
|
164
|
+
list[index] = id;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function initialize(root: RenderedTextTree) {
|
|
168
|
+
if (!isDebugEnabled()) return;
|
|
169
|
+
ensureDevtoolsHandler();
|
|
170
|
+
nodeIds = new WeakMap();
|
|
171
|
+
idToNode = new Map();
|
|
172
|
+
entryIds = new WeakMap();
|
|
173
|
+
nodeKinds = new WeakMap();
|
|
174
|
+
fileNodes = new Map();
|
|
175
|
+
directoryNodes = new Map();
|
|
176
|
+
nodeProps = new Map();
|
|
177
|
+
rerenderActions = new Map();
|
|
178
|
+
nextId = 1;
|
|
179
|
+
notifyRenderReset();
|
|
180
|
+
const rootId = getOrCreateNodeId(root);
|
|
181
|
+
insertRenderNode(
|
|
182
|
+
rootId,
|
|
183
|
+
null,
|
|
184
|
+
"root",
|
|
185
|
+
undefined,
|
|
186
|
+
undefined,
|
|
187
|
+
undefined,
|
|
188
|
+
undefined,
|
|
189
|
+
undefined,
|
|
190
|
+
null,
|
|
191
|
+
undefined,
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function registerRenderNodeActions(
|
|
196
|
+
node: RenderedTextTree | PrintHook,
|
|
197
|
+
actions: RenderNodeActions,
|
|
198
|
+
) {
|
|
199
|
+
if (!isDebugEnabled()) return;
|
|
200
|
+
const id = getOrCreateNodeId(node);
|
|
201
|
+
rerenderActions.set(id, actions);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function unregisterRenderNodeActions(
|
|
205
|
+
node: RenderedTextTree | PrintHook,
|
|
206
|
+
) {
|
|
207
|
+
if (!isDebugEnabled()) return;
|
|
208
|
+
const id = nodeIds.get(node);
|
|
209
|
+
if (id !== undefined) {
|
|
210
|
+
rerenderActions.delete(id);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function ensureDevtoolsHandler() {
|
|
215
|
+
if (handlerRegistered || !isDevtoolsEnabled()) return;
|
|
216
|
+
handlerRegistered = true;
|
|
217
|
+
registerDevtoolsMessageHandler((message) => {
|
|
218
|
+
if (
|
|
219
|
+
message.type !== "render:rerender" &&
|
|
220
|
+
message.type !== "render:rerenderAndBreak"
|
|
221
|
+
) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const rawId = (message as { id?: unknown }).id;
|
|
225
|
+
if (typeof rawId !== "number" && typeof rawId !== "string") return;
|
|
226
|
+
const id = Number(rawId);
|
|
227
|
+
if (!Number.isFinite(id)) return;
|
|
228
|
+
const actions = rerenderActions.get(id);
|
|
229
|
+
if (!actions) return;
|
|
230
|
+
if (message.type === "render:rerender") {
|
|
231
|
+
actions.rerender();
|
|
232
|
+
} else {
|
|
233
|
+
actions.rerenderAndBreak();
|
|
234
|
+
}
|
|
235
|
+
void flushJobsAsync();
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export function recordTextNode(
|
|
240
|
+
parent: RenderedTextTree,
|
|
241
|
+
index: number,
|
|
242
|
+
value: string,
|
|
243
|
+
) {
|
|
244
|
+
if (!isDebugEnabled()) return;
|
|
245
|
+
const id = nextId++;
|
|
246
|
+
setEntryId(parent, index, id);
|
|
247
|
+
insertRenderNode(
|
|
248
|
+
id,
|
|
249
|
+
getOrCreateNodeId(parent),
|
|
250
|
+
"text",
|
|
251
|
+
undefined,
|
|
252
|
+
undefined,
|
|
253
|
+
undefined,
|
|
254
|
+
undefined,
|
|
255
|
+
undefined,
|
|
256
|
+
null,
|
|
257
|
+
value,
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function recordNodeAdded(
|
|
262
|
+
parent: RenderedTextTree,
|
|
263
|
+
index: number,
|
|
264
|
+
node: RenderedTextTree | PrintHook,
|
|
265
|
+
info: RenderTreeNodeInfo,
|
|
266
|
+
) {
|
|
267
|
+
if (!isDebugEnabled()) return;
|
|
268
|
+
const id = getOrCreateNodeId(node);
|
|
269
|
+
if (info.propsSerialized !== undefined) {
|
|
270
|
+
nodeProps.set(id, info.propsSerialized);
|
|
271
|
+
}
|
|
272
|
+
// Remember the kind so cached re-adds preserve it
|
|
273
|
+
nodeKinds.set(node, { kind: info.kind, name: info.name });
|
|
274
|
+
setEntryId(parent, index, id);
|
|
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
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function recordSubtreeAdded(
|
|
290
|
+
parentNode: RenderedTextTree | PrintHook,
|
|
291
|
+
subtree: RenderedTextTree,
|
|
292
|
+
info: RenderTreeNodeInfo = { kind: "fragment" },
|
|
293
|
+
) {
|
|
294
|
+
if (!isDebugEnabled()) return;
|
|
295
|
+
const parentId = getOrCreateNodeId(parentNode);
|
|
296
|
+
// Check if this node was previously rendered (cached) by seeing if it already has an ID
|
|
297
|
+
const existingId = nodeIds.get(subtree);
|
|
298
|
+
const isCached = existingId !== undefined;
|
|
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 });
|
|
302
|
+
// Track in entryIds so clearRenderTreeChildren can find and remove it
|
|
303
|
+
if (Array.isArray(parentNode)) {
|
|
304
|
+
const list = getEntryList(parentNode);
|
|
305
|
+
list.push(id);
|
|
306
|
+
}
|
|
307
|
+
insertRenderNode(
|
|
308
|
+
id,
|
|
309
|
+
parentId,
|
|
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
|
+
|
|
320
|
+
// For cached nodes, we need to recursively re-add all their children since
|
|
321
|
+
// clearRenderTreeChildren removed them when the parent re-rendered
|
|
322
|
+
if (isCached) {
|
|
323
|
+
recordCachedSubtreeChildrenRecursively(subtree);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Recursively re-adds all children of a cached render tree node to devtools.
|
|
329
|
+
* This is needed because clearRenderTreeChildren recursively removes all
|
|
330
|
+
* descendants, but cached nodes aren't re-rendered so their children need
|
|
331
|
+
* to be explicitly re-added.
|
|
332
|
+
*/
|
|
333
|
+
function recordCachedSubtreeChildrenRecursively(node: RenderedTextTree) {
|
|
334
|
+
if (!isDebugEnabled()) return;
|
|
335
|
+
const parentId = getOrCreateNodeId(node);
|
|
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
|
+
|
|
343
|
+
// Rebuild the entryIds for this node
|
|
344
|
+
const list = getEntryList(node);
|
|
345
|
+
list.length = 0;
|
|
346
|
+
|
|
347
|
+
for (let i = 0; i < node.length; i++) {
|
|
348
|
+
const child = node[i];
|
|
349
|
+
if (typeof child === "string") {
|
|
350
|
+
// Text nodes - re-record them with new IDs
|
|
351
|
+
if (child !== "") {
|
|
352
|
+
const id = nextId++;
|
|
353
|
+
list.push(id);
|
|
354
|
+
idToNode.set(id, child as unknown as RenderedTextTree);
|
|
355
|
+
insertRenderNode(
|
|
356
|
+
id,
|
|
357
|
+
parentId,
|
|
358
|
+
"text",
|
|
359
|
+
undefined,
|
|
360
|
+
undefined,
|
|
361
|
+
undefined,
|
|
362
|
+
undefined,
|
|
363
|
+
undefined,
|
|
364
|
+
null,
|
|
365
|
+
child,
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
} else if (Array.isArray(child)) {
|
|
369
|
+
// Nested RenderedTextTree - record and recurse, preserving original kind
|
|
370
|
+
const id = getOrCreateNodeId(child);
|
|
371
|
+
list.push(id);
|
|
372
|
+
const savedKind = nodeKinds.get(child);
|
|
373
|
+
insertRenderNode(
|
|
374
|
+
id,
|
|
375
|
+
parentId,
|
|
376
|
+
savedKind?.kind ?? "fragment",
|
|
377
|
+
savedKind?.name,
|
|
378
|
+
undefined,
|
|
379
|
+
undefined,
|
|
380
|
+
undefined,
|
|
381
|
+
undefined,
|
|
382
|
+
null,
|
|
383
|
+
undefined,
|
|
384
|
+
);
|
|
385
|
+
recordCachedSubtreeChildrenRecursively(child);
|
|
386
|
+
} else if (isPrintHook(child)) {
|
|
387
|
+
// PrintHook - record and recurse into subtree
|
|
388
|
+
const id = getOrCreateNodeId(child);
|
|
389
|
+
list.push(id);
|
|
390
|
+
insertRenderNode(
|
|
391
|
+
id,
|
|
392
|
+
parentId,
|
|
393
|
+
"printHook",
|
|
394
|
+
(child as { name?: string }).name ?? "hook",
|
|
395
|
+
undefined,
|
|
396
|
+
undefined,
|
|
397
|
+
undefined,
|
|
398
|
+
undefined,
|
|
399
|
+
null,
|
|
400
|
+
undefined,
|
|
401
|
+
);
|
|
402
|
+
if (child.subtree) {
|
|
403
|
+
const subtreeId = getOrCreateNodeId(child.subtree);
|
|
404
|
+
const hookList = getEntryList(child as unknown as RenderedTextTree);
|
|
405
|
+
hookList.length = 0;
|
|
406
|
+
hookList.push(subtreeId);
|
|
407
|
+
insertRenderNode(
|
|
408
|
+
subtreeId,
|
|
409
|
+
id,
|
|
410
|
+
"fragment",
|
|
411
|
+
undefined,
|
|
412
|
+
undefined,
|
|
413
|
+
undefined,
|
|
414
|
+
undefined,
|
|
415
|
+
undefined,
|
|
416
|
+
null,
|
|
417
|
+
undefined,
|
|
418
|
+
);
|
|
419
|
+
recordCachedSubtreeChildrenRecursively(child.subtree);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function recordNodePropsUpdated(
|
|
426
|
+
node: RenderedTextTree | PrintHook,
|
|
427
|
+
propsSerialized: string | undefined,
|
|
428
|
+
) {
|
|
429
|
+
if (!isDebugEnabled()) return;
|
|
430
|
+
const id = getOrCreateNodeId(node);
|
|
431
|
+
const previous = nodeProps.get(id);
|
|
432
|
+
if (previous === propsSerialized) return;
|
|
433
|
+
nodeProps.set(id, propsSerialized);
|
|
434
|
+
traceUpdateRenderNodeProps(id, propsSerialized);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function clearRenderTreeChildren(parent: RenderedTextTree) {
|
|
438
|
+
if (!isDebugEnabled()) return;
|
|
439
|
+
const list = entryIds.get(parent);
|
|
440
|
+
if (!list || list.length === 0) return;
|
|
441
|
+
const parentId = getOrCreateNodeId(parent);
|
|
442
|
+
for (const id of list) {
|
|
443
|
+
if (id !== undefined) {
|
|
444
|
+
emitNodeRemoved(parentId, id);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
entryIds.set(parent, []);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function clearRenderTreeChildrenForId(id: number) {
|
|
451
|
+
const node = idToNode.get(id);
|
|
452
|
+
if (!node) return;
|
|
453
|
+
if (Array.isArray(node)) {
|
|
454
|
+
clearRenderTreeChildren(node);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
// For PrintHook nodes: clear the subtree's children, then remove
|
|
458
|
+
// the subtree node itself (which is a child of this hook).
|
|
459
|
+
const subtree = (node as { subtree?: RenderedTextTree }).subtree;
|
|
460
|
+
if (subtree && Array.isArray(subtree)) {
|
|
461
|
+
clearRenderTreeChildren(subtree);
|
|
462
|
+
const subtreeId = nodeIds.get(subtree);
|
|
463
|
+
if (subtreeId !== undefined) {
|
|
464
|
+
emitNodeRemoved(id, subtreeId);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
470
|
+
// File / directory node tracking
|
|
471
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
472
|
+
|
|
473
|
+
function recordDirectoryNode(node: RenderedTextTree, path: string) {
|
|
474
|
+
if (!isDebugEnabled()) return;
|
|
475
|
+
const id = getOrCreateNodeId(node);
|
|
476
|
+
if (directoryNodes.has(id)) return;
|
|
477
|
+
directoryNodes.set(id, { path });
|
|
478
|
+
insertDirectory(path);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function recordFileNode(
|
|
482
|
+
node: RenderedTextTree,
|
|
483
|
+
path: string,
|
|
484
|
+
filetype: string,
|
|
485
|
+
) {
|
|
486
|
+
if (!isDebugEnabled()) return;
|
|
487
|
+
const id = getOrCreateNodeId(node);
|
|
488
|
+
if (fileNodes.has(id)) return;
|
|
489
|
+
fileNodes.set(id, { path, filetype });
|
|
490
|
+
insertOutputFile(path, filetype, id);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function removeFileEntriesForNode(node: RenderedTextTree | PrintHook) {
|
|
494
|
+
if (!isDebugEnabled()) return;
|
|
495
|
+
const id = nodeIds.get(node);
|
|
496
|
+
if (id === undefined) return;
|
|
497
|
+
const fileInfo = fileNodes.get(id);
|
|
498
|
+
if (fileInfo) {
|
|
499
|
+
deleteOutputFile(fileInfo.path);
|
|
500
|
+
fileNodes.delete(id);
|
|
501
|
+
}
|
|
502
|
+
const dirInfo = directoryNodes.get(id);
|
|
503
|
+
if (dirInfo) {
|
|
504
|
+
deleteDirectory(dirInfo.path);
|
|
505
|
+
directoryNodes.delete(id);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
510
|
+
// Public API — called from render.ts via the debug object
|
|
511
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
512
|
+
|
|
513
|
+
/** Begin tracking a component render. Returns a session to record files/dirs and dispose watchers. */
|
|
514
|
+
export function beginComponent(
|
|
515
|
+
options: BeginComponentOptions,
|
|
516
|
+
): ComponentDebugSession {
|
|
517
|
+
const {
|
|
518
|
+
parent,
|
|
519
|
+
index,
|
|
520
|
+
node,
|
|
521
|
+
component,
|
|
522
|
+
propsSource,
|
|
523
|
+
source,
|
|
524
|
+
isExisting,
|
|
525
|
+
actions,
|
|
526
|
+
} = options;
|
|
527
|
+
|
|
528
|
+
if (!isDebugEnabled()) {
|
|
529
|
+
return {
|
|
530
|
+
recordDirectory() {},
|
|
531
|
+
recordFile() {},
|
|
532
|
+
dispose() {},
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
return untrack(() => {
|
|
537
|
+
let componentName = component.component.name;
|
|
538
|
+
if (componentName === "Provider") {
|
|
539
|
+
const contextName = (component.component as any).contextName as
|
|
540
|
+
| string
|
|
541
|
+
| undefined;
|
|
542
|
+
if (contextName) {
|
|
543
|
+
componentName = `Context ${contextName}`;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
const propsSerialized = serializeRenderTreeProps(propsSource);
|
|
547
|
+
if (isExisting) {
|
|
548
|
+
clearRenderTreeChildren(node);
|
|
549
|
+
} else {
|
|
550
|
+
recordNodeAdded(parent, index, node, {
|
|
551
|
+
kind: "component",
|
|
552
|
+
name: componentName,
|
|
553
|
+
propsSerialized,
|
|
554
|
+
source,
|
|
555
|
+
});
|
|
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
|
+
}
|
|
565
|
+
recordNodePropsUpdated(node, propsSerialized);
|
|
566
|
+
registerRenderNodeActions(node, actions);
|
|
567
|
+
|
|
568
|
+
let stopWatch: (() => void) | undefined;
|
|
569
|
+
if (propsSource) {
|
|
570
|
+
const propKeys = Object.keys(propsSource).filter(
|
|
571
|
+
(key) => key !== "children",
|
|
572
|
+
);
|
|
573
|
+
if (propKeys.length > 0) {
|
|
574
|
+
stopWatch = watch(
|
|
575
|
+
() => propKeys.map((key) => propsSource[key]),
|
|
576
|
+
() => {
|
|
577
|
+
const nextSerialized = serializeRenderTreeProps(propsSource);
|
|
578
|
+
recordNodePropsUpdated(node, nextSerialized);
|
|
579
|
+
},
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return {
|
|
585
|
+
recordDirectory(path: string) {
|
|
586
|
+
recordDirectoryNode(node, path);
|
|
587
|
+
},
|
|
588
|
+
recordFile(path: string, filetype: string) {
|
|
589
|
+
recordFileNode(node, path, filetype);
|
|
590
|
+
},
|
|
591
|
+
dispose() {
|
|
592
|
+
stopWatch?.();
|
|
593
|
+
removeFileEntriesForNode(node);
|
|
594
|
+
unregisterRenderNodeActions(node);
|
|
595
|
+
},
|
|
596
|
+
};
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
export function appendCustomContext(
|
|
601
|
+
parent: RenderedTextTree,
|
|
602
|
+
node: RenderedTextTree,
|
|
603
|
+
) {
|
|
604
|
+
recordSubtreeAdded(parent, node, { kind: "customContext" });
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
export function appendPrintHook(
|
|
608
|
+
parent: RenderedTextTree,
|
|
609
|
+
index: number,
|
|
610
|
+
hook: PrintHook,
|
|
611
|
+
name: string,
|
|
612
|
+
subtree?: RenderedTextTree,
|
|
613
|
+
) {
|
|
614
|
+
recordNodeAdded(parent, index, hook, { kind: "printHook", name });
|
|
615
|
+
if (subtree) {
|
|
616
|
+
recordSubtreeAdded(hook, subtree);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
export function appendFragmentChild(
|
|
621
|
+
parent: RenderedTextTree,
|
|
622
|
+
child: RenderedTextTree,
|
|
623
|
+
) {
|
|
624
|
+
recordSubtreeAdded(parent, child, { kind: "fragment" });
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
export function appendTextNode(
|
|
628
|
+
parent: RenderedTextTree,
|
|
629
|
+
index: number,
|
|
630
|
+
value: string,
|
|
631
|
+
) {
|
|
632
|
+
recordTextNode(parent, index, value);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
export function prepareMemoNode(
|
|
636
|
+
parent: RenderedTextTree,
|
|
637
|
+
node: RenderedTextTree,
|
|
638
|
+
isExisting: boolean,
|
|
639
|
+
) {
|
|
640
|
+
if (isExisting) {
|
|
641
|
+
clearRenderTreeChildren(node);
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
recordSubtreeAdded(parent, node, { kind: "memo" });
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
let nextErrorId = 1;
|
|
648
|
+
|
|
649
|
+
export interface RenderErrorInfo {
|
|
650
|
+
name: string;
|
|
651
|
+
message: string;
|
|
652
|
+
stack?: string;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/** Render error stack entry with optional runtime props (extends protocol type). */
|
|
656
|
+
export interface RenderErrorStackEntry extends ProtocolRenderErrorStackEntry {
|
|
657
|
+
props?: Record<string, unknown> | undefined;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
export function error(
|
|
661
|
+
error: RenderErrorInfo,
|
|
662
|
+
componentStack: RenderErrorStackEntry[],
|
|
663
|
+
) {
|
|
664
|
+
if (!isDebugEnabled()) return;
|
|
665
|
+
const serializedStack = untrack(() =>
|
|
666
|
+
componentStack.map((entry) => ({
|
|
667
|
+
name: entry.name,
|
|
668
|
+
propsSerialized: entry.propsSerialized,
|
|
669
|
+
renderNodeId: entry.renderNodeId,
|
|
670
|
+
source: entry.source,
|
|
671
|
+
})),
|
|
672
|
+
);
|
|
673
|
+
logDevtoolsMessage({
|
|
674
|
+
type: "render:error" as const,
|
|
675
|
+
id: nextErrorId++,
|
|
676
|
+
name: error.name,
|
|
677
|
+
message: error.message,
|
|
678
|
+
stack: error.stack,
|
|
679
|
+
componentStack: serializedStack,
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
insertRenderError(
|
|
683
|
+
error.name,
|
|
684
|
+
error.message,
|
|
685
|
+
error.stack,
|
|
686
|
+
JSON.stringify(serializedStack),
|
|
687
|
+
);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
export function complete() {
|
|
691
|
+
logDevtoolsMessage({ type: "render:complete" });
|
|
692
|
+
notifyRenderComplete();
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
export function flushJobsComplete() {
|
|
696
|
+
logDevtoolsMessage({ type: "flushJobs:complete" });
|
|
697
|
+
notifyFlushComplete();
|
|
698
|
+
}
|