@alloy-js/core 0.23.0-dev.1 → 0.23.0-dev.10
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/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/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/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 +45 -0
- package/dist/src/debug/diagnostics.test.js.map +1 -0
- package/dist/src/debug/effects.d.ts +73 -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 +84 -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 +61 -0
- package/dist/src/debug/index.d.ts.map +1 -0
- package/dist/src/debug/index.js +69 -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 +15 -0
- package/dist/src/debug/symbols.d.ts.map +1 -0
- package/dist/src/debug/symbols.js +173 -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 +28 -3
- package/dist/src/reactive-union-set.js.map +1 -1
- package/dist/src/reactivity.d.ts +50 -8
- package/dist/src/reactivity.d.ts.map +1 -1
- package/dist/src/reactivity.js +225 -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 +370 -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 +8 -0
- package/dist/src/scheduler.d.ts.map +1 -1
- package/dist/src/scheduler.js +69 -3
- 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 +7 -5
- 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 +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/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/Prose.tsx +1 -1
- package/src/components/Scope.tsx +6 -1
- package/src/components/SourceDirectory.tsx +1 -2
- 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 +55 -0
- package/src/debug/effects.test.tsx +89 -0
- package/src/debug/effects.ts +317 -0
- package/src/debug/files.test.tsx +96 -0
- package/src/debug/files.ts +40 -0
- package/src/debug/index.ts +128 -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 +239 -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 -7
- package/src/print-hook.ts +22 -0
- package/src/reactive-union-set.ts +85 -44
- package/src/reactivity.ts +301 -59
- package/src/render-stack.ts +73 -1
- package/src/render.ts +470 -161
- package/src/resource.ts +28 -19
- package/src/scheduler.ts +80 -4
- 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 +24 -17
- package/temp/api.json +5658 -3095
- 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 +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);
|
|
@@ -368,11 +498,12 @@ export function notifyContentState() {
|
|
|
368
498
|
const startContext = getContext()!;
|
|
369
499
|
|
|
370
500
|
if (startContext.childrenWithContent === 0) {
|
|
371
|
-
if (startContext.
|
|
501
|
+
if (startContext._lastEmpty) {
|
|
372
502
|
// it was already empty, no work to do.
|
|
373
503
|
return;
|
|
374
504
|
}
|
|
375
505
|
|
|
506
|
+
startContext._lastEmpty = true;
|
|
376
507
|
if (startContext.isEmpty) {
|
|
377
508
|
startContext.isEmpty.value = true;
|
|
378
509
|
}
|
|
@@ -384,18 +515,24 @@ export function notifyContentState() {
|
|
|
384
515
|
break;
|
|
385
516
|
}
|
|
386
517
|
current.childrenWithContent--;
|
|
518
|
+
if (current.childrenWithContent > 0) {
|
|
519
|
+
// This isn't the last content so we have no work to do
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
current._lastEmpty = true;
|
|
387
523
|
if (current.isEmpty) {
|
|
388
524
|
current.isEmpty.value = true;
|
|
389
525
|
}
|
|
390
526
|
current = current.owner;
|
|
391
527
|
}
|
|
392
528
|
} else {
|
|
393
|
-
if (startContext.
|
|
529
|
+
if (!startContext._lastEmpty) {
|
|
394
530
|
// it was already non-empty, no work to do.
|
|
395
531
|
return;
|
|
396
532
|
}
|
|
397
533
|
|
|
398
|
-
|
|
534
|
+
startContext._lastEmpty = false;
|
|
535
|
+
if (startContext.isEmpty) {
|
|
399
536
|
startContext.isEmpty.value = false;
|
|
400
537
|
}
|
|
401
538
|
|
|
@@ -408,7 +545,8 @@ export function notifyContentState() {
|
|
|
408
545
|
break;
|
|
409
546
|
}
|
|
410
547
|
|
|
411
|
-
|
|
548
|
+
current._lastEmpty = false;
|
|
549
|
+
if (current.isEmpty) {
|
|
412
550
|
current.isEmpty.value = false;
|
|
413
551
|
}
|
|
414
552
|
|
|
@@ -419,95 +557,120 @@ export function notifyContentState() {
|
|
|
419
557
|
}
|
|
420
558
|
|
|
421
559
|
function appendChild(node: RenderedTextTree, rawChild: Child) {
|
|
422
|
-
|
|
560
|
+
if (lastRenderError) return;
|
|
423
561
|
const child = normalizeChild(rawChild);
|
|
424
562
|
|
|
425
563
|
if (typeof child === "string") {
|
|
426
564
|
if (child !== "") {
|
|
427
565
|
contentAdded();
|
|
566
|
+
debug.render.appendTextNode(node, node.length, child);
|
|
428
567
|
}
|
|
429
568
|
node.push(child);
|
|
430
569
|
} else {
|
|
431
570
|
const cache = getElementCache();
|
|
432
571
|
if (cache.has(child as any)) {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
572
|
+
const cachedNode = cache.get(child as any)!;
|
|
573
|
+
// recordSubtreeAdded detects cached nodes automatically and re-adds their children
|
|
574
|
+
if (isCustomContext(child)) {
|
|
575
|
+
debug.render.appendCustomContext(node, cachedNode);
|
|
576
|
+
} else {
|
|
577
|
+
debug.render.appendFragmentChild(node, cachedNode);
|
|
578
|
+
}
|
|
579
|
+
node.push(cachedNode);
|
|
438
580
|
return;
|
|
439
581
|
}
|
|
440
582
|
if (isCustomContext(child)) {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
() => "CustomContext: " + debugPrintChild(child),
|
|
444
|
-
);
|
|
583
|
+
const newNode: RenderedTextTree = [];
|
|
584
|
+
debug.render.appendCustomContext(node, newNode);
|
|
445
585
|
child.useCustomContext((children) => {
|
|
446
|
-
const newNode: RenderedTextTree = [];
|
|
447
586
|
renderWorker(newNode, children);
|
|
448
587
|
node.push(newNode);
|
|
449
588
|
cache.set(child, newNode);
|
|
450
589
|
notifyContentState();
|
|
590
|
+
notifyFileUpdateForNode(node);
|
|
451
591
|
});
|
|
452
592
|
} else if (isIntrinsicElement(child)) {
|
|
453
|
-
trace(
|
|
454
|
-
TracePhase.render.appendChild,
|
|
455
|
-
() => "IntrinsicElement: " + debugPrintChild(child),
|
|
456
|
-
);
|
|
457
593
|
// don't need a new context here because intrinsics are never reactive
|
|
594
|
+
const intrinsic = child as IntrinsicElement;
|
|
458
595
|
const newNode: RenderedTextTree = [];
|
|
459
596
|
|
|
460
597
|
function formatHookWithChildren(command: (doc: Doc) => Doc) {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
print(tree
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
598
|
+
const hook = createRenderTreeHook(newNode, {
|
|
599
|
+
print(tree, print) {
|
|
600
|
+
return command(print(tree));
|
|
601
|
+
},
|
|
602
|
+
});
|
|
603
|
+
debug.render.appendPrintHook(
|
|
604
|
+
node,
|
|
605
|
+
node.length,
|
|
606
|
+
hook,
|
|
607
|
+
intrinsic.name,
|
|
608
|
+
newNode,
|
|
467
609
|
);
|
|
610
|
+
node.push(hook);
|
|
468
611
|
renderWorker(newNode, (child as any).props.children);
|
|
612
|
+
notifyFileUpdateForNode(node);
|
|
469
613
|
}
|
|
470
614
|
|
|
471
615
|
function formatHook(command: Doc) {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
);
|
|
616
|
+
const hook = createRenderTreeHook(newNode, {
|
|
617
|
+
print() {
|
|
618
|
+
return command;
|
|
619
|
+
},
|
|
620
|
+
});
|
|
621
|
+
debug.render.appendPrintHook(node, node.length, hook, intrinsic.name);
|
|
622
|
+
node.push(hook);
|
|
623
|
+
return hook;
|
|
479
624
|
}
|
|
480
625
|
|
|
481
626
|
switch (child.name) {
|
|
482
627
|
case "indent":
|
|
483
628
|
return formatHookWithChildren(indent);
|
|
484
629
|
case "indentIfBreak":
|
|
485
|
-
|
|
486
|
-
createRenderTreeHook(newNode, {
|
|
630
|
+
{
|
|
631
|
+
const hook = createRenderTreeHook(newNode, {
|
|
487
632
|
print(tree, print) {
|
|
488
633
|
return indentIfBreak(print(tree), {
|
|
489
634
|
groupId: child.props.groupId,
|
|
490
635
|
negate: child.props.negate,
|
|
491
636
|
});
|
|
492
637
|
},
|
|
493
|
-
})
|
|
494
|
-
|
|
638
|
+
});
|
|
639
|
+
debug.render.appendPrintHook(
|
|
640
|
+
node,
|
|
641
|
+
node.length,
|
|
642
|
+
hook,
|
|
643
|
+
intrinsic.name,
|
|
644
|
+
newNode,
|
|
645
|
+
);
|
|
646
|
+
node.push(hook);
|
|
647
|
+
}
|
|
495
648
|
renderWorker(newNode, child.props.children);
|
|
649
|
+
notifyFileUpdateForNode(node);
|
|
496
650
|
return;
|
|
497
651
|
case "fill":
|
|
498
652
|
return formatHookWithChildren(fill as any);
|
|
499
653
|
case "group":
|
|
500
|
-
|
|
501
|
-
createRenderTreeHook(newNode, {
|
|
654
|
+
{
|
|
655
|
+
const hook = createRenderTreeHook(newNode, {
|
|
502
656
|
print(tree, print) {
|
|
503
657
|
return group(print(tree), {
|
|
504
658
|
id: child.props.id,
|
|
505
659
|
shouldBreak: child.props.shouldBreak,
|
|
506
660
|
});
|
|
507
661
|
},
|
|
508
|
-
})
|
|
509
|
-
|
|
662
|
+
});
|
|
663
|
+
debug.render.appendPrintHook(
|
|
664
|
+
node,
|
|
665
|
+
node.length,
|
|
666
|
+
hook,
|
|
667
|
+
intrinsic.name,
|
|
668
|
+
newNode,
|
|
669
|
+
);
|
|
670
|
+
node.push(hook);
|
|
671
|
+
}
|
|
510
672
|
renderWorker(newNode, child.props.children);
|
|
673
|
+
notifyFileUpdateForNode(node);
|
|
511
674
|
return;
|
|
512
675
|
case "line":
|
|
513
676
|
case "br":
|
|
@@ -522,17 +685,26 @@ function appendChild(node: RenderedTextTree, rawChild: Child) {
|
|
|
522
685
|
case "lbr":
|
|
523
686
|
return formatHook(literalline);
|
|
524
687
|
case "align":
|
|
525
|
-
|
|
526
|
-
createRenderTreeHook(newNode, {
|
|
688
|
+
{
|
|
689
|
+
const hook = createRenderTreeHook(newNode, {
|
|
527
690
|
print(tree, print) {
|
|
528
691
|
return align(
|
|
529
692
|
(child.props as any).width ?? (child.props as any).string!,
|
|
530
693
|
print(tree),
|
|
531
694
|
);
|
|
532
695
|
},
|
|
533
|
-
})
|
|
534
|
-
|
|
696
|
+
});
|
|
697
|
+
debug.render.appendPrintHook(
|
|
698
|
+
node,
|
|
699
|
+
node.length,
|
|
700
|
+
hook,
|
|
701
|
+
intrinsic.name,
|
|
702
|
+
newNode,
|
|
703
|
+
);
|
|
704
|
+
node.push(hook);
|
|
705
|
+
}
|
|
535
706
|
renderWorker(newNode, (child as any).props.children);
|
|
707
|
+
notifyFileUpdateForNode(node);
|
|
536
708
|
return;
|
|
537
709
|
case "lineSuffix":
|
|
538
710
|
return formatHookWithChildren(lineSuffix);
|
|
@@ -547,17 +719,33 @@ function appendChild(node: RenderedTextTree, rawChild: Child) {
|
|
|
547
719
|
case "markAsRoot":
|
|
548
720
|
return formatHookWithChildren(markAsRoot);
|
|
549
721
|
case "ifBreak":
|
|
550
|
-
|
|
551
|
-
createRenderTreeHook(newNode, {
|
|
722
|
+
{
|
|
723
|
+
const hook = createRenderTreeHook(newNode, {
|
|
552
724
|
print(tree, print) {
|
|
553
725
|
return ifBreak(
|
|
554
726
|
print((tree as RenderedTextTree[])[0]),
|
|
555
727
|
print((tree as RenderedTextTree[])[1]),
|
|
556
728
|
);
|
|
557
729
|
},
|
|
558
|
-
})
|
|
559
|
-
|
|
730
|
+
});
|
|
731
|
+
debug.render.appendPrintHook(
|
|
732
|
+
node,
|
|
733
|
+
node.length,
|
|
734
|
+
hook,
|
|
735
|
+
intrinsic.name,
|
|
736
|
+
newNode,
|
|
737
|
+
);
|
|
738
|
+
node.push(hook);
|
|
739
|
+
}
|
|
560
740
|
newNode.push([], []);
|
|
741
|
+
debug.render.appendFragmentChild(
|
|
742
|
+
newNode,
|
|
743
|
+
newNode[0] as RenderedTextTree,
|
|
744
|
+
);
|
|
745
|
+
debug.render.appendFragmentChild(
|
|
746
|
+
newNode,
|
|
747
|
+
newNode[1] as RenderedTextTree,
|
|
748
|
+
);
|
|
561
749
|
renderWorker(
|
|
562
750
|
newNode[0] as RenderedTextTree[],
|
|
563
751
|
(child as any).props.children,
|
|
@@ -566,66 +754,204 @@ function appendChild(node: RenderedTextTree, rawChild: Child) {
|
|
|
566
754
|
newNode[1] as RenderedTextTree[],
|
|
567
755
|
(child as any).props.flatContents,
|
|
568
756
|
);
|
|
757
|
+
notifyFileUpdateForNode(node);
|
|
569
758
|
return;
|
|
570
759
|
default:
|
|
571
760
|
throw new Error("Unknown intrinsic element");
|
|
572
761
|
}
|
|
573
762
|
} else if (isComponentCreator(child)) {
|
|
763
|
+
const index = node.length;
|
|
764
|
+
const rerenderToken = isDevtoolsEnabled() ? ref(0) : undefined;
|
|
765
|
+
const breakNext = isDevtoolsEnabled() ? ref(false) : undefined;
|
|
574
766
|
// 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
|
-
|
|
767
|
+
effect(
|
|
768
|
+
() => {
|
|
769
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
770
|
+
rerenderToken?.value;
|
|
771
|
+
const context = getContext();
|
|
772
|
+
context!.childrenWithContent = 0;
|
|
773
|
+
|
|
774
|
+
if (context) context.componentOwner = child;
|
|
775
|
+
const existing = node[index];
|
|
776
|
+
const componentRoot: RenderedTextTree =
|
|
777
|
+
Array.isArray(existing) ? existing : [];
|
|
778
|
+
context!.meta ??= {};
|
|
779
|
+
context!.meta.renderNode = componentRoot;
|
|
780
|
+
const propsSource = (child.props ?? undefined) as
|
|
781
|
+
| Record<string, unknown>
|
|
782
|
+
| undefined;
|
|
783
|
+
const debugSession = debug.render.beginComponent({
|
|
784
|
+
parent: node,
|
|
785
|
+
index,
|
|
786
|
+
node: componentRoot,
|
|
787
|
+
component: child,
|
|
788
|
+
propsSource,
|
|
789
|
+
source: child.source,
|
|
790
|
+
isExisting: Array.isArray(existing),
|
|
791
|
+
actions: {
|
|
792
|
+
rerender: () => {
|
|
793
|
+
lastRenderError = null;
|
|
794
|
+
if (rerenderToken) rerenderToken.value++;
|
|
795
|
+
},
|
|
796
|
+
rerenderAndBreak: () => {
|
|
797
|
+
lastRenderError = null;
|
|
798
|
+
if (breakNext) breakNext.value = true;
|
|
799
|
+
if (rerenderToken) rerenderToken.value++;
|
|
800
|
+
},
|
|
801
|
+
},
|
|
802
|
+
});
|
|
803
|
+
if (Array.isArray(existing)) {
|
|
804
|
+
componentRoot.length = 0;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
pushStack(child.component, child.props, child.source);
|
|
808
|
+
let renderFailed = false;
|
|
809
|
+
let childResult: Children | undefined;
|
|
810
|
+
try {
|
|
811
|
+
childResult = untrack(() => {
|
|
812
|
+
const shouldBreak = breakNext?.value;
|
|
813
|
+
if (shouldBreak) {
|
|
814
|
+
breakNext!.value = false;
|
|
815
|
+
// eslint-disable-next-line no-debugger
|
|
816
|
+
debugger;
|
|
817
|
+
}
|
|
818
|
+
return child();
|
|
819
|
+
});
|
|
820
|
+
} catch (error) {
|
|
821
|
+
notifyRenderError(error);
|
|
822
|
+
renderFailed = true;
|
|
823
|
+
throw error;
|
|
824
|
+
}
|
|
825
|
+
try {
|
|
826
|
+
if (context?.meta?.directory) {
|
|
827
|
+
debugSession.recordDirectory(context.meta.directory.path);
|
|
828
|
+
}
|
|
829
|
+
if (context?.meta?.sourceFile) {
|
|
830
|
+
context.meta.renderNode = componentRoot;
|
|
831
|
+
debugSession.recordFile(
|
|
832
|
+
context.meta.sourceFile.path,
|
|
833
|
+
context.meta.sourceFile.filetype,
|
|
834
|
+
);
|
|
835
|
+
context.meta.sourceFileReady = false;
|
|
836
|
+
}
|
|
837
|
+
if (!renderFailed) {
|
|
838
|
+
renderWorker(componentRoot, childResult);
|
|
839
|
+
}
|
|
840
|
+
} finally {
|
|
841
|
+
popStack();
|
|
842
|
+
}
|
|
843
|
+
if (renderFailed) {
|
|
844
|
+
node[index] = componentRoot;
|
|
845
|
+
cache.set(child, componentRoot);
|
|
846
|
+
notifyFileUpdateForNode(node);
|
|
847
|
+
notifyContentState();
|
|
848
|
+
onCleanup(() => debugSession.dispose());
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
if (context?.meta?.sourceFile) {
|
|
852
|
+
context.meta.sourceFileReady = true;
|
|
853
|
+
notifyFileUpdateForNode(componentRoot);
|
|
854
|
+
}
|
|
855
|
+
node[index] = componentRoot;
|
|
856
|
+
cache.set(child, componentRoot);
|
|
857
|
+
notifyContentState();
|
|
858
|
+
onCleanup(() => debugSession.dispose());
|
|
859
|
+
},
|
|
860
|
+
undefined,
|
|
861
|
+
{
|
|
862
|
+
debug: {
|
|
863
|
+
name: `render:${child.component.name || "Anonymous"}`,
|
|
864
|
+
type: "render",
|
|
865
|
+
},
|
|
866
|
+
},
|
|
867
|
+
);
|
|
602
868
|
} else if (typeof child === "function") {
|
|
603
|
-
trace(TracePhase.render.appendChild, () => "Memo: " + child.toString());
|
|
604
869
|
const index = node.length;
|
|
605
|
-
effect(
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
870
|
+
effect(
|
|
871
|
+
() => {
|
|
872
|
+
let res: Child | Children | undefined;
|
|
873
|
+
let renderFailed = false;
|
|
874
|
+
try {
|
|
875
|
+
res = child();
|
|
876
|
+
while (typeof res === "function" && !isComponentCreator(res)) {
|
|
877
|
+
res = res();
|
|
878
|
+
}
|
|
879
|
+
} catch (error) {
|
|
880
|
+
notifyRenderError(error);
|
|
881
|
+
renderFailed = true;
|
|
882
|
+
throw error;
|
|
883
|
+
}
|
|
884
|
+
const context = getContext();
|
|
885
|
+
context!.childrenWithContent = 0;
|
|
886
|
+
|
|
887
|
+
const existing = node[index];
|
|
888
|
+
const memoNode: RenderedTextTree =
|
|
889
|
+
Array.isArray(existing) ? existing : [];
|
|
890
|
+
|
|
891
|
+
debug.render.prepareMemoNode(node, memoNode, Array.isArray(existing));
|
|
892
|
+
if (Array.isArray(existing)) {
|
|
893
|
+
memoNode.length = 0;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
if (!renderFailed) {
|
|
897
|
+
renderWorker(memoNode, res);
|
|
898
|
+
}
|
|
899
|
+
node[index] = memoNode;
|
|
900
|
+
cache.set(child, memoNode);
|
|
901
|
+
notifyFileUpdateForNode(node);
|
|
902
|
+
notifyContentState();
|
|
903
|
+
return memoNode;
|
|
904
|
+
},
|
|
905
|
+
undefined,
|
|
906
|
+
{
|
|
907
|
+
debug: {
|
|
908
|
+
name: `render:memo:${child.name || "anonymous"}`,
|
|
909
|
+
type: "render",
|
|
910
|
+
},
|
|
911
|
+
},
|
|
912
|
+
);
|
|
623
913
|
} else {
|
|
624
914
|
throw new Error("Unexpected child type");
|
|
625
915
|
}
|
|
626
916
|
}
|
|
627
917
|
}
|
|
628
918
|
|
|
919
|
+
function findSourceFileContext(node: RenderedTextTree) {
|
|
920
|
+
let context: Context | null | undefined =
|
|
921
|
+
getContextForRenderNode(node) ?? null;
|
|
922
|
+
while (context) {
|
|
923
|
+
if (context.meta?.sourceFile) return context;
|
|
924
|
+
context = context.owner;
|
|
925
|
+
}
|
|
926
|
+
return undefined;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
function notifyFileUpdateForNode(node: RenderedTextTree) {
|
|
930
|
+
// Only do the expensive printTree when devtools are actually enabled
|
|
931
|
+
if (!isDevtoolsEnabled()) return;
|
|
932
|
+
const context = findSourceFileContext(node);
|
|
933
|
+
if (!context?.meta?.sourceFile) return;
|
|
934
|
+
if (context.meta.sourceFileReady === false) return;
|
|
935
|
+
const sourceFile = context.meta.sourceFile;
|
|
936
|
+
const renderNode: RenderedTextTree =
|
|
937
|
+
(context.meta.renderNode as RenderedTextTree | undefined) ?? node;
|
|
938
|
+
// Pass noFlush here since it flushes jobs and can re-enter rendering
|
|
939
|
+
// during effect setup, triggering premature cleanup.
|
|
940
|
+
const contents = printTree(renderNode, {
|
|
941
|
+
printWidth: context.meta?.printOptions?.printWidth,
|
|
942
|
+
tabWidth: context.meta?.printOptions?.tabWidth,
|
|
943
|
+
useTabs: context.meta?.printOptions?.useTabs,
|
|
944
|
+
insertFinalNewLine: context.meta?.printOptions?.insertFinalNewLine ?? true,
|
|
945
|
+
noFlush: true,
|
|
946
|
+
});
|
|
947
|
+
|
|
948
|
+
debug.files.updated({
|
|
949
|
+
path: sourceFile.path,
|
|
950
|
+
filetype: sourceFile.filetype,
|
|
951
|
+
contents,
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
|
|
629
955
|
type NormalizedChildren = NormalizedChild | NormalizedChildren[];
|
|
630
956
|
type NormalizedChild =
|
|
631
957
|
| string
|
|
@@ -668,31 +994,6 @@ function normalizeChild(child: Child): NormalizedChildren {
|
|
|
668
994
|
}
|
|
669
995
|
}
|
|
670
996
|
|
|
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
997
|
export interface PrintTreeOptions {
|
|
697
998
|
/**
|
|
698
999
|
* The number of characters the printer will wrap on. Defaults to 100
|
|
@@ -715,6 +1016,12 @@ export interface PrintTreeOptions {
|
|
|
715
1016
|
* @default true
|
|
716
1017
|
*/
|
|
717
1018
|
insertFinalNewLine?: boolean;
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* Skip flushing scheduled jobs before printing.
|
|
1022
|
+
* @default false
|
|
1023
|
+
*/
|
|
1024
|
+
noFlush?: boolean;
|
|
718
1025
|
}
|
|
719
1026
|
|
|
720
1027
|
const defaultPrintTreeOptions: PrintTreeOptions = {
|
|
@@ -734,8 +1041,10 @@ export function printTree(tree: RenderedTextTree, options?: PrintTreeOptions) {
|
|
|
734
1041
|
),
|
|
735
1042
|
};
|
|
736
1043
|
|
|
737
|
-
|
|
738
|
-
|
|
1044
|
+
if (!options.noFlush) {
|
|
1045
|
+
// make sure queue is empty
|
|
1046
|
+
flushJobs();
|
|
1047
|
+
}
|
|
739
1048
|
|
|
740
1049
|
const d = printTreeWorker(tree);
|
|
741
1050
|
const result = doc.printer.printDocToString(
|