@fluixi/devtools 0.2.0-alpha.3 → 0.2.0-alpha.5
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/callsite.cjs +72 -0
- package/dist/callsite.d.ts +1 -1
- package/dist/callsite.js +1 -1
- package/dist/callsite.mjs +51 -0
- package/dist/change-view.cjs +134 -0
- package/dist/change-view.js +2 -2
- package/dist/change-view.mjs +111 -0
- package/dist/copy.cjs +63 -0
- package/dist/copy.mjs +42 -0
- package/dist/describe.cjs +55 -0
- package/dist/describe.js +2 -2
- package/dist/describe.mjs +34 -0
- package/dist/detail-panel.cjs +307 -0
- package/dist/detail-panel.d.ts +1 -1
- package/dist/detail-panel.d.ts.map +1 -1
- package/dist/detail-panel.js +1 -1
- package/dist/detail-panel.mjs +284 -0
- package/dist/diff.cjs +225 -0
- package/dist/diff.js +1 -1
- package/dist/diff.mjs +202 -0
- package/dist/dom.cjs +204 -0
- package/dist/dom.mjs +183 -0
- package/dist/export.cjs +221 -0
- package/dist/export.d.ts +2 -2
- package/dist/export.d.ts.map +1 -1
- package/dist/export.js +1 -1
- package/dist/export.mjs +209 -0
- package/dist/float.cjs +232 -0
- package/dist/float.d.ts +1 -1
- package/dist/float.js +3 -3
- package/dist/float.mjs +211 -0
- package/dist/format.cjs +175 -0
- package/dist/format.js +3 -3
- package/dist/format.mjs +154 -0
- package/dist/graph-view.cjs +893 -0
- package/dist/graph-view.mjs +870 -0
- package/dist/highlight.cjs +140 -0
- package/dist/highlight.mjs +119 -0
- package/dist/history.cjs +95 -0
- package/dist/history.d.ts +2 -2
- package/dist/history.js +2 -2
- package/dist/history.mjs +74 -0
- package/dist/hook.cjs +1562 -0
- package/dist/hook.d.ts +3 -3
- package/dist/hook.js +6 -6
- package/dist/hook.mjs +1553 -0
- package/dist/index.cjs +4552 -0
- package/dist/index.mjs +4544 -0
- package/dist/inspector.cjs +688 -0
- package/dist/inspector.d.ts +2 -2
- package/dist/inspector.js +7 -7
- package/dist/inspector.mjs +676 -0
- package/dist/instrument.cjs +497 -0
- package/dist/instrument.mjs +487 -0
- package/dist/kind-filter.cjs +172 -0
- package/dist/kind-filter.d.ts +2 -2
- package/dist/kind-filter.js +1 -1
- package/dist/kind-filter.mjs +151 -0
- package/dist/menu.cjs +141 -0
- package/dist/menu.mjs +120 -0
- package/dist/observe.cjs +1352 -0
- package/dist/observe.mjs +1345 -0
- package/dist/palette.cjs +52 -0
- package/dist/palette.mjs +31 -0
- package/dist/path.cjs +45 -0
- package/dist/path.d.ts +2 -2
- package/dist/path.js +2 -2
- package/dist/path.mjs +24 -0
- package/dist/plugin.cjs +87 -0
- package/dist/plugin.mjs +66 -0
- package/dist/plugins/context.cjs +98 -0
- package/dist/plugins/context.mjs +75 -0
- package/dist/plugins/directives.cjs +98 -0
- package/dist/plugins/directives.mjs +75 -0
- package/dist/plugins/index.cjs +162 -0
- package/dist/plugins/index.mjs +140 -0
- package/dist/source.cjs +111 -0
- package/dist/source.d.ts +2 -2
- package/dist/source.js +4 -4
- package/dist/source.mjs +90 -0
- package/dist/timeline.cjs +350 -0
- package/dist/timeline.js +3 -3
- package/dist/timeline.mjs +327 -0
- package/dist/tree.cjs +574 -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.mjs +200 -0
- package/dist/wire.cjs +109 -0
- package/dist/wire.mjs +89 -0
- package/package.json +19 -6
package/dist/dom.mjs
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// src/dom.ts
|
|
2
|
+
var LOC_TAG = "__fx_loc";
|
|
3
|
+
function locationOf(element) {
|
|
4
|
+
return element[LOC_TAG];
|
|
5
|
+
}
|
|
6
|
+
var DOM_BUDGET = 200;
|
|
7
|
+
function describeElement(element) {
|
|
8
|
+
let out = element.tagName.toLowerCase();
|
|
9
|
+
if (element.id) out += `#${element.id}`;
|
|
10
|
+
const classes = element.classList;
|
|
11
|
+
if (classes.length > 0) {
|
|
12
|
+
out += `.${classes[0]}`;
|
|
13
|
+
if (classes.length > 1) out += `.${classes[1]}`;
|
|
14
|
+
}
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
function describeAll(graph, roots, writtenBy, kinds, extraFor) {
|
|
18
|
+
const owners = /* @__PURE__ */ new Map();
|
|
19
|
+
const writers = /* @__PURE__ */ new Map();
|
|
20
|
+
const rendered = /* @__PURE__ */ new Map();
|
|
21
|
+
for (const node of graph.values()) {
|
|
22
|
+
if (kinds.has(node.kind)) {
|
|
23
|
+
const found = roots(node.id);
|
|
24
|
+
rendered.set(node.id, found);
|
|
25
|
+
for (const element of found) if (!owners.has(element)) owners.set(element, node.id);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
for (const element of writtenBy(node.id)) {
|
|
29
|
+
const held = writers.get(element);
|
|
30
|
+
if (held) held.push(node.id);
|
|
31
|
+
else writers.set(element, [node.id]);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const { claimed, containers } = claimOrphans(graph, rendered, writtenBy, kinds, owners);
|
|
35
|
+
const claims = /* @__PURE__ */ new Map();
|
|
36
|
+
for (const [element, id] of claimed) {
|
|
37
|
+
const held = claims.get(id);
|
|
38
|
+
if (held) held.push(element);
|
|
39
|
+
else claims.set(id, [element]);
|
|
40
|
+
}
|
|
41
|
+
const landing = landings(graph, rendered, writtenBy, kinds, claimed, containers);
|
|
42
|
+
const out = /* @__PURE__ */ new Map();
|
|
43
|
+
for (const node of graph.values()) {
|
|
44
|
+
if (!kinds.has(node.kind)) continue;
|
|
45
|
+
const budget = { left: DOM_BUDGET };
|
|
46
|
+
const walk = (element) => {
|
|
47
|
+
const owner = owners.get(element) ?? claimed.get(element);
|
|
48
|
+
const where = locationOf(element);
|
|
49
|
+
if (owner !== void 0 && owner !== node.id) {
|
|
50
|
+
return { label: describeElement(element), children: [], owner, element, ...where ? { at: where } : {} };
|
|
51
|
+
}
|
|
52
|
+
if (containers.has(element)) {
|
|
53
|
+
return { label: describeElement(element), children: [], container: true, element, ...where ? { at: where } : {} };
|
|
54
|
+
}
|
|
55
|
+
const children = [];
|
|
56
|
+
const kids = element.children;
|
|
57
|
+
for (let i = 0, n = kids.length; i < n && budget.left > 0; i++) {
|
|
58
|
+
budget.left -= 1;
|
|
59
|
+
children.push(walk(kids[i]));
|
|
60
|
+
}
|
|
61
|
+
const writes = writers.get(element);
|
|
62
|
+
const extra = extraFor?.(element);
|
|
63
|
+
const inside = landing.get(element)?.filter((id) => within(graph, id, node.id));
|
|
64
|
+
return {
|
|
65
|
+
label: describeElement(element),
|
|
66
|
+
children,
|
|
67
|
+
element,
|
|
68
|
+
...where ? { at: where } : {},
|
|
69
|
+
...writes?.length ? { writes } : {},
|
|
70
|
+
...inside?.length ? { inside } : {},
|
|
71
|
+
...extra ? { extra } : {}
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
out.set(node.id, [...rendered.get(node.id) ?? [], ...claims.get(node.id) ?? []].map(walk));
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
function within(graph, id, ancestor) {
|
|
79
|
+
const seen = /* @__PURE__ */ new Set();
|
|
80
|
+
for (let at = graph.get(id)?.createdIn; at !== void 0 && !seen.has(at); at = graph.get(at)?.createdIn) {
|
|
81
|
+
if (at === ancestor) return true;
|
|
82
|
+
seen.add(at);
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
function landings(graph, rendered, writtenBy, kinds, claimed, containers) {
|
|
87
|
+
const claimers = new Set(claimed.values());
|
|
88
|
+
const landing = /* @__PURE__ */ new Map();
|
|
89
|
+
for (const node of graph.values()) {
|
|
90
|
+
if (!kinds.has(node.kind) || (rendered.get(node.id) ?? []).length) continue;
|
|
91
|
+
if (claimers.has(node.id)) continue;
|
|
92
|
+
let shallowest;
|
|
93
|
+
let best = Infinity;
|
|
94
|
+
for (const element of writtenBy(node.id)) {
|
|
95
|
+
if (containers.has(element)) continue;
|
|
96
|
+
const depth = depthInDocument(element);
|
|
97
|
+
if (depth < best) {
|
|
98
|
+
best = depth;
|
|
99
|
+
shallowest = element;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (!shallowest) continue;
|
|
103
|
+
const held = landing.get(shallowest);
|
|
104
|
+
if (held) held.push(node.id);
|
|
105
|
+
else landing.set(shallowest, [node.id]);
|
|
106
|
+
}
|
|
107
|
+
for (const [element, ids] of landing) {
|
|
108
|
+
landing.set(element, ids.filter((id) => !ids.some((other) => other !== id && within(graph, id, other))));
|
|
109
|
+
}
|
|
110
|
+
return landing;
|
|
111
|
+
}
|
|
112
|
+
function tagDepths(graph, kinds) {
|
|
113
|
+
const depth = /* @__PURE__ */ new Map();
|
|
114
|
+
const of = (id, seen) => {
|
|
115
|
+
const held = depth.get(id);
|
|
116
|
+
if (held !== void 0) return held;
|
|
117
|
+
if (seen.has(id)) return 0;
|
|
118
|
+
seen.add(id);
|
|
119
|
+
const parent = graph.get(id)?.createdIn;
|
|
120
|
+
const value = parent === void 0 ? 0 : of(parent, seen) + 1;
|
|
121
|
+
depth.set(id, value);
|
|
122
|
+
return value;
|
|
123
|
+
};
|
|
124
|
+
for (const node of graph.values()) if (kinds.has(node.kind)) of(node.id, /* @__PURE__ */ new Set());
|
|
125
|
+
return depth;
|
|
126
|
+
}
|
|
127
|
+
function depthInDocument(element) {
|
|
128
|
+
let steps = 0;
|
|
129
|
+
for (let at = element.parentElement; at; at = at.parentElement) steps++;
|
|
130
|
+
return steps;
|
|
131
|
+
}
|
|
132
|
+
function claimOrphans(graph, rendered, writtenBy, kinds, owners) {
|
|
133
|
+
const depth = tagDepths(graph, kinds);
|
|
134
|
+
const wraps = (element) => {
|
|
135
|
+
for (const owned of owners.keys()) if (element !== owned && element.contains(owned)) return true;
|
|
136
|
+
return false;
|
|
137
|
+
};
|
|
138
|
+
const writing = /* @__PURE__ */ new Map();
|
|
139
|
+
for (const node of graph.values()) {
|
|
140
|
+
if (!kinds.has(node.kind) || (rendered.get(node.id) ?? []).length) continue;
|
|
141
|
+
for (const element of writtenBy(node.id)) {
|
|
142
|
+
if (owners.has(element)) continue;
|
|
143
|
+
const held = writing.get(element);
|
|
144
|
+
if (held) held.push(node.id);
|
|
145
|
+
else writing.set(element, [node.id]);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const claimed = /* @__PURE__ */ new Map();
|
|
149
|
+
const containers = /* @__PURE__ */ new Set();
|
|
150
|
+
const covered = (element) => {
|
|
151
|
+
for (let at = element.parentElement; at; at = at.parentElement) {
|
|
152
|
+
if (owners.has(at) || claimed.has(at)) return true;
|
|
153
|
+
}
|
|
154
|
+
return false;
|
|
155
|
+
};
|
|
156
|
+
const order = [...writing.keys()].sort((a, b) => depthInDocument(a) - depthInDocument(b));
|
|
157
|
+
for (const element of order) {
|
|
158
|
+
if (covered(element)) continue;
|
|
159
|
+
const ids = writing.get(element);
|
|
160
|
+
const container = wraps(element);
|
|
161
|
+
const pick = ids.reduce((best, id) => {
|
|
162
|
+
const a = depth.get(id) ?? 0;
|
|
163
|
+
const b = depth.get(best) ?? 0;
|
|
164
|
+
return container ? a < b ? id : best : a > b ? id : best;
|
|
165
|
+
});
|
|
166
|
+
claimed.set(element, pick);
|
|
167
|
+
if (container) containers.add(element);
|
|
168
|
+
}
|
|
169
|
+
return { claimed, containers };
|
|
170
|
+
}
|
|
171
|
+
function withoutElements(nodes) {
|
|
172
|
+
return nodes.map(({ element, children, ...rest }) => ({
|
|
173
|
+
...rest,
|
|
174
|
+
children: withoutElements(children)
|
|
175
|
+
}));
|
|
176
|
+
}
|
|
177
|
+
export {
|
|
178
|
+
DOM_BUDGET,
|
|
179
|
+
describeAll,
|
|
180
|
+
describeElement,
|
|
181
|
+
tagDepths,
|
|
182
|
+
withoutElements
|
|
183
|
+
};
|
package/dist/export.cjs
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
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/export.ts
|
|
21
|
+
var export_exports = {};
|
|
22
|
+
__export(export_exports, {
|
|
23
|
+
exportGraph: () => exportGraph,
|
|
24
|
+
graphToJson: () => graphToJson
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(export_exports);
|
|
27
|
+
|
|
28
|
+
// src/instrument.ts
|
|
29
|
+
var import_signal = require("@fluixi/reactive/signal");
|
|
30
|
+
var import_store = require("@fluixi/reactive/store");
|
|
31
|
+
|
|
32
|
+
// src/source.ts
|
|
33
|
+
var MARKS = "__FLUIXI_DEVTOOLS_MARKS__";
|
|
34
|
+
var host = globalThis;
|
|
35
|
+
var shared = host[MARKS] ?? {
|
|
36
|
+
pending: null,
|
|
37
|
+
expiring: false,
|
|
38
|
+
components: /* @__PURE__ */ new Map()
|
|
39
|
+
};
|
|
40
|
+
host[MARKS] = shared;
|
|
41
|
+
|
|
42
|
+
// src/format.ts
|
|
43
|
+
var MAX_DEPTH = 3;
|
|
44
|
+
var MAX_ENTRIES = 8;
|
|
45
|
+
function domName(v) {
|
|
46
|
+
if (typeof v?.nodeType !== "number" || typeof v.nodeName !== "string") return null;
|
|
47
|
+
return v.tagName ? `<${v.tagName.toLowerCase()}>` : `#${v.nodeName.toLowerCase()}`;
|
|
48
|
+
}
|
|
49
|
+
function fnName(v) {
|
|
50
|
+
return v.name ? `ƒ ${v.name}()` : "ƒ";
|
|
51
|
+
}
|
|
52
|
+
function className(v) {
|
|
53
|
+
const name = v.constructor?.name;
|
|
54
|
+
return name && name !== "Object" ? `${name} ` : "";
|
|
55
|
+
}
|
|
56
|
+
function primitive(v) {
|
|
57
|
+
if (v === null) return "null";
|
|
58
|
+
switch (typeof v) {
|
|
59
|
+
case "undefined":
|
|
60
|
+
return "undefined";
|
|
61
|
+
case "string":
|
|
62
|
+
return JSON.stringify(v);
|
|
63
|
+
case "number":
|
|
64
|
+
case "boolean":
|
|
65
|
+
return String(v);
|
|
66
|
+
case "bigint":
|
|
67
|
+
return `${v}n`;
|
|
68
|
+
case "symbol":
|
|
69
|
+
return v.toString();
|
|
70
|
+
case "function":
|
|
71
|
+
return fnName(v);
|
|
72
|
+
default:
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function walk(value, depth, seen) {
|
|
77
|
+
const simple = primitive(value);
|
|
78
|
+
if (simple !== null) return simple;
|
|
79
|
+
const object = value;
|
|
80
|
+
if (seen.has(object)) return "[circular]";
|
|
81
|
+
const dom = domName(object);
|
|
82
|
+
if (dom) return dom;
|
|
83
|
+
if (object instanceof Date) return Number.isNaN(object.getTime()) ? "Invalid Date" : object.toISOString();
|
|
84
|
+
if (object instanceof RegExp) return String(object);
|
|
85
|
+
if (object instanceof Error) return `${object.name}: ${object.message}`;
|
|
86
|
+
if (object instanceof Promise) return "Promise";
|
|
87
|
+
if (ArrayBuffer.isView(object)) {
|
|
88
|
+
return `${className(object).trim()}(${object.length ?? ""})`;
|
|
89
|
+
}
|
|
90
|
+
if (depth >= MAX_DEPTH) return Array.isArray(object) ? "[…]" : "{…}";
|
|
91
|
+
seen.add(object);
|
|
92
|
+
try {
|
|
93
|
+
if (Array.isArray(object)) {
|
|
94
|
+
const shown2 = object.slice(0, MAX_ENTRIES).map((item) => walk(item, depth + 1, seen));
|
|
95
|
+
if (object.length > MAX_ENTRIES) shown2.push("…");
|
|
96
|
+
return `[${shown2.join(", ")}]`;
|
|
97
|
+
}
|
|
98
|
+
if (object instanceof Map) {
|
|
99
|
+
const shown2 = [];
|
|
100
|
+
for (const [k, v] of object) {
|
|
101
|
+
if (shown2.length === MAX_ENTRIES) {
|
|
102
|
+
shown2.push("…");
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
shown2.push(`${walk(k, depth + 1, seen)} => ${walk(v, depth + 1, seen)}`);
|
|
106
|
+
}
|
|
107
|
+
return `Map(${object.size}) {${shown2.join(", ")}}`;
|
|
108
|
+
}
|
|
109
|
+
if (object instanceof Set) {
|
|
110
|
+
const shown2 = [];
|
|
111
|
+
for (const item of object) {
|
|
112
|
+
if (shown2.length === MAX_ENTRIES) {
|
|
113
|
+
shown2.push("…");
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
shown2.push(walk(item, depth + 1, seen));
|
|
117
|
+
}
|
|
118
|
+
return `Set(${object.size}) {${shown2.join(", ")}}`;
|
|
119
|
+
}
|
|
120
|
+
const keys = Object.keys(object);
|
|
121
|
+
const shown = keys.slice(0, MAX_ENTRIES).map((key) => {
|
|
122
|
+
let read;
|
|
123
|
+
try {
|
|
124
|
+
read = walk(object[key], depth + 1, seen);
|
|
125
|
+
} catch {
|
|
126
|
+
read = "[unreadable]";
|
|
127
|
+
}
|
|
128
|
+
return `${key}: ${read}`;
|
|
129
|
+
});
|
|
130
|
+
if (keys.length > MAX_ENTRIES) shown.push("…");
|
|
131
|
+
return `${className(object)}{${shown.join(", ")}}`;
|
|
132
|
+
} finally {
|
|
133
|
+
seen.delete(object);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function formatValue(value, limit = 240) {
|
|
137
|
+
let text;
|
|
138
|
+
try {
|
|
139
|
+
text = walk(value, 0, /* @__PURE__ */ new Set());
|
|
140
|
+
} catch {
|
|
141
|
+
text = "[unreadable]";
|
|
142
|
+
}
|
|
143
|
+
return text.length > limit ? `${text.slice(0, limit - 1)}…` : text;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// src/instrument.ts
|
|
147
|
+
var CORE_STATE = { 0: "clean", 1: "check", 2: "dirty" };
|
|
148
|
+
function nodeVersion(n) {
|
|
149
|
+
return n.core && typeof n.core.version === "number" ? n.core.version : n.runs;
|
|
150
|
+
}
|
|
151
|
+
function nodeState(n) {
|
|
152
|
+
return n.core && typeof n.core.state === "number" ? CORE_STATE[n.core.state] : void 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/export.ts
|
|
156
|
+
var at = (source) => {
|
|
157
|
+
if (!source) return void 0;
|
|
158
|
+
const where = `${source.file ?? ""}:${source.line ?? ""}:${source.column ?? ""}`;
|
|
159
|
+
const out = source.compiled;
|
|
160
|
+
const same = out?.line === source.line && out?.column === source.column;
|
|
161
|
+
return out && !same ? `${where} (out ${out.line ?? ""}:${out.column ?? ""})` : where;
|
|
162
|
+
};
|
|
163
|
+
function naming(graph) {
|
|
164
|
+
const seen = /* @__PURE__ */ new Map();
|
|
165
|
+
for (const node of graph.values()) seen.set(node.label, (seen.get(node.label) ?? 0) + 1);
|
|
166
|
+
return (id) => {
|
|
167
|
+
const node = graph.get(id);
|
|
168
|
+
if (!node) return `#${id}`;
|
|
169
|
+
return (seen.get(node.label) ?? 0) > 1 ? `${node.label}#${node.id}` : node.label;
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function exportGraph(graph, options = {}) {
|
|
173
|
+
const limit = options.limit ?? 400;
|
|
174
|
+
const name = naming(graph);
|
|
175
|
+
const nodes = [...graph.values()].map((node) => {
|
|
176
|
+
let value = node.detail ?? node.value;
|
|
177
|
+
if (node.read) {
|
|
178
|
+
try {
|
|
179
|
+
value = formatValue(node.read(), limit);
|
|
180
|
+
} catch {
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const feeds = [...node.deps].map(name);
|
|
184
|
+
const wrote = [...node.writes].map(name);
|
|
185
|
+
const state = nodeState(node);
|
|
186
|
+
return {
|
|
187
|
+
id: node.id,
|
|
188
|
+
label: node.label,
|
|
189
|
+
kind: node.kind,
|
|
190
|
+
...node.authored === false ? { authored: false } : {},
|
|
191
|
+
...value ? { value } : {},
|
|
192
|
+
...node.runs ? { runs: node.runs } : {},
|
|
193
|
+
// Only a node with a core has one; a static node would report a version of 0.
|
|
194
|
+
...node.core?.version !== void 0 ? { version: nodeVersion(node) } : {},
|
|
195
|
+
...state ? { state } : {},
|
|
196
|
+
...feeds.length ? { reads: feeds } : {},
|
|
197
|
+
...wrote.length ? { writes: wrote } : {},
|
|
198
|
+
...node.createdIn !== void 0 ? { madeIn: name(node.createdIn) } : {},
|
|
199
|
+
...at(node.source) ? { source: at(node.source) } : {},
|
|
200
|
+
...at(node.declaredAt) ? { declaredAt: at(node.declaredAt) } : {},
|
|
201
|
+
...at(node.usedAt) ? { usedAt: at(node.usedAt) } : {},
|
|
202
|
+
...node.targets?.length ? {
|
|
203
|
+
updates: node.targets.map((target) => {
|
|
204
|
+
const what = target.name ? `${target.name} of ${target.element}` : target.element;
|
|
205
|
+
const where = at(target.source);
|
|
206
|
+
return where ? `${what} — ${where}` : what;
|
|
207
|
+
})
|
|
208
|
+
} : {},
|
|
209
|
+
...node.setAt?.length ? { setAt: node.setAt.map((s) => at(s)).filter(Boolean) } : {}
|
|
210
|
+
};
|
|
211
|
+
});
|
|
212
|
+
return {
|
|
213
|
+
t: Date.now(),
|
|
214
|
+
from: options.fromSource ? "source" : "running application",
|
|
215
|
+
nodes,
|
|
216
|
+
...options.events?.length ? { events: [...options.events] } : {}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function graphToJson(graph, options = {}) {
|
|
220
|
+
return JSON.stringify(exportGraph(graph, options), null, 2);
|
|
221
|
+
}
|
package/dist/export.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The graph as something to paste somewhere else.
|
|
3
3
|
*
|
|
4
4
|
* A panel shows one node at a time; a bug report needs all of them at once. This is the whole
|
|
5
|
-
* graph as plain json
|
|
5
|
+
* graph as plain json: values, kinds, ownership, sources, what each node reaches in the
|
|
6
6
|
* document and where it is written from.
|
|
7
7
|
*
|
|
8
8
|
* Names rather than ids wherever a reader has to follow a reference: `deps: ["count"]` can be
|
|
@@ -23,7 +23,7 @@ interface ExportedNode {
|
|
|
23
23
|
id: number;
|
|
24
24
|
label: string;
|
|
25
25
|
kind: string;
|
|
26
|
-
/** Absent when the framework named it
|
|
26
|
+
/** Absent when the framework named it: see RNode.authored. */
|
|
27
27
|
authored?: boolean;
|
|
28
28
|
value?: string;
|
|
29
29
|
runs?: number;
|
package/dist/export.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAA0B,KAAK,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAErE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,MAAM,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAC/B,kFAAkF;IAClF,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAA0B,KAAK,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAErE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,MAAM,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAC/B,kFAAkF;IAClF,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAsBD,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,mDAAmD;IACnD,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IACtB,IAAI,EAAE,QAAQ,GAAG,qBAAqB,CAAC;CACxC;AAED,mCAAmC;AACnC,wBAAgB,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAE,aAAkB,GAAG,aAAa,CAoDjG;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAE1F"}
|
package/dist/export.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The graph as something to paste somewhere else.
|
|
3
3
|
*
|
|
4
4
|
* A panel shows one node at a time; a bug report needs all of them at once. This is the whole
|
|
5
|
-
* graph as plain json
|
|
5
|
+
* graph as plain json: values, kinds, ownership, sources, what each node reaches in the
|
|
6
6
|
* document and where it is written from.
|
|
7
7
|
*
|
|
8
8
|
* Names rather than ids wherever a reader has to follow a reference: `deps: ["count"]` can be
|
package/dist/export.mjs
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
// src/instrument.ts
|
|
2
|
+
import {
|
|
3
|
+
createSignal,
|
|
4
|
+
createMemo,
|
|
5
|
+
createEffect,
|
|
6
|
+
createResource,
|
|
7
|
+
createRoot,
|
|
8
|
+
untrack,
|
|
9
|
+
onCleanup,
|
|
10
|
+
getOwner,
|
|
11
|
+
runWithOwner,
|
|
12
|
+
Signal
|
|
13
|
+
} from "@fluixi/reactive/signal";
|
|
14
|
+
import { createStore } from "@fluixi/reactive/store";
|
|
15
|
+
|
|
16
|
+
// src/source.ts
|
|
17
|
+
var MARKS = "__FLUIXI_DEVTOOLS_MARKS__";
|
|
18
|
+
var host = globalThis;
|
|
19
|
+
var shared = host[MARKS] ?? {
|
|
20
|
+
pending: null,
|
|
21
|
+
expiring: false,
|
|
22
|
+
components: /* @__PURE__ */ new Map()
|
|
23
|
+
};
|
|
24
|
+
host[MARKS] = shared;
|
|
25
|
+
|
|
26
|
+
// src/format.ts
|
|
27
|
+
var MAX_DEPTH = 3;
|
|
28
|
+
var MAX_ENTRIES = 8;
|
|
29
|
+
function domName(v) {
|
|
30
|
+
if (typeof v?.nodeType !== "number" || typeof v.nodeName !== "string") return null;
|
|
31
|
+
return v.tagName ? `<${v.tagName.toLowerCase()}>` : `#${v.nodeName.toLowerCase()}`;
|
|
32
|
+
}
|
|
33
|
+
function fnName(v) {
|
|
34
|
+
return v.name ? `ƒ ${v.name}()` : "ƒ";
|
|
35
|
+
}
|
|
36
|
+
function className(v) {
|
|
37
|
+
const name = v.constructor?.name;
|
|
38
|
+
return name && name !== "Object" ? `${name} ` : "";
|
|
39
|
+
}
|
|
40
|
+
function primitive(v) {
|
|
41
|
+
if (v === null) return "null";
|
|
42
|
+
switch (typeof v) {
|
|
43
|
+
case "undefined":
|
|
44
|
+
return "undefined";
|
|
45
|
+
case "string":
|
|
46
|
+
return JSON.stringify(v);
|
|
47
|
+
case "number":
|
|
48
|
+
case "boolean":
|
|
49
|
+
return String(v);
|
|
50
|
+
case "bigint":
|
|
51
|
+
return `${v}n`;
|
|
52
|
+
case "symbol":
|
|
53
|
+
return v.toString();
|
|
54
|
+
case "function":
|
|
55
|
+
return fnName(v);
|
|
56
|
+
default:
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function walk(value, depth, seen) {
|
|
61
|
+
const simple = primitive(value);
|
|
62
|
+
if (simple !== null) return simple;
|
|
63
|
+
const object = value;
|
|
64
|
+
if (seen.has(object)) return "[circular]";
|
|
65
|
+
const dom = domName(object);
|
|
66
|
+
if (dom) return dom;
|
|
67
|
+
if (object instanceof Date) return Number.isNaN(object.getTime()) ? "Invalid Date" : object.toISOString();
|
|
68
|
+
if (object instanceof RegExp) return String(object);
|
|
69
|
+
if (object instanceof Error) return `${object.name}: ${object.message}`;
|
|
70
|
+
if (object instanceof Promise) return "Promise";
|
|
71
|
+
if (ArrayBuffer.isView(object)) {
|
|
72
|
+
return `${className(object).trim()}(${object.length ?? ""})`;
|
|
73
|
+
}
|
|
74
|
+
if (depth >= MAX_DEPTH) return Array.isArray(object) ? "[…]" : "{…}";
|
|
75
|
+
seen.add(object);
|
|
76
|
+
try {
|
|
77
|
+
if (Array.isArray(object)) {
|
|
78
|
+
const shown2 = object.slice(0, MAX_ENTRIES).map((item) => walk(item, depth + 1, seen));
|
|
79
|
+
if (object.length > MAX_ENTRIES) shown2.push("…");
|
|
80
|
+
return `[${shown2.join(", ")}]`;
|
|
81
|
+
}
|
|
82
|
+
if (object instanceof Map) {
|
|
83
|
+
const shown2 = [];
|
|
84
|
+
for (const [k, v] of object) {
|
|
85
|
+
if (shown2.length === MAX_ENTRIES) {
|
|
86
|
+
shown2.push("…");
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
shown2.push(`${walk(k, depth + 1, seen)} => ${walk(v, depth + 1, seen)}`);
|
|
90
|
+
}
|
|
91
|
+
return `Map(${object.size}) {${shown2.join(", ")}}`;
|
|
92
|
+
}
|
|
93
|
+
if (object instanceof Set) {
|
|
94
|
+
const shown2 = [];
|
|
95
|
+
for (const item of object) {
|
|
96
|
+
if (shown2.length === MAX_ENTRIES) {
|
|
97
|
+
shown2.push("…");
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
shown2.push(walk(item, depth + 1, seen));
|
|
101
|
+
}
|
|
102
|
+
return `Set(${object.size}) {${shown2.join(", ")}}`;
|
|
103
|
+
}
|
|
104
|
+
const keys = Object.keys(object);
|
|
105
|
+
const shown = keys.slice(0, MAX_ENTRIES).map((key) => {
|
|
106
|
+
let read;
|
|
107
|
+
try {
|
|
108
|
+
read = walk(object[key], depth + 1, seen);
|
|
109
|
+
} catch {
|
|
110
|
+
read = "[unreadable]";
|
|
111
|
+
}
|
|
112
|
+
return `${key}: ${read}`;
|
|
113
|
+
});
|
|
114
|
+
if (keys.length > MAX_ENTRIES) shown.push("…");
|
|
115
|
+
return `${className(object)}{${shown.join(", ")}}`;
|
|
116
|
+
} finally {
|
|
117
|
+
seen.delete(object);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function formatValue(value, limit = 240) {
|
|
121
|
+
let text;
|
|
122
|
+
try {
|
|
123
|
+
text = walk(value, 0, /* @__PURE__ */ new Set());
|
|
124
|
+
} catch {
|
|
125
|
+
text = "[unreadable]";
|
|
126
|
+
}
|
|
127
|
+
return text.length > limit ? `${text.slice(0, limit - 1)}…` : text;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/instrument.ts
|
|
131
|
+
var CORE_STATE = { 0: "clean", 1: "check", 2: "dirty" };
|
|
132
|
+
function nodeVersion(n) {
|
|
133
|
+
return n.core && typeof n.core.version === "number" ? n.core.version : n.runs;
|
|
134
|
+
}
|
|
135
|
+
function nodeState(n) {
|
|
136
|
+
return n.core && typeof n.core.state === "number" ? CORE_STATE[n.core.state] : void 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/export.ts
|
|
140
|
+
var at = (source) => {
|
|
141
|
+
if (!source) return void 0;
|
|
142
|
+
const where = `${source.file ?? ""}:${source.line ?? ""}:${source.column ?? ""}`;
|
|
143
|
+
const out = source.compiled;
|
|
144
|
+
const same = out?.line === source.line && out?.column === source.column;
|
|
145
|
+
return out && !same ? `${where} (out ${out.line ?? ""}:${out.column ?? ""})` : where;
|
|
146
|
+
};
|
|
147
|
+
function naming(graph) {
|
|
148
|
+
const seen = /* @__PURE__ */ new Map();
|
|
149
|
+
for (const node of graph.values()) seen.set(node.label, (seen.get(node.label) ?? 0) + 1);
|
|
150
|
+
return (id) => {
|
|
151
|
+
const node = graph.get(id);
|
|
152
|
+
if (!node) return `#${id}`;
|
|
153
|
+
return (seen.get(node.label) ?? 0) > 1 ? `${node.label}#${node.id}` : node.label;
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function exportGraph(graph, options = {}) {
|
|
157
|
+
const limit = options.limit ?? 400;
|
|
158
|
+
const name = naming(graph);
|
|
159
|
+
const nodes = [...graph.values()].map((node) => {
|
|
160
|
+
let value = node.detail ?? node.value;
|
|
161
|
+
if (node.read) {
|
|
162
|
+
try {
|
|
163
|
+
value = formatValue(node.read(), limit);
|
|
164
|
+
} catch {
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const feeds = [...node.deps].map(name);
|
|
168
|
+
const wrote = [...node.writes].map(name);
|
|
169
|
+
const state = nodeState(node);
|
|
170
|
+
return {
|
|
171
|
+
id: node.id,
|
|
172
|
+
label: node.label,
|
|
173
|
+
kind: node.kind,
|
|
174
|
+
...node.authored === false ? { authored: false } : {},
|
|
175
|
+
...value ? { value } : {},
|
|
176
|
+
...node.runs ? { runs: node.runs } : {},
|
|
177
|
+
// Only a node with a core has one; a static node would report a version of 0.
|
|
178
|
+
...node.core?.version !== void 0 ? { version: nodeVersion(node) } : {},
|
|
179
|
+
...state ? { state } : {},
|
|
180
|
+
...feeds.length ? { reads: feeds } : {},
|
|
181
|
+
...wrote.length ? { writes: wrote } : {},
|
|
182
|
+
...node.createdIn !== void 0 ? { madeIn: name(node.createdIn) } : {},
|
|
183
|
+
...at(node.source) ? { source: at(node.source) } : {},
|
|
184
|
+
...at(node.declaredAt) ? { declaredAt: at(node.declaredAt) } : {},
|
|
185
|
+
...at(node.usedAt) ? { usedAt: at(node.usedAt) } : {},
|
|
186
|
+
...node.targets?.length ? {
|
|
187
|
+
updates: node.targets.map((target) => {
|
|
188
|
+
const what = target.name ? `${target.name} of ${target.element}` : target.element;
|
|
189
|
+
const where = at(target.source);
|
|
190
|
+
return where ? `${what} — ${where}` : what;
|
|
191
|
+
})
|
|
192
|
+
} : {},
|
|
193
|
+
...node.setAt?.length ? { setAt: node.setAt.map((s) => at(s)).filter(Boolean) } : {}
|
|
194
|
+
};
|
|
195
|
+
});
|
|
196
|
+
return {
|
|
197
|
+
t: Date.now(),
|
|
198
|
+
from: options.fromSource ? "source" : "running application",
|
|
199
|
+
nodes,
|
|
200
|
+
...options.events?.length ? { events: [...options.events] } : {}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function graphToJson(graph, options = {}) {
|
|
204
|
+
return JSON.stringify(exportGraph(graph, options), null, 2);
|
|
205
|
+
}
|
|
206
|
+
export {
|
|
207
|
+
exportGraph,
|
|
208
|
+
graphToJson
|
|
209
|
+
};
|