@alloy-js/core 0.23.0-dev.1 → 0.23.0-dev.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -22
- package/dist/devtools/index.html +68 -0
- package/dist/src/binder.d.ts +2 -0
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +55 -12
- package/dist/src/binder.js.map +1 -1
- 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/Scope.d.ts.map +1 -1
- package/dist/src/components/Scope.js +4 -1
- package/dist/src/components/Scope.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/content-slot.d.ts.map +1 -1
- package/dist/src/content-slot.js +6 -5
- package/dist/src/content-slot.js.map +1 -1
- package/dist/src/context.d.ts.map +1 -1
- package/dist/src/context.js +8 -1
- 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 +45 -0
- package/dist/src/debug/diagnostics.test.js.map +1 -0
- package/dist/src/debug/effects.d.ts +69 -0
- package/dist/src/debug/effects.d.ts.map +1 -0
- package/dist/src/debug/effects.js +228 -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 +86 -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 +40 -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 +89 -0
- package/dist/src/debug/files.test.js.map +1 -0
- package/dist/src/debug/index.d.ts +60 -0
- package/dist/src/debug/index.d.ts.map +1 -0
- package/dist/src/debug/index.js +68 -0
- package/dist/src/debug/index.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 +519 -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 +328 -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 +9 -0
- package/dist/src/debug/symbols.d.ts.map +1 -0
- package/dist/src/debug/symbols.js +164 -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 +104 -0
- package/dist/src/debug/symbols.test.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 +443 -0
- package/dist/src/debug/trace.js.map +1 -0
- package/dist/src/devtools/devtools-protocol.d.ts +232 -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 +28 -0
- package/dist/src/devtools/devtools-server.browser.d.ts.map +1 -0
- package/dist/src/devtools/devtools-server.browser.js +36 -0
- package/dist/src/devtools/devtools-server.browser.js.map +1 -0
- package/dist/src/devtools/devtools-server.d.ts +72 -0
- package/dist/src/devtools/devtools-server.d.ts.map +1 -0
- package/dist/src/devtools/devtools-server.js +256 -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 +15 -0
- package/dist/src/reactive-union-set.js.map +1 -1
- package/dist/src/reactivity.d.ts +17 -3
- package/dist/src/reactivity.d.ts.map +1 -1
- package/dist/src/reactivity.js +162 -14
- package/dist/src/reactivity.js.map +1 -1
- package/dist/src/render-stack.d.ts +17 -1
- package/dist/src/render-stack.d.ts.map +1 -1
- package/dist/src/render-stack.js +57 -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 +362 -103
- 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 +3 -0
- package/dist/src/scheduler.d.ts.map +1 -1
- package/dist/src/scheduler.js +45 -2
- 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 +23 -6
- 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 +22 -6
- 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 +5 -0
- 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/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/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 +26 -0
- package/dist/testing/devtools-utils.d.ts.map +1 -0
- package/dist/testing/devtools-utils.js +140 -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 +71 -16
- package/src/components/AppendFile.tsx +14 -9
- package/src/components/Block.tsx +1 -1
- package/src/components/Declaration.tsx +2 -1
- package/src/components/Scope.tsx +4 -1
- package/src/components/TemplateFile.tsx +18 -9
- package/src/content-slot.tsx +6 -6
- package/src/context.ts +15 -4
- package/src/{debug.ts → debug/cli.ts} +114 -125
- package/src/debug/diagnostics.test.tsx +55 -0
- package/src/debug/effects.test.tsx +96 -0
- package/src/debug/effects.ts +313 -0
- package/src/debug/files.test.tsx +96 -0
- package/src/debug/files.ts +40 -0
- package/src/debug/index.ts +126 -0
- package/src/debug/render.test.tsx +379 -0
- package/src/debug/render.ts +639 -0
- package/src/debug/serialize.ts +85 -0
- package/src/debug/symbols.test.tsx +106 -0
- package/src/debug/symbols.ts +230 -0
- package/src/debug/trace.ts +312 -0
- package/src/devtools/devtools-protocol.ts +312 -0
- package/src/devtools/devtools-server.browser.ts +71 -0
- package/src/devtools/devtools-server.ts +290 -0
- package/src/devtools/devtools-transport.ts +154 -0
- package/src/devtools-entry.browser.ts +52 -0
- package/src/devtools-entry.ts +54 -0
- package/src/diagnostics.ts +141 -0
- package/src/index.ts +2 -6
- package/src/print-hook.ts +22 -0
- package/src/reactive-union-set.ts +71 -41
- package/src/reactivity.ts +206 -23
- package/src/render-stack.ts +68 -1
- package/src/render.ts +464 -157
- package/src/resource.ts +28 -19
- package/src/scheduler.ts +55 -3
- package/src/symbols/basic-symbol.ts +6 -1
- package/src/symbols/decl.ts +5 -1
- package/src/symbols/output-scope.ts +21 -12
- package/src/symbols/output-symbol.ts +33 -12
- package/src/symbols/symbol-flow.ts +68 -37
- 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 +22 -13
- package/temp/api.json +1675 -162
- package/test/components/append-file.test.tsx +36 -29
- package/test/components/template-file.test.tsx +11 -11
- package/test/rendering/basic.test.tsx +4 -0
- package/test/rendering/print-render-stack.test.tsx +52 -43
- package/testing/create-test-wrapper.tsx +1 -1
- package/testing/devtools-utils.ts +203 -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
package/src/render.ts
CHANGED
|
@@ -1,8 +1,27 @@
|
|
|
1
|
-
import { isRef
|
|
1
|
+
import { isRef } from "@vue/reactivity";
|
|
2
2
|
import { Doc, doc } from "prettier";
|
|
3
3
|
import prettier from "prettier/doc.js";
|
|
4
4
|
import { useContext } from "./context.js";
|
|
5
5
|
import { SourceFileContext } from "./context/source-file.js";
|
|
6
|
+
import {
|
|
7
|
+
debug,
|
|
8
|
+
getRenderNodeId,
|
|
9
|
+
isDevtoolsEnabled,
|
|
10
|
+
type RenderTreeNodeInfo,
|
|
11
|
+
} from "./debug/index.js";
|
|
12
|
+
import { broadcastDevtoolsMessage } from "./devtools/devtools-server.js";
|
|
13
|
+
import {
|
|
14
|
+
attachDiagnosticsCollector,
|
|
15
|
+
DiagnosticsCollector,
|
|
16
|
+
emitDiagnostic,
|
|
17
|
+
reportDiagnostics,
|
|
18
|
+
} from "./diagnostics.js";
|
|
19
|
+
import {
|
|
20
|
+
isPrintHook,
|
|
21
|
+
printHookTag,
|
|
22
|
+
type PrintHook,
|
|
23
|
+
type RenderedTextTree,
|
|
24
|
+
} from "./print-hook.js";
|
|
6
25
|
import {
|
|
7
26
|
Context,
|
|
8
27
|
CustomContext,
|
|
@@ -10,11 +29,18 @@ import {
|
|
|
10
29
|
getContext,
|
|
11
30
|
getElementCache,
|
|
12
31
|
isCustomContext,
|
|
32
|
+
onCleanup,
|
|
33
|
+
ref,
|
|
13
34
|
root,
|
|
14
35
|
untrack,
|
|
15
36
|
} from "./reactivity.js";
|
|
16
37
|
import { isRefkeyable, toRefkey } from "./refkey.js";
|
|
17
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
getRenderStackSnapshot,
|
|
40
|
+
popStack,
|
|
41
|
+
printRenderStack,
|
|
42
|
+
pushStack,
|
|
43
|
+
} from "./render-stack.js";
|
|
18
44
|
import {
|
|
19
45
|
Child,
|
|
20
46
|
Children,
|
|
@@ -23,8 +49,91 @@ import {
|
|
|
23
49
|
RENDERABLE,
|
|
24
50
|
} from "./runtime/component.js";
|
|
25
51
|
import { IntrinsicElement, isIntrinsicElement } from "./runtime/intrinsic.js";
|
|
26
|
-
import { flushJobs, flushJobsAsync } from "./scheduler.js";
|
|
27
|
-
|
|
52
|
+
import { flushJobs, flushJobsAsync, waitForSignal } from "./scheduler.js";
|
|
53
|
+
|
|
54
|
+
const notifiedErrors = new WeakSet<object>();
|
|
55
|
+
let lastRenderError: {
|
|
56
|
+
error: { name: string; message: string; stack?: string };
|
|
57
|
+
componentStack: Array<{
|
|
58
|
+
name: string;
|
|
59
|
+
props?: Record<string, unknown> | undefined;
|
|
60
|
+
propsSerialized?: string;
|
|
61
|
+
renderNodeId?: number;
|
|
62
|
+
source?: RenderTreeNodeInfo["source"];
|
|
63
|
+
}>;
|
|
64
|
+
} | null = null;
|
|
65
|
+
|
|
66
|
+
function normalizeRenderError(error: unknown): {
|
|
67
|
+
name: string;
|
|
68
|
+
message: string;
|
|
69
|
+
stack?: string;
|
|
70
|
+
} {
|
|
71
|
+
if (error instanceof Error) {
|
|
72
|
+
return {
|
|
73
|
+
name: error.name || error.constructor?.name || "Error",
|
|
74
|
+
message: error.message || "",
|
|
75
|
+
stack: error.stack,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (error && typeof error === "object") {
|
|
79
|
+
const anyError = error as {
|
|
80
|
+
name?: string;
|
|
81
|
+
message?: string;
|
|
82
|
+
stack?: string;
|
|
83
|
+
};
|
|
84
|
+
return {
|
|
85
|
+
name: anyError.name || "Error",
|
|
86
|
+
message: anyError.message || String(error),
|
|
87
|
+
stack: anyError.stack,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
name: "Error",
|
|
92
|
+
message: String(error),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function notifyRenderError(error: unknown) {
|
|
97
|
+
if (error && typeof error === "object") {
|
|
98
|
+
if (notifiedErrors.has(error)) return;
|
|
99
|
+
notifiedErrors.add(error);
|
|
100
|
+
}
|
|
101
|
+
if (lastRenderError) return;
|
|
102
|
+
|
|
103
|
+
const { name, message, stack } = normalizeRenderError(error);
|
|
104
|
+
const componentStack = getRenderStackSnapshot().map((entry) => {
|
|
105
|
+
const renderNode = entry.context?.meta?.renderNode as
|
|
106
|
+
| RenderedTextTree
|
|
107
|
+
| undefined;
|
|
108
|
+
const renderNodeId = renderNode ? getRenderNodeId(renderNode) : undefined;
|
|
109
|
+
return {
|
|
110
|
+
name: entry.displayName,
|
|
111
|
+
props: entry.props as Record<string, unknown> | undefined,
|
|
112
|
+
renderNodeId,
|
|
113
|
+
source: entry.source,
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Output to console
|
|
118
|
+
printRenderStack(error);
|
|
119
|
+
|
|
120
|
+
// Send to devtools if enabled
|
|
121
|
+
debug.render.error({ name, message, stack }, componentStack);
|
|
122
|
+
|
|
123
|
+
// Store for diagnostics
|
|
124
|
+
lastRenderError = { error: { name, message, stack }, componentStack };
|
|
125
|
+
const lastEntry = componentStack.at(-1);
|
|
126
|
+
emitDiagnostic({
|
|
127
|
+
severity: "error",
|
|
128
|
+
message: `${name}: ${message}`,
|
|
129
|
+
source: lastEntry?.source,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function reportLastRenderError() {
|
|
134
|
+
// Error already reported in notifyRenderError via debug.renderError
|
|
135
|
+
lastRenderError = null;
|
|
136
|
+
}
|
|
28
137
|
|
|
29
138
|
const {
|
|
30
139
|
builders: {
|
|
@@ -150,23 +259,36 @@ export interface ContentOutputFile extends OutputFileBase {
|
|
|
150
259
|
export type OutputFile = ContentOutputFile | CopyOutputFile;
|
|
151
260
|
|
|
152
261
|
const nodesToContext = new WeakMap<RenderedTextTree, Context>();
|
|
262
|
+
const diagnosticsByTree = new WeakMap<RenderedTextTree, DiagnosticsCollector>();
|
|
153
263
|
|
|
154
264
|
export function getContextForRenderNode(node: RenderedTextTree) {
|
|
155
265
|
return nodesToContext.get(node);
|
|
156
266
|
}
|
|
157
267
|
|
|
158
|
-
export
|
|
268
|
+
export function getDiagnosticsForTree(tree: RenderedTextTree) {
|
|
269
|
+
return diagnosticsByTree.get(tree)?.getDiagnostics() ?? [];
|
|
270
|
+
}
|
|
159
271
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
272
|
+
function reportDiagnosticsForTree(tree: RenderedTextTree) {
|
|
273
|
+
const diagnostics = diagnosticsByTree.get(tree);
|
|
274
|
+
if (!diagnostics) return;
|
|
275
|
+
const entries = diagnostics.getDiagnostics();
|
|
276
|
+
if (entries.length === 0) return;
|
|
277
|
+
reportDiagnostics(diagnostics);
|
|
278
|
+
void broadcastDevtoolsMessage({
|
|
279
|
+
type: "diagnostics:report",
|
|
280
|
+
diagnostics: entries,
|
|
281
|
+
});
|
|
168
282
|
}
|
|
169
283
|
|
|
284
|
+
// Re-export from print-hook.ts to maintain backwards compatibility
|
|
285
|
+
export {
|
|
286
|
+
isPrintHook,
|
|
287
|
+
printHookTag,
|
|
288
|
+
type PrintHook,
|
|
289
|
+
type RenderedTextTree,
|
|
290
|
+
} from "./print-hook.js";
|
|
291
|
+
|
|
170
292
|
export function createRenderTreeHook(
|
|
171
293
|
subtree: RenderedTextTree,
|
|
172
294
|
hooks: Omit<PrintHook, typeof printHookTag | "subtree">,
|
|
@@ -178,12 +300,6 @@ export function createRenderTreeHook(
|
|
|
178
300
|
};
|
|
179
301
|
}
|
|
180
302
|
|
|
181
|
-
export function isPrintHook(type: unknown): type is PrintHook {
|
|
182
|
-
return typeof type === "object" && type !== null && printHookTag in type;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export type RenderedTextTree = (string | RenderedTextTree | PrintHook)[];
|
|
186
|
-
|
|
187
303
|
/**
|
|
188
304
|
* Render a component tree to source directories and files. Will ensure that
|
|
189
305
|
* all non-async scheduled jobs are completed before returning. If async jobs
|
|
@@ -196,7 +312,14 @@ export function render(
|
|
|
196
312
|
): OutputDirectory {
|
|
197
313
|
const tree = renderTree(children);
|
|
198
314
|
flushJobs();
|
|
199
|
-
|
|
315
|
+
const output = sourceFilesForTree(tree, options);
|
|
316
|
+
reportDiagnosticsForTree(tree);
|
|
317
|
+
reportLastRenderError();
|
|
318
|
+
debug.render.complete();
|
|
319
|
+
if (isDevtoolsEnabled()) {
|
|
320
|
+
void waitForSignal();
|
|
321
|
+
}
|
|
322
|
+
return output;
|
|
200
323
|
}
|
|
201
324
|
|
|
202
325
|
/**
|
|
@@ -207,23 +330,16 @@ export async function renderAsync(
|
|
|
207
330
|
children: Children,
|
|
208
331
|
options?: PrintTreeOptions,
|
|
209
332
|
): Promise<OutputDirectory> {
|
|
333
|
+
await debug.prepare();
|
|
210
334
|
const tree = renderTree(children);
|
|
211
|
-
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Convert a rendered text tree to source directories and files. Will ensure that
|
|
216
|
-
* all scheduled jobs are completed, including async ones.
|
|
217
|
-
*/
|
|
218
|
-
export async function sourceFilesForTreeAsync(
|
|
219
|
-
tree: RenderedTextTree,
|
|
220
|
-
options?: PrintTreeOptions,
|
|
221
|
-
) {
|
|
222
|
-
// if we await here, we ensure all reactive updates are flushed.
|
|
223
|
-
// sourceFilesForTree will flush again, but won't find anything, because tree
|
|
224
|
-
// printing won't schedule anything.
|
|
335
|
+
// Ensure all reactive updates are flushed before printing.
|
|
225
336
|
await flushJobsAsync();
|
|
226
|
-
|
|
337
|
+
const output = sourceFilesForTree(tree, options);
|
|
338
|
+
reportDiagnosticsForTree(tree);
|
|
339
|
+
reportLastRenderError();
|
|
340
|
+
debug.render.complete();
|
|
341
|
+
|
|
342
|
+
return output;
|
|
227
343
|
}
|
|
228
344
|
|
|
229
345
|
/**
|
|
@@ -239,9 +355,12 @@ export function sourceFilesForTree(
|
|
|
239
355
|
collectSourceFiles(undefined, tree);
|
|
240
356
|
|
|
241
357
|
if (!rootDirectory) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
358
|
+
emitDiagnostic({
|
|
359
|
+
severity: "error",
|
|
360
|
+
message:
|
|
361
|
+
"No root directory found. Make sure you are using the output component.",
|
|
362
|
+
});
|
|
363
|
+
return { kind: "directory", path: "", contents: [] };
|
|
245
364
|
}
|
|
246
365
|
|
|
247
366
|
return rootDirectory;
|
|
@@ -325,25 +444,35 @@ export function sourceFilesForTree(
|
|
|
325
444
|
}
|
|
326
445
|
export function renderTree(children: Children) {
|
|
327
446
|
const rootElem: RenderedTextTree = [];
|
|
447
|
+
const diagnostics = new DiagnosticsCollector();
|
|
448
|
+
lastRenderError = null;
|
|
449
|
+
debug.effect.reset();
|
|
450
|
+
debug.symbols.reset();
|
|
451
|
+
debug.files.reset();
|
|
452
|
+
debug.render.initialize(rootElem);
|
|
328
453
|
try {
|
|
329
454
|
root(() => {
|
|
455
|
+
attachDiagnosticsCollector(diagnostics);
|
|
330
456
|
renderWorker(rootElem, children);
|
|
331
457
|
});
|
|
332
458
|
} catch (e) {
|
|
333
|
-
|
|
459
|
+
notifyRenderError(e);
|
|
460
|
+
reportLastRenderError();
|
|
334
461
|
throw e;
|
|
335
462
|
}
|
|
336
463
|
|
|
464
|
+
diagnosticsByTree.set(rootElem, diagnostics);
|
|
465
|
+
|
|
337
466
|
return rootElem;
|
|
338
467
|
}
|
|
339
468
|
|
|
340
469
|
function renderWorker(node: RenderedTextTree, children: Children) {
|
|
470
|
+
if (lastRenderError) return;
|
|
341
471
|
if (!getContext()) {
|
|
342
472
|
throw new Error(
|
|
343
473
|
"Cannot render without a context. Make sure you are using the Output component.",
|
|
344
474
|
);
|
|
345
475
|
}
|
|
346
|
-
trace(TracePhase.render.worker, () => dumpChildren(children));
|
|
347
476
|
|
|
348
477
|
if (Array.isArray(node)) {
|
|
349
478
|
nodesToContext.set(node, getContext()!);
|
|
@@ -352,6 +481,7 @@ function renderWorker(node: RenderedTextTree, children: Children) {
|
|
|
352
481
|
if (Array.isArray(children)) {
|
|
353
482
|
for (const child of (children as any).flat(Infinity)) {
|
|
354
483
|
appendChild(node, child);
|
|
484
|
+
if (lastRenderError) break;
|
|
355
485
|
}
|
|
356
486
|
} else {
|
|
357
487
|
appendChild(node, children);
|
|
@@ -384,6 +514,10 @@ export function notifyContentState() {
|
|
|
384
514
|
break;
|
|
385
515
|
}
|
|
386
516
|
current.childrenWithContent--;
|
|
517
|
+
if (current.childrenWithContent > 0) {
|
|
518
|
+
// This isn't the last content so we have no work to do
|
|
519
|
+
break;
|
|
520
|
+
}
|
|
387
521
|
if (current.isEmpty) {
|
|
388
522
|
current.isEmpty.value = true;
|
|
389
523
|
}
|
|
@@ -419,95 +553,120 @@ export function notifyContentState() {
|
|
|
419
553
|
}
|
|
420
554
|
|
|
421
555
|
function appendChild(node: RenderedTextTree, rawChild: Child) {
|
|
422
|
-
|
|
556
|
+
if (lastRenderError) return;
|
|
423
557
|
const child = normalizeChild(rawChild);
|
|
424
558
|
|
|
425
559
|
if (typeof child === "string") {
|
|
426
560
|
if (child !== "") {
|
|
427
561
|
contentAdded();
|
|
562
|
+
debug.render.appendTextNode(node, node.length, child);
|
|
428
563
|
}
|
|
429
564
|
node.push(child);
|
|
430
565
|
} else {
|
|
431
566
|
const cache = getElementCache();
|
|
432
567
|
if (cache.has(child as any)) {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
568
|
+
const cachedNode = cache.get(child as any)!;
|
|
569
|
+
// recordSubtreeAdded detects cached nodes automatically and re-adds their children
|
|
570
|
+
if (isCustomContext(child)) {
|
|
571
|
+
debug.render.appendCustomContext(node, cachedNode);
|
|
572
|
+
} else {
|
|
573
|
+
debug.render.appendFragmentChild(node, cachedNode);
|
|
574
|
+
}
|
|
575
|
+
node.push(cachedNode);
|
|
438
576
|
return;
|
|
439
577
|
}
|
|
440
578
|
if (isCustomContext(child)) {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
() => "CustomContext: " + debugPrintChild(child),
|
|
444
|
-
);
|
|
579
|
+
const newNode: RenderedTextTree = [];
|
|
580
|
+
debug.render.appendCustomContext(node, newNode);
|
|
445
581
|
child.useCustomContext((children) => {
|
|
446
|
-
const newNode: RenderedTextTree = [];
|
|
447
582
|
renderWorker(newNode, children);
|
|
448
583
|
node.push(newNode);
|
|
449
584
|
cache.set(child, newNode);
|
|
450
585
|
notifyContentState();
|
|
586
|
+
notifyFileUpdateForNode(node);
|
|
451
587
|
});
|
|
452
588
|
} else if (isIntrinsicElement(child)) {
|
|
453
|
-
trace(
|
|
454
|
-
TracePhase.render.appendChild,
|
|
455
|
-
() => "IntrinsicElement: " + debugPrintChild(child),
|
|
456
|
-
);
|
|
457
589
|
// don't need a new context here because intrinsics are never reactive
|
|
590
|
+
const intrinsic = child as IntrinsicElement;
|
|
458
591
|
const newNode: RenderedTextTree = [];
|
|
459
592
|
|
|
460
593
|
function formatHookWithChildren(command: (doc: Doc) => Doc) {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
print(tree
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
594
|
+
const hook = createRenderTreeHook(newNode, {
|
|
595
|
+
print(tree, print) {
|
|
596
|
+
return command(print(tree));
|
|
597
|
+
},
|
|
598
|
+
});
|
|
599
|
+
debug.render.appendPrintHook(
|
|
600
|
+
node,
|
|
601
|
+
node.length,
|
|
602
|
+
hook,
|
|
603
|
+
intrinsic.name,
|
|
604
|
+
newNode,
|
|
467
605
|
);
|
|
606
|
+
node.push(hook);
|
|
468
607
|
renderWorker(newNode, (child as any).props.children);
|
|
608
|
+
notifyFileUpdateForNode(node);
|
|
469
609
|
}
|
|
470
610
|
|
|
471
611
|
function formatHook(command: Doc) {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
);
|
|
612
|
+
const hook = createRenderTreeHook(newNode, {
|
|
613
|
+
print() {
|
|
614
|
+
return command;
|
|
615
|
+
},
|
|
616
|
+
});
|
|
617
|
+
debug.render.appendPrintHook(node, node.length, hook, intrinsic.name);
|
|
618
|
+
node.push(hook);
|
|
619
|
+
return hook;
|
|
479
620
|
}
|
|
480
621
|
|
|
481
622
|
switch (child.name) {
|
|
482
623
|
case "indent":
|
|
483
624
|
return formatHookWithChildren(indent);
|
|
484
625
|
case "indentIfBreak":
|
|
485
|
-
|
|
486
|
-
createRenderTreeHook(newNode, {
|
|
626
|
+
{
|
|
627
|
+
const hook = createRenderTreeHook(newNode, {
|
|
487
628
|
print(tree, print) {
|
|
488
629
|
return indentIfBreak(print(tree), {
|
|
489
630
|
groupId: child.props.groupId,
|
|
490
631
|
negate: child.props.negate,
|
|
491
632
|
});
|
|
492
633
|
},
|
|
493
|
-
})
|
|
494
|
-
|
|
634
|
+
});
|
|
635
|
+
debug.render.appendPrintHook(
|
|
636
|
+
node,
|
|
637
|
+
node.length,
|
|
638
|
+
hook,
|
|
639
|
+
intrinsic.name,
|
|
640
|
+
newNode,
|
|
641
|
+
);
|
|
642
|
+
node.push(hook);
|
|
643
|
+
}
|
|
495
644
|
renderWorker(newNode, child.props.children);
|
|
645
|
+
notifyFileUpdateForNode(node);
|
|
496
646
|
return;
|
|
497
647
|
case "fill":
|
|
498
648
|
return formatHookWithChildren(fill as any);
|
|
499
649
|
case "group":
|
|
500
|
-
|
|
501
|
-
createRenderTreeHook(newNode, {
|
|
650
|
+
{
|
|
651
|
+
const hook = createRenderTreeHook(newNode, {
|
|
502
652
|
print(tree, print) {
|
|
503
653
|
return group(print(tree), {
|
|
504
654
|
id: child.props.id,
|
|
505
655
|
shouldBreak: child.props.shouldBreak,
|
|
506
656
|
});
|
|
507
657
|
},
|
|
508
|
-
})
|
|
509
|
-
|
|
658
|
+
});
|
|
659
|
+
debug.render.appendPrintHook(
|
|
660
|
+
node,
|
|
661
|
+
node.length,
|
|
662
|
+
hook,
|
|
663
|
+
intrinsic.name,
|
|
664
|
+
newNode,
|
|
665
|
+
);
|
|
666
|
+
node.push(hook);
|
|
667
|
+
}
|
|
510
668
|
renderWorker(newNode, child.props.children);
|
|
669
|
+
notifyFileUpdateForNode(node);
|
|
511
670
|
return;
|
|
512
671
|
case "line":
|
|
513
672
|
case "br":
|
|
@@ -522,17 +681,26 @@ function appendChild(node: RenderedTextTree, rawChild: Child) {
|
|
|
522
681
|
case "lbr":
|
|
523
682
|
return formatHook(literalline);
|
|
524
683
|
case "align":
|
|
525
|
-
|
|
526
|
-
createRenderTreeHook(newNode, {
|
|
684
|
+
{
|
|
685
|
+
const hook = createRenderTreeHook(newNode, {
|
|
527
686
|
print(tree, print) {
|
|
528
687
|
return align(
|
|
529
688
|
(child.props as any).width ?? (child.props as any).string!,
|
|
530
689
|
print(tree),
|
|
531
690
|
);
|
|
532
691
|
},
|
|
533
|
-
})
|
|
534
|
-
|
|
692
|
+
});
|
|
693
|
+
debug.render.appendPrintHook(
|
|
694
|
+
node,
|
|
695
|
+
node.length,
|
|
696
|
+
hook,
|
|
697
|
+
intrinsic.name,
|
|
698
|
+
newNode,
|
|
699
|
+
);
|
|
700
|
+
node.push(hook);
|
|
701
|
+
}
|
|
535
702
|
renderWorker(newNode, (child as any).props.children);
|
|
703
|
+
notifyFileUpdateForNode(node);
|
|
536
704
|
return;
|
|
537
705
|
case "lineSuffix":
|
|
538
706
|
return formatHookWithChildren(lineSuffix);
|
|
@@ -547,17 +715,33 @@ function appendChild(node: RenderedTextTree, rawChild: Child) {
|
|
|
547
715
|
case "markAsRoot":
|
|
548
716
|
return formatHookWithChildren(markAsRoot);
|
|
549
717
|
case "ifBreak":
|
|
550
|
-
|
|
551
|
-
createRenderTreeHook(newNode, {
|
|
718
|
+
{
|
|
719
|
+
const hook = createRenderTreeHook(newNode, {
|
|
552
720
|
print(tree, print) {
|
|
553
721
|
return ifBreak(
|
|
554
722
|
print((tree as RenderedTextTree[])[0]),
|
|
555
723
|
print((tree as RenderedTextTree[])[1]),
|
|
556
724
|
);
|
|
557
725
|
},
|
|
558
|
-
})
|
|
559
|
-
|
|
726
|
+
});
|
|
727
|
+
debug.render.appendPrintHook(
|
|
728
|
+
node,
|
|
729
|
+
node.length,
|
|
730
|
+
hook,
|
|
731
|
+
intrinsic.name,
|
|
732
|
+
newNode,
|
|
733
|
+
);
|
|
734
|
+
node.push(hook);
|
|
735
|
+
}
|
|
560
736
|
newNode.push([], []);
|
|
737
|
+
debug.render.appendFragmentChild(
|
|
738
|
+
newNode,
|
|
739
|
+
newNode[0] as RenderedTextTree,
|
|
740
|
+
);
|
|
741
|
+
debug.render.appendFragmentChild(
|
|
742
|
+
newNode,
|
|
743
|
+
newNode[1] as RenderedTextTree,
|
|
744
|
+
);
|
|
561
745
|
renderWorker(
|
|
562
746
|
newNode[0] as RenderedTextTree[],
|
|
563
747
|
(child as any).props.children,
|
|
@@ -566,66 +750,206 @@ function appendChild(node: RenderedTextTree, rawChild: Child) {
|
|
|
566
750
|
newNode[1] as RenderedTextTree[],
|
|
567
751
|
(child as any).props.flatContents,
|
|
568
752
|
);
|
|
753
|
+
notifyFileUpdateForNode(node);
|
|
569
754
|
return;
|
|
570
755
|
default:
|
|
571
756
|
throw new Error("Unknown intrinsic element");
|
|
572
757
|
}
|
|
573
758
|
} else if (isComponentCreator(child)) {
|
|
759
|
+
const index = node.length;
|
|
760
|
+
const rerenderToken = ref(0);
|
|
761
|
+
const breakNext = ref(false);
|
|
574
762
|
// todo: remove this effect (only needed for context, not needed for anything else)
|
|
575
|
-
effect(
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
763
|
+
effect(
|
|
764
|
+
() => {
|
|
765
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
766
|
+
rerenderToken.value;
|
|
767
|
+
const context = getContext();
|
|
768
|
+
context!.childrenWithContent = 0;
|
|
769
|
+
context!.isEmpty ??= ref(true);
|
|
770
|
+
|
|
771
|
+
if (context) context.componentOwner = child;
|
|
772
|
+
const existing = node[index];
|
|
773
|
+
const componentRoot: RenderedTextTree =
|
|
774
|
+
Array.isArray(existing) ? existing : [];
|
|
775
|
+
context!.meta ??= {};
|
|
776
|
+
context!.meta.renderNode = componentRoot;
|
|
777
|
+
const propsSource = (child.props ?? undefined) as
|
|
778
|
+
| Record<string, unknown>
|
|
779
|
+
| undefined;
|
|
780
|
+
const debugSession = debug.render.beginComponent({
|
|
781
|
+
parent: node,
|
|
782
|
+
index,
|
|
783
|
+
node: componentRoot,
|
|
784
|
+
component: child,
|
|
785
|
+
propsSource,
|
|
786
|
+
source: child.source,
|
|
787
|
+
isExisting: Array.isArray(existing),
|
|
788
|
+
actions: {
|
|
789
|
+
rerender: () => {
|
|
790
|
+
lastRenderError = null;
|
|
791
|
+
rerenderToken.value++;
|
|
792
|
+
},
|
|
793
|
+
rerenderAndBreak: () => {
|
|
794
|
+
lastRenderError = null;
|
|
795
|
+
breakNext.value = true;
|
|
796
|
+
rerenderToken.value++;
|
|
797
|
+
},
|
|
798
|
+
},
|
|
799
|
+
});
|
|
800
|
+
if (Array.isArray(existing)) {
|
|
801
|
+
componentRoot.length = 0;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
pushStack(child.component, child.props, child.source);
|
|
805
|
+
let renderFailed = false;
|
|
806
|
+
let childResult: Children | undefined;
|
|
807
|
+
try {
|
|
808
|
+
childResult = untrack(() => {
|
|
809
|
+
const shouldBreak = breakNext.value;
|
|
810
|
+
if (shouldBreak) {
|
|
811
|
+
breakNext.value = false;
|
|
812
|
+
// eslint-disable-next-line no-debugger
|
|
813
|
+
debugger;
|
|
814
|
+
}
|
|
815
|
+
return child();
|
|
816
|
+
});
|
|
817
|
+
} catch (error) {
|
|
818
|
+
notifyRenderError(error);
|
|
819
|
+
renderFailed = true;
|
|
820
|
+
throw error;
|
|
821
|
+
}
|
|
822
|
+
try {
|
|
823
|
+
if (context?.meta?.directory) {
|
|
824
|
+
debugSession.recordDirectory(context.meta.directory.path);
|
|
825
|
+
}
|
|
826
|
+
if (context?.meta?.sourceFile) {
|
|
827
|
+
context.meta.renderNode = componentRoot;
|
|
828
|
+
debugSession.recordFile(
|
|
829
|
+
context.meta.sourceFile.path,
|
|
830
|
+
context.meta.sourceFile.filetype,
|
|
831
|
+
);
|
|
832
|
+
context.meta.sourceFileReady = false;
|
|
833
|
+
}
|
|
834
|
+
if (!renderFailed) {
|
|
835
|
+
renderWorker(componentRoot, childResult);
|
|
836
|
+
}
|
|
837
|
+
} finally {
|
|
838
|
+
popStack();
|
|
839
|
+
}
|
|
840
|
+
if (renderFailed) {
|
|
841
|
+
node[index] = componentRoot;
|
|
842
|
+
cache.set(child, componentRoot);
|
|
843
|
+
notifyFileUpdateForNode(node);
|
|
844
|
+
notifyContentState();
|
|
845
|
+
onCleanup(() => debugSession.dispose());
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
if (context?.meta?.sourceFile) {
|
|
849
|
+
context.meta.sourceFileReady = true;
|
|
850
|
+
notifyFileUpdateForNode(componentRoot);
|
|
851
|
+
}
|
|
852
|
+
node[index] = componentRoot;
|
|
853
|
+
cache.set(child, componentRoot);
|
|
854
|
+
notifyContentState();
|
|
855
|
+
onCleanup(() => debugSession.dispose());
|
|
856
|
+
},
|
|
857
|
+
undefined,
|
|
858
|
+
{
|
|
859
|
+
debug: {
|
|
860
|
+
name: `render:${child.component.name || "Anonymous"}`,
|
|
861
|
+
type: "render",
|
|
862
|
+
},
|
|
863
|
+
},
|
|
864
|
+
);
|
|
602
865
|
} else if (typeof child === "function") {
|
|
603
|
-
trace(TracePhase.render.appendChild, () => "Memo: " + child.toString());
|
|
604
866
|
const index = node.length;
|
|
605
|
-
effect(
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
867
|
+
effect(
|
|
868
|
+
() => {
|
|
869
|
+
let res: Child | Children | undefined;
|
|
870
|
+
let renderFailed = false;
|
|
871
|
+
try {
|
|
872
|
+
res = child();
|
|
873
|
+
while (typeof res === "function" && !isComponentCreator(res)) {
|
|
874
|
+
res = res();
|
|
875
|
+
}
|
|
876
|
+
} catch (error) {
|
|
877
|
+
notifyRenderError(error);
|
|
878
|
+
renderFailed = true;
|
|
879
|
+
throw error;
|
|
880
|
+
}
|
|
881
|
+
const context = getContext();
|
|
882
|
+
context!.childrenWithContent = 0;
|
|
883
|
+
context!.isEmpty ??= ref(true);
|
|
884
|
+
|
|
885
|
+
const existing = node[index];
|
|
886
|
+
const memoNode: RenderedTextTree =
|
|
887
|
+
Array.isArray(existing) ? existing : [];
|
|
888
|
+
|
|
889
|
+
debug.render.prepareMemoNode(node, memoNode, Array.isArray(existing));
|
|
890
|
+
if (Array.isArray(existing)) {
|
|
891
|
+
memoNode.length = 0;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
if (!renderFailed) {
|
|
895
|
+
renderWorker(memoNode, res);
|
|
896
|
+
}
|
|
897
|
+
node[index] = memoNode;
|
|
898
|
+
cache.set(child, memoNode);
|
|
899
|
+
notifyFileUpdateForNode(node);
|
|
900
|
+
notifyContentState();
|
|
901
|
+
return memoNode;
|
|
902
|
+
},
|
|
903
|
+
undefined,
|
|
904
|
+
{
|
|
905
|
+
debug: {
|
|
906
|
+
name: `render:memo:${child.name || "anonymous"}`,
|
|
907
|
+
type: "render",
|
|
908
|
+
},
|
|
909
|
+
},
|
|
910
|
+
);
|
|
623
911
|
} else {
|
|
624
912
|
throw new Error("Unexpected child type");
|
|
625
913
|
}
|
|
626
914
|
}
|
|
627
915
|
}
|
|
628
916
|
|
|
917
|
+
function findSourceFileContext(node: RenderedTextTree) {
|
|
918
|
+
let context: Context | null | undefined =
|
|
919
|
+
getContextForRenderNode(node) ?? null;
|
|
920
|
+
while (context) {
|
|
921
|
+
if (context.meta?.sourceFile) return context;
|
|
922
|
+
context = context.owner;
|
|
923
|
+
}
|
|
924
|
+
return undefined;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
function notifyFileUpdateForNode(node: RenderedTextTree) {
|
|
928
|
+
// Only do the expensive printTree when devtools are actually enabled
|
|
929
|
+
if (!isDevtoolsEnabled()) return;
|
|
930
|
+
const context = findSourceFileContext(node);
|
|
931
|
+
if (!context?.meta?.sourceFile) return;
|
|
932
|
+
if (context.meta.sourceFileReady === false) return;
|
|
933
|
+
const sourceFile = context.meta.sourceFile;
|
|
934
|
+
const renderNode: RenderedTextTree =
|
|
935
|
+
(context.meta.renderNode as RenderedTextTree | undefined) ?? node;
|
|
936
|
+
// Pass noFlush here since it flushes jobs and can re-enter rendering
|
|
937
|
+
// during effect setup, triggering premature cleanup.
|
|
938
|
+
const contents = printTree(renderNode, {
|
|
939
|
+
printWidth: context.meta?.printOptions?.printWidth,
|
|
940
|
+
tabWidth: context.meta?.printOptions?.tabWidth,
|
|
941
|
+
useTabs: context.meta?.printOptions?.useTabs,
|
|
942
|
+
insertFinalNewLine: context.meta?.printOptions?.insertFinalNewLine ?? true,
|
|
943
|
+
noFlush: true,
|
|
944
|
+
});
|
|
945
|
+
|
|
946
|
+
debug.files.updated({
|
|
947
|
+
path: sourceFile.path,
|
|
948
|
+
filetype: sourceFile.filetype,
|
|
949
|
+
contents,
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
|
|
629
953
|
type NormalizedChildren = NormalizedChild | NormalizedChildren[];
|
|
630
954
|
type NormalizedChild =
|
|
631
955
|
| string
|
|
@@ -668,31 +992,6 @@ function normalizeChild(child: Child): NormalizedChildren {
|
|
|
668
992
|
}
|
|
669
993
|
}
|
|
670
994
|
|
|
671
|
-
function dumpChildren(children: Children): string {
|
|
672
|
-
if (Array.isArray(children)) {
|
|
673
|
-
return `[ ${children.map(debugPrintChild).join(", ")} ]`;
|
|
674
|
-
}
|
|
675
|
-
return debugPrintChild(children);
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
function debugPrintChild(child: Children): string {
|
|
679
|
-
if (isComponentCreator(child)) {
|
|
680
|
-
return "<" + child.component.name + ">";
|
|
681
|
-
} else if (typeof child === "function") {
|
|
682
|
-
return "$memo";
|
|
683
|
-
} else if (isRef(child)) {
|
|
684
|
-
return "$ref";
|
|
685
|
-
} else if (isIntrinsicElement(child)) {
|
|
686
|
-
return `<${child.name}>`;
|
|
687
|
-
} else if (isRenderableObject(child)) {
|
|
688
|
-
return `CustomChildElement(${JSON.stringify(child)})`;
|
|
689
|
-
} else if (isRefkeyable(child)) {
|
|
690
|
-
return `refkey`;
|
|
691
|
-
} else {
|
|
692
|
-
return JSON.stringify(child);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
|
|
696
995
|
export interface PrintTreeOptions {
|
|
697
996
|
/**
|
|
698
997
|
* The number of characters the printer will wrap on. Defaults to 100
|
|
@@ -715,6 +1014,12 @@ export interface PrintTreeOptions {
|
|
|
715
1014
|
* @default true
|
|
716
1015
|
*/
|
|
717
1016
|
insertFinalNewLine?: boolean;
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* Skip flushing scheduled jobs before printing.
|
|
1020
|
+
* @default false
|
|
1021
|
+
*/
|
|
1022
|
+
noFlush?: boolean;
|
|
718
1023
|
}
|
|
719
1024
|
|
|
720
1025
|
const defaultPrintTreeOptions: PrintTreeOptions = {
|
|
@@ -734,8 +1039,10 @@ export function printTree(tree: RenderedTextTree, options?: PrintTreeOptions) {
|
|
|
734
1039
|
),
|
|
735
1040
|
};
|
|
736
1041
|
|
|
737
|
-
|
|
738
|
-
|
|
1042
|
+
if (!options.noFlush) {
|
|
1043
|
+
// make sure queue is empty
|
|
1044
|
+
flushJobs();
|
|
1045
|
+
}
|
|
739
1046
|
|
|
740
1047
|
const d = printTreeWorker(tree);
|
|
741
1048
|
const result = doc.printer.printDocToString(
|