@tsplc/debug 0.2.17 → 0.2.19
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/dist/format.js +36 -18
- package/dist/format.js.map +4 -4
- package/dist/index.js +768 -516
- package/dist/index.js.map +20 -17
- package/dist/manifest.js +6 -2
- package/dist/manifest.js.map +3 -3
- package/dist/paths.js +60 -28
- package/dist/paths.js.map +3 -3
- package/package.json +47 -46
- package/src/adapter.ts +43 -36
- package/src/api.ts +126 -123
- package/src/debugger.ts +584 -467
- package/src/errors.ts +3 -0
- package/src/hardware.ts +127 -96
- package/src/http.ts +147 -116
- package/src/index.ts +34 -4
- package/src/jobs.ts +102 -77
- package/src/login-value.ts +165 -0
- package/src/login.ts +233 -253
- package/src/manifest.ts +200 -194
- package/src/opcua.ts +55 -55
- package/src/paths.ts +230 -157
- package/src/requests.ts +86 -0
- package/src/telemetry.ts +104 -90
- package/src/timeline.ts +96 -61
- package/src/trace.ts +41 -31
- package/src/ui/bits.ts +45 -29
- package/src/ui/client.ts +33 -26
- package/src/ui/dom.ts +189 -108
- package/src/ui/format.ts +127 -72
- package/src/ui/hardware.ts +416 -343
- package/src/ui/header.ts +186 -164
- package/src/ui/index.ts +16 -9
- package/src/ui/jobs.ts +263 -214
- package/src/ui/main.ts +52 -48
- package/src/ui/overview.ts +152 -108
- package/src/ui/recent.ts +329 -276
- package/src/ui/requests.ts +69 -73
- package/src/ui/store.ts +236 -198
- package/src/ui/tree.ts +162 -130
- package/src/ui/variables.ts +557 -431
- package/src/watch.ts +22 -17
- package/src/ui/dev.ts +0 -579
- package/src/ui/fixture.ts +0 -548
package/dist/format.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// packages/debug/src/paths.ts
|
|
2
|
+
import { isArrayIndexSegment, symbolPathSegments } from "@tsplc/opcua/contract";
|
|
2
3
|
var typeOf = (manifest, id) => manifest.types[id] ?? { kind: "scalar", iec: id };
|
|
3
4
|
|
|
4
5
|
// packages/debug/src/ui/format.ts
|
|
@@ -11,30 +12,39 @@ var valueStateLabels = {
|
|
|
11
12
|
constant: "constant"
|
|
12
13
|
};
|
|
13
14
|
var valueState = (quality, ageMs, context) => {
|
|
14
|
-
if (quality === "unavailable")
|
|
15
|
+
if (quality === "unavailable") {
|
|
15
16
|
return "unavailable";
|
|
16
|
-
|
|
17
|
+
}
|
|
18
|
+
if (!context.connected || ageMs > 3 * context.intervalMs) {
|
|
17
19
|
return "stale";
|
|
18
|
-
|
|
20
|
+
}
|
|
21
|
+
if (quality === "bad") {
|
|
19
22
|
return "bad";
|
|
20
|
-
|
|
23
|
+
}
|
|
24
|
+
if (quality === "uncertain") {
|
|
21
25
|
return "uncertain";
|
|
26
|
+
}
|
|
22
27
|
return "live";
|
|
23
28
|
};
|
|
24
29
|
var formatAge = (ms) => {
|
|
25
|
-
if (ms < 1000)
|
|
30
|
+
if (ms < 1000) {
|
|
26
31
|
return "now";
|
|
27
|
-
|
|
32
|
+
}
|
|
33
|
+
if (ms < 60000) {
|
|
28
34
|
return `${Math.floor(ms / 1000)} s ago`;
|
|
29
|
-
|
|
35
|
+
}
|
|
36
|
+
if (ms < 3600000) {
|
|
30
37
|
return `${Math.floor(ms / 60000)} min ago`;
|
|
38
|
+
}
|
|
31
39
|
return `${Math.floor(ms / 3600000)} h ago`;
|
|
32
40
|
};
|
|
33
41
|
var formatDuration = (ms) => {
|
|
34
|
-
if (ms < 1000)
|
|
42
|
+
if (ms < 1000) {
|
|
35
43
|
return `${Math.round(ms)} ms`;
|
|
36
|
-
|
|
44
|
+
}
|
|
45
|
+
if (ms < 60000) {
|
|
37
46
|
return `${(ms / 1000).toFixed(1)} s`;
|
|
47
|
+
}
|
|
38
48
|
return `${Math.floor(ms / 60000)} min ${Math.floor(ms % 60000 / 1000)} s`;
|
|
39
49
|
};
|
|
40
50
|
var formatInterval = (ms) => ms < 1000 ? `${ms} ms` : `${ms / 1000} s`;
|
|
@@ -45,24 +55,31 @@ var formatClock = (iso) => {
|
|
|
45
55
|
};
|
|
46
56
|
var formatReadAt = (iso) => `read ${formatClock(iso).slice(0, 8)}`;
|
|
47
57
|
var formatScalar = (value) => {
|
|
48
|
-
if (typeof value === "boolean")
|
|
58
|
+
if (typeof value === "boolean") {
|
|
49
59
|
return value ? "TRUE" : "FALSE";
|
|
50
|
-
|
|
60
|
+
}
|
|
61
|
+
if (typeof value === "number") {
|
|
51
62
|
return Number.isInteger(value) ? String(value) : String(Number(value.toPrecision(6)));
|
|
52
|
-
|
|
63
|
+
}
|
|
64
|
+
if (typeof value === "string") {
|
|
53
65
|
return JSON.stringify(value);
|
|
54
|
-
|
|
66
|
+
}
|
|
67
|
+
if (value === null || value === undefined) {
|
|
55
68
|
return "—";
|
|
69
|
+
}
|
|
56
70
|
return JSON.stringify(value);
|
|
57
71
|
};
|
|
58
72
|
var formatValue = (manifest, typeId, value) => {
|
|
59
73
|
const type = typeOf(manifest, typeId);
|
|
60
|
-
if (type.kind !== "enum")
|
|
74
|
+
if (type.kind !== "enum") {
|
|
61
75
|
return formatScalar(value);
|
|
62
|
-
|
|
76
|
+
}
|
|
77
|
+
if (typeof value === "string" && Object.hasOwn(type.members, value)) {
|
|
63
78
|
return value;
|
|
64
|
-
|
|
79
|
+
}
|
|
80
|
+
if (typeof value !== "number") {
|
|
65
81
|
return formatScalar(value);
|
|
82
|
+
}
|
|
66
83
|
const member = Object.entries(type.members).find(([, number]) => number === value)?.[0];
|
|
67
84
|
return member ?? `${value} (not a ${type.name})`;
|
|
68
85
|
};
|
|
@@ -84,8 +101,9 @@ var formatProperties = (properties) => Object.entries(properties).map(([key, val
|
|
|
84
101
|
return `${key}=${text.length > PROPERTY_TEXT ? `${text.slice(0, PROPERTY_TEXT)}…` : text}`;
|
|
85
102
|
}).join(" ");
|
|
86
103
|
var fileHref = (projectRoot, file, line, column) => {
|
|
87
|
-
if (projectRoot === undefined)
|
|
104
|
+
if (projectRoot === undefined) {
|
|
88
105
|
return;
|
|
106
|
+
}
|
|
89
107
|
const root = projectRoot.replaceAll("\\", "/").replace(/\/$/, "");
|
|
90
108
|
const absolute = `${root}/${file}`.replace(/^\/?/, "/");
|
|
91
109
|
return `vscode://file${absolute}:${line}:${column}`;
|
|
@@ -117,5 +135,5 @@ export {
|
|
|
117
135
|
valueStateLabels
|
|
118
136
|
};
|
|
119
137
|
|
|
120
|
-
//# debugId=
|
|
138
|
+
//# debugId=2270CEF4083E476B64756E2164756E21
|
|
121
139
|
//# sourceMappingURL=format.js.map
|
package/dist/format.js.map
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/paths.ts", "../src/ui/format.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { DebugManifest, DebugType, SourceRange } from \"./manifest.ts\";\n\n/**\n * TypeScript paths over a manifest: `program.diverters.binTrackers[10].bin` names a root\n * (`program.diverters`), then record fields and array indexes. Pure, so the browser UI can use it.\n */\n\n/** A path that reads a target, or a constant the compiler folded. */\nexport type ResolvedPath =\n
|
|
6
|
-
"import type { Quality } from \"../api.ts\";\nimport type { DebugManifest, SourceRange } from \"../manifest.ts\";\nimport { typeOf } from \"../paths.ts\";\n\n/** How a value is shown: each state has its own styling and label, so none passes for live. */\nexport type ValueState
|
|
5
|
+
"import { isArrayIndexSegment, symbolPathSegments } from \"@tsplc/opcua/contract\";\nimport type { DebugManifest, DebugType, SourceRange } from \"./manifest.ts\";\n\n/**\n * TypeScript paths over a manifest: `program.diverters.binTrackers[10].bin` names a root\n * (`program.diverters`), then record fields and array indexes. Pure, so the browser UI can use it.\n */\n\n/** A path that reads a target, or a constant the compiler folded. */\nexport type ResolvedPath =\n\t| {\n\t\t\tkind: \"target\";\n\t\t\tpath: string;\n\t\t\ttarget: string;\n\t\t\ttype: string;\n\t\t\treadable: boolean;\n\t\t\tgenerated?: true;\n\t\t\tdeclaration?: SourceRange;\n\t }\n\t| {\n\t\t\tkind: \"constant\";\n\t\t\tpath: string;\n\t\t\ttype: string;\n\t\t\tvalue: unknown;\n\t\t\tdeclaration?: SourceRange;\n\t };\n\n/** Roots or constants that share a prefix, such as `program` above `program.diverters`. */\ninterface GroupPath {\n\tkind: \"group\";\n\tpath: string;\n}\n\n/** A child in the instance tree. */\nexport type PathNode = { name: string } & (ResolvedPath | GroupPath);\n\n/** In a pattern, every index of an array. */\nconst anyIndex = \"[*]\";\n\n/** Names and indexes as the controller's symbol paths split them, and `[*]` in patterns. */\nexport const pathSegments = (path: string) =>\n\tpath\n\t\t.split(anyIndex)\n\t\t.flatMap((part, index) => [\n\t\t\t...(index > 0 ? [anyIndex] : []),\n\t\t\t...symbolPathSegments(part),\n\t\t]);\n\nexport const joinPath = (prefix: string, segment: string) =>\n\tsegment.startsWith(\"[\") || !prefix\n\t\t? `${prefix}${segment}`\n\t\t: `${prefix}.${segment}`;\n\n/** Scalar type ids are their IEC names, and may have no entry in `types`. */\nexport const typeOf = (manifest: DebugManifest, id: string): DebugType =>\n\tmanifest.types[id] ?? { kind: \"scalar\", iec: id };\n\nexport const createPaths = (manifest: DebugManifest) => {\n\tconst typeOfId = (id: string) => typeOf(manifest, id);\n\t// I/O bindings are readable symbols with TypeScript paths of their own.\n\tconst bases = new Map<string, Extract<ResolvedPath, { kind: \"target\" }>>([\n\t\t...manifest.roots.map(\n\t\t\t({ path, ...root }) =>\n\t\t\t\t[path, { kind: \"target\" as const, path, ...root }] as const,\n\t\t),\n\t\t...manifest.io.map(\n\t\t\t({ path, target, type }) =>\n\t\t\t\t[\n\t\t\t\t\tpath,\n\t\t\t\t\t{ kind: \"target\" as const, path, target, type, readable: true },\n\t\t\t\t] as const,\n\t\t),\n\t]);\n\tconst constants = new Map(\n\t\tmanifest.constants.map(({ path, ...constant }) => [\n\t\t\tpath,\n\t\t\t{ kind: \"constant\" as const, path, ...constant },\n\t\t]),\n\t);\n\t/** Children of the prefixes of every root and constant path, which are groups unless they resolve. */\n\tconst groups = new Map<string, Set<string>>();\n\tfor (const path of [...bases.keys(), ...constants.keys()]) {\n\t\tlet prefix = \"\";\n\t\tfor (const segment of pathSegments(path)) {\n\t\t\tlet children = groups.get(prefix);\n\t\t\tif (!children) {\n\t\t\t\tgroups.set(prefix, (children = new Set()));\n\t\t\t}\n\t\t\tchildren.add(segment);\n\t\t\tprefix = joinPath(prefix, segment);\n\t\t}\n\t}\n\n\tconst resolve = (path: string): ResolvedPath | undefined => {\n\t\tconst constant = constants.get(path);\n\t\tif (constant) {\n\t\t\treturn constant;\n\t\t}\n\t\tconst segments = pathSegments(path);\n\t\tfor (let length = segments.length; length > 0; length--) {\n\t\t\tconst base = bases.get(segments.slice(0, length).reduce(joinPath, \"\"));\n\t\t\tif (!base) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tlet resolved: ResolvedPath = base;\n\t\t\tfor (const segment of segments.slice(length)) {\n\t\t\t\tconst type = typeOfId(resolved.type);\n\t\t\t\tif (type.kind === \"record\") {\n\t\t\t\t\tconst field = type.fields.find(({ name }) => name === segment);\n\t\t\t\t\tif (!field) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tresolved = {\n\t\t\t\t\t\tkind: \"target\",\n\t\t\t\t\t\tpath: joinPath(resolved.path, segment),\n\t\t\t\t\t\ttarget: `${resolved.target}.${field.target}`,\n\t\t\t\t\t\ttype: field.type,\n\t\t\t\t\t\treadable: resolved.readable,\n\t\t\t\t\t\t...(field.generated && { generated: true }),\n\t\t\t\t\t\t...(field.declaration && { declaration: field.declaration }),\n\t\t\t\t\t};\n\t\t\t\t} else if (type.kind === \"array\") {\n\t\t\t\t\tif (!isArrayIndexSegment(segment)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst index = Number(segment.slice(1, -1));\n\t\t\t\t\tif (index < type.lower || index >= type.lower + type.length) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tresolved = {\n\t\t\t\t\t\tkind: \"target\",\n\t\t\t\t\t\tpath: joinPath(resolved.path, segment),\n\t\t\t\t\t\ttarget: `${resolved.target}${segment}`,\n\t\t\t\t\t\ttype: type.element,\n\t\t\t\t\t\treadable: resolved.readable,\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn resolved;\n\t\t}\n\t};\n\n\tconst typedChildren = (resolved: ResolvedPath | undefined) => {\n\t\tconst type =\n\t\t\tresolved?.kind === \"target\" ? typeOfId(resolved.type) : undefined;\n\t\tif (type?.kind === \"record\") {\n\t\t\treturn type.fields.map(({ name }) => name);\n\t\t}\n\t\tif (type?.kind === \"array\") {\n\t\t\treturn Array.from(\n\t\t\t\t{ length: type.length },\n\t\t\t\t(_, index) => `[${type.lower + index}]`,\n\t\t\t);\n\t\t}\n\t\treturn [];\n\t};\n\n\t/** A path's fields or indexes, and the roots and constants below it. */\n\tconst children = (path: string): PathNode[] => {\n\t\tconst names = [\n\t\t\t...typedChildren(resolve(path)),\n\t\t\t...(groups.get(path) ?? []),\n\t\t];\n\t\treturn [...new Set(names)].map((name) => {\n\t\t\tconst child = joinPath(path, name);\n\t\t\treturn { name, ...(resolve(child) ?? { kind: \"group\", path: child }) };\n\t\t});\n\t};\n\n\tconst isLeaf = (node: ResolvedPath | GroupPath) =>\n\t\tnode.kind === \"constant\" ||\n\t\t(node.kind === \"target\" &&\n\t\t\t[\"scalar\", \"enum\"].includes(typeOfId(node.type).kind));\n\n\t/**\n\t * Leaf paths matching `patterns`, where `*` stands for one segment. A pattern naming a record,\n\t * array or group stands for all its leaves; wildcards and expansion skip compiler-made fields.\n\t * Paths that don't resolve are kept, so callers can report them.\n\t */\n\tconst expand = (patterns: readonly string[], limit = 2000) => {\n\t\tconst leaves = new Set<string>();\n\t\tconst add = (path: string) => {\n\t\t\tleaves.add(path);\n\t\t\tif (leaves.size > limit) {\n\t\t\t\tthrow new RangeError(`More than ${limit} values match`);\n\t\t\t}\n\t\t};\n\t\tconst below = (node: ResolvedPath | GroupPath) => {\n\t\t\tif (isLeaf(node)) {\n\t\t\t\treturn add(node.path);\n\t\t\t}\n\t\t\tfor (const child of children(node.path)) {\n\t\t\t\tif (!(child.kind === \"target\" && child.generated)) {\n\t\t\t\t\tbelow(child);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tconst match = (\n\t\t\tprefix: string,\n\t\t\trest: readonly string[],\n\t\t\twildcard: boolean,\n\t\t) => {\n\t\t\tconst [head, ...tail] = rest;\n\t\t\tif (head === undefined) {\n\t\t\t\tconst node: ResolvedPath | GroupPath | undefined =\n\t\t\t\t\tresolve(prefix) ??\n\t\t\t\t\t(groups.has(prefix) ? { kind: \"group\", path: prefix } : undefined);\n\t\t\t\tif (node) {\n\t\t\t\t\tbelow(node);\n\t\t\t\t} else if (!wildcard) {\n\t\t\t\t\tadd(prefix);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (head === \"*\" || head === anyIndex) {\n\t\t\t\tfor (const child of children(prefix)) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(child.kind === \"target\" && child.generated) &&\n\t\t\t\t\t\t(head === \"*\" || child.name.startsWith(\"[\"))\n\t\t\t\t\t) {\n\t\t\t\t\t\tmatch(child.path, tail, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmatch(joinPath(prefix, head), tail, wildcard);\n\t\t\t}\n\t\t};\n\t\tfor (const pattern of patterns) {\n\t\t\tmatch(\"\", pathSegments(pattern), false);\n\t\t}\n\t\treturn [...leaves];\n\t};\n\n\t/** A value as TypeScript shows it: enum members by name, BOOL as a boolean. */\n\tconst decode = (typeId: string, raw: unknown) => {\n\t\tconst type = typeOfId(typeId);\n\t\tif (type.kind === \"enum\") {\n\t\t\treturn (\n\t\t\t\tObject.entries(type.members).find(([, value]) => value === raw)?.[0] ??\n\t\t\t\traw\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\ttype.kind === \"scalar\" &&\n\t\t\ttype.iec === \"BOOL\" &&\n\t\t\ttypeof raw === \"number\"\n\t\t) {\n\t\t\treturn raw !== 0;\n\t\t}\n\t\treturn raw;\n\t};\n\n\treturn { typeOf: typeOfId, resolve, children, isLeaf, expand, decode };\n};\n\nexport type Paths = ReturnType<typeof createPaths>;\n",
|
|
6
|
+
"import type { Quality } from \"../api.ts\";\nimport type { DebugManifest, SourceRange } from \"../manifest.ts\";\nimport { typeOf } from \"../paths.ts\";\n\n/** How a value is shown: each state has its own styling and label, so none passes for live. */\nexport type ValueState =\n\t\"live\" | \"uncertain\" | \"bad\" | \"stale\" | \"unavailable\" | \"constant\";\n\nexport const valueStateLabels: Record<ValueState, string> = {\n\tlive: \"good\",\n\tuncertain: \"uncertain\",\n\tbad: \"bad\",\n\tstale: \"stale\",\n\tunavailable: \"unavailable\",\n\tconstant: \"constant\",\n};\n\n/** A sample is stale when the controller connection is down or the sample is older than three sample intervals. */\nexport const valueState = (\n\tquality: Quality,\n\tageMs: number,\n\tcontext: { connected: boolean; intervalMs: number },\n): ValueState => {\n\tif (quality === \"unavailable\") {\n\t\treturn \"unavailable\";\n\t}\n\tif (!context.connected || ageMs > 3 * context.intervalMs) {\n\t\treturn \"stale\";\n\t}\n\tif (quality === \"bad\") {\n\t\treturn \"bad\";\n\t}\n\tif (quality === \"uncertain\") {\n\t\treturn \"uncertain\";\n\t}\n\treturn \"live\";\n};\n\nexport const formatAge = (ms: number) => {\n\tif (ms < 1000) {\n\t\treturn \"now\";\n\t}\n\tif (ms < 60_000) {\n\t\treturn `${Math.floor(ms / 1000)} s ago`;\n\t}\n\tif (ms < 3_600_000) {\n\t\treturn `${Math.floor(ms / 60_000)} min ago`;\n\t}\n\treturn `${Math.floor(ms / 3_600_000)} h ago`;\n};\n\nexport const formatDuration = (ms: number) => {\n\tif (ms < 1000) {\n\t\treturn `${Math.round(ms)} ms`;\n\t}\n\tif (ms < 60_000) {\n\t\treturn `${(ms / 1000).toFixed(1)} s`;\n\t}\n\treturn `${Math.floor(ms / 60_000)} min ${Math.floor((ms % 60_000) / 1000)} s`;\n};\n\n/** How often values are read: `250 ms`, `1 s`, `1.5 s`. */\nexport const formatInterval = (ms: number) =>\n\tms < 1000 ? `${ms} ms` : `${ms / 1000} s`;\n\n/** Local time of day with milliseconds, for ordering events by eye. */\nexport const formatClock = (iso: string) => {\n\tconst date = new Date(iso);\n\tconst pad = (value: number, width = 2) => String(value).padStart(width, \"0\");\n\treturn `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}.${pad(date.getMilliseconds(), 3)}`;\n};\n\n/** When a value was read, to the second: `read 14:03:27`. */\nexport const formatReadAt = (iso: string) =>\n\t`read ${formatClock(iso).slice(0, 8)}`;\n\n/** A value of unknown type: booleans as IEC literals, strings quoted. */\nexport const formatScalar = (value: unknown): string => {\n\tif (typeof value === \"boolean\") {\n\t\treturn value ? \"TRUE\" : \"FALSE\";\n\t}\n\tif (typeof value === \"number\") {\n\t\treturn Number.isInteger(value)\n\t\t\t? String(value)\n\t\t\t: String(Number(value.toPrecision(6)));\n\t}\n\tif (typeof value === \"string\") {\n\t\treturn JSON.stringify(value);\n\t}\n\tif (value === null || value === undefined) {\n\t\treturn \"—\";\n\t}\n\treturn JSON.stringify(value);\n};\n\n/** A value in the program's terms: enum members by name, whether the host decoded them already or not. */\nexport const formatValue = (\n\tmanifest: DebugManifest,\n\ttypeId: string,\n\tvalue: unknown,\n): string => {\n\tconst type = typeOf(manifest, typeId);\n\tif (type.kind !== \"enum\") {\n\t\treturn formatScalar(value);\n\t}\n\tif (typeof value === \"string\" && Object.hasOwn(type.members, value)) {\n\t\treturn value;\n\t}\n\tif (typeof value !== \"number\") {\n\t\treturn formatScalar(value);\n\t}\n\tconst member = Object.entries(type.members).find(\n\t\t([, number]) => number === value,\n\t)?.[0];\n\treturn member ?? `${value} (not a ${type.name})`;\n};\n\nexport const typeLabel = (manifest: DebugManifest, typeId: string): string => {\n\tconst type = typeOf(manifest, typeId);\n\tswitch (type.kind) {\n\t\tcase \"scalar\":\n\t\t\treturn type.iec;\n\t\tcase \"enum\":\n\t\tcase \"record\":\n\t\t\treturn type.name;\n\t\tcase \"array\":\n\t\t\treturn `${typeLabel(manifest, type.element)}[${type.length}]`;\n\t}\n};\n\nconst PROPERTY_TEXT = 16;\n\n/** A record's properties as `barcode=CON-MD3-884… scanner=3`, long strings cut short. */\nexport const formatProperties = (properties: Record<string, unknown>) =>\n\tObject.entries(properties)\n\t\t.map(([key, value]) => {\n\t\t\tconst text = typeof value === \"string\" ? value : formatScalar(value);\n\t\t\treturn `${key}=${text.length > PROPERTY_TEXT ? `${text.slice(0, PROPERTY_TEXT)}…` : text}`;\n\t\t})\n\t\t.join(\" \");\n\n/** A VS Code link to a project file, when the project root on the debugger host is known. */\nconst fileHref = (\n\tprojectRoot: string | undefined,\n\tfile: string,\n\tline: number,\n\tcolumn: number,\n) => {\n\tif (projectRoot === undefined) {\n\t\treturn undefined;\n\t}\n\tconst root = projectRoot.replaceAll(\"\\\\\", \"/\").replace(/\\/$/, \"\");\n\tconst absolute = `${root}/${file}`.replace(/^\\/?/, \"/\");\n\treturn `vscode://file${absolute}:${line}:${column}`;\n};\n\n/** `file:line`, and a VS Code link when the project root on the debugger host is known. */\nexport const sourceLocation = (\n\tmanifest: DebugManifest,\n\tprojectRoot: string | undefined,\n\trange: SourceRange,\n) => {\n\tconst file = manifest.sources[range.file] ?? `source ${range.file}`;\n\tconst href = fileHref(projectRoot, file, range.line, range.column);\n\treturn { label: `${file}:${range.line}`, ...(href && { href }) };\n};\n\n/** A record's project-relative `file:line` as `basename:line`, with the same VS Code link. */\nexport const recordLocation = (\n\tprojectRoot: string | undefined,\n\tsource: string,\n) => {\n\tconst [, file = source, line] = /^(.*):(\\d+)$/.exec(source) ?? [];\n\tconst label = `${file.slice(file.lastIndexOf(\"/\") + 1)}${line ? `:${line}` : \"\"}`;\n\tconst href =\n\t\tline === undefined\n\t\t\t? undefined\n\t\t\t: fileHref(projectRoot, file, Number(line), 1);\n\treturn { label, ...(href && { href }) };\n};\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": ";
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "2270CEF4083E476B64756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|