@alloy-js/core 0.23.0-dev.1 → 0.23.0-dev.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -22
- package/dist/devtools/index.html +80 -0
- package/dist/src/binder.d.ts +2 -0
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +60 -12
- package/dist/src/binder.js.map +1 -1
- package/dist/src/components/AccessExpression.d.ts +78 -0
- package/dist/src/components/AccessExpression.d.ts.map +1 -0
- package/dist/src/components/AccessExpression.js +218 -0
- package/dist/src/components/AccessExpression.js.map +1 -0
- package/dist/src/components/AccessExpression.test.d.ts +2 -0
- package/dist/src/components/AccessExpression.test.d.ts.map +1 -0
- package/dist/src/components/AccessExpression.test.js +137 -0
- package/dist/src/components/AccessExpression.test.js.map +1 -0
- package/dist/src/components/AppendFile.d.ts.map +1 -1
- package/dist/src/components/AppendFile.js +14 -3
- package/dist/src/components/AppendFile.js.map +1 -1
- package/dist/src/components/Block.js +1 -1
- package/dist/src/components/Block.js.map +1 -1
- package/dist/src/components/Declaration.d.ts.map +1 -1
- package/dist/src/components/Declaration.js +2 -1
- package/dist/src/components/Declaration.js.map +1 -1
- package/dist/src/components/For.d.ts.map +1 -1
- package/dist/src/components/For.js +1 -1
- package/dist/src/components/For.js.map +1 -1
- package/dist/src/components/List.d.ts.map +1 -1
- package/dist/src/components/List.js +1 -1
- package/dist/src/components/List.js.map +1 -1
- package/dist/src/components/Prose.js +2 -2
- package/dist/src/components/Prose.js.map +1 -1
- package/dist/src/components/Scope.d.ts.map +1 -1
- package/dist/src/components/Scope.js +6 -1
- package/dist/src/components/Scope.js.map +1 -1
- package/dist/src/components/SourceDirectory.d.ts.map +1 -1
- package/dist/src/components/SourceDirectory.js +1 -2
- package/dist/src/components/SourceDirectory.js.map +1 -1
- package/dist/src/components/Switch.d.ts.map +1 -1
- package/dist/src/components/Switch.js +1 -1
- package/dist/src/components/Switch.js.map +1 -1
- package/dist/src/components/TemplateFile.d.ts.map +1 -1
- package/dist/src/components/TemplateFile.js +18 -3
- package/dist/src/components/TemplateFile.js.map +1 -1
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +1 -0
- package/dist/src/components/index.js.map +1 -1
- package/dist/src/content-slot.d.ts.map +1 -1
- package/dist/src/content-slot.js +7 -6
- package/dist/src/content-slot.js.map +1 -1
- package/dist/src/context.d.ts.map +1 -1
- package/dist/src/context.js +10 -3
- package/dist/src/context.js.map +1 -1
- package/dist/src/debug/cli.d.ts +6 -0
- package/dist/src/debug/cli.d.ts.map +1 -0
- package/dist/src/{debug.js → debug/cli.js} +79 -82
- package/dist/src/debug/cli.js.map +1 -0
- package/dist/src/debug/diagnostics.test.d.ts +2 -0
- package/dist/src/debug/diagnostics.test.d.ts.map +1 -0
- package/dist/src/debug/diagnostics.test.js +46 -0
- package/dist/src/debug/diagnostics.test.js.map +1 -0
- package/dist/src/debug/effects.d.ts +81 -0
- package/dist/src/debug/effects.d.ts.map +1 -0
- package/dist/src/debug/effects.js +358 -0
- package/dist/src/debug/effects.js.map +1 -0
- package/dist/src/debug/effects.test.d.ts +2 -0
- package/dist/src/debug/effects.test.d.ts.map +1 -0
- package/dist/src/debug/effects.test.js +256 -0
- package/dist/src/debug/effects.test.js.map +1 -0
- package/dist/src/debug/files.d.ts +14 -0
- package/dist/src/debug/files.d.ts.map +1 -0
- package/dist/src/debug/files.js +29 -0
- package/dist/src/debug/files.js.map +1 -0
- package/dist/src/debug/files.test.d.ts +2 -0
- package/dist/src/debug/files.test.d.ts.map +1 -0
- package/dist/src/debug/files.test.js +66 -0
- package/dist/src/debug/files.test.js.map +1 -0
- package/dist/src/debug/index.d.ts +63 -0
- package/dist/src/debug/index.d.ts.map +1 -0
- package/dist/src/debug/index.js +71 -0
- package/dist/src/debug/index.js.map +1 -0
- package/dist/src/debug/message-format.test.d.ts +2 -0
- package/dist/src/debug/message-format.test.d.ts.map +1 -0
- package/dist/src/debug/message-format.test.js +700 -0
- package/dist/src/debug/message-format.test.js.map +1 -0
- package/dist/src/debug/render-tree-orphans.test.d.ts +2 -0
- package/dist/src/debug/render-tree-orphans.test.d.ts.map +1 -0
- package/dist/src/debug/render-tree-orphans.test.js +297 -0
- package/dist/src/debug/render-tree-orphans.test.js.map +1 -0
- package/dist/src/debug/render.d.ts +57 -0
- package/dist/src/debug/render.d.ts.map +1 -0
- package/dist/src/debug/render.js +472 -0
- package/dist/src/debug/render.js.map +1 -0
- package/dist/src/debug/render.test.d.ts +2 -0
- package/dist/src/debug/render.test.d.ts.map +1 -0
- package/dist/src/debug/render.test.js +291 -0
- package/dist/src/debug/render.test.js.map +1 -0
- package/dist/src/debug/serialize.d.ts +9 -0
- package/dist/src/debug/serialize.d.ts.map +1 -0
- package/dist/src/debug/serialize.js +70 -0
- package/dist/src/debug/serialize.js.map +1 -0
- package/dist/src/debug/symbols.d.ts +16 -0
- package/dist/src/debug/symbols.d.ts.map +1 -0
- package/dist/src/debug/symbols.js +196 -0
- package/dist/src/debug/symbols.js.map +1 -0
- package/dist/src/debug/symbols.test.d.ts +2 -0
- package/dist/src/debug/symbols.test.d.ts.map +1 -0
- package/dist/src/debug/symbols.test.js +93 -0
- package/dist/src/debug/symbols.test.js.map +1 -0
- package/dist/src/debug/trace-writer.d.ts +55 -0
- package/dist/src/debug/trace-writer.d.ts.map +1 -0
- package/dist/src/debug/trace-writer.js +658 -0
- package/dist/src/debug/trace-writer.js.map +1 -0
- package/dist/src/debug/trace.d.ts +342 -0
- package/dist/src/debug/trace.d.ts.map +1 -0
- package/dist/src/debug/trace.js +446 -0
- package/dist/src/debug/trace.js.map +1 -0
- package/dist/src/devtools/devtools-protocol.d.ts +389 -0
- package/dist/src/devtools/devtools-protocol.d.ts.map +1 -0
- package/dist/src/devtools/devtools-protocol.js +2 -0
- package/dist/src/devtools/devtools-protocol.js.map +1 -0
- package/dist/src/devtools/devtools-server.browser.d.ts +23 -0
- package/dist/src/devtools/devtools-server.browser.d.ts.map +1 -0
- package/dist/src/devtools/devtools-server.browser.js +33 -0
- package/dist/src/devtools/devtools-server.browser.js.map +1 -0
- package/dist/src/devtools/devtools-server.d.ts +66 -0
- package/dist/src/devtools/devtools-server.d.ts.map +1 -0
- package/dist/src/devtools/devtools-server.js +444 -0
- package/dist/src/devtools/devtools-server.js.map +1 -0
- package/dist/src/devtools/devtools-transport.d.ts +23 -0
- package/dist/src/devtools/devtools-transport.d.ts.map +1 -0
- package/dist/src/devtools/devtools-transport.js +114 -0
- package/dist/src/devtools/devtools-transport.js.map +1 -0
- package/dist/src/devtools-entry.browser.d.ts +4 -0
- package/dist/src/devtools-entry.browser.d.ts.map +1 -0
- package/dist/src/devtools-entry.browser.js +2 -0
- package/dist/src/devtools-entry.browser.js.map +1 -0
- package/dist/src/devtools-entry.d.ts +4 -0
- package/dist/src/devtools-entry.d.ts.map +1 -0
- package/dist/src/devtools-entry.js +2 -0
- package/dist/src/devtools-entry.js.map +1 -0
- package/dist/src/diagnostics.d.ts +34 -0
- package/dist/src/diagnostics.d.ts.map +1 -0
- package/dist/src/diagnostics.js +89 -0
- package/dist/src/diagnostics.js.map +1 -0
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/print-hook.d.ts +14 -0
- package/dist/src/print-hook.d.ts.map +1 -0
- package/dist/src/print-hook.js +10 -0
- package/dist/src/print-hook.js.map +1 -0
- package/dist/src/reactive-union-set.d.ts.map +1 -1
- package/dist/src/reactive-union-set.js +28 -3
- package/dist/src/reactive-union-set.js.map +1 -1
- package/dist/src/reactivity.d.ts +60 -7
- package/dist/src/reactivity.d.ts.map +1 -1
- package/dist/src/reactivity.js +308 -39
- package/dist/src/reactivity.js.map +1 -1
- package/dist/src/render-stack.d.ts +18 -1
- package/dist/src/render-stack.d.ts.map +1 -1
- package/dist/src/render-stack.js +61 -1
- package/dist/src/render-stack.js.map +1 -1
- package/dist/src/render.d.ts +8 -15
- package/dist/src/render.d.ts.map +1 -1
- package/dist/src/render.js +424 -109
- package/dist/src/render.js.map +1 -1
- package/dist/src/resource.d.ts.map +1 -1
- package/dist/src/resource.js +5 -0
- package/dist/src/resource.js.map +1 -1
- package/dist/src/scheduler.d.ts +13 -0
- package/dist/src/scheduler.d.ts.map +1 -1
- package/dist/src/scheduler.js +150 -13
- package/dist/src/scheduler.js.map +1 -1
- package/dist/src/symbols/basic-symbol.d.ts.map +1 -1
- package/dist/src/symbols/basic-symbol.js +6 -1
- package/dist/src/symbols/basic-symbol.js.map +1 -1
- package/dist/src/symbols/decl.d.ts.map +1 -1
- package/dist/src/symbols/decl.js +5 -1
- package/dist/src/symbols/decl.js.map +1 -1
- package/dist/src/symbols/output-scope.d.ts +2 -1
- package/dist/src/symbols/output-scope.d.ts.map +1 -1
- package/dist/src/symbols/output-scope.js +13 -8
- package/dist/src/symbols/output-scope.js.map +1 -1
- package/dist/src/symbols/output-symbol.d.ts +1 -0
- package/dist/src/symbols/output-symbol.d.ts.map +1 -1
- package/dist/src/symbols/output-symbol.js +25 -8
- package/dist/src/symbols/output-symbol.js.map +1 -1
- package/dist/src/symbols/symbol-flow.d.ts.map +1 -1
- package/dist/src/symbols/symbol-flow.js +24 -8
- package/dist/src/symbols/symbol-flow.js.map +1 -1
- package/dist/src/symbols/symbol-slot.d.ts.map +1 -1
- package/dist/src/symbols/symbol-slot.js +15 -0
- package/dist/src/symbols/symbol-slot.js.map +1 -1
- package/dist/src/symbols/symbol-slot.test.d.ts +2 -0
- package/dist/src/symbols/symbol-slot.test.d.ts.map +1 -0
- package/dist/src/symbols/symbol-slot.test.js +35 -0
- package/dist/src/symbols/symbol-slot.test.js.map +1 -0
- package/dist/src/symbols/symbol-table.d.ts.map +1 -1
- package/dist/src/symbols/symbol-table.js +6 -5
- package/dist/src/symbols/symbol-table.js.map +1 -1
- package/dist/src/trace.d.ts +2 -0
- package/dist/src/trace.d.ts.map +1 -0
- package/dist/src/trace.js +2 -0
- package/dist/src/trace.js.map +1 -0
- package/dist/src/tracer.d.ts +2 -228
- package/dist/src/tracer.d.ts.map +1 -1
- package/dist/src/tracer.js +5 -298
- package/dist/src/tracer.js.map +1 -1
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +17 -9
- package/dist/src/utils.js.map +1 -1
- package/dist/test/components/append-file.test.d.ts.map +1 -1
- package/dist/test/components/append-file.test.js +18 -10
- package/dist/test/components/append-file.test.js.map +1 -1
- package/dist/test/components/template-file.test.d.ts.map +1 -1
- package/dist/test/components/template-file.test.js +6 -4
- package/dist/test/components/template-file.test.js.map +1 -1
- package/dist/test/lazy-isempty.test.d.ts +2 -0
- package/dist/test/lazy-isempty.test.d.ts.map +1 -0
- package/dist/test/lazy-isempty.test.js +89 -0
- package/dist/test/lazy-isempty.test.js.map +1 -0
- package/dist/test/reactive-union-set-disposers.test.d.ts +2 -0
- package/dist/test/reactive-union-set-disposers.test.d.ts.map +1 -0
- package/dist/test/reactive-union-set-disposers.test.js +98 -0
- package/dist/test/reactive-union-set-disposers.test.js.map +1 -0
- package/dist/test/reactivity/shallow-reactive.test.d.ts +2 -0
- package/dist/test/reactivity/shallow-reactive.test.d.ts.map +1 -0
- package/dist/test/reactivity/shallow-reactive.test.js +52 -0
- package/dist/test/reactivity/shallow-reactive.test.js.map +1 -0
- package/dist/test/rendering/basic.test.js +3 -0
- package/dist/test/rendering/basic.test.js.map +1 -1
- package/dist/test/rendering/print-render-stack.test.d.ts.map +1 -1
- package/dist/test/rendering/print-render-stack.test.js +91 -98
- package/dist/test/rendering/print-render-stack.test.js.map +1 -1
- package/dist/test/scheduler-extended.test.d.ts +2 -0
- package/dist/test/scheduler-extended.test.d.ts.map +1 -0
- package/dist/test/scheduler-extended.test.js +96 -0
- package/dist/test/scheduler-extended.test.js.map +1 -0
- package/dist/test/scheduler.test.d.ts +2 -0
- package/dist/test/scheduler.test.d.ts.map +1 -0
- package/dist/test/scheduler.test.js +46 -0
- package/dist/test/scheduler.test.js.map +1 -0
- package/dist/testing/create-test-wrapper.d.ts +1 -1
- package/dist/testing/create-test-wrapper.d.ts.map +1 -1
- package/dist/testing/create-test-wrapper.js +1 -1
- package/dist/testing/create-test-wrapper.js.map +1 -1
- package/dist/testing/devtools-utils.d.ts +35 -0
- package/dist/testing/devtools-utils.d.ts.map +1 -0
- package/dist/testing/devtools-utils.js +162 -0
- package/dist/testing/devtools-utils.js.map +1 -0
- package/dist/testing/extend-expect.d.ts.map +1 -1
- package/dist/testing/extend-expect.js +63 -1
- package/dist/testing/extend-expect.js.map +1 -1
- package/dist/testing/render.d.ts +2 -2
- package/dist/testing/render.d.ts.map +1 -1
- package/dist/testing/render.js +2 -2
- package/dist/testing/render.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +21 -7
- package/scripts/copy-devtools-ui.mjs +26 -0
- package/src/binder.ts +117 -53
- package/src/components/AccessExpression.test.tsx +132 -0
- package/src/components/AccessExpression.tsx +344 -0
- package/src/components/AppendFile.tsx +14 -9
- package/src/components/Block.tsx +1 -1
- package/src/components/Declaration.tsx +2 -1
- package/src/components/For.tsx +14 -10
- package/src/components/List.tsx +7 -4
- package/src/components/Prose.tsx +1 -1
- package/src/components/Scope.tsx +6 -1
- package/src/components/SourceDirectory.tsx +1 -2
- package/src/components/Switch.tsx +11 -7
- package/src/components/TemplateFile.tsx +18 -9
- package/src/components/index.tsx +1 -0
- package/src/content-slot.tsx +7 -7
- package/src/context.ts +17 -6
- package/src/{debug.ts → debug/cli.ts} +114 -125
- package/src/debug/diagnostics.test.tsx +56 -0
- package/src/debug/effects.test.tsx +301 -0
- package/src/debug/effects.ts +531 -0
- package/src/debug/files.test.tsx +76 -0
- package/src/debug/files.ts +40 -0
- package/src/debug/index.ts +132 -0
- package/src/debug/message-format.test.tsx +759 -0
- package/src/debug/render-tree-orphans.test.tsx +344 -0
- package/src/debug/render.test.tsx +357 -0
- package/src/debug/render.ts +698 -0
- package/src/debug/serialize.ts +85 -0
- package/src/debug/symbols.test.tsx +105 -0
- package/src/debug/symbols.ts +322 -0
- package/src/debug/trace-writer.ts +969 -0
- package/src/debug/trace.ts +309 -0
- package/src/devtools/devtools-protocol.ts +497 -0
- package/src/devtools/devtools-server.browser.ts +62 -0
- package/src/devtools/devtools-server.ts +468 -0
- package/src/devtools/devtools-transport.ts +154 -0
- package/src/devtools-entry.browser.ts +48 -0
- package/src/devtools-entry.ts +48 -0
- package/src/diagnostics.ts +150 -0
- package/src/index.ts +2 -7
- package/src/print-hook.ts +22 -0
- package/src/reactive-union-set.ts +85 -44
- package/src/reactivity.ts +396 -58
- package/src/render-stack.ts +73 -1
- package/src/render.ts +544 -161
- package/src/resource.ts +28 -19
- package/src/scheduler.ts +209 -14
- package/src/symbols/basic-symbol.ts +6 -1
- package/src/symbols/decl.ts +5 -1
- package/src/symbols/output-scope.ts +21 -13
- package/src/symbols/output-symbol.ts +34 -14
- package/src/symbols/symbol-flow.ts +76 -39
- package/src/symbols/symbol-slot.test.tsx +41 -0
- package/src/symbols/symbol-slot.tsx +47 -20
- package/src/symbols/symbol-table.ts +6 -10
- package/src/trace.ts +1 -0
- package/src/tracer.ts +13 -242
- package/src/utils.tsx +31 -21
- package/temp/api.json +5700 -3015
- package/test/components/append-file.test.tsx +36 -29
- package/test/components/template-file.test.tsx +11 -11
- package/test/lazy-isempty.test.tsx +106 -0
- package/test/reactive-union-set-disposers.test.tsx +112 -0
- package/test/reactivity/shallow-reactive.test.tsx +56 -0
- package/test/rendering/basic.test.tsx +4 -0
- package/test/rendering/print-render-stack.test.tsx +52 -43
- package/test/scheduler-extended.test.tsx +122 -0
- package/test/scheduler.test.tsx +50 -0
- package/testing/create-test-wrapper.tsx +1 -1
- package/testing/devtools-utils.ts +245 -0
- package/testing/extend-expect.ts +89 -0
- package/testing/render.ts +2 -2
- package/testing/vitest.d.ts +9 -0
- package/dist/src/debug.d.ts +0 -14
- package/dist/src/debug.d.ts.map +0 -1
- package/dist/src/debug.js.map +0 -1
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
import { isReactive, isRef } from "@vue/reactivity";
|
|
2
|
+
import {
|
|
3
|
+
formatReactivePropertyLabel,
|
|
4
|
+
getReactiveCreationLocation,
|
|
5
|
+
nextReactiveId,
|
|
6
|
+
} from "../reactivity.js";
|
|
7
|
+
import { insertEdge, insertEffect, insertRef } from "./trace-writer.js";
|
|
8
|
+
import {
|
|
9
|
+
isDebugEnabled,
|
|
10
|
+
isTraceEnabled,
|
|
11
|
+
logDevtoolsMessage,
|
|
12
|
+
TracePhase,
|
|
13
|
+
traceType,
|
|
14
|
+
} from "./trace.js";
|
|
15
|
+
|
|
16
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
17
|
+
// Effects debug
|
|
18
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
export interface SourceLocation {
|
|
21
|
+
fileName?: string;
|
|
22
|
+
lineNumber?: number;
|
|
23
|
+
columnNumber?: number;
|
|
24
|
+
stack?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface EffectDebugInfo {
|
|
28
|
+
id: number;
|
|
29
|
+
name?: string;
|
|
30
|
+
type?: string;
|
|
31
|
+
createdAt?: SourceLocation;
|
|
32
|
+
contextId?: number;
|
|
33
|
+
ownerContextId?: number | null;
|
|
34
|
+
component?: string;
|
|
35
|
+
lastTriggeredByRefId?: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface RefDebugInfo {
|
|
39
|
+
id: number;
|
|
40
|
+
kind?: string;
|
|
41
|
+
label?: string;
|
|
42
|
+
createdAt?: SourceLocation;
|
|
43
|
+
createdByEffectId?: number;
|
|
44
|
+
isApproxLocation?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface EffectEdgeDebugInfo {
|
|
48
|
+
id: number;
|
|
49
|
+
type: "track" | "trigger" | "triggered-by";
|
|
50
|
+
effectId: number;
|
|
51
|
+
refId?: number;
|
|
52
|
+
targetId?: number;
|
|
53
|
+
targetKind?: "ref" | "target";
|
|
54
|
+
targetLabel?: string;
|
|
55
|
+
targetKey?: string | number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const effects = new Map<number, EffectDebugInfo>();
|
|
59
|
+
const refs = new Map<number, RefDebugInfo>();
|
|
60
|
+
let effectIdCounter = 1;
|
|
61
|
+
let edgeEventIdCounter = 1;
|
|
62
|
+
const nonRefTargetIds = new WeakMap<object, number>();
|
|
63
|
+
const primitiveTargetIds = new Map<unknown, number>();
|
|
64
|
+
|
|
65
|
+
// Alloy-internal paths to skip when capturing source locations.
|
|
66
|
+
// We skip core infrastructure (reactivity, render, debug, scheduler, etc.)
|
|
67
|
+
// but allow component and symbol frames through so the location points at
|
|
68
|
+
// the component/symbol that created the effect.
|
|
69
|
+
// These patterns match both src/ and dist/src/ paths.
|
|
70
|
+
const CORE_INTERNAL_PATHS = [
|
|
71
|
+
"/core/src/reactivity",
|
|
72
|
+
"/core/src/render",
|
|
73
|
+
"/core/src/scheduler",
|
|
74
|
+
"/core/src/debug/",
|
|
75
|
+
"/core/src/devtools/",
|
|
76
|
+
"/core/src/resource",
|
|
77
|
+
"/core/src/context",
|
|
78
|
+
"/core/src/tracer",
|
|
79
|
+
"/core/src/reactive-union-set",
|
|
80
|
+
"/core/src/utils",
|
|
81
|
+
"/core/dist/src/reactivity",
|
|
82
|
+
"/core/dist/src/render",
|
|
83
|
+
"/core/dist/src/scheduler",
|
|
84
|
+
"/core/dist/src/debug/",
|
|
85
|
+
"/core/dist/src/devtools/",
|
|
86
|
+
"/core/dist/src/resource",
|
|
87
|
+
"/core/dist/src/context",
|
|
88
|
+
"/core/dist/src/tracer",
|
|
89
|
+
"/core/dist/src/reactive-union-set",
|
|
90
|
+
"/core/dist/src/utils",
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
const STACK_SKIP = [
|
|
94
|
+
"node:internal",
|
|
95
|
+
"/@vue/",
|
|
96
|
+
"\\@vue\\",
|
|
97
|
+
"captureSourceLocation",
|
|
98
|
+
...CORE_INTERNAL_PATHS,
|
|
99
|
+
...CORE_INTERNAL_PATHS.map((p) => p.replace(/\//g, "\\")),
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
const VUE_REACTIVITY_MARKERS = [
|
|
103
|
+
"@vue/reactivity",
|
|
104
|
+
"reactivity.esm",
|
|
105
|
+
"reactivity.cjs",
|
|
106
|
+
"reactivity.global",
|
|
107
|
+
"/@vue/",
|
|
108
|
+
"\\@vue\\",
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
112
|
+
// Fast source location capture using V8 structured CallSite API
|
|
113
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
114
|
+
|
|
115
|
+
// Lazily loaded findSourceMap from node:module
|
|
116
|
+
let findSourceMap:
|
|
117
|
+
| ((path: string) =>
|
|
118
|
+
| {
|
|
119
|
+
findEntry: (
|
|
120
|
+
line: number,
|
|
121
|
+
col: number,
|
|
122
|
+
) =>
|
|
123
|
+
| {
|
|
124
|
+
originalSource: string;
|
|
125
|
+
originalLine: number;
|
|
126
|
+
originalColumn: number;
|
|
127
|
+
}
|
|
128
|
+
| undefined;
|
|
129
|
+
}
|
|
130
|
+
| undefined)
|
|
131
|
+
| undefined;
|
|
132
|
+
let findSourceMapLoaded = false;
|
|
133
|
+
let realpathSync: ((path: string) => string) | undefined;
|
|
134
|
+
// Cache realpath lookups to avoid repeated fs calls
|
|
135
|
+
const realpathCache = new Map<string, string>();
|
|
136
|
+
|
|
137
|
+
function loadFindSourceMap() {
|
|
138
|
+
if (findSourceMapLoaded) return;
|
|
139
|
+
findSourceMapLoaded = true;
|
|
140
|
+
// process.getBuiltinModule works in both ESM and CJS contexts
|
|
141
|
+
try {
|
|
142
|
+
const mod = process.getBuiltinModule?.("node:module") as
|
|
143
|
+
| typeof import("node:module")
|
|
144
|
+
| undefined;
|
|
145
|
+
if (mod && typeof mod.findSourceMap === "function") {
|
|
146
|
+
findSourceMap = mod.findSourceMap as typeof findSourceMap;
|
|
147
|
+
}
|
|
148
|
+
} catch {
|
|
149
|
+
// not available
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
const fs = process.getBuiltinModule?.("node:fs") as
|
|
153
|
+
| typeof import("node:fs")
|
|
154
|
+
| undefined;
|
|
155
|
+
if (fs) {
|
|
156
|
+
realpathSync = fs.realpathSync;
|
|
157
|
+
}
|
|
158
|
+
} catch {
|
|
159
|
+
// not available
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function getRealPath(fileName: string): string {
|
|
164
|
+
if (!realpathSync) return fileName;
|
|
165
|
+
let real = realpathCache.get(fileName);
|
|
166
|
+
if (real === undefined) {
|
|
167
|
+
try {
|
|
168
|
+
real = realpathSync(fileName);
|
|
169
|
+
} catch {
|
|
170
|
+
real = fileName;
|
|
171
|
+
}
|
|
172
|
+
realpathCache.set(fileName, real);
|
|
173
|
+
}
|
|
174
|
+
return real;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function isSkipFile(fileName: string): boolean {
|
|
178
|
+
for (const skip of STACK_SKIP) {
|
|
179
|
+
if (fileName.includes(skip)) return true;
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function isVueReactivityFile(fileName: string): boolean {
|
|
185
|
+
for (const marker of VUE_REACTIVITY_MARKERS) {
|
|
186
|
+
if (fileName.includes(marker)) return true;
|
|
187
|
+
}
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function resolveSourceMap(
|
|
192
|
+
fileName: string,
|
|
193
|
+
line: number,
|
|
194
|
+
col: number,
|
|
195
|
+
): { fileName: string; line: number; col: number } {
|
|
196
|
+
if (!findSourceMap) return { fileName, line, col };
|
|
197
|
+
// pnpm uses symlinks; findSourceMap only matches the real path
|
|
198
|
+
const real = getRealPath(fileName);
|
|
199
|
+
const map = findSourceMap(real);
|
|
200
|
+
if (!map) return { fileName, line, col };
|
|
201
|
+
const entry = map.findEntry(line - 1, col - 1);
|
|
202
|
+
if (!entry) return { fileName, line, col };
|
|
203
|
+
return {
|
|
204
|
+
fileName: entry.originalSource,
|
|
205
|
+
line: entry.originalLine + 1,
|
|
206
|
+
col: entry.originalColumn + 1,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// V8 structured stack capture — avoids string formatting entirely
|
|
211
|
+
const structuredPrepare = (
|
|
212
|
+
_err: Error,
|
|
213
|
+
callSites: NodeJS.CallSite[],
|
|
214
|
+
): NodeJS.CallSite[] => callSites;
|
|
215
|
+
|
|
216
|
+
function captureCallSites(): NodeJS.CallSite[] {
|
|
217
|
+
const orig = Error.prepareStackTrace;
|
|
218
|
+
Error.prepareStackTrace = structuredPrepare;
|
|
219
|
+
const obj: { stack?: NodeJS.CallSite[] } = {};
|
|
220
|
+
Error.captureStackTrace(obj, captureCallSites);
|
|
221
|
+
const sites = obj.stack ?? [];
|
|
222
|
+
Error.prepareStackTrace = orig;
|
|
223
|
+
return sites;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export function captureSourceLocation(
|
|
227
|
+
skipReactives = true,
|
|
228
|
+
): SourceLocation | undefined {
|
|
229
|
+
if (!isDebugEnabled()) return undefined;
|
|
230
|
+
loadFindSourceMap();
|
|
231
|
+
|
|
232
|
+
const sites = captureCallSites();
|
|
233
|
+
|
|
234
|
+
// First pass: skip internal/framework frames
|
|
235
|
+
for (const site of sites) {
|
|
236
|
+
const fn = site.getFileName();
|
|
237
|
+
if (!fn) continue;
|
|
238
|
+
if (isSkipFile(fn)) continue;
|
|
239
|
+
if (skipReactives && isVueReactivityFile(fn)) continue;
|
|
240
|
+
|
|
241
|
+
const line = site.getLineNumber() ?? 0;
|
|
242
|
+
const col = site.getColumnNumber() ?? 0;
|
|
243
|
+
const resolved = resolveSourceMap(fn, line, col);
|
|
244
|
+
return {
|
|
245
|
+
fileName: resolved.fileName,
|
|
246
|
+
lineNumber: resolved.line,
|
|
247
|
+
columnNumber: resolved.col,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Second pass without reactive filter
|
|
252
|
+
if (skipReactives) {
|
|
253
|
+
for (const site of sites) {
|
|
254
|
+
const fn = site.getFileName();
|
|
255
|
+
if (!fn) continue;
|
|
256
|
+
if (isSkipFile(fn)) continue;
|
|
257
|
+
|
|
258
|
+
const line = site.getLineNumber() ?? 0;
|
|
259
|
+
const col = site.getColumnNumber() ?? 0;
|
|
260
|
+
const resolved = resolveSourceMap(fn, line, col);
|
|
261
|
+
return {
|
|
262
|
+
fileName: resolved.fileName,
|
|
263
|
+
lineNumber: resolved.line,
|
|
264
|
+
columnNumber: resolved.col,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return undefined;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function getNonRefTargetId(target: unknown): number {
|
|
273
|
+
if (typeof target === "object" && target !== null) {
|
|
274
|
+
const existing = nonRefTargetIds.get(target);
|
|
275
|
+
if (existing) return existing;
|
|
276
|
+
const id = nextReactiveId();
|
|
277
|
+
nonRefTargetIds.set(target, id);
|
|
278
|
+
return id;
|
|
279
|
+
}
|
|
280
|
+
if (typeof target === "function") {
|
|
281
|
+
const existing = nonRefTargetIds.get(target as object);
|
|
282
|
+
if (existing) return existing;
|
|
283
|
+
const id = nextReactiveId();
|
|
284
|
+
nonRefTargetIds.set(target as object, id);
|
|
285
|
+
return id;
|
|
286
|
+
}
|
|
287
|
+
const existing = primitiveTargetIds.get(target);
|
|
288
|
+
if (existing) return existing;
|
|
289
|
+
const id = nextReactiveId();
|
|
290
|
+
primitiveTargetIds.set(target, id);
|
|
291
|
+
return id;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function formatNonRefTargetLabel(target: unknown): string {
|
|
295
|
+
if (Array.isArray(target)) return "[]";
|
|
296
|
+
try {
|
|
297
|
+
return String(target);
|
|
298
|
+
} catch {
|
|
299
|
+
return "[Unserializable]";
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Sanitize a Map/object key to ensure it's serializable.
|
|
305
|
+
*/
|
|
306
|
+
function sanitizeTargetKey(key: unknown): string | number | undefined {
|
|
307
|
+
if (key === undefined) return undefined;
|
|
308
|
+
if (typeof key === "string" || typeof key === "number") return key;
|
|
309
|
+
if (typeof key === "symbol") return key.toString();
|
|
310
|
+
if (typeof key === "object" || typeof key === "function") return "Object";
|
|
311
|
+
return String(key);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function buildEffectTargetInfo(input: {
|
|
315
|
+
target: unknown;
|
|
316
|
+
refId?: number;
|
|
317
|
+
}): Pick<
|
|
318
|
+
EffectEdgeDebugInfo,
|
|
319
|
+
"refId" | "targetId" | "targetKind" | "targetLabel"
|
|
320
|
+
> {
|
|
321
|
+
if (input.refId !== undefined) {
|
|
322
|
+
return {
|
|
323
|
+
refId: input.refId,
|
|
324
|
+
targetId: input.refId,
|
|
325
|
+
targetKind: "ref",
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const targetId = getNonRefTargetId(input.target);
|
|
330
|
+
return {
|
|
331
|
+
targetId,
|
|
332
|
+
targetKind: "target",
|
|
333
|
+
targetLabel: formatNonRefTargetLabel(input.target),
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function emitEffect(message: { type: string; [key: string]: unknown }) {
|
|
338
|
+
logDevtoolsMessage(message);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export function update(input: Partial<EffectDebugInfo> & { id: number }) {
|
|
342
|
+
if (!isDebugEnabled()) return;
|
|
343
|
+
const existing = effects.get(input.id);
|
|
344
|
+
if (!existing) return;
|
|
345
|
+
const next: EffectDebugInfo = { ...existing, ...input };
|
|
346
|
+
effects.set(input.id, next);
|
|
347
|
+
emitEffect({
|
|
348
|
+
type: traceType(TracePhase.effect.effectUpdated),
|
|
349
|
+
effect: next,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export function register(input: {
|
|
354
|
+
name?: string;
|
|
355
|
+
type?: string;
|
|
356
|
+
createdAt?: SourceLocation;
|
|
357
|
+
contextId?: number;
|
|
358
|
+
ownerContextId?: number | null;
|
|
359
|
+
}): number {
|
|
360
|
+
if (!isDebugEnabled()) return -1;
|
|
361
|
+
const id = effectIdCounter++;
|
|
362
|
+
const info: EffectDebugInfo = {
|
|
363
|
+
id,
|
|
364
|
+
name: input.name,
|
|
365
|
+
type: input.type,
|
|
366
|
+
createdAt: input.createdAt ?? captureSourceLocation(),
|
|
367
|
+
contextId: input.contextId,
|
|
368
|
+
ownerContextId: input.ownerContextId ?? null,
|
|
369
|
+
};
|
|
370
|
+
effects.set(id, info);
|
|
371
|
+
emitEffect({ type: traceType(TracePhase.effect.effectAdded), effect: info });
|
|
372
|
+
|
|
373
|
+
if (isTraceEnabled()) {
|
|
374
|
+
insertEffect(
|
|
375
|
+
id,
|
|
376
|
+
input.name,
|
|
377
|
+
input.type,
|
|
378
|
+
input.contextId,
|
|
379
|
+
input.ownerContextId ?? null,
|
|
380
|
+
info.createdAt?.fileName,
|
|
381
|
+
info.createdAt?.lineNumber,
|
|
382
|
+
info.createdAt?.columnNumber,
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return id;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export function registerRef(input: {
|
|
390
|
+
id: number;
|
|
391
|
+
kind?: string;
|
|
392
|
+
createdAt?: SourceLocation;
|
|
393
|
+
createdByEffectId?: number;
|
|
394
|
+
isInfrastructure?: boolean;
|
|
395
|
+
isApproxLocation?: boolean;
|
|
396
|
+
label?: string;
|
|
397
|
+
}) {
|
|
398
|
+
if (!isDebugEnabled()) return;
|
|
399
|
+
if (refs.has(input.id)) return;
|
|
400
|
+
const info: RefDebugInfo = {
|
|
401
|
+
id: input.id,
|
|
402
|
+
kind: input.kind,
|
|
403
|
+
createdAt: input.createdAt ?? captureSourceLocation(),
|
|
404
|
+
createdByEffectId: input.createdByEffectId,
|
|
405
|
+
label: input.label,
|
|
406
|
+
isApproxLocation: input.isApproxLocation,
|
|
407
|
+
};
|
|
408
|
+
refs.set(input.id, info);
|
|
409
|
+
emitEffect({ type: traceType(TracePhase.effect.refAdded), ref: info });
|
|
410
|
+
|
|
411
|
+
if (isTraceEnabled()) {
|
|
412
|
+
insertRef(
|
|
413
|
+
input.id,
|
|
414
|
+
input.kind,
|
|
415
|
+
input.createdByEffectId,
|
|
416
|
+
info.createdAt?.fileName,
|
|
417
|
+
info.createdAt?.lineNumber,
|
|
418
|
+
info.createdAt?.columnNumber,
|
|
419
|
+
input.label,
|
|
420
|
+
input.isApproxLocation,
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export function ensureRef(input: { id: number; kind?: string }) {
|
|
426
|
+
if (!isDebugEnabled()) return;
|
|
427
|
+
if (refs.has(input.id)) return;
|
|
428
|
+
registerRef({ id: input.id, kind: input.kind });
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export function ensureReactivePropertyRef(input: {
|
|
432
|
+
id: number;
|
|
433
|
+
target: object;
|
|
434
|
+
key: string | number;
|
|
435
|
+
}) {
|
|
436
|
+
if (!isDebugEnabled()) return;
|
|
437
|
+
if (refs.has(input.id)) return;
|
|
438
|
+
const label = formatReactivePropertyLabel(input.target, input.key);
|
|
439
|
+
const createdAt = getReactiveCreationLocation(input.target);
|
|
440
|
+
// If the reactive wasn't created via alloy's shallowReactive wrapper,
|
|
441
|
+
// createdAt is undefined and registerRef falls back to captureSourceLocation
|
|
442
|
+
// (the first track site). Flag this as approximate.
|
|
443
|
+
const isApproxLocation = !createdAt;
|
|
444
|
+
registerRef({
|
|
445
|
+
id: input.id,
|
|
446
|
+
kind: "reactive-property",
|
|
447
|
+
label,
|
|
448
|
+
createdAt,
|
|
449
|
+
isApproxLocation,
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
export function track(input: {
|
|
454
|
+
effectId: number;
|
|
455
|
+
target: unknown;
|
|
456
|
+
refId?: number;
|
|
457
|
+
targetKey?: unknown;
|
|
458
|
+
}) {
|
|
459
|
+
if (!isDebugEnabled()) return;
|
|
460
|
+
const edge: EffectEdgeDebugInfo = {
|
|
461
|
+
id: edgeEventIdCounter++,
|
|
462
|
+
type: "track",
|
|
463
|
+
effectId: input.effectId,
|
|
464
|
+
...buildEffectTargetInfo({ target: input.target, refId: input.refId }),
|
|
465
|
+
targetKey: sanitizeTargetKey(input.targetKey),
|
|
466
|
+
};
|
|
467
|
+
emitEffect({ type: traceType(TracePhase.effect.track), edge });
|
|
468
|
+
|
|
469
|
+
if (isTraceEnabled()) {
|
|
470
|
+
insertEdge(
|
|
471
|
+
"track",
|
|
472
|
+
input.effectId,
|
|
473
|
+
edge.refId,
|
|
474
|
+
edge.targetId,
|
|
475
|
+
edge.targetKey,
|
|
476
|
+
undefined,
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
export function trigger(input: {
|
|
482
|
+
effectId: number;
|
|
483
|
+
target: unknown;
|
|
484
|
+
refId?: number;
|
|
485
|
+
targetKey?: unknown;
|
|
486
|
+
kind?: "trigger" | "triggered-by";
|
|
487
|
+
causedBy?: number;
|
|
488
|
+
}) {
|
|
489
|
+
if (!isDebugEnabled()) return;
|
|
490
|
+
const edge: EffectEdgeDebugInfo = {
|
|
491
|
+
id: edgeEventIdCounter++,
|
|
492
|
+
type: input.kind ?? "trigger",
|
|
493
|
+
effectId: input.effectId,
|
|
494
|
+
...buildEffectTargetInfo({ target: input.target, refId: input.refId }),
|
|
495
|
+
targetKey: sanitizeTargetKey(input.targetKey),
|
|
496
|
+
};
|
|
497
|
+
emitEffect({ type: traceType(TracePhase.effect.trigger), edge });
|
|
498
|
+
|
|
499
|
+
if (isTraceEnabled()) {
|
|
500
|
+
insertEdge(
|
|
501
|
+
edge.type,
|
|
502
|
+
input.effectId,
|
|
503
|
+
edge.refId,
|
|
504
|
+
edge.targetId,
|
|
505
|
+
edge.targetKey,
|
|
506
|
+
input.causedBy,
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
update({
|
|
511
|
+
id: input.effectId,
|
|
512
|
+
...(input.refId !== undefined ? { lastTriggeredByRefId: input.refId } : {}),
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
export function reset() {
|
|
517
|
+
effects.clear();
|
|
518
|
+
refs.clear();
|
|
519
|
+
primitiveTargetIds.clear();
|
|
520
|
+
effectIdCounter = 1;
|
|
521
|
+
edgeEventIdCounter = 1;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Utilities used by other debug sections
|
|
525
|
+
export function isRefTarget(value: unknown) {
|
|
526
|
+
return isRef(value);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export function isReactiveTarget(value: unknown) {
|
|
530
|
+
return isReactive(value);
|
|
531
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { afterEach, beforeEach, expect, it } from "vitest";
|
|
2
|
+
import WebSocket from "ws";
|
|
3
|
+
import {
|
|
4
|
+
createMessageCollector,
|
|
5
|
+
type DevtoolsMessage,
|
|
6
|
+
} from "../../testing/devtools-utils.js";
|
|
7
|
+
import { Output } from "../components/Output.jsx";
|
|
8
|
+
import { SourceDirectory } from "../components/SourceDirectory.jsx";
|
|
9
|
+
import { SourceFile } from "../components/SourceFile.jsx";
|
|
10
|
+
import {
|
|
11
|
+
enableDevtools,
|
|
12
|
+
resetDevtoolsServerForTests,
|
|
13
|
+
} from "../devtools/devtools-server.js";
|
|
14
|
+
import { renderAsync } from "../render.js";
|
|
15
|
+
|
|
16
|
+
let socket: WebSocket | undefined;
|
|
17
|
+
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
const server = await enableDevtools({ port: 0 });
|
|
20
|
+
socket = new WebSocket(`ws://127.0.0.1:${server.port}`);
|
|
21
|
+
|
|
22
|
+
await new Promise<void>((resolve, reject) => {
|
|
23
|
+
socket?.once("open", resolve);
|
|
24
|
+
socket?.once("error", reject);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(async () => {
|
|
29
|
+
if (socket) {
|
|
30
|
+
socket.close();
|
|
31
|
+
socket = undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
await resetDevtoolsServerForTests();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("emits file and directory add/update/remove messages", async () => {
|
|
38
|
+
const collector = await createMessageCollector(socket!);
|
|
39
|
+
|
|
40
|
+
await renderAsync(
|
|
41
|
+
<Output>
|
|
42
|
+
<SourceDirectory path="src">
|
|
43
|
+
<SourceFile path="index.ts" filetype="ts">
|
|
44
|
+
{"export const value = 1;"}
|
|
45
|
+
</SourceFile>
|
|
46
|
+
</SourceDirectory>
|
|
47
|
+
</Output>,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const initialMessages = await collector.waitForRender();
|
|
51
|
+
const initialFiles = initialMessages.filter(
|
|
52
|
+
(m: DevtoolsMessage) =>
|
|
53
|
+
(m.type.startsWith("file:") || m.type.startsWith("directory:")) &&
|
|
54
|
+
!("triggerIds" in m),
|
|
55
|
+
);
|
|
56
|
+
expect(initialFiles[0]).toMatchObject({
|
|
57
|
+
type: "directory:added",
|
|
58
|
+
path: "./",
|
|
59
|
+
});
|
|
60
|
+
expect(initialFiles[1]).toMatchObject({
|
|
61
|
+
type: "directory:added",
|
|
62
|
+
path: "src",
|
|
63
|
+
});
|
|
64
|
+
expect(initialFiles[2]).toMatchObject({
|
|
65
|
+
type: "file:added",
|
|
66
|
+
path: "src/index.ts",
|
|
67
|
+
filetype: "ts",
|
|
68
|
+
});
|
|
69
|
+
expect(initialFiles[3]).toMatchObject({
|
|
70
|
+
type: "file:updated",
|
|
71
|
+
path: "src/index.ts",
|
|
72
|
+
content: expect.any(String),
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
collector.stop();
|
|
76
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {
|
|
2
|
+
insertDirectory,
|
|
3
|
+
insertOutputFile,
|
|
4
|
+
updateOutputFileContent,
|
|
5
|
+
} from "./trace-writer.js";
|
|
6
|
+
import { isDebugEnabled } from "./trace.js";
|
|
7
|
+
|
|
8
|
+
export interface FileUpdateInfo {
|
|
9
|
+
path: string;
|
|
10
|
+
filetype: string;
|
|
11
|
+
contents: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const fileContentCache = new Map<string, string>();
|
|
15
|
+
|
|
16
|
+
/** Record a directory being added to the output. */
|
|
17
|
+
export function recordDirectory(path: string) {
|
|
18
|
+
if (!isDebugEnabled()) return;
|
|
19
|
+
insertDirectory(path);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Record a file being added to the output. */
|
|
23
|
+
export function recordFile(path: string, filetype: string) {
|
|
24
|
+
if (!isDebugEnabled()) return;
|
|
25
|
+
insertOutputFile(path, filetype, undefined);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Notify devtools that a file's contents have changed. De-duplicates by content. */
|
|
29
|
+
export function updated(info: FileUpdateInfo) {
|
|
30
|
+
const previous = fileContentCache.get(info.path);
|
|
31
|
+
if (previous === info.contents) return;
|
|
32
|
+
fileContentCache.set(info.path, info.contents);
|
|
33
|
+
|
|
34
|
+
updateOutputFileContent(info.path, info.contents);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Clear all cached file state. Called when a new render begins. */
|
|
38
|
+
export function reset() {
|
|
39
|
+
fileContentCache.clear();
|
|
40
|
+
}
|