@fluixi/devtools 0.2.0-alpha.2 → 0.2.0-alpha.4
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/README.md +80 -2
- package/dist/callsite.cjs +72 -0
- package/dist/callsite.d.ts +22 -0
- package/dist/callsite.d.ts.map +1 -0
- package/dist/callsite.js +82 -0
- package/dist/callsite.mjs +51 -0
- package/dist/change-view.cjs +134 -0
- package/dist/change-view.d.ts +10 -0
- package/dist/change-view.d.ts.map +1 -0
- package/dist/change-view.js +102 -0
- package/dist/change-view.mjs +111 -0
- package/dist/copy.cjs +63 -0
- package/dist/copy.d.ts +9 -0
- package/dist/copy.d.ts.map +1 -0
- package/dist/copy.js +52 -0
- package/dist/copy.mjs +42 -0
- package/dist/describe.cjs +55 -0
- package/dist/describe.d.ts +3 -0
- package/dist/describe.d.ts.map +1 -0
- package/dist/describe.js +47 -0
- package/dist/describe.mjs +34 -0
- package/dist/detail-panel.cjs +307 -0
- package/dist/detail-panel.d.ts +17 -0
- package/dist/detail-panel.d.ts.map +1 -0
- package/dist/detail-panel.js +217 -0
- package/dist/detail-panel.mjs +284 -0
- package/dist/diff.cjs +225 -0
- package/dist/diff.d.ts +31 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +132 -0
- package/dist/diff.mjs +202 -0
- package/dist/dom.cjs +204 -0
- package/dist/dom.d.ts +81 -0
- package/dist/dom.d.ts.map +1 -0
- package/dist/dom.js +269 -0
- package/dist/dom.mjs +183 -0
- package/dist/export.cjs +221 -0
- package/dist/export.d.ts +55 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +90 -0
- package/dist/export.mjs +209 -0
- package/dist/float.cjs +232 -0
- package/dist/float.d.ts +54 -0
- package/dist/float.d.ts.map +1 -0
- package/dist/float.js +256 -0
- package/dist/float.mjs +211 -0
- package/dist/format.cjs +175 -0
- package/dist/format.d.ts +16 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +188 -0
- package/dist/format.mjs +154 -0
- package/dist/graph-view.cjs +893 -0
- package/dist/graph-view.d.ts +79 -2
- package/dist/graph-view.d.ts.map +1 -1
- package/dist/graph-view.js +866 -50
- package/dist/graph-view.mjs +870 -0
- package/dist/highlight.cjs +140 -0
- package/dist/highlight.d.ts +56 -0
- package/dist/highlight.d.ts.map +1 -0
- package/dist/highlight.js +154 -0
- package/dist/highlight.mjs +119 -0
- package/dist/history.cjs +95 -0
- package/dist/history.d.ts +59 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +85 -0
- package/dist/history.mjs +74 -0
- package/dist/hook.cjs +1562 -0
- package/dist/hook.d.ts +60 -0
- package/dist/hook.d.ts.map +1 -0
- package/dist/hook.js +142 -0
- package/dist/hook.mjs +1553 -0
- package/dist/index.cjs +4552 -0
- package/dist/index.d.ts +44 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -1
- package/dist/index.mjs +4544 -0
- package/dist/inspector.cjs +688 -0
- package/dist/inspector.d.ts +60 -0
- package/dist/inspector.d.ts.map +1 -0
- package/dist/inspector.js +415 -0
- package/dist/inspector.mjs +676 -0
- package/dist/instrument.cjs +497 -0
- package/dist/instrument.d.ts +147 -5
- package/dist/instrument.d.ts.map +1 -1
- package/dist/instrument.js +164 -44
- package/dist/instrument.mjs +487 -0
- package/dist/kind-filter.cjs +172 -0
- package/dist/kind-filter.d.ts +39 -0
- package/dist/kind-filter.d.ts.map +1 -0
- package/dist/kind-filter.js +151 -0
- package/dist/kind-filter.mjs +151 -0
- package/dist/menu.cjs +141 -0
- package/dist/menu.d.ts +37 -0
- package/dist/menu.d.ts.map +1 -0
- package/dist/menu.js +125 -0
- package/dist/menu.mjs +120 -0
- package/dist/observe.cjs +1352 -0
- package/dist/observe.d.ts +80 -0
- package/dist/observe.d.ts.map +1 -0
- package/dist/observe.js +893 -0
- package/dist/observe.mjs +1345 -0
- package/dist/palette.cjs +52 -0
- package/dist/palette.d.ts +11 -0
- package/dist/palette.d.ts.map +1 -0
- package/dist/palette.js +27 -0
- package/dist/palette.mjs +31 -0
- package/dist/path.cjs +45 -0
- package/dist/path.d.ts +19 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +49 -0
- package/dist/path.mjs +24 -0
- package/dist/plugin.cjs +87 -0
- package/dist/plugin.d.ts +121 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +74 -0
- package/dist/plugin.mjs +66 -0
- package/dist/plugins/context.cjs +98 -0
- package/dist/plugins/context.d.ts +10 -0
- package/dist/plugins/context.d.ts.map +1 -0
- package/dist/plugins/context.js +80 -0
- package/dist/plugins/context.mjs +75 -0
- package/dist/plugins/directives.cjs +98 -0
- package/dist/plugins/directives.d.ts +25 -0
- package/dist/plugins/directives.d.ts.map +1 -0
- package/dist/plugins/directives.js +78 -0
- package/dist/plugins/directives.mjs +75 -0
- package/dist/plugins/index.cjs +162 -0
- package/dist/plugins/index.d.ts +7 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +9 -0
- package/dist/plugins/index.mjs +140 -0
- package/dist/source.cjs +111 -0
- package/dist/source.d.ts +72 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +153 -0
- package/dist/source.mjs +90 -0
- package/dist/timeline.cjs +350 -0
- package/dist/timeline.d.ts +30 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +271 -0
- package/dist/timeline.mjs +327 -0
- package/dist/tree.cjs +574 -0
- package/dist/tree.d.ts +128 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +645 -0
- package/dist/tree.mjs +551 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/value-pane.cjs +223 -0
- package/dist/value-pane.d.ts +10 -0
- package/dist/value-pane.d.ts.map +1 -0
- package/dist/value-pane.js +61 -0
- package/dist/value-pane.mjs +200 -0
- package/dist/wire.cjs +109 -0
- package/dist/wire.d.ts +100 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +93 -0
- package/dist/wire.mjs +89 -0
- package/package.json +17 -5
package/dist/diff.mjs
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// src/format.ts
|
|
2
|
+
var MAX_DEPTH = 3;
|
|
3
|
+
var MAX_ENTRIES = 8;
|
|
4
|
+
function domName(v) {
|
|
5
|
+
if (typeof v?.nodeType !== "number" || typeof v.nodeName !== "string") return null;
|
|
6
|
+
return v.tagName ? `<${v.tagName.toLowerCase()}>` : `#${v.nodeName.toLowerCase()}`;
|
|
7
|
+
}
|
|
8
|
+
function fnName(v) {
|
|
9
|
+
return v.name ? `ƒ ${v.name}()` : "ƒ";
|
|
10
|
+
}
|
|
11
|
+
function className(v) {
|
|
12
|
+
const name = v.constructor?.name;
|
|
13
|
+
return name && name !== "Object" ? `${name} ` : "";
|
|
14
|
+
}
|
|
15
|
+
function primitive(v) {
|
|
16
|
+
if (v === null) return "null";
|
|
17
|
+
switch (typeof v) {
|
|
18
|
+
case "undefined":
|
|
19
|
+
return "undefined";
|
|
20
|
+
case "string":
|
|
21
|
+
return JSON.stringify(v);
|
|
22
|
+
case "number":
|
|
23
|
+
case "boolean":
|
|
24
|
+
return String(v);
|
|
25
|
+
case "bigint":
|
|
26
|
+
return `${v}n`;
|
|
27
|
+
case "symbol":
|
|
28
|
+
return v.toString();
|
|
29
|
+
case "function":
|
|
30
|
+
return fnName(v);
|
|
31
|
+
default:
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function walk(value, depth, seen) {
|
|
36
|
+
const simple = primitive(value);
|
|
37
|
+
if (simple !== null) return simple;
|
|
38
|
+
const object = value;
|
|
39
|
+
if (seen.has(object)) return "[circular]";
|
|
40
|
+
const dom = domName(object);
|
|
41
|
+
if (dom) return dom;
|
|
42
|
+
if (object instanceof Date) return Number.isNaN(object.getTime()) ? "Invalid Date" : object.toISOString();
|
|
43
|
+
if (object instanceof RegExp) return String(object);
|
|
44
|
+
if (object instanceof Error) return `${object.name}: ${object.message}`;
|
|
45
|
+
if (object instanceof Promise) return "Promise";
|
|
46
|
+
if (ArrayBuffer.isView(object)) {
|
|
47
|
+
return `${className(object).trim()}(${object.length ?? ""})`;
|
|
48
|
+
}
|
|
49
|
+
if (depth >= MAX_DEPTH) return Array.isArray(object) ? "[…]" : "{…}";
|
|
50
|
+
seen.add(object);
|
|
51
|
+
try {
|
|
52
|
+
if (Array.isArray(object)) {
|
|
53
|
+
const shown2 = object.slice(0, MAX_ENTRIES).map((item) => walk(item, depth + 1, seen));
|
|
54
|
+
if (object.length > MAX_ENTRIES) shown2.push("…");
|
|
55
|
+
return `[${shown2.join(", ")}]`;
|
|
56
|
+
}
|
|
57
|
+
if (object instanceof Map) {
|
|
58
|
+
const shown2 = [];
|
|
59
|
+
for (const [k, v] of object) {
|
|
60
|
+
if (shown2.length === MAX_ENTRIES) {
|
|
61
|
+
shown2.push("…");
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
shown2.push(`${walk(k, depth + 1, seen)} => ${walk(v, depth + 1, seen)}`);
|
|
65
|
+
}
|
|
66
|
+
return `Map(${object.size}) {${shown2.join(", ")}}`;
|
|
67
|
+
}
|
|
68
|
+
if (object instanceof Set) {
|
|
69
|
+
const shown2 = [];
|
|
70
|
+
for (const item of object) {
|
|
71
|
+
if (shown2.length === MAX_ENTRIES) {
|
|
72
|
+
shown2.push("…");
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
shown2.push(walk(item, depth + 1, seen));
|
|
76
|
+
}
|
|
77
|
+
return `Set(${object.size}) {${shown2.join(", ")}}`;
|
|
78
|
+
}
|
|
79
|
+
const keys = Object.keys(object);
|
|
80
|
+
const shown = keys.slice(0, MAX_ENTRIES).map((key) => {
|
|
81
|
+
let read;
|
|
82
|
+
try {
|
|
83
|
+
read = walk(object[key], depth + 1, seen);
|
|
84
|
+
} catch {
|
|
85
|
+
read = "[unreadable]";
|
|
86
|
+
}
|
|
87
|
+
return `${key}: ${read}`;
|
|
88
|
+
});
|
|
89
|
+
if (keys.length > MAX_ENTRIES) shown.push("…");
|
|
90
|
+
return `${className(object)}{${shown.join(", ")}}`;
|
|
91
|
+
} finally {
|
|
92
|
+
seen.delete(object);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function formatValue(value, limit = 240) {
|
|
96
|
+
let text;
|
|
97
|
+
try {
|
|
98
|
+
text = walk(value, 0, /* @__PURE__ */ new Set());
|
|
99
|
+
} catch {
|
|
100
|
+
text = "[unreadable]";
|
|
101
|
+
}
|
|
102
|
+
return text.length > limit ? `${text.slice(0, limit - 1)}…` : text;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// src/diff.ts
|
|
106
|
+
var MAX_ENTRIES2 = 24;
|
|
107
|
+
var ENTRY_VALUE = 120;
|
|
108
|
+
var ENTRY_JSON = 4e3;
|
|
109
|
+
var show = (value) => formatValue(value, ENTRY_VALUE);
|
|
110
|
+
function json(value) {
|
|
111
|
+
if (value === null || typeof value !== "object") return void 0;
|
|
112
|
+
try {
|
|
113
|
+
const text = JSON.stringify(value);
|
|
114
|
+
return text && text.length <= ENTRY_JSON ? text : void 0;
|
|
115
|
+
} catch {
|
|
116
|
+
return void 0;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
var side = (value, key) => {
|
|
120
|
+
const text = json(value);
|
|
121
|
+
return { [key]: show(value), ...text ? { [`${key}Json`]: text } : {} };
|
|
122
|
+
};
|
|
123
|
+
var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
124
|
+
function same(a, b) {
|
|
125
|
+
if (Object.is(a, b)) return true;
|
|
126
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
127
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
128
|
+
const ka = Object.keys(a);
|
|
129
|
+
const kb = Object.keys(b);
|
|
130
|
+
if (ka.length !== kb.length) return false;
|
|
131
|
+
return ka.every((k) => Object.is(a[k], b[k]));
|
|
132
|
+
}
|
|
133
|
+
function diffArray(before, after) {
|
|
134
|
+
let head = 0;
|
|
135
|
+
while (head < before.length && head < after.length && same(before[head], after[head])) head++;
|
|
136
|
+
let tail = 0;
|
|
137
|
+
while (tail < before.length - head && tail < after.length - head && same(before[before.length - 1 - tail], after[after.length - 1 - tail])) {
|
|
138
|
+
tail++;
|
|
139
|
+
}
|
|
140
|
+
const entries = [];
|
|
141
|
+
let skipped = 0;
|
|
142
|
+
const push = (entry) => {
|
|
143
|
+
if (entries.length < MAX_ENTRIES2) entries.push(entry);
|
|
144
|
+
else skipped++;
|
|
145
|
+
};
|
|
146
|
+
const removedCount = before.length - head - tail;
|
|
147
|
+
const addedCount = after.length - head - tail;
|
|
148
|
+
const overlap = Math.min(removedCount, addedCount);
|
|
149
|
+
for (let i = 0; i < overlap; i++) {
|
|
150
|
+
push({
|
|
151
|
+
key: String(head + i),
|
|
152
|
+
op: "changed",
|
|
153
|
+
...side(before[head + i], "from"),
|
|
154
|
+
...side(after[head + i], "to")
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
for (let i = overlap; i < addedCount; i++) {
|
|
158
|
+
push({ key: String(head + i), op: "added", ...side(after[head + i], "to") });
|
|
159
|
+
}
|
|
160
|
+
for (let i = overlap; i < removedCount; i++) {
|
|
161
|
+
push({ key: String(head + i), op: "removed", ...side(before[head + i], "from") });
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
shape: "array",
|
|
165
|
+
entries,
|
|
166
|
+
...skipped ? { more: skipped } : {},
|
|
167
|
+
...before.length !== after.length ? { length: { from: before.length, to: after.length } } : {}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function diffObject(before, after) {
|
|
171
|
+
const entries = [];
|
|
172
|
+
let skipped = 0;
|
|
173
|
+
const push = (entry) => {
|
|
174
|
+
if (entries.length < MAX_ENTRIES2) entries.push(entry);
|
|
175
|
+
else skipped++;
|
|
176
|
+
};
|
|
177
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])) {
|
|
178
|
+
const had = key in before;
|
|
179
|
+
const has = key in after;
|
|
180
|
+
if (had && has) {
|
|
181
|
+
if (!same(before[key], after[key])) {
|
|
182
|
+
push({ key, op: "changed", ...side(before[key], "from"), ...side(after[key], "to") });
|
|
183
|
+
}
|
|
184
|
+
} else if (has) push({ key, op: "added", ...side(after[key], "to") });
|
|
185
|
+
else push({ key, op: "removed", ...side(before[key], "from") });
|
|
186
|
+
}
|
|
187
|
+
return { shape: "object", entries, ...skipped ? { more: skipped } : {} };
|
|
188
|
+
}
|
|
189
|
+
function diffValues(before, after) {
|
|
190
|
+
if (Array.isArray(before) && Array.isArray(after)) {
|
|
191
|
+
const change = diffArray(before, after);
|
|
192
|
+
return change.entries?.length || change.length ? change : void 0;
|
|
193
|
+
}
|
|
194
|
+
if (isPlainObject(before) && isPlainObject(after)) {
|
|
195
|
+
const change = diffObject(before, after);
|
|
196
|
+
return change.entries?.length ? change : void 0;
|
|
197
|
+
}
|
|
198
|
+
return void 0;
|
|
199
|
+
}
|
|
200
|
+
export {
|
|
201
|
+
diffValues
|
|
202
|
+
};
|
package/dist/dom.cjs
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/dom.ts
|
|
21
|
+
var dom_exports = {};
|
|
22
|
+
__export(dom_exports, {
|
|
23
|
+
DOM_BUDGET: () => DOM_BUDGET,
|
|
24
|
+
describeAll: () => describeAll,
|
|
25
|
+
describeElement: () => describeElement,
|
|
26
|
+
tagDepths: () => tagDepths,
|
|
27
|
+
withoutElements: () => withoutElements
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(dom_exports);
|
|
30
|
+
var LOC_TAG = "__fx_loc";
|
|
31
|
+
function locationOf(element) {
|
|
32
|
+
return element[LOC_TAG];
|
|
33
|
+
}
|
|
34
|
+
var DOM_BUDGET = 200;
|
|
35
|
+
function describeElement(element) {
|
|
36
|
+
let out = element.tagName.toLowerCase();
|
|
37
|
+
if (element.id) out += `#${element.id}`;
|
|
38
|
+
const classes = element.classList;
|
|
39
|
+
if (classes.length > 0) {
|
|
40
|
+
out += `.${classes[0]}`;
|
|
41
|
+
if (classes.length > 1) out += `.${classes[1]}`;
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
function describeAll(graph, roots, writtenBy, kinds, extraFor) {
|
|
46
|
+
const owners = /* @__PURE__ */ new Map();
|
|
47
|
+
const writers = /* @__PURE__ */ new Map();
|
|
48
|
+
const rendered = /* @__PURE__ */ new Map();
|
|
49
|
+
for (const node of graph.values()) {
|
|
50
|
+
if (kinds.has(node.kind)) {
|
|
51
|
+
const found = roots(node.id);
|
|
52
|
+
rendered.set(node.id, found);
|
|
53
|
+
for (const element of found) if (!owners.has(element)) owners.set(element, node.id);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
for (const element of writtenBy(node.id)) {
|
|
57
|
+
const held = writers.get(element);
|
|
58
|
+
if (held) held.push(node.id);
|
|
59
|
+
else writers.set(element, [node.id]);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const { claimed, containers } = claimOrphans(graph, rendered, writtenBy, kinds, owners);
|
|
63
|
+
const claims = /* @__PURE__ */ new Map();
|
|
64
|
+
for (const [element, id] of claimed) {
|
|
65
|
+
const held = claims.get(id);
|
|
66
|
+
if (held) held.push(element);
|
|
67
|
+
else claims.set(id, [element]);
|
|
68
|
+
}
|
|
69
|
+
const landing = landings(graph, rendered, writtenBy, kinds, claimed, containers);
|
|
70
|
+
const out = /* @__PURE__ */ new Map();
|
|
71
|
+
for (const node of graph.values()) {
|
|
72
|
+
if (!kinds.has(node.kind)) continue;
|
|
73
|
+
const budget = { left: DOM_BUDGET };
|
|
74
|
+
const walk = (element) => {
|
|
75
|
+
const owner = owners.get(element) ?? claimed.get(element);
|
|
76
|
+
const where = locationOf(element);
|
|
77
|
+
if (owner !== void 0 && owner !== node.id) {
|
|
78
|
+
return { label: describeElement(element), children: [], owner, element, ...where ? { at: where } : {} };
|
|
79
|
+
}
|
|
80
|
+
if (containers.has(element)) {
|
|
81
|
+
return { label: describeElement(element), children: [], container: true, element, ...where ? { at: where } : {} };
|
|
82
|
+
}
|
|
83
|
+
const children = [];
|
|
84
|
+
const kids = element.children;
|
|
85
|
+
for (let i = 0, n = kids.length; i < n && budget.left > 0; i++) {
|
|
86
|
+
budget.left -= 1;
|
|
87
|
+
children.push(walk(kids[i]));
|
|
88
|
+
}
|
|
89
|
+
const writes = writers.get(element);
|
|
90
|
+
const extra = extraFor?.(element);
|
|
91
|
+
const inside = landing.get(element)?.filter((id) => within(graph, id, node.id));
|
|
92
|
+
return {
|
|
93
|
+
label: describeElement(element),
|
|
94
|
+
children,
|
|
95
|
+
element,
|
|
96
|
+
...where ? { at: where } : {},
|
|
97
|
+
...writes?.length ? { writes } : {},
|
|
98
|
+
...inside?.length ? { inside } : {},
|
|
99
|
+
...extra ? { extra } : {}
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
out.set(node.id, [...rendered.get(node.id) ?? [], ...claims.get(node.id) ?? []].map(walk));
|
|
103
|
+
}
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
function within(graph, id, ancestor) {
|
|
107
|
+
const seen = /* @__PURE__ */ new Set();
|
|
108
|
+
for (let at = graph.get(id)?.createdIn; at !== void 0 && !seen.has(at); at = graph.get(at)?.createdIn) {
|
|
109
|
+
if (at === ancestor) return true;
|
|
110
|
+
seen.add(at);
|
|
111
|
+
}
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
function landings(graph, rendered, writtenBy, kinds, claimed, containers) {
|
|
115
|
+
const claimers = new Set(claimed.values());
|
|
116
|
+
const landing = /* @__PURE__ */ new Map();
|
|
117
|
+
for (const node of graph.values()) {
|
|
118
|
+
if (!kinds.has(node.kind) || (rendered.get(node.id) ?? []).length) continue;
|
|
119
|
+
if (claimers.has(node.id)) continue;
|
|
120
|
+
let shallowest;
|
|
121
|
+
let best = Infinity;
|
|
122
|
+
for (const element of writtenBy(node.id)) {
|
|
123
|
+
if (containers.has(element)) continue;
|
|
124
|
+
const depth = depthInDocument(element);
|
|
125
|
+
if (depth < best) {
|
|
126
|
+
best = depth;
|
|
127
|
+
shallowest = element;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (!shallowest) continue;
|
|
131
|
+
const held = landing.get(shallowest);
|
|
132
|
+
if (held) held.push(node.id);
|
|
133
|
+
else landing.set(shallowest, [node.id]);
|
|
134
|
+
}
|
|
135
|
+
for (const [element, ids] of landing) {
|
|
136
|
+
landing.set(element, ids.filter((id) => !ids.some((other) => other !== id && within(graph, id, other))));
|
|
137
|
+
}
|
|
138
|
+
return landing;
|
|
139
|
+
}
|
|
140
|
+
function tagDepths(graph, kinds) {
|
|
141
|
+
const depth = /* @__PURE__ */ new Map();
|
|
142
|
+
const of = (id, seen) => {
|
|
143
|
+
const held = depth.get(id);
|
|
144
|
+
if (held !== void 0) return held;
|
|
145
|
+
if (seen.has(id)) return 0;
|
|
146
|
+
seen.add(id);
|
|
147
|
+
const parent = graph.get(id)?.createdIn;
|
|
148
|
+
const value = parent === void 0 ? 0 : of(parent, seen) + 1;
|
|
149
|
+
depth.set(id, value);
|
|
150
|
+
return value;
|
|
151
|
+
};
|
|
152
|
+
for (const node of graph.values()) if (kinds.has(node.kind)) of(node.id, /* @__PURE__ */ new Set());
|
|
153
|
+
return depth;
|
|
154
|
+
}
|
|
155
|
+
function depthInDocument(element) {
|
|
156
|
+
let steps = 0;
|
|
157
|
+
for (let at = element.parentElement; at; at = at.parentElement) steps++;
|
|
158
|
+
return steps;
|
|
159
|
+
}
|
|
160
|
+
function claimOrphans(graph, rendered, writtenBy, kinds, owners) {
|
|
161
|
+
const depth = tagDepths(graph, kinds);
|
|
162
|
+
const wraps = (element) => {
|
|
163
|
+
for (const owned of owners.keys()) if (element !== owned && element.contains(owned)) return true;
|
|
164
|
+
return false;
|
|
165
|
+
};
|
|
166
|
+
const writing = /* @__PURE__ */ new Map();
|
|
167
|
+
for (const node of graph.values()) {
|
|
168
|
+
if (!kinds.has(node.kind) || (rendered.get(node.id) ?? []).length) continue;
|
|
169
|
+
for (const element of writtenBy(node.id)) {
|
|
170
|
+
if (owners.has(element)) continue;
|
|
171
|
+
const held = writing.get(element);
|
|
172
|
+
if (held) held.push(node.id);
|
|
173
|
+
else writing.set(element, [node.id]);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const claimed = /* @__PURE__ */ new Map();
|
|
177
|
+
const containers = /* @__PURE__ */ new Set();
|
|
178
|
+
const covered = (element) => {
|
|
179
|
+
for (let at = element.parentElement; at; at = at.parentElement) {
|
|
180
|
+
if (owners.has(at) || claimed.has(at)) return true;
|
|
181
|
+
}
|
|
182
|
+
return false;
|
|
183
|
+
};
|
|
184
|
+
const order = [...writing.keys()].sort((a, b) => depthInDocument(a) - depthInDocument(b));
|
|
185
|
+
for (const element of order) {
|
|
186
|
+
if (covered(element)) continue;
|
|
187
|
+
const ids = writing.get(element);
|
|
188
|
+
const container = wraps(element);
|
|
189
|
+
const pick = ids.reduce((best, id) => {
|
|
190
|
+
const a = depth.get(id) ?? 0;
|
|
191
|
+
const b = depth.get(best) ?? 0;
|
|
192
|
+
return container ? a < b ? id : best : a > b ? id : best;
|
|
193
|
+
});
|
|
194
|
+
claimed.set(element, pick);
|
|
195
|
+
if (container) containers.add(element);
|
|
196
|
+
}
|
|
197
|
+
return { claimed, containers };
|
|
198
|
+
}
|
|
199
|
+
function withoutElements(nodes) {
|
|
200
|
+
return nodes.map(({ element, children, ...rest }) => ({
|
|
201
|
+
...rest,
|
|
202
|
+
children: withoutElements(children)
|
|
203
|
+
}));
|
|
204
|
+
}
|
package/dist/dom.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A serialisable description of the DOM a tag rendered.
|
|
3
|
+
*
|
|
4
|
+
* The chrome panel reads the graph through `eval` and the editor panel over http, so neither
|
|
5
|
+
* can hold Elements. This is the same tree with the elements reduced to labels.
|
|
6
|
+
*
|
|
7
|
+
* The walk stops at any element that is another tag's root and records that tag's id in
|
|
8
|
+
* `owner`. That keeps the result a tree of the application rather than the whole document,
|
|
9
|
+
* and lets the consumer nest the child tag's own DOM under its own row.
|
|
10
|
+
*/
|
|
11
|
+
import type { RNode } from './instrument.js';
|
|
12
|
+
export interface DomNode {
|
|
13
|
+
/** The element as a selector: `div#app.card`. */
|
|
14
|
+
label: string;
|
|
15
|
+
children: DomNode[];
|
|
16
|
+
/** The node whose root this element is, when it is one. */
|
|
17
|
+
owner?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Ids of the values that write into this element. A consumer outside the page has no
|
|
20
|
+
* elements to compare, so it cannot work this out for itself.
|
|
21
|
+
*/
|
|
22
|
+
writes?: number[];
|
|
23
|
+
/**
|
|
24
|
+
* Tags that render inside this element without producing one of their own, such as a boundary
|
|
25
|
+
* like Suspense, or a component whose body is another component. They sit here rather than
|
|
26
|
+
* beside the element, which is where the nesting actually puts them.
|
|
27
|
+
*/
|
|
28
|
+
inside?: number[];
|
|
29
|
+
/**
|
|
30
|
+
* The element the application was mounted into. It is nobody's output, having been on the
|
|
31
|
+
* page first, so it belongs above the root tag rather than under it.
|
|
32
|
+
*/
|
|
33
|
+
container?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Where the element was written. Stamped on it by the runtime when the compiler listed
|
|
36
|
+
* the positions of a template's elements; absent in a build without source locations.
|
|
37
|
+
*/
|
|
38
|
+
at?: {
|
|
39
|
+
file: string;
|
|
40
|
+
line: number;
|
|
41
|
+
column: number;
|
|
42
|
+
};
|
|
43
|
+
/** What plugins attached to this element, by plugin name. */
|
|
44
|
+
extra?: Record<string, unknown>;
|
|
45
|
+
/** Set only in-page. A description that crossed a wire has no element. */
|
|
46
|
+
element?: Element;
|
|
47
|
+
}
|
|
48
|
+
/** Elements described per tag. Caps how large a snapshot can get. */
|
|
49
|
+
export declare const DOM_BUDGET = 200;
|
|
50
|
+
/**
|
|
51
|
+
* Static attributes only: a class computed at runtime is not in the source.
|
|
52
|
+
*
|
|
53
|
+
* Written out rather than spread-and-join. This runs once per element of the page on every
|
|
54
|
+
* sample, and building three throwaway arrays to read at most two class names cost more
|
|
55
|
+
* than everything else the walk does.
|
|
56
|
+
*/
|
|
57
|
+
export declare function describeElement(element: Element): string;
|
|
58
|
+
/**
|
|
59
|
+
* Describe what every tag rendered, in one pass.
|
|
60
|
+
*
|
|
61
|
+
* Per-tag would rebuild the element maps each time, which is enough work to stall a render
|
|
62
|
+
* loop on a page of any size.
|
|
63
|
+
*/
|
|
64
|
+
export declare function describeAll(graph: Map<number, RNode>,
|
|
65
|
+
/** What a tag returned. Must not fall back to anything, or two tags claim one element. */
|
|
66
|
+
roots: (of: number) => readonly Element[],
|
|
67
|
+
/** Where a value writes. */
|
|
68
|
+
writtenBy: (of: number) => readonly Element[], kinds: ReadonlySet<string>,
|
|
69
|
+
/** What plugins attached to an element, when any did. */
|
|
70
|
+
extraFor?: (element: Element) => Record<string, unknown> | undefined): Map<number, DomNode[]>;
|
|
71
|
+
/** How deep a tag sits in the component nesting, following what created it. */
|
|
72
|
+
export declare function tagDepths(graph: Map<number, RNode>, kinds: ReadonlySet<string>): Map<number, number>;
|
|
73
|
+
/**
|
|
74
|
+
* Drop the Elements so the result can be serialised.
|
|
75
|
+
*
|
|
76
|
+
* Everything else is copied as-is rather than field by field. The copy that describes and the
|
|
77
|
+
* copy that strips are built separately, since an extension bundles its own, so a list of fields
|
|
78
|
+
* here goes stale against a description made elsewhere, and the field just disappears.
|
|
79
|
+
*/
|
|
80
|
+
export declare function withoutElements(nodes: readonly DomNode[]): DomNode[];
|
|
81
|
+
//# sourceMappingURL=dom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,WAAW,OAAO;IACtB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,EAAE,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAUD,qEAAqE;AACrE,eAAO,MAAM,UAAU,MAAM,CAAC;AAE9B;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CASxD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC;AACzB,0FAA0F;AAC1F,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,SAAS,OAAO,EAAE;AACzC,4BAA4B;AAC5B,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,SAAS,OAAO,EAAE,EAC7C,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC;AAC1B,yDAAyD;AACzD,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GACnE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAwExB;AAwDD,+EAA+E;AAC/E,wBAAgB,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAcpG;AAuED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE,CAKpE"}
|