@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
package/dist/src/render.js
CHANGED
|
@@ -1,15 +1,122 @@
|
|
|
1
|
-
import { isRef
|
|
1
|
+
import { isRef } from "@vue/reactivity";
|
|
2
2
|
import { 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 {
|
|
6
|
+
import { debug, getRenderNodeId, isDevtoolsConnected, isDevtoolsEnabled } from "./debug/index.js";
|
|
7
|
+
import { beginTransaction, closeTrace, commitTransaction, notifyDiagnosticsReport } from "./debug/trace-writer.js";
|
|
8
|
+
import { isTraceEnabled } from "./debug/trace.js";
|
|
9
|
+
import { attachDiagnosticsCollector, DiagnosticsCollector, emitDiagnostic, reportDiagnostics } from "./diagnostics.js";
|
|
10
|
+
import { isPrintHook, printHookTag } from "./print-hook.js";
|
|
11
|
+
import { effect, getContext, getElementCache, isCustomContext, onCleanup, ref, root, untrack } from "./reactivity.js";
|
|
7
12
|
import { isRefkeyable, toRefkey } from "./refkey.js";
|
|
8
|
-
import { popStack, printRenderStack, pushStack } from "./render-stack.js";
|
|
13
|
+
import { getRenderStackSnapshot, popStack, printRenderStack, pushStack } from "./render-stack.js";
|
|
9
14
|
import { isComponentCreator, isRenderableObject, RENDERABLE } from "./runtime/component.js";
|
|
10
15
|
import { isIntrinsicElement } from "./runtime/intrinsic.js";
|
|
11
|
-
import { flushJobs, flushJobsAsync } from "./scheduler.js";
|
|
12
|
-
|
|
16
|
+
import { flushJobs, flushJobsAsync, waitForSignal } from "./scheduler.js";
|
|
17
|
+
const notifiedErrors = new WeakSet();
|
|
18
|
+
|
|
19
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
+
// Deferred file printing: mark files dirty during render, print once at end
|
|
21
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
const dirtyFiles = new Map();
|
|
24
|
+
const lastFlushTimeByFile = new Map();
|
|
25
|
+
const DEVTOOLS_FLUSH_INTERVAL_MS = 1000;
|
|
26
|
+
function flushDirtyFile(path) {
|
|
27
|
+
const entry = dirtyFiles.get(path);
|
|
28
|
+
if (!entry) return;
|
|
29
|
+
dirtyFiles.delete(path);
|
|
30
|
+
const contents = printTree(entry.renderNode, {
|
|
31
|
+
...entry.printOptions,
|
|
32
|
+
insertFinalNewLine: entry.printOptions.insertFinalNewLine ?? true,
|
|
33
|
+
noFlush: true
|
|
34
|
+
});
|
|
35
|
+
debug.files.updated({
|
|
36
|
+
path: entry.path,
|
|
37
|
+
filetype: entry.filetype,
|
|
38
|
+
contents
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function flushDirtyFiles() {
|
|
42
|
+
for (const path of [...dirtyFiles.keys()]) {
|
|
43
|
+
flushDirtyFile(path);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
let lastRenderError = null;
|
|
47
|
+
function normalizeRenderError(error) {
|
|
48
|
+
if (error instanceof Error) {
|
|
49
|
+
return {
|
|
50
|
+
name: error.name || error.constructor?.name || "Error",
|
|
51
|
+
message: error.message || "",
|
|
52
|
+
stack: error.stack
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (error && typeof error === "object") {
|
|
56
|
+
const anyError = error;
|
|
57
|
+
return {
|
|
58
|
+
name: anyError.name || "Error",
|
|
59
|
+
message: anyError.message || String(error),
|
|
60
|
+
stack: anyError.stack
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
name: "Error",
|
|
65
|
+
message: String(error)
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function notifyRenderError(error) {
|
|
69
|
+
if (error && typeof error === "object") {
|
|
70
|
+
if (notifiedErrors.has(error)) return;
|
|
71
|
+
notifiedErrors.add(error);
|
|
72
|
+
}
|
|
73
|
+
if (lastRenderError) return;
|
|
74
|
+
const {
|
|
75
|
+
name,
|
|
76
|
+
message,
|
|
77
|
+
stack
|
|
78
|
+
} = normalizeRenderError(error);
|
|
79
|
+
const componentStack = getRenderStackSnapshot().map(entry => {
|
|
80
|
+
const renderNode = entry.context?.meta?.renderNode;
|
|
81
|
+
const renderNodeId = renderNode ? getRenderNodeId(renderNode) : undefined;
|
|
82
|
+
return {
|
|
83
|
+
name: entry.displayName,
|
|
84
|
+
props: entry.props,
|
|
85
|
+
renderNodeId,
|
|
86
|
+
source: entry.source
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Output to console
|
|
91
|
+
printRenderStack(error);
|
|
92
|
+
|
|
93
|
+
// Send to devtools if enabled
|
|
94
|
+
debug.render.error({
|
|
95
|
+
name,
|
|
96
|
+
message,
|
|
97
|
+
stack
|
|
98
|
+
}, componentStack);
|
|
99
|
+
|
|
100
|
+
// Store for diagnostics
|
|
101
|
+
lastRenderError = {
|
|
102
|
+
error: {
|
|
103
|
+
name,
|
|
104
|
+
message,
|
|
105
|
+
stack
|
|
106
|
+
},
|
|
107
|
+
componentStack
|
|
108
|
+
};
|
|
109
|
+
const lastEntry = componentStack.at(-1);
|
|
110
|
+
emitDiagnostic({
|
|
111
|
+
severity: "error",
|
|
112
|
+
message: `${name}: ${message}`,
|
|
113
|
+
source: lastEntry?.source
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
function reportLastRenderError() {
|
|
117
|
+
// Error already reported in notifyRenderError via debug.renderError
|
|
118
|
+
lastRenderError = null;
|
|
119
|
+
}
|
|
13
120
|
const {
|
|
14
121
|
builders: {
|
|
15
122
|
align,
|
|
@@ -112,10 +219,24 @@ const {
|
|
|
112
219
|
*/
|
|
113
220
|
|
|
114
221
|
const nodesToContext = new WeakMap();
|
|
222
|
+
const diagnosticsByTree = new WeakMap();
|
|
115
223
|
export function getContextForRenderNode(node) {
|
|
116
224
|
return nodesToContext.get(node);
|
|
117
225
|
}
|
|
118
|
-
export
|
|
226
|
+
export function getDiagnosticsForTree(tree) {
|
|
227
|
+
return diagnosticsByTree.get(tree)?.getDiagnostics() ?? [];
|
|
228
|
+
}
|
|
229
|
+
function reportDiagnosticsForTree(tree) {
|
|
230
|
+
const diagnostics = diagnosticsByTree.get(tree);
|
|
231
|
+
if (!diagnostics) return;
|
|
232
|
+
const entries = diagnostics.getDiagnostics();
|
|
233
|
+
if (entries.length === 0) return;
|
|
234
|
+
reportDiagnostics(diagnostics);
|
|
235
|
+
notifyDiagnosticsReport(entries);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Re-export from print-hook.ts to maintain backwards compatibility
|
|
239
|
+
export { isPrintHook, printHookTag } from "./print-hook.js";
|
|
119
240
|
export function createRenderTreeHook(subtree, hooks) {
|
|
120
241
|
return {
|
|
121
242
|
[printHookTag]: true,
|
|
@@ -123,9 +244,7 @@ export function createRenderTreeHook(subtree, hooks) {
|
|
|
123
244
|
...hooks
|
|
124
245
|
};
|
|
125
246
|
}
|
|
126
|
-
|
|
127
|
-
return typeof type === "object" && type !== null && printHookTag in type;
|
|
128
|
-
}
|
|
247
|
+
|
|
129
248
|
/**
|
|
130
249
|
* Render a component tree to source directories and files. Will ensure that
|
|
131
250
|
* all non-async scheduled jobs are completed before returning. If async jobs
|
|
@@ -135,7 +254,18 @@ export function isPrintHook(type) {
|
|
|
135
254
|
export function render(children, options) {
|
|
136
255
|
const tree = renderTree(children);
|
|
137
256
|
flushJobs();
|
|
138
|
-
|
|
257
|
+
const output = sourceFilesForTree(tree, options);
|
|
258
|
+
flushDirtyFiles();
|
|
259
|
+
reportDiagnosticsForTree(tree);
|
|
260
|
+
reportLastRenderError();
|
|
261
|
+
debug.render.complete();
|
|
262
|
+
// Only close the trace DB when devtools is NOT running. When devtools is
|
|
263
|
+
// active the DB must remain open for post-render reactive updates.
|
|
264
|
+
if (isTraceEnabled() && !isDevtoolsEnabled()) closeTrace();
|
|
265
|
+
if (isDevtoolsEnabled()) {
|
|
266
|
+
void waitForSignal();
|
|
267
|
+
}
|
|
268
|
+
return output;
|
|
139
269
|
}
|
|
140
270
|
|
|
141
271
|
/**
|
|
@@ -143,20 +273,19 @@ export function render(children, options) {
|
|
|
143
273
|
* scheduled jobs are completed before returning.
|
|
144
274
|
*/
|
|
145
275
|
export async function renderAsync(children, options) {
|
|
276
|
+
await debug.prepare();
|
|
146
277
|
const tree = renderTree(children);
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Convert a rendered text tree to source directories and files. Will ensure that
|
|
152
|
-
* all scheduled jobs are completed, including async ones.
|
|
153
|
-
*/
|
|
154
|
-
export async function sourceFilesForTreeAsync(tree, options) {
|
|
155
|
-
// if we await here, we ensure all reactive updates are flushed.
|
|
156
|
-
// sourceFilesForTree will flush again, but won't find anything, because tree
|
|
157
|
-
// printing won't schedule anything.
|
|
278
|
+
// Ensure all reactive updates are flushed before printing.
|
|
158
279
|
await flushJobsAsync();
|
|
159
|
-
|
|
280
|
+
const output = sourceFilesForTree(tree, options);
|
|
281
|
+
flushDirtyFiles();
|
|
282
|
+
reportDiagnosticsForTree(tree);
|
|
283
|
+
reportLastRenderError();
|
|
284
|
+
debug.render.complete();
|
|
285
|
+
// Only close the trace DB when devtools is NOT running. When devtools is
|
|
286
|
+
// active the DB must remain open for post-render reactive updates.
|
|
287
|
+
if (isTraceEnabled() && !isDevtoolsEnabled()) closeTrace();
|
|
288
|
+
return output;
|
|
160
289
|
}
|
|
161
290
|
|
|
162
291
|
/**
|
|
@@ -167,7 +296,15 @@ export function sourceFilesForTree(tree, options) {
|
|
|
167
296
|
let rootDirectory = undefined;
|
|
168
297
|
collectSourceFiles(undefined, tree);
|
|
169
298
|
if (!rootDirectory) {
|
|
170
|
-
|
|
299
|
+
emitDiagnostic({
|
|
300
|
+
severity: "error",
|
|
301
|
+
message: "No root directory found. Make sure you are using the output component."
|
|
302
|
+
});
|
|
303
|
+
return {
|
|
304
|
+
kind: "directory",
|
|
305
|
+
path: "",
|
|
306
|
+
contents: []
|
|
307
|
+
};
|
|
171
308
|
}
|
|
172
309
|
return rootDirectory;
|
|
173
310
|
function collectSourceFiles(currentDirectory, root) {
|
|
@@ -230,27 +367,43 @@ export function sourceFilesForTree(tree, options) {
|
|
|
230
367
|
}
|
|
231
368
|
export function renderTree(children) {
|
|
232
369
|
const rootElem = [];
|
|
370
|
+
const diagnostics = new DiagnosticsCollector();
|
|
371
|
+
lastRenderError = null;
|
|
372
|
+
debug.effect.reset();
|
|
373
|
+
debug.symbols.reset();
|
|
374
|
+
debug.files.reset();
|
|
375
|
+
dirtyFiles.clear();
|
|
376
|
+
lastFlushTimeByFile.clear();
|
|
377
|
+
debug.render.initialize(rootElem);
|
|
378
|
+
if (isTraceEnabled()) beginTransaction();
|
|
233
379
|
try {
|
|
234
380
|
root(() => {
|
|
381
|
+
attachDiagnosticsCollector(diagnostics);
|
|
235
382
|
renderWorker(rootElem, children);
|
|
236
383
|
});
|
|
237
384
|
} catch (e) {
|
|
238
|
-
|
|
385
|
+
if (isTraceEnabled()) commitTransaction();
|
|
386
|
+
flushDirtyFiles();
|
|
387
|
+
notifyRenderError(e);
|
|
388
|
+
reportLastRenderError();
|
|
239
389
|
throw e;
|
|
240
390
|
}
|
|
391
|
+
if (isTraceEnabled()) commitTransaction();
|
|
392
|
+
diagnosticsByTree.set(rootElem, diagnostics);
|
|
241
393
|
return rootElem;
|
|
242
394
|
}
|
|
243
395
|
function renderWorker(node, children) {
|
|
396
|
+
if (lastRenderError) return;
|
|
244
397
|
if (!getContext()) {
|
|
245
398
|
throw new Error("Cannot render without a context. Make sure you are using the Output component.");
|
|
246
399
|
}
|
|
247
|
-
trace(TracePhase.render.worker, () => dumpChildren(children));
|
|
248
400
|
if (Array.isArray(node)) {
|
|
249
401
|
nodesToContext.set(node, getContext());
|
|
250
402
|
}
|
|
251
403
|
if (Array.isArray(children)) {
|
|
252
404
|
for (const child of children.flat(Infinity)) {
|
|
253
405
|
appendChild(node, child);
|
|
406
|
+
if (lastRenderError) break;
|
|
254
407
|
}
|
|
255
408
|
} else {
|
|
256
409
|
appendChild(node, children);
|
|
@@ -264,10 +417,11 @@ export function notifyContentState() {
|
|
|
264
417
|
untrack(() => {
|
|
265
418
|
const startContext = getContext();
|
|
266
419
|
if (startContext.childrenWithContent === 0) {
|
|
267
|
-
if (startContext.
|
|
420
|
+
if (startContext._lastEmpty) {
|
|
268
421
|
// it was already empty, no work to do.
|
|
269
422
|
return;
|
|
270
423
|
}
|
|
424
|
+
startContext._lastEmpty = true;
|
|
271
425
|
if (startContext.isEmpty) {
|
|
272
426
|
startContext.isEmpty.value = true;
|
|
273
427
|
}
|
|
@@ -279,17 +433,23 @@ export function notifyContentState() {
|
|
|
279
433
|
break;
|
|
280
434
|
}
|
|
281
435
|
current.childrenWithContent--;
|
|
436
|
+
if (current.childrenWithContent > 0) {
|
|
437
|
+
// This isn't the last content so we have no work to do
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
current._lastEmpty = true;
|
|
282
441
|
if (current.isEmpty) {
|
|
283
442
|
current.isEmpty.value = true;
|
|
284
443
|
}
|
|
285
444
|
current = current.owner;
|
|
286
445
|
}
|
|
287
446
|
} else {
|
|
288
|
-
if (startContext.
|
|
447
|
+
if (!startContext._lastEmpty) {
|
|
289
448
|
// it was already non-empty, no work to do.
|
|
290
449
|
return;
|
|
291
450
|
}
|
|
292
|
-
|
|
451
|
+
startContext._lastEmpty = false;
|
|
452
|
+
if (startContext.isEmpty) {
|
|
293
453
|
startContext.isEmpty.value = false;
|
|
294
454
|
}
|
|
295
455
|
|
|
@@ -301,7 +461,8 @@ export function notifyContentState() {
|
|
|
301
461
|
// This isn't the first content so we have no work to do
|
|
302
462
|
break;
|
|
303
463
|
}
|
|
304
|
-
|
|
464
|
+
current._lastEmpty = false;
|
|
465
|
+
if (current.isEmpty) {
|
|
305
466
|
current.isEmpty.value = false;
|
|
306
467
|
}
|
|
307
468
|
current = current.owner;
|
|
@@ -310,74 +471,98 @@ export function notifyContentState() {
|
|
|
310
471
|
});
|
|
311
472
|
}
|
|
312
473
|
function appendChild(node, rawChild) {
|
|
313
|
-
|
|
474
|
+
if (lastRenderError) return;
|
|
314
475
|
const child = normalizeChild(rawChild);
|
|
315
476
|
if (typeof child === "string") {
|
|
316
477
|
if (child !== "") {
|
|
317
478
|
contentAdded();
|
|
479
|
+
debug.render.appendTextNode(node, node.length, child);
|
|
318
480
|
}
|
|
319
481
|
node.push(child);
|
|
320
482
|
} else {
|
|
321
483
|
const cache = getElementCache();
|
|
322
484
|
if (cache.has(child)) {
|
|
323
|
-
|
|
324
|
-
|
|
485
|
+
const cachedNode = cache.get(child);
|
|
486
|
+
// recordSubtreeAdded detects cached nodes automatically and re-adds their children
|
|
487
|
+
if (isCustomContext(child)) {
|
|
488
|
+
debug.render.appendCustomContext(node, cachedNode);
|
|
489
|
+
} else {
|
|
490
|
+
debug.render.appendFragmentChild(node, cachedNode);
|
|
491
|
+
}
|
|
492
|
+
node.push(cachedNode);
|
|
325
493
|
return;
|
|
326
494
|
}
|
|
327
495
|
if (isCustomContext(child)) {
|
|
328
|
-
|
|
496
|
+
const newNode = [];
|
|
497
|
+
debug.render.appendCustomContext(node, newNode);
|
|
329
498
|
child.useCustomContext(children => {
|
|
330
|
-
const newNode = [];
|
|
331
499
|
renderWorker(newNode, children);
|
|
332
500
|
node.push(newNode);
|
|
333
501
|
cache.set(child, newNode);
|
|
334
502
|
notifyContentState();
|
|
503
|
+
notifyFileUpdateForNode(node);
|
|
335
504
|
});
|
|
336
505
|
} else if (isIntrinsicElement(child)) {
|
|
337
|
-
trace(TracePhase.render.appendChild, () => "IntrinsicElement: " + debugPrintChild(child));
|
|
338
506
|
// don't need a new context here because intrinsics are never reactive
|
|
507
|
+
const intrinsic = child;
|
|
339
508
|
const newNode = [];
|
|
340
509
|
function formatHookWithChildren(command) {
|
|
341
|
-
|
|
510
|
+
const hook = createRenderTreeHook(newNode, {
|
|
342
511
|
print(tree, print) {
|
|
343
512
|
return command(print(tree));
|
|
344
513
|
}
|
|
345
|
-
})
|
|
514
|
+
});
|
|
515
|
+
debug.render.appendPrintHook(node, node.length, hook, intrinsic.name, newNode);
|
|
516
|
+
node.push(hook);
|
|
346
517
|
renderWorker(newNode, child.props.children);
|
|
518
|
+
notifyFileUpdateForNode(node);
|
|
347
519
|
}
|
|
348
520
|
function formatHook(command) {
|
|
349
|
-
|
|
521
|
+
const hook = createRenderTreeHook(newNode, {
|
|
350
522
|
print() {
|
|
351
523
|
return command;
|
|
352
524
|
}
|
|
353
|
-
})
|
|
525
|
+
});
|
|
526
|
+
debug.render.appendPrintHook(node, node.length, hook, intrinsic.name);
|
|
527
|
+
node.push(hook);
|
|
528
|
+
return hook;
|
|
354
529
|
}
|
|
355
530
|
switch (child.name) {
|
|
356
531
|
case "indent":
|
|
357
532
|
return formatHookWithChildren(indent);
|
|
358
533
|
case "indentIfBreak":
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
534
|
+
{
|
|
535
|
+
const hook = createRenderTreeHook(newNode, {
|
|
536
|
+
print(tree, print) {
|
|
537
|
+
return indentIfBreak(print(tree), {
|
|
538
|
+
groupId: child.props.groupId,
|
|
539
|
+
negate: child.props.negate
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
debug.render.appendPrintHook(node, node.length, hook, intrinsic.name, newNode);
|
|
544
|
+
node.push(hook);
|
|
545
|
+
}
|
|
367
546
|
renderWorker(newNode, child.props.children);
|
|
547
|
+
notifyFileUpdateForNode(node);
|
|
368
548
|
return;
|
|
369
549
|
case "fill":
|
|
370
550
|
return formatHookWithChildren(fill);
|
|
371
551
|
case "group":
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
552
|
+
{
|
|
553
|
+
const hook = createRenderTreeHook(newNode, {
|
|
554
|
+
print(tree, print) {
|
|
555
|
+
return group(print(tree), {
|
|
556
|
+
id: child.props.id,
|
|
557
|
+
shouldBreak: child.props.shouldBreak
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
debug.render.appendPrintHook(node, node.length, hook, intrinsic.name, newNode);
|
|
562
|
+
node.push(hook);
|
|
563
|
+
}
|
|
380
564
|
renderWorker(newNode, child.props.children);
|
|
565
|
+
notifyFileUpdateForNode(node);
|
|
381
566
|
return;
|
|
382
567
|
case "line":
|
|
383
568
|
case "br":
|
|
@@ -392,12 +577,17 @@ function appendChild(node, rawChild) {
|
|
|
392
577
|
case "lbr":
|
|
393
578
|
return formatHook(literalline);
|
|
394
579
|
case "align":
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
580
|
+
{
|
|
581
|
+
const hook = createRenderTreeHook(newNode, {
|
|
582
|
+
print(tree, print) {
|
|
583
|
+
return align(child.props.width ?? child.props.string, print(tree));
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
debug.render.appendPrintHook(node, node.length, hook, intrinsic.name, newNode);
|
|
587
|
+
node.push(hook);
|
|
588
|
+
}
|
|
400
589
|
renderWorker(newNode, child.props.children);
|
|
590
|
+
notifyFileUpdateForNode(node);
|
|
401
591
|
return;
|
|
402
592
|
case "lineSuffix":
|
|
403
593
|
return formatHookWithChildren(lineSuffix);
|
|
@@ -412,59 +602,206 @@ function appendChild(node, rawChild) {
|
|
|
412
602
|
case "markAsRoot":
|
|
413
603
|
return formatHookWithChildren(markAsRoot);
|
|
414
604
|
case "ifBreak":
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
605
|
+
{
|
|
606
|
+
const hook = createRenderTreeHook(newNode, {
|
|
607
|
+
print(tree, print) {
|
|
608
|
+
return ifBreak(print(tree[0]), print(tree[1]));
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
debug.render.appendPrintHook(node, node.length, hook, intrinsic.name, newNode);
|
|
612
|
+
node.push(hook);
|
|
613
|
+
}
|
|
420
614
|
newNode.push([], []);
|
|
615
|
+
debug.render.appendFragmentChild(newNode, newNode[0]);
|
|
616
|
+
debug.render.appendFragmentChild(newNode, newNode[1]);
|
|
421
617
|
renderWorker(newNode[0], child.props.children);
|
|
422
618
|
renderWorker(newNode[1], child.props.flatContents);
|
|
619
|
+
notifyFileUpdateForNode(node);
|
|
423
620
|
return;
|
|
424
621
|
default:
|
|
425
622
|
throw new Error("Unknown intrinsic element");
|
|
426
623
|
}
|
|
427
624
|
} else if (isComponentCreator(child)) {
|
|
625
|
+
const index = node.length;
|
|
626
|
+
const rerenderToken = isDevtoolsEnabled() ? ref(0, {
|
|
627
|
+
isInfrastructure: true
|
|
628
|
+
}) : undefined;
|
|
629
|
+
const breakNext = isDevtoolsEnabled() ? ref(false, {
|
|
630
|
+
isInfrastructure: true
|
|
631
|
+
}) : undefined;
|
|
428
632
|
// todo: remove this effect (only needed for context, not needed for anything else)
|
|
429
633
|
effect(() => {
|
|
430
|
-
|
|
634
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
635
|
+
rerenderToken?.value;
|
|
431
636
|
const context = getContext();
|
|
432
637
|
context.childrenWithContent = 0;
|
|
433
|
-
context.isEmpty ??= ref(true);
|
|
434
638
|
if (context) context.componentOwner = child;
|
|
435
|
-
const
|
|
639
|
+
const existing = node[index];
|
|
640
|
+
const componentRoot = Array.isArray(existing) ? existing : [];
|
|
641
|
+
context.meta ??= {};
|
|
642
|
+
context.meta.renderNode = componentRoot;
|
|
643
|
+
const propsSource = child.props ?? undefined;
|
|
644
|
+
const debugSession = debug.render.beginComponent({
|
|
645
|
+
parent: node,
|
|
646
|
+
index,
|
|
647
|
+
node: componentRoot,
|
|
648
|
+
component: child,
|
|
649
|
+
propsSource,
|
|
650
|
+
source: child.source,
|
|
651
|
+
isExisting: Array.isArray(existing),
|
|
652
|
+
actions: {
|
|
653
|
+
rerender: rerenderToken ? () => {
|
|
654
|
+
lastRenderError = null;
|
|
655
|
+
rerenderToken.value++;
|
|
656
|
+
} : () => {},
|
|
657
|
+
rerenderAndBreak: breakNext && rerenderToken ? () => {
|
|
658
|
+
lastRenderError = null;
|
|
659
|
+
breakNext.value = true;
|
|
660
|
+
rerenderToken.value++;
|
|
661
|
+
} : () => {}
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
if (Array.isArray(existing)) {
|
|
665
|
+
componentRoot.length = 0;
|
|
666
|
+
}
|
|
436
667
|
pushStack(child.component, child.props, child.source);
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
668
|
+
let renderFailed = false;
|
|
669
|
+
let childResult;
|
|
670
|
+
try {
|
|
671
|
+
childResult = untrack(() => {
|
|
672
|
+
const shouldBreak = breakNext?.value ?? false;
|
|
673
|
+
if (shouldBreak) {
|
|
674
|
+
breakNext.value = false;
|
|
675
|
+
// eslint-disable-next-line no-debugger
|
|
676
|
+
debugger;
|
|
677
|
+
}
|
|
678
|
+
return child();
|
|
679
|
+
});
|
|
680
|
+
} catch (error) {
|
|
681
|
+
notifyRenderError(error);
|
|
682
|
+
renderFailed = true;
|
|
683
|
+
throw error;
|
|
684
|
+
}
|
|
685
|
+
try {
|
|
686
|
+
if (context?.meta?.directory) {
|
|
687
|
+
debugSession.recordDirectory(context.meta.directory.path);
|
|
688
|
+
}
|
|
689
|
+
if (context?.meta?.sourceFile) {
|
|
690
|
+
context.meta.renderNode = componentRoot;
|
|
691
|
+
debugSession.recordFile(context.meta.sourceFile.path, context.meta.sourceFile.filetype);
|
|
692
|
+
context.meta.sourceFileReady = false;
|
|
693
|
+
}
|
|
694
|
+
if (!renderFailed) {
|
|
695
|
+
renderWorker(componentRoot, childResult);
|
|
696
|
+
}
|
|
697
|
+
} finally {
|
|
698
|
+
popStack();
|
|
699
|
+
}
|
|
700
|
+
if (renderFailed) {
|
|
701
|
+
node[index] = componentRoot;
|
|
702
|
+
cache.set(child, componentRoot);
|
|
703
|
+
notifyFileUpdateForNode(node);
|
|
704
|
+
notifyContentState();
|
|
705
|
+
onCleanup(() => debugSession.dispose());
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
if (context?.meta?.sourceFile) {
|
|
709
|
+
context.meta.sourceFileReady = true;
|
|
710
|
+
notifyFileUpdateForNode(componentRoot);
|
|
711
|
+
}
|
|
712
|
+
node[index] = componentRoot;
|
|
440
713
|
cache.set(child, componentRoot);
|
|
441
714
|
notifyContentState();
|
|
442
|
-
|
|
715
|
+
onCleanup(() => debugSession.dispose());
|
|
716
|
+
}, undefined, {
|
|
717
|
+
debug: {
|
|
718
|
+
name: `render:${child.component.name || "Anonymous"}`,
|
|
719
|
+
type: "render"
|
|
720
|
+
}
|
|
443
721
|
});
|
|
444
722
|
} else if (typeof child === "function") {
|
|
445
|
-
trace(TracePhase.render.appendChild, () => "Memo: " + child.toString());
|
|
446
723
|
const index = node.length;
|
|
447
724
|
effect(() => {
|
|
448
|
-
|
|
449
|
-
let
|
|
450
|
-
|
|
451
|
-
res =
|
|
725
|
+
let res;
|
|
726
|
+
let renderFailed = false;
|
|
727
|
+
try {
|
|
728
|
+
res = child();
|
|
729
|
+
while (typeof res === "function" && !isComponentCreator(res)) {
|
|
730
|
+
res = res();
|
|
731
|
+
}
|
|
732
|
+
} catch (error) {
|
|
733
|
+
notifyRenderError(error);
|
|
734
|
+
renderFailed = true;
|
|
735
|
+
throw error;
|
|
452
736
|
}
|
|
453
737
|
const context = getContext();
|
|
454
738
|
context.childrenWithContent = 0;
|
|
455
|
-
|
|
456
|
-
const
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
739
|
+
const existing = node[index];
|
|
740
|
+
const memoNode = Array.isArray(existing) ? existing : [];
|
|
741
|
+
debug.render.prepareMemoNode(node, memoNode, Array.isArray(existing));
|
|
742
|
+
if (Array.isArray(existing)) {
|
|
743
|
+
memoNode.length = 0;
|
|
744
|
+
}
|
|
745
|
+
if (!renderFailed) {
|
|
746
|
+
renderWorker(memoNode, res);
|
|
747
|
+
}
|
|
748
|
+
node[index] = memoNode;
|
|
749
|
+
cache.set(child, memoNode);
|
|
750
|
+
notifyFileUpdateForNode(node);
|
|
460
751
|
notifyContentState();
|
|
461
|
-
return
|
|
752
|
+
return memoNode;
|
|
753
|
+
}, undefined, {
|
|
754
|
+
debug: {
|
|
755
|
+
name: `render:memo:${child.name || "anonymous"}`,
|
|
756
|
+
type: "render"
|
|
757
|
+
}
|
|
462
758
|
});
|
|
463
759
|
} else {
|
|
464
760
|
throw new Error("Unexpected child type");
|
|
465
761
|
}
|
|
466
762
|
}
|
|
467
763
|
}
|
|
764
|
+
function findSourceFileContext(node) {
|
|
765
|
+
let context = getContextForRenderNode(node) ?? null;
|
|
766
|
+
while (context) {
|
|
767
|
+
if (context.meta?.sourceFile) return context;
|
|
768
|
+
context = context.owner;
|
|
769
|
+
}
|
|
770
|
+
return undefined;
|
|
771
|
+
}
|
|
772
|
+
function notifyFileUpdateForNode(node) {
|
|
773
|
+
// Only track when devtools or trace are actually enabled
|
|
774
|
+
if (!isDevtoolsEnabled() && !isTraceEnabled()) return;
|
|
775
|
+
const context = findSourceFileContext(node);
|
|
776
|
+
if (!context?.meta?.sourceFile) return;
|
|
777
|
+
if (context.meta.sourceFileReady === false) return;
|
|
778
|
+
const sourceFile = context.meta.sourceFile;
|
|
779
|
+
const renderNode = context.meta.renderNode ?? node;
|
|
780
|
+
|
|
781
|
+
// Mark this file as dirty — defer the expensive printTree to end of render
|
|
782
|
+
dirtyFiles.set(sourceFile.path, {
|
|
783
|
+
renderNode,
|
|
784
|
+
printOptions: {
|
|
785
|
+
printWidth: context.meta?.printOptions?.printWidth,
|
|
786
|
+
tabWidth: context.meta?.printOptions?.tabWidth,
|
|
787
|
+
useTabs: context.meta?.printOptions?.useTabs,
|
|
788
|
+
insertFinalNewLine: context.meta?.printOptions?.insertFinalNewLine
|
|
789
|
+
},
|
|
790
|
+
path: sourceFile.path,
|
|
791
|
+
filetype: sourceFile.filetype
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
// When a devtools client is connected, throttle file flushing to ~1s per file
|
|
795
|
+
// so the user can watch content build up during rendering.
|
|
796
|
+
if (isDevtoolsConnected()) {
|
|
797
|
+
const now = Date.now();
|
|
798
|
+
const lastFlush = lastFlushTimeByFile.get(sourceFile.path) ?? 0;
|
|
799
|
+
if (now - lastFlush >= DEVTOOLS_FLUSH_INTERVAL_MS) {
|
|
800
|
+
lastFlushTimeByFile.set(sourceFile.path, now);
|
|
801
|
+
flushDirtyFile(sourceFile.path);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
468
805
|
function normalizeChild(child) {
|
|
469
806
|
if (Array.isArray(child)) {
|
|
470
807
|
return child.map(normalizeChild);
|
|
@@ -496,29 +833,6 @@ function normalizeChild(child) {
|
|
|
496
833
|
return String(child);
|
|
497
834
|
}
|
|
498
835
|
}
|
|
499
|
-
function dumpChildren(children) {
|
|
500
|
-
if (Array.isArray(children)) {
|
|
501
|
-
return `[ ${children.map(debugPrintChild).join(", ")} ]`;
|
|
502
|
-
}
|
|
503
|
-
return debugPrintChild(children);
|
|
504
|
-
}
|
|
505
|
-
function debugPrintChild(child) {
|
|
506
|
-
if (isComponentCreator(child)) {
|
|
507
|
-
return "<" + child.component.name + ">";
|
|
508
|
-
} else if (typeof child === "function") {
|
|
509
|
-
return "$memo";
|
|
510
|
-
} else if (isRef(child)) {
|
|
511
|
-
return "$ref";
|
|
512
|
-
} else if (isIntrinsicElement(child)) {
|
|
513
|
-
return `<${child.name}>`;
|
|
514
|
-
} else if (isRenderableObject(child)) {
|
|
515
|
-
return `CustomChildElement(${JSON.stringify(child)})`;
|
|
516
|
-
} else if (isRefkeyable(child)) {
|
|
517
|
-
return `refkey`;
|
|
518
|
-
} else {
|
|
519
|
-
return JSON.stringify(child);
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
836
|
const defaultPrintTreeOptions = {
|
|
523
837
|
printWidth: 80,
|
|
524
838
|
tabWidth: 2
|
|
@@ -533,9 +847,10 @@ export function printTree(tree, options) {
|
|
|
533
847
|
...defaultPrintTreeOptions,
|
|
534
848
|
...Object.fromEntries(Object.entries(options ?? {}).filter(([_, v]) => v !== undefined))
|
|
535
849
|
};
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
850
|
+
if (!options.noFlush) {
|
|
851
|
+
// make sure queue is empty
|
|
852
|
+
flushJobs();
|
|
853
|
+
}
|
|
539
854
|
const d = printTreeWorker(tree);
|
|
540
855
|
const result = doc.printer.printDocToString(d, options).formatted;
|
|
541
856
|
return options.insertFinalNewLine && !result.endsWith("\n") ? `${result}\n` : result;
|